Als erstes entschuldige ich mich für die Länge des Codes "Beispiel", ich habe versucht, das kleinste ausführbare Beispiel, das ich könnte.Warteschlange verliert Zeiger nach Aufruf von swapcontext()
ich erwähnen sollte, ist die Warteschlange der Form:
Wenn Lauf aufgerufen wird, wird das erste Element erfolgreich aus der Warteschlange entfernt, die dann durch den globalen Zeiger Curr_Thread
verwiesen wird. Ich überprüfe die Form der Warteschlange vorher und nachher, alles ist wo es sein soll.
Swapcontext funktioniert und Kontrolle wird an func_1()
übergeben, aber hier liegt das Problem. Sobald es in func_1()
eintritt, wird die Queue irgendwie verstümmelt, was bedeutet, dass der Kopfzeiger immer noch auf das "Dummy" Element zeigt, wie vor dem Schalter (mit den nächsten und vorherigen Zeigern dorthin zeigend), aber alles nach dem Dummy element zeigt nun auf ein Müllelement mit zufälligen nächsten und vorherigen Zeigeradressen. Wenn func_1
yield()
aufruft, stürzt der Aufruf an AddTcb()
innerhalb ab, da es das Ende der Warteschlange nie finden kann, um Curr_Thread
hinzuzufügen.
vor dem Eintritt in func_1()
von swapcontext
:
Unmittelbar nach dem Eintritt in func_1()
von swapcontext
Warum ist die Struktur meiner Warteschlange plötzlich nach swapcontext
Aufruf geändert? Warum ändert es sich mit keiner anderen Interaktion?
Vielen Dank.
#include <ucontext.h>
#include <string.h>
#include <stdio.h>
#include <malloc.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX_QUEUE 100
TCB_t *ReadyQ;
TCB_t *Curr_Thread;
int global_thread_id = 0;
typedef struct TCB_t {
struct TCB_t *next;
struct TCB_t *prev;
ucontext_t context;
int thread_id;
} TCB_t;
void start_thread(void (*function) (void));
void run();
void yield();
void print_id(TCB_t *tcb);
void func_1();
void (*f1)();
TCB_t* newItem();
TCB_t* newTcb(TCB_t* head);
void AddTcb(TCB_t* head_node, TCB_t* new_node);
TCB_t* DelTcb(TCB_t* head);
void init_TCB (TCB_t *tcb, void *function, void *stackP, int stack_size)
{
memset(tcb, '\0', sizeof(TCB_t));
getcontext(&tcb->context);
tcb->context.uc_stack.ss_sp = stackP;
tcb->context.uc_stack.ss_size = (size_t) stack_size;
tcb->thread_id = global_thread_id ++;
makecontext(&tcb->context, function, 0);// context is now cooked
}
void start_thread(void (*function) (void)){
void *stack; //generic stack pointer
TCB_t *new_tcb; //new TCB
stack = malloc(STACK_SIZE);
new_tcb = (TCB_t*) malloc(sizeof(TCB_t));
init_TCB(new_tcb, function, stack, sizeof(stack));
AddTcb(ReadyQ, new_tcb);
}
void run(){
Curr_Thread = DelTcb(ReadyQ);
ucontext_t parent;
getcontext(&parent); //get the current running context
swapcontext(&parent, &(Curr_Thread->context)); //switch it to the next q element
}
void yield(){
TCB_t *prev_thread;
AddTcb(ReadyQ, Curr_Thread);
prev_thread = Curr_Thread;
Curr_Thread = DelTcb(ReadyQ);
//swap the context from the previous thread to the thread pointed to by Curr_Thread
swapcontext(&(prev_thread->context), &(Curr_Thread->context));
}
struct TCB_t* newItem(){
TCB_t* new_tcb; //create new node on heap
new_tcb = (TCB_t*) malloc(sizeof(TCB_t));
return new_tcb; //return the new node
}
TCB_t* newQueue(){
TCB_t *dummy = newItem(); //create dummy node
TCB_t *head = newItem();
dummy->next = NULL; //set dummy elements to NULL
dummy->prev = NULL;
head->next = dummy; //point head at dummy
head->prev = NULL;
return head; //return head
}
//Add new item to queue
void AddTcb(TCB_t* head_tcb_node, TCB_t* new_tcb_node){
TCB_t* tmp, *dummy;
dummy = head_tcb_node->next; //tmp is header node
if(dummy->next == NULL){
dummy->next = new_tcb_node;
dummy->prev = new_tcb_node;
new_tcb_node->next = dummy;
new_tcb_node->prev = dummy;
}else{
tmp = dummy->next;
while(tmp->next != dummy){
tmp = tmp->next;
}
new_tcb_node->next = tmp->next;
new_tcb_node->prev = tmp;
tmp->next = new_tcb_node;
dummy->prev = new_tcb_node;
}
}
//Remove and return first queue element
TCB_t* DelTcb(TCB_t *head){
TCB_t *dummy, *pop, *tmp;
dummy = head->next;
if (dummy->next == NULL){
pop = NULL;
}else{
pop = dummy->next;
if(pop->next == dummy){
dummy->next = NULL;
dummy->prev = NULL;
}else{
tmp = pop->next;
tmp->prev = dummy;
dummy->next = tmp;
}
pop->next = pop->prev = NULL;
}
return pop;
}
void func_1(){
int local_1 = 0;
while(1){
//print_id(ReadyQ);
printf("\n");
printf("Global int: %d\t", gbl_num);
printf("Local int, function 1: %d\n\n", local_1);
gbl_num++;
local_1++;
yield();
sleep(1);
}
}
int main(){
ReadyQ = newQueue();
f1 = func_1;
start_thread(f1);
run();
return 0;
}
zu dieser Antwort finden: http://stackoverflow.com/questions/25841144/seg-fault-when-returning-to-function-execution-after-successful-swapcontext – Murali
Danke. Ich hatte diese Lösung bereits ausprobiert, hatte aber ein anderes Problem, das die Ergebnisse maskierte. Funktioniert jetzt großartig. – corporateWhore
Fügen Sie es als Antwort hinzu und ich werde es akzeptieren – corporateWhore