Многопоточность - RunQ, случайно меняющийся - PullRequest
1 голос
/ 09 марта 2020

Моя программа запускает потоки и запускает их. Предполагается, что RunQ - это очередь (struct Q) блоков TCB_t, в которых хранится контекст потока. Проблема в том, что RunQ случайно меняется как I go через функции, и я не уверен почему. Как вы можете видеть на этом изображении, простое объявление и инициализация нового значения int равным 0 изменяет значение RunQ-> tail на 0. Почему это происходит?

main:

#include "threads.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define _GNU_SOURCE

int numAnimals;
void countAnimals(){
    int numSheep = 0;
    int numCows = 0;
    while(1){
        if(numSheep >= 500)
            yield();
        else numSheep = incrementCount(numSheep);
        if(numCows >= 500)
            yield();
        else numCows = incrementCount(numCows);
        numAnimals = numSheep + numCows;
    }
}

int numFruit;
void countFruit(){
    int numApples = 0;
    int numOranges = 0;
    while(1){
        if(numApples >=500)
            yield();
        else numApples = incrementCount(numApples);
        if(numOranges >= 500)
            yield();
        else numOranges = incrementCount(numOranges);
        numFruit = numApples + numOranges;
    }
}

int incrementCount(int count){
    return ++count;
}

int main (){
    start_thread(countAnimals);
    start_thread(countFruit);
    run();
}

threads.h:

#include "q.h"

struct Q* RunQ;
struct TCB_t* Curr_Thread;
struct TCB_t* Prev_Thread;

void start_thread(void (*function) (void)){

    int* stack = malloc(8192); //allocate a stack of 8192 bytes
    TCB_t* TCB = (TCB_t*)malloc(sizeof(TCB_t)); //allocate a TCB
    init_TCB(TCB, function, stack, sizeof(stack)); //call init_TCB
    if(global_thread_id == 1){
        RunQ = (struct Q*) malloc(sizeof(struct Q));
        InitQueue(RunQ, TCB);
    }
    AddQueue(RunQ, TCB); //call addQ to add this TCB into the "RunQ"
}

void run(){   // real code
    Curr_Thread = RunQ->head;
    ucontext_t parent; // get a place to store the main context, for faking
    getcontext(&parent); // magic sauce
    swapcontext(&parent, &(Curr_Thread->context)); // start the first thread
}

void yield(){
    Prev_Thread = RunQ->head;
    RotateQ(RunQ);
    Curr_Thread = RunQ->head;
    swapcontext(&(Prev_Thread->context), &(Curr_Thread->context)); //swap the context, from Prev_Thread to the thread pointed to by Curr_Thread
}

qh:

#include <unistd.h>
#include <stdlib.h>
#include "TCB.h"

#define _GNU_SOURCE

struct Q {
    struct TCB_t* head;
    struct TCB_t* tail;
};

void InitQueue(struct Q* q,struct TCB_t* head){
    q->head = head;
    q->tail = q->head;
};

void AddQueue(struct Q* q, struct TCB_t* item){
    if(q->head == NULL) {
        q-> head = item;
        q-> tail = item;
    } else if(q->tail == q->head) {
        item->prev = q->head;
        item->next = q->head;

        q->tail = item;

        q->head->prev = q->tail;
        q->head->next = q->tail;
    } else {
        item->prev = q->tail;
        item->next = q->head;

        q->tail->next = item;
        q->head->prev = item;

        q->tail = item;
    }
}

 struct TCB_t* DelQueue(struct Q* q){
     if(q->head == NULL) {
         return NULL;
     }
     else if(q->head == q->tail) {
         struct TCB_t* temp = q->head;
         q->head = NULL;
         q->tail = NULL;
         return temp;
     }
     else {
         struct TCB_t* temp = q->head;
         q->tail->next = q->head->next;
         q->head = q->head->next;
         q->head->prev = q->tail;
         return temp;
     }
};

void RotateQ(struct Q* q){
    q->tail = q->head;
    q->head = q->head->next;
}

TCB.h:

#include <ucontext.h>
#include <string.h>

typedef struct TCB_t {
     struct TCB_t *next;
     struct TCB_t *prev;
     ucontext_t context;
     int thread_id;
} TCB_t;

int global_thread_id = 0;

void init_TCB (TCB_t *tcb, void (*function) (void), void *stackP, int stack_size)
{
    memset(tcb, '\0', sizeof(TCB_t));       // wash, rinse
    getcontext(&tcb->context);              // have to get parent context, else snow forms on hell
    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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...