Hi,
I'm trying to implement a simple user thread library. all threads are stored in a 'ready' state queue, and when the timer runs out of time a signal causes a signal handler to switch to the next ready thread.
now i'm having a segmentation fault, and couldn't find the reason. it happens during the longjmp call (setting registers back to previous state...), and seems to be like the jmp_buf isn't set correctly.
valgrind tells me:
'conditional jump or move depends on uninitialised values...
at.... sigprocmask
at... lonjmp
at... dispatch' <-- my signal handler
this error occurs in the first call to dispatch, so i guess i'm not setting right something in the thread's initializer. the functions i use are thread_spawn(void (*f)(void)) which is the .h function, and thread_init(** thread) which is called by thread_spawn.
the struct:
Code:
typedef struct{
struct thread_status status;
int state;
jmp_buf *env;
char *stack;
} thread;
the functions:
Code:
int thread_init(thread **new_thread) {
if ((*new_thread =(thread *)malloc(sizeof(thread))) == NULL)
return FAILED;
if (((*new_thread)->env =(jmp_buf *)malloc(sizeof(jmp_buf))) == NULL) {
FREE(*new_thread);
return FAILED;
}
(*new_thread)->stack = (char*)malloc(STACKSIZE);
if (!(*new_thread)->stack) {
FREE(*new_thread);
FREE(*new_thread);
return FAILED;
}
(*new_thread)->state = READY;
((*new_thread)->status).bursts = 0;
return SUCCESS;
}
int thread_spawn(void (*f)(void)){
sigset_t set; // starting termination process,
mask_all_signals(&set); // masking all signals.
if (running_thread == -1)
process_init(); // if first call, init process and MAIN thread
if (tids.empty())
return FAILED; // if no more thread ids to allocate, fail
thread *newthread;
if(!thread_init(&newthread))
return FAILED; // if could not initialize the thread, fail
//setjmp(*(newthread->env));
((*(newthread->env))->__jmpbuf)[JB_SP] = (unsigned) newthread->stack + STACKSIZE - sizeof(int);
((*(newthread->env))->__jmpbuf)[JB_PC] = (unsigned) f;
(*(newthread->env))->__mask_was_saved = 1;
int new_id = tids.top();
tids.pop();
threads[new_id] = newthread;
ready.push_back(new_id);
set_mask(&set); // switching to previous mask
return new_id;
}
the signal_handler
Code:
void dispatch(int sig){
set_timer(QUANTUM); //resetting the timer
if (sig == CALL){ //specific call to dispatch
if (ready.empty())
error_handler(FATAL_THREAD_ERROR);
}
else { //dispatch called by signal
if (ready.empty())
return; // no ready threads, current keeps running
}
int ready_tid = ready.front();
ready.pop_front();
if(setjmp(*(threads[running_thread]->env)) == 0){ // Save the running thread
if (sig != CALL) {
threads[running_thread]->state = READY;
ready.push_back(running_thread);
}
running_thread = ready_tid;
threads[running_thread]->state = RUN;
threads[running_thread]->status.bursts++;
longjmp(*(threads[running_thread]->env), 1);
}
}
I know it's a lot of code, but i'm desperate!!!
thanks!