Example #1
0
static void wake_next(async_rwlock_t *const lock) {
	if(lock->upgrade) {
		if(lock->state > 0) return;
		lock->state = s_write;
		async_t *const next = lock->upgrade;
		lock->upgrade = NULL;
		async_wakeup(next);
	} else if(lock->wrhead) {
		if(lock->state > 0) return;
		lock->state = s_write;
		async_thread_list *const next = lock->wrhead;
		lock->wrhead = next->next;
		if(!lock->wrhead) lock->wrtail = NULL;
		async_wakeup(next->thread);
	} else while(lock->rdhead) {
		if(lock->state >= READERS_MAX) return;
		++lock->state;
		async_thread_list *const next = lock->rdhead;
		lock->rdhead = next->next;
		if(!lock->rdhead) lock->rdtail = NULL;
		async_wakeup(next->thread);
	}
}
void async_mutex_unlock(async_mutex_t *const mutex) {
	assert(mutex && "Mutex must not be null");
	cothread_t const thread = co_active();
	assert(mutex->active.thread && "Leaving empty mutex");
	assert(thread == mutex->active.thread && "Leaving someone else's mutex");
	assert(mutex->depth > 0 && "Mutex recursion depth going negative");
	if(--mutex->depth) return;
	if(!mutex->active.next) return;
	list_entry *const next = mutex->active.next;
	if(!next->next) mutex->tail = &mutex->active;
	mutex->active.thread = next->thread;
	mutex->active.next = next->next;
	mutex->depth = 1;
	async_wakeup(next->thread);
	// Set everything up ahead of time so we aren't dependent on whether the wakeup is synchronous or not.
}
Example #3
0
void async_cancel(async_t *const thread) {
	if(!thread) return;
	thread->flags |= ASYNC_CANCELED;
	if(ASYNC_CANCELABLE & thread->flags) async_wakeup(thread);
}