【问题标题】:Queue loses pointers after call to swapcontext()调用 swapcontext() 后队列丢失指针
【发布时间】:2016-10-09 03:07:11
【问题描述】:

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

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

当调用 run 时,第一个元素被成功地从队列中移除,然后被全局指针 Curr_Thread 引用。我检查了前后队列的形式,一切都在它应该在的地方。

Swapcontext 有效,控制权被传递给func_1(),但这就是问题所在。一旦它进入func_1(),队列就会以某种方式被破坏,这意味着,头指针仍然指向“虚拟”元素,就像它在切换之前所做的那样(下一个和前一个指针指向它们应该指向的位置),但之后的一切虚拟元素现在指向一些具有随机下一个和前一个指针地址的垃圾元素。当func_1 调用yield() 时,内部对AddTcb() 的调用会崩溃,因为它永远找不到队列的末尾添加Curr_Thread

在从swapcontext进入func_1()之前:

swapcontext进入func_1()后立即

为什么在调用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;
}

【问题讨论】:

  • 谢谢。我已经尝试过该解决方案,但有另一个问题掩盖了结果。现在效果很好。
  • 添加它作为答案,我会接受它

标签: c multithreading queue


【解决方案1】:

我有类似的问题。我像下面这样直接分配了值,它对我有用。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 2011-04-19
    • 1970-01-01
    • 1970-01-01
    • 2013-04-17
    相关资源
    最近更新 更多