rem: int err = 0;
add: status_t err = 0;
context: int release_sem_etc(sem_id id, int count, int flags){	int slot = id % MAX_SEMS;	int state;	int released_threads = 0;	int err = 0;	struct thread_queue release_queue;	if (sems_active == false)		return B_NO_MORE_SEMS;	if (id < 0)		return B_BAD_SEM_ID;	if (count <= 0)		return EINVAL;	state = disable_interrupts();	GRAB_SEM_LOCK(sems[slot]);	if (sems[slot].id != id) {		dprintf("sem_release_etc: invalid sem_id %d\n", id);		err = B_BAD_SEM_ID;		goto err;	}	// clear out a queue we will use to hold all of the threads that we will have to	// put back into the run list. This is done so the thread lock wont be held	// while this sems lock is held since the two locks are grabbed in the other	// order in sem_interrupt_thread.	release_queue.head = release_queue.tail = NULL;	while (count > 0) {		int delta = count;		if (sems[slot].count < 0) {			struct thread *t = thread_lookat_queue(&sems[slot].q);			delta = min(count, t->sem_count);			t->sem_count -= delta;			if (t->sem_count <= 0) {				// release this thread				t = thread_dequeue(&sems[slot].q);				thread_enqueue(t, &release_queue);				t->state = B_THREAD_READY;				released_threads++;				t->sem_count = 0;				t->sem_deleted_retcode = 0;			}		}		sems[slot].count += delta;		count -= delta;	}	RELEASE_SEM_LOCK(sems[slot]);	// pull off any items in the release queue and put them in the run queue	if (released_threads > 0) {		struct thread *t;		int priority;		GRAB_THREAD_LOCK();		while ((t = thread_dequeue(&release_queue)) != NULL) {			// temporarily place thread in a run queue with high priority to boost it up			priority = t->priority;			t->priority = t->priority >= B_FIRST_REAL_TIME_PRIORITY ? t->priority : B_FIRST_REAL_TIME_PRIORITY;			thread_enqueue_run_q(t);			t->priority = priority;		}		if ((flags & B_DO_NOT_RESCHEDULE) == 0) {			resched();		}		RELEASE_THREAD_LOCK();	}	goto outnolock;err:	RELEASE_SEM_LOCK(sems[slot]);outnolock:	restore_interrupts(state);	return err;}