/* * Free the stack for the current thread */ void _st_stack_free(_st_stack_t *ts) { if (!ts) return; /* Put the stack on the free list *///走这里 ST_APPEND_LINK(&ts->links, _st_free_stacks.prev); _st_num_free_stacks++; }
void _st_add_sleep_q(st_thread_t *thread, st_utime_t timeout) { st_utime_t sleep; st_clist_t *q; st_thread_t *t; /* sort onto global sleep queue */ sleep = timeout; /* Check if we are longest timeout */ if (timeout >= _ST_SLEEPQMAX) { ST_APPEND_LINK(&thread->links, &_ST_SLEEPQ); thread->sleep = timeout - _ST_SLEEPQMAX; _ST_SLEEPQMAX = timeout; } else { /* Sort thread into global sleep queue at appropriate point */ q = _ST_SLEEPQ.next; /* Now scan the list for where to insert this entry */ while (q != &_ST_SLEEPQ) { t = _ST_THREAD_PTR(q); if (sleep < t->sleep) { /* Found sleeper to insert in front of */ break; } sleep -= t->sleep; q = q->next; } thread->sleep = sleep; ST_INSERT_BEFORE(&thread->links, q); /* Subtract our sleep time from the sleeper that follows us */ ST_ASSERT(thread->links.next != &_ST_SLEEPQ); t = _ST_THREAD_PTR(thread->links.next); ST_ASSERT(_ST_THREAD_PTR(t->links.prev) == thread); t->sleep -= sleep; } thread->flags |= _ST_FL_ON_SLEEPQ; }
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; }