rem: TRACE("timer index %d\n", index);
context: timer_thread(void *cookie){	status_t status = 0;	TRACE("timer_thread enter\n");	do {		bigtime_t timeout;		bigtime_t now;		cpu_status cpu;		timer_function func;		void * cookie;		int i;		int index;		cpu = disable_interrupts();		acquire_spinlock(&sTimerSpinlock);		now = system_time();		cookie = 0;		func = 0;						// find timer with smallest event time		index = -1;		timeout = B_INFINITE_TIMEOUT;		for (i = 0; i < sTimerCount; i++) {			if (sTimerData[i].next_event < timeout) {				timeout = sTimerData[i].next_event;				index = i;			}		}				TRACE("timer index %d\n", index);		if (timeout < now) {			// timer is ready for execution, load func and cookie			ASSERT(index >= 0 && index < sTimerCount);			func = sTimerData[index].func;			cookie = sTimerData[index].cookie;			if (sTimerData[index].periodic) {				// periodic timer is ready, update the entry				sTimerData[index].next_event += sTimerData[index].interval;			} else {				// single shot timer is ready, delete the entry				if (index != (sTimerCount - 1) && sTimerCount != 1) {					memcpy(&sTimerData[index], &sTimerData[sTimerCount - 1], sizeof(struct timer_info));				}				sTimerCount--;			}		}		release_spinlock(&sTimerSpinlock);		restore_interrupts(cpu);				// execute timer hook		if (timeout < now) {			ASSERT(func);			func(cookie);			continue;		}		status = acquire_sem_etc(sTimerSem, 1, B_ABSOLUTE_TIMEOUT, timeout);	} while (status == B_OK || status == B_TIMED_OUT);	TRACE("timer_thread leave\n");		return 0;}