2016-10-09 6 views
0

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:

circular queue

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_1yield() 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:

pointer pointing where they should

Unmittelbar nach dem Eintritt in func_1() von swapcontext

pointers to nowhere

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; 
} 
+1

zu dieser Antwort finden: http://stackoverflow.com/questions/25841144/seg-fault-when-returning-to-function-execution-after-successful-swapcontext – Murali

+0

Danke. Ich hatte diese Lösung bereits ausprobiert, hatte aber ein anderes Problem, das die Ergebnisse maskierte. Funktioniert jetzt großartig. – corporateWhore

+0

Fügen Sie es als Antwort hinzu und ich werde es akzeptieren – corporateWhore

Antwort

1

Ich hatte das ähnliche Problem. Ich habe die Werte direkt wie unten angegeben und es hat für mich funktioniert.

tcb->context.uc_stack.ss_sp = malloc(8192); 
tcb->context.uc_stack.ss_size = 8192; 
Verwandte Themen