调用swapcontext()

时间:2016-10-09 03:07:11

标签: c multithreading queue

首先,让我为代码“sample”的长度道歉,我试图提供最小的可执行示例。

我应该提一下,队列的形式是:

circular queue

调用run时,第一个元素从队列中成功删除,然后由全局指针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 个答案:

答案 0 :(得分:1)

我有类似的问题。我直接分配了这些值,如下所示,它对我有用。

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