Прежде всего, позвольте мне извиниться за длину кода «sample», я пытался предоставить наименьший пример исполняемого файла, который я мог бы сделать.Очередь теряет указатели после вызова swapcontext()
Я должен упомянуть, очередь имеет вид:
При запуске называется, первый элемент успешно удален из очереди, который затем ссылается глобальный указатель Curr_Thread
. Я проверяю форму очереди до и после, все, где она должна быть.
Работы и управление Swapcontext передается func_1()
, но в этом проблема. Как только он входит в func_1()
, очередь становится каким-то образом искалеченной, то есть указатель на голову по-прежнему указывает на элемент «фиктивный», как и до переключателя (со следующим и предыдущим указателями, указывающими, где они должны), но все после манекена элемент теперь указывает на некоторый элемент мусора со случайными следующими и предыдущими адресами указателей. Когда func_1
звонит yield()
, вызов AddTcb()
во время сбоев, потому что он никогда не сможет найти конец очереди, чтобы добавить Curr_Thread
.
Перед входа в func_1()
из swapcontext
:
Сразу после вступления в func_1()
из swapcontext
Почему структура моей очереди вдруг изменилась после вызова 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;
}
Обратитесь к этому ответу: http://stackoverflow.com/questions/25841144/seg-fault-when-returning-to-function-execution-after-successful-swapcontext – Murali
Спасибо. Я уже пробовал это решение, но у меня была другая проблема, которая маскировала результаты. Прекрасно работает. – corporateWhore
Добавьте это как ответ, и я соглашусь с ним. – corporateWhore