rem: dprintf("acquire_sem_etc: bad sem_id %d\n", id);
add: dprintf("acquire_sem_etc: bad sem_id %ld\n", id);
context: int acquire_sem_etc(sem_id id, int count, int flags, bigtime_t timeout){	int slot = id % MAX_SEMS;	int state;	int err = 0;	if (sems_active == false)		return B_NO_MORE_SEMS;	if (id < 0) {		dprintf("acquire_sem_etc: invalid sem handle %d\n", id);		return B_BAD_SEM_ID;	}	if (count <= 0)		return EINVAL;	state = disable_interrupts();	GRAB_SEM_LOCK(sems[slot]);		if (sems[slot].id != id) {		dprintf("acquire_sem_etc: bad sem_id %d\n", id);		err = B_BAD_SEM_ID;		goto err;	}	if (sems[slot].count - count < 0 && (flags & B_TIMEOUT) != 0 && timeout <= 0) {		// immediate timeout		err = B_TIMED_OUT;		goto err;	}	if ((sems[slot].count -= count) < 0) {		// we need to block		struct thread *t = thread_get_current_thread();		timer timeout_timer; // stick it on the stack, since we may be blocking here		struct sem_timeout_args args;		// do a quick check to see if the thread has any pending kill signals		// this should catch most of the cases where the thread had a signal		if ((flags & B_CAN_INTERRUPT) && (t->pending_signals & SIG_KILL)) {			sems[slot].count += count;			err = EINTR;			goto err;		}		t->next_state = B_THREAD_WAITING;		t->sem_flags = flags;		t->sem_blocking = id;		t->sem_acquire_count = count;		t->sem_count = min(-sems[slot].count, count); // store the count we need to restore upon release		t->sem_deleted_retcode = 0;		t->sem_errcode = B_NO_ERROR;		thread_enqueue(t, &sems[slot].q);		if ((flags & (B_TIMEOUT | B_ABSOLUTE_TIMEOUT)) != 0) {//			dprintf("sem_acquire_etc: setting timeout sem for %d %d usecs, semid %d, tid %d\n",//				timeout, sem_id, t->id);			// set up an event to go off with the thread struct as the data			args.blocked_sem_id = id;			args.blocked_thread = t->id;			args.sem_count = count;						// another evil hack: pass the args into timer->entry.prev			timeout_timer.entry.prev = (qent *)&args;			add_timer(&timeout_timer, &sem_timeout, timeout,				flags & B_RELATIVE_TIMEOUT ?					B_ONE_SHOT_RELATIVE_TIMER : B_ONE_SHOT_ABSOLUTE_TIMER);					}		RELEASE_SEM_LOCK(sems[slot]);		GRAB_THREAD_LOCK();		// check again to see if a kill signal is pending.		// it may have been delivered while setting up the sem, though it's pretty unlikely		if ((flags & B_CAN_INTERRUPT) && (t->pending_signals & SIG_KILL)) {			struct thread_queue wakeup_queue;			// ok, so a tiny race happened where a signal was delivered to this thread while			// it was setting up the sem. We can only be sure a signal wasn't delivered			// here, since the threadlock is held. The previous check would have found most			// instances, but there was a race, so we have to handle it. It'll be more messy...			wakeup_queue.head = wakeup_queue.tail = NULL;			GRAB_SEM_LOCK(sems[slot]);			if (sems[slot].id == id) {				remove_thread_from_sem(t, &sems[slot], &wakeup_queue, EINTR);			}			RELEASE_SEM_LOCK(sems[slot]);			while ((t = thread_dequeue(&wakeup_queue)) != NULL) {				thread_enqueue_run_q(t);			}			// fall through and reschedule since another thread with a higher priority may have been woken up		}		resched();		RELEASE_THREAD_LOCK();		if ((flags & (B_TIMEOUT | B_ABSOLUTE_TIMEOUT)) != 0) {			if (t->sem_errcode != B_TIMED_OUT) {				// cancel the timer event, the sem may have been deleted or interrupted				// with the timer still active				cancel_timer(&timeout_timer);			}		}		restore_interrupts(state);		return t->sem_errcode;	}err:	RELEASE_SEM_LOCK(sems[slot]);	restore_interrupts(state);	return err;}