/* Enables queue_send on the specified queue - caller allocates the extra * data structure. Only queues which are taken to be owned by a thread should * enable this however an official owner is not compulsory but must be * specified for priority inheritance to operate. * * Use of queue_wait(_w_tmo) by multiple threads on a queue using synchronous * messages results in an undefined order of message replies or possible default * replies if two or more waits happen before a reply is done. */ void queue_enable_queue_send(struct event_queue *q, struct queue_sender_list *send, unsigned int owner_id) { int oldlevel = disable_irq_save(); corelock_lock(&q->cl); if(send != NULL && q->send == NULL) { memset(send, 0, sizeof(*send)); #ifdef HAVE_PRIORITY_SCHEDULING send->blocker.wakeup_protocol = wakeup_priority_protocol_release; send->blocker.priority = PRIORITY_IDLE; if(owner_id != 0) { send->blocker.thread = thread_id_entry(owner_id); q->blocker_p = &send->blocker; } #endif q->send = send; } corelock_unlock(&q->cl); restore_irq(oldlevel); (void)owner_id; }
void thread_exit(void) { remove_thread(THREAD_ID_CURRENT); /* This should never and must never be reached - if it is, the * state is corrupted */ THREAD_PANICF("thread_exit->K:*R", thread_id_entry(THREAD_ID_CURRENT)); while (1); }
void remove_thread(unsigned int thread_id) #endif { struct thread_entry *current = cores[CURRENT_CORE].running; struct thread_entry *thread = thread_id_entry(thread_id); SDL_Thread *t; SDL_sem *s; if (thread_id != THREAD_ID_CURRENT && thread->id != thread_id) return; int oldlevel = disable_irq_save(); t = thread->context.t; s = thread->context.s; thread->context.t = NULL; if (thread != current) { switch (thread->state) { case STATE_BLOCKED: case STATE_BLOCKED_W_TMO: /* Remove thread from object it's waiting on */ remove_from_list_l(thread->bqp, thread); #ifdef HAVE_WAKEUP_EXT_CB if (thread->wakeup_ext_cb != NULL) thread->wakeup_ext_cb(thread); #endif break; } SDL_SemPost(s); } THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n", thread - threads, THREAD_SDL_GET_NAME(thread)); new_thread_id(thread->id, thread); thread->state = STATE_KILLED; thread_queue_wake(&thread->queue); SDL_DestroySemaphore(s); if (thread == current) { /* Do a graceful exit - perform the longjmp back into the thread function to return */ restore_irq(oldlevel); longjmp(thread_jmpbufs[current - threads], 1); } SDL_KillThread(t); restore_irq(oldlevel); }
void thread_thaw(unsigned int thread_id) { struct thread_entry *thread = thread_id_entry(thread_id); if (thread->id == thread_id && thread->state == STATE_FROZEN) { thread->state = STATE_RUNNING; SDL_SemPost(thread->context.s); } }
void lcd_remote_on(void) { /* Only wake the remote thread if it's in the blocked state. */ struct thread_entry *rc_thread = thread_id_entry(remote_thread_id); if (rc_thread->state == STATE_BLOCKED || (rc_status & RC_FORCE_DETECT)) { rc_status &= ~RC_FORCE_DETECT; rc_status &= ~RC_POWER_OFF; semaphore_release(&rc_thread_wakeup); } }
void thread_wait(unsigned int thread_id) { struct thread_entry *current = cores[CURRENT_CORE].running; struct thread_entry *thread = thread_id_entry(thread_id); if (thread->id == thread_id && thread->state != STATE_KILLED) { current->bqp = &thread->queue; block_thread(current); switch_thread(); } }
static void ata_lock_lock(struct ata_lock *l) { struct thread_entry * const current = thread_id_entry(THREAD_ID_CURRENT); if (current == l->thread) { l->count++; return; } corelock_lock(&l->cl); IF_PRIO( current->skip_count = -1; ) while (l->locked != 0)
void remove_thread(unsigned int thread_id) #endif { struct thread_entry *current = cores[CURRENT_CORE].running; struct thread_entry *thread = thread_id_entry(thread_id); SDL_Thread *t; SDL_sem *s; if (thread_id != THREAD_ID_CURRENT && thread->id != thread_id) return; int oldlevel = disable_irq_save(); t = thread->context.t; s = thread->context.s; /* Wait the last thread here and keep this one or SDL will leak it since * it doesn't free its own library allocations unless a wait is performed. * Such behavior guards against the memory being invalid by the time * SDL_WaitThread is reached and also against two different threads having * the same pointer. It also makes SDL_WaitThread a non-concurrent function. * * However, see more below about SDL_KillThread. */ SDL_WaitThread(thread->context.told, NULL); thread->context.t = NULL; thread->context.s = NULL; thread->context.told = t; if (thread != current) { switch (thread->state) { case STATE_BLOCKED: case STATE_BLOCKED_W_TMO: /* Remove thread from object it's waiting on */ remove_from_list_l(thread->bqp, thread); #ifdef HAVE_WAKEUP_EXT_CB if (thread->wakeup_ext_cb != NULL) thread->wakeup_ext_cb(thread); #endif break; } SDL_SemPost(s); } THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n", thread - threads, THREAD_SDL_GET_NAME(thread)); new_thread_id(thread->id, thread); thread->state = STATE_KILLED; thread_queue_wake(&thread->queue); SDL_DestroySemaphore(s); if (thread == current) { /* Do a graceful exit - perform the longjmp back into the thread function to return */ restore_irq(oldlevel); longjmp(thread_jmpbufs[current - threads], 1); } /* SDL_KillThread frees the old pointer too because it uses SDL_WaitThread * to wait for the host to remove it. */ thread->context.told = NULL; SDL_KillThread(t); restore_irq(oldlevel); }