void condition_broadcast(struct condition* c){ struct thread* ready_thread = thread_dequeue(&c->waiting_threads); while(ready_thread){ ready_thread->state = READY; thread_enqueue(&ready_list, ready_thread); ready_thread = thread_dequeue(&c->waiting_threads); } };
void thread_manager_start() /* call this once after launching at least one thread */ /* this only returns when all threads are blocked! */ { current = thread_dequeue( &readylist ); if (current == thread_null) { /* crisis */ fprintf(stderr, "Thread manager start failure, no threads!\n"); exit(-1); } if (_setjmp( thread_death )) { /* comes here when _longjmp( thread_death, 1 ) done */ fprintf(stderr, "Thread manager terminated, %s!\n", thread_error ); if (mem_to_free != (void *)0 ) { /* see comments below */ free( mem_to_free ); } } else { /* we will come back here whenever we need to deallocate */ (void) _setjmp( go_free_it ); if (mem_to_free != (void *)0 ) { /* it's not safe to call free() anywhere but on the real stack, so once the thread manager is running, this is the only safe place to call it! */ free( mem_to_free ); mem_to_free = (void *)0; } _longjmp( current->state, 1 ); } }
void condition_signal(struct condition* c){ struct thread* ready_thread = thread_dequeue(&c->waiting_threads); if(ready_thread){ ready_thread->state = READY; thread_enqueue(&ready_list, ready_thread); } };
/** * \brief Called on the inter-disp handler thread, when another thread * on this dispatcher wants to wakeup a thread on a foreign dispatcher. */ static void handle_wakeup_on(void *arg) { struct domain_state *domain_state = get_domain_state(); errval_t err; assert(domain_state != NULL); // Dequeue all (disable to ensure mutual exclusion -- per dispatcher) for(;;) { struct thread *thread = NULL; dispatcher_handle_t disp = disp_disable(); if(domain_state->remote_wakeup_queue != NULL) { thread = thread_dequeue(&domain_state->remote_wakeup_queue); } disp_enable(disp); // Break if queue empty if(thread == NULL) { break; } // XXX: Hack /* coreid_t core_id = disp_handle_get_core_id(thread->disp); */ coreid_t core_id = thread->coreid; assert(domain_state->b[core_id] != NULL); struct interdisp_binding *b = domain_state->b[core_id]; err = b->tx_vtbl.wakeup_thread(b, NOP_CONT, (genvaddr_t)(uintptr_t)thread); if (err_is_fail(err)) { USER_PANIC_ERR(err, "wakeup_thread"); } } }
void thread_relinquish() /* call this within a thread to allow scheduling of a new thread */ { if (_setjmp( current->state ) == 0) { thread_enqueue( current, &readylist ); current = thread_dequeue( &readylist ); _longjmp( current->state, 1 ); } }
void thread_signal( struct thread_semaphore * s ) /* call this within a thread to signal a semaphore */ { struct thread * t = thread_dequeue( &s->queue ); if (t == thread_null) { s->count++; } else { thread_enqueue( t, &readylist ); } }
void mutex_unlock(struct mutex * m){ if(is_empty(&m->waiting_threads)){ m->held = 0; }else{ struct thread* temp = thread_dequeue(&m->waiting_threads); if(temp){ temp->state = READY; thread_enqueue(&ready_list, temp); } } };
static int thread_read( UThread* ut, UBuffer* port, UCell* dest, int part ) { UBuffer tbuf; ThreadExt* ext = (ThreadExt*) port->ptr.v; ThreadQueue* queue; (void) part; tbuf.type = 0; queue = (port->SIDE == SIDE_A) ? &ext->B : &ext->A; if( ! queue->readIt ) readEvent( queue ); // Waits until data is available. mutexLock( queue->mutex ); while( queue->readIt >= queue->buf.used ) { if( condWaitF( queue->cond, queue->mutex ) ) { mutexUnlock( queue->mutex ); goto waitError; } } queue->readIt = thread_dequeue( &queue->buf, queue->readIt, dest, &tbuf ); mutexUnlock( queue->mutex ); if( tbuf.type ) { UIndex bufN; dest->series.buf = UR_INVALID_BUF; ur_genBuffers( ut, 1, &bufN ); dest->series.buf = bufN; memCpy( ur_buffer( bufN ), &tbuf, sizeof(UBuffer) ); } else { int type = ur_type(dest); if( ur_isWordType(type) ) { if( ur_binding(dest) == UR_BIND_THREAD ) ur_unbind(dest); } } return UR_OK; waitError: return ur_error( ut, UR_ERR_INTERNAL, "thread_read condWait failed" ); }
// yield is very similar to thread_fork, with the main difference being that // it is pulling the next thread to run off of the ready list instead of creating it. yield should: void yield(){ // If the current thread is not DONE, set its state to READY and enqueue it on the ready list. if(current_thread->state != DONE && current_thread->state != BLOCKED){ current_thread->state = READY; thread_enqueue(&ready_list, current_thread); } // Dequeue the next thread from the ready list and set its state to RUNNING. struct thread* next_thread = thread_dequeue(&ready_list); next_thread->state = RUNNING; // Save a pointer to the current thread in a temporary variable, then set the current thread to the next thread. struct thread* temp = current_thread; current_thread = next_thread; // Call thread_switch with the old current thread as old and the new current thread as new. thread_switch(temp, current_thread); };
void thread_exit() /* call this within a thread to terminate that thread */ { /* we can't deallocate, so we schedule this thread for deallocation */ mem_to_free = (void *)current; /* now, get the next thread to run */ current = thread_dequeue( &readylist ); if (current == thread_null) { /* crisis */ thread_error = "ready list empty"; _longjmp( thread_death, 1 ); } _longjmp( go_free_it, 1 ); }
void thread_wait( struct thread_semaphore * s ) /* call this within a thread to block on a semaphore */ { if (s->count > 0) { s->count--; } else { if (_setjmp( current->state ) == 0) { thread_enqueue( current, &s->queue ); current = thread_dequeue( &readylist ); if (current == thread_null) { /* crisis */ thread_error = "possible deadlock"; _longjmp( thread_death, 1 ); } _longjmp( current->state, 1 ); } } }
void yield() { /* If the current thread is not DONE, set its state to READY and enqueue it on the ready list. */ if (current_thread->state != DONE) { current_thread->state = READY; thread_enqueue(&ready_list, current_thread); //printf("YIELD: current thread not finished, back on queue\n"); } // Dequeue the next thread from the ready list and set its state to RUNNING. thread *next_thread = thread_dequeue(&ready_list); /* Save a pointer to the current thread in a temporary variable, then set the current thread to the next thread. */ thread *temp = current_thread; current_thread = next_thread; /* Call thread_switch with the old current thread as old and the new current thread as new. */ thread_switch(temp, current_thread); //printf("YIELD: Running dequeued thread\n"); }