2016-10-09 1 views
0

Tout d'abord, permettez-moi de m'excuser pour la longueur du code "sample", j'essayais de fournir le plus petit exemple exécutable possible.La file d'attente perd des pointeurs après l'appel à swapcontext()

Je dois mentionner, la file d'attente est de la forme:

circular queue

Lorsque l'exécution est appelée, le premier élément est supprimé de la file d'attente qui est ensuite référencé par le pointeur global Curr_Thread. Je vérifie la forme de la file d'attente avant et après, tout est supposé être. Swapcontext fonctionne et le contrôle est passé à func_1(), mais c'est là que réside le problème. Dès qu'il entre func_1(), la file d'attente est mutilée, ce qui signifie que le pointeur de la tête pointe toujours sur l'élément "factice" comme avant le changement (avec les pointeurs suivant et précédent pointant où ils devraient), mais tout après le mannequin element pointe maintenant vers un élément poubelle avec des adresses de pointeur aléatoires suivantes et précédentes. Lorsque func_1 appelle yield(), l'appel à AddTcb() se bloque à l'intérieur car il ne peut jamais trouver la fin de la file d'attente pour ajouter Curr_Thread.

Avant l'entrée en func_1() de swapcontext:

pointer pointing where they should

Immédiatement après l'entrée en func_1() de swapcontext

pointers to nowhere

Pourquoi la structure de ma file d'attente a soudainement changé après avoir appelé swapcontext? Pourquoi change-t-il sans autre interaction?

Merci.

#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

Reportez-vous à cette réponse: http://stackoverflow.com/questions/25841144/seg-fault-when-returning-to-function-execution-after-successful-swapcontext – Murali

+0

Merci. J'avais déjà essayé cette solution mais j'avais un autre problème qui masquait les résultats. Fonctionne bien maintenant. – corporateWhore

+0

Ajoutez-le comme une réponse et je l'accepterai – corporateWhore

Répondre

1

J'ai eu le même problème. J'ai assigné les valeurs directement comme ci-dessous et cela a fonctionné pour moi.

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