void st_thread_exit(void *retval) { _st_thread_t *thread = _ST_CURRENT_THREAD(); thread->retval = retval; _st_thread_cleanup(thread); _st_active_count--; if (thread->term) { /* Put thread on the zombie queue */ thread->state = _ST_ST_ZOMBIE; _ST_ADD_ZOMBIEQ(thread); /* Notify on our termination condition variable */ st_cond_signal(thread->term); /* Switch context and come back later */ _ST_SWITCH_CONTEXT(thread); /* Continue the cleanup */ st_cond_destroy(thread->term); thread->term = NULL; } #ifdef DEBUG _ST_DEL_THREADQ(thread); #endif if (!(thread->flags & _ST_FL_PRIMORDIAL)) _st_stack_free(thread->stack); /* Find another thread to run */ _ST_SWITCH_CONTEXT(thread); /* Not going to land here */ }
int st_usleep(st_utime_t usecs) { _st_thread_t *me = _ST_CURRENT_THREAD(); if (me->flags & _ST_FL_INTERRUPT) { me->flags &= ~_ST_FL_INTERRUPT; errno = EINTR; return -1; } if (usecs != ST_UTIME_NO_TIMEOUT) { me->state = _ST_ST_SLEEPING; _ST_ADD_SLEEPQ(me, usecs); } else me->state = _ST_ST_SUSPENDED; _ST_SWITCH_CONTEXT(me); if (me->flags & _ST_FL_INTERRUPT) { me->flags &= ~_ST_FL_INTERRUPT; errno = EINTR; return -1; } return 0; }
int st_poll(struct pollfd *pds, int npds, st_utime_t timeout) { struct pollfd *pd; struct pollfd *epd = pds + npds; _st_pollq_t pq; _st_thread_t *me = _ST_CURRENT_THREAD(); int n; if (me->flags & _ST_FL_INTERRUPT) { me->flags &= ~_ST_FL_INTERRUPT; errno = EINTR; return -1; } if ((*_st_eventsys->pollset_add)(pds, npds) < 0) return -1; pq.pds = pds; pq.npds = npds; pq.thread = me; pq.on_ioq = 1; _ST_ADD_IOQ(pq); if (timeout != ST_UTIME_NO_TIMEOUT) _ST_ADD_SLEEPQ(me, timeout); me->state = _ST_ST_IO_WAIT; _ST_SWITCH_CONTEXT(me); n = 0; if (pq.on_ioq) { /* If we timed out, the pollq might still be on the ioq. Remove it */ _ST_DEL_IOQ(pq); (*_st_eventsys->pollset_del)(pds, npds); } else { /* Count the number of ready descriptors */ for (pd = pds; pd < epd; pd++) { if (pd->revents) n++; } } if (me->flags & _ST_FL_INTERRUPT) { me->flags &= ~_ST_FL_INTERRUPT; errno = EINTR; return -1; } return n; }
/* ARGSUSED */ void *_st_idle_thread_start(void *arg) { _st_thread_t *me = _ST_CURRENT_THREAD(); while (_st_active_count > 0) { /* Idle vp till I/O is ready or the smallest timeout expired */ (*_st_eventsys->dispatch)(); /* Check sleep queue for expired threads */ _st_vp_check_clock(); me->state = _ST_ST_RUNNABLE; _ST_SWITCH_CONTEXT(me); } /* No more threads */ exit(0); /* NOTREACHED */ return NULL; }
/* ARGSUSED */ void *_st_idle_thread_start(void *arg) { _st_thread_t *me = _ST_CURRENT_THREAD(); while (_st_active_count > 0) { /* Idle vp till I/O is ready or the smallest timeout expired */ _ST_VP_IDLE(); /* Check sleep queue for expired threads */ _st_vp_check_clock(); me->state = _ST_ST_RUNNABLE; _ST_SWITCH_CONTEXT(me); } _ST_RESTORE_CONTEXT(_st_this_vp.primorial_thread); /* No more threads */ free(_st_this_vp.primorial_thread); /* Free resources in use by event system */ (*_st_eventsys->free)(); return NULL; }
int _st_wait(st_utime_t timeout) { st_thread_t *me = _ST_CURRENT_THREAD(); if (me->flags & _ST_FL_INTERRUPT) { me->flags &= ~_ST_FL_INTERRUPT; errno = EINTR; return 1; } /* if (timeout != ST_UTIME_NO_TIMEOUT) _ST_ADD_SLEEPQ(me, timeout);*/ me->state = _ST_ST_IO_WAIT; _ST_SWITCH_CONTEXT(me); if (me->flags & _ST_FL_INTERRUPT) { me->flags &= ~_ST_FL_INTERRUPT; errno = EINTR; return 1; } return 0; }
int st_mutex_lock(_st_mutex_t *lock) { _st_thread_t *me = _ST_CURRENT_THREAD(); if (me->flags & _ST_FL_INTERRUPT) { me->flags &= ~_ST_FL_INTERRUPT; errno = EINTR; return -1; } if (lock->owner == NULL) { /* Got the mutex */ lock->owner = me; return 0; } if (lock->owner == me) { errno = EDEADLK; return -1; } /* Put caller thread on the mutex's wait queue */ me->state = _ST_ST_LOCK_WAIT; ST_APPEND_LINK(&me->wait_links, &lock->wait_q); _ST_SWITCH_CONTEXT(me); ST_REMOVE_LINK(&me->wait_links); if ((me->flags & _ST_FL_INTERRUPT) && lock->owner != me) { me->flags &= ~_ST_FL_INTERRUPT; errno = EINTR; return -1; } return 0; }
int st_cond_timedwait(_st_cond_t *cvar, st_utime_t timeout) { _st_thread_t *me = _ST_CURRENT_THREAD(); int rv; if (me->flags & _ST_FL_INTERRUPT) { me->flags &= ~_ST_FL_INTERRUPT; errno = EINTR; return -1; } /* Put caller thread on the condition variable's wait queue */ me->state = _ST_ST_COND_WAIT; ST_APPEND_LINK(&me->wait_links, &cvar->wait_q); if (timeout != ST_UTIME_NO_TIMEOUT) _ST_ADD_SLEEPQ(me, timeout); _ST_SWITCH_CONTEXT(me); ST_REMOVE_LINK(&me->wait_links); rv = 0; if (me->flags & _ST_FL_TIMEDOUT) { me->flags &= ~_ST_FL_TIMEDOUT; errno = ETIME; rv = -1; } if (me->flags & _ST_FL_INTERRUPT) { me->flags &= ~_ST_FL_INTERRUPT; errno = EINTR; rv = -1; } return rv; }