Моя программа запускает потоки и запускает их. Предполагается, что 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
}