2016-10-09 2 views
0

Прежде всего, позвольте мне извиниться за длину кода «sample», я пытался предоставить наименьший пример исполняемого файла, который я мог бы сделать.Очередь теряет указатели после вызова swapcontext()

Я должен упомянуть, очередь имеет вид:

circular queue

При запуске называется, первый элемент успешно удален из очереди, который затем ссылается глобальный указатель Curr_Thread. Я проверяю форму очереди до и после, все, где она должна быть.

Работы и управление Swapcontext передается func_1(), но в этом проблема. Как только он входит в func_1(), очередь становится каким-то образом искалеченной, то есть указатель на голову по-прежнему указывает на элемент «фиктивный», как и до переключателя (со следующим и предыдущим указателями, указывающими, где они должны), но все после манекена элемент теперь указывает на некоторый элемент мусора со случайными следующими и предыдущими адресами указателей. Когда func_1 звонит yield(), вызов AddTcb() во время сбоев, потому что он никогда не сможет найти конец очереди, чтобы добавить Curr_Thread.

Перед входа в func_1() из swapcontext:

pointer pointing where they should

Сразу после вступления в func_1() из swapcontext

pointers to nowhere

Почему структура моей очереди вдруг изменилась после вызова swapcontext? Почему это меняется без какого-либо другого взаимодействия?

спасибо.

#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

Обратитесь к этому ответу: http://stackoverflow.com/questions/25841144/seg-fault-when-returning-to-function-execution-after-successful-swapcontext – Murali

+0

Спасибо. Я уже пробовал это решение, но у меня была другая проблема, которая маскировала результаты. Прекрасно работает. – corporateWhore

+0

Добавьте это как ответ, и я соглашусь с ним. – corporateWhore

ответ

1

У меня была аналогичная проблема. Я назначил значения прямо так, как показано ниже, и это сработало для меня.

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