Beispiel #1
0
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 */
}
Beispiel #2
0
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;
}
Beispiel #3
0
int st_mutex_unlock(_st_mutex_t *lock)
{
  _st_thread_t *thread;
  _st_clist_t *q;

  if (lock->owner != _ST_CURRENT_THREAD()) {
    errno = EPERM;
    return -1;
  }

  for (q = lock->wait_q.next; q != &lock->wait_q; q = q->next) {
    thread = _ST_THREAD_WAITQ_PTR(q);
    if (thread->state == _ST_ST_LOCK_WAIT) {
      lock->owner = thread;
      /* Make thread runnable */
      thread->state = _ST_ST_RUNNABLE;
      _ST_ADD_RUNQ(thread);
      return 0;
    }
  }

  /* No threads waiting on this mutex */
  lock->owner = NULL;

  return 0;
}
Beispiel #4
0
void *st_thread_getspecific(int key)
{
  if (key < 0 || key >= key_max)
    return NULL;

  return ((_ST_CURRENT_THREAD())->private_data[key]);
}
Beispiel #5
0
void _st_thread_main(void)
{
	st_thread_t *thread = _ST_CURRENT_THREAD();

	/* Run thread main */
	thread->retval = (*thread->start)(thread->arg);

	/* All done, time to go away */
	st_thread_exit(thread->retval);
}
Beispiel #6
0
int st_mutex_trylock(_st_mutex_t *lock)
{
  if (lock->owner != NULL) {
    errno = EBUSY;
    return -1;
  }

  /* Got the mutex */
  lock->owner = _ST_CURRENT_THREAD();

  return 0;
}
Beispiel #7
0
void _st_iterate_threads(void)
{
  static _st_thread_t *thread = NULL;
  static jmp_buf orig_jb, save_jb;
  _st_clist_t *q;

  if (!_st_iterate_threads_flag) {
    if (thread) {
      memcpy(thread->context, save_jb, sizeof(jmp_buf));
      MD_LONGJMP(orig_jb, 1);
    }
    return;
  }

  if (thread) {
    memcpy(thread->context, save_jb, sizeof(jmp_buf));
    _st_show_thread_stack(thread, NULL);
  } else {
    if (MD_SETJMP(orig_jb)) {
      _st_iterate_threads_flag = 0;
      thread = NULL;
      _st_show_thread_stack(thread, "Iteration completed");
      return;
    }
    thread = _ST_CURRENT_THREAD();
    _st_show_thread_stack(thread, "Iteration started");
  }

  q = thread->tlink.next;
  if (q == &_ST_THREADQ)
    q = q->next;
  ST_ASSERT(q != &_ST_THREADQ);
  thread = _ST_THREAD_THREADQ_PTR(q);
  if (thread == _ST_CURRENT_THREAD())
    MD_LONGJMP(orig_jb, 1);
  memcpy(save_jb, thread->context, sizeof(jmp_buf));
  MD_LONGJMP(thread->context, 1);
}
Beispiel #8
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;
}
Beispiel #9
0
void _st_thread_main(void)
{
  _st_thread_t *thread = _ST_CURRENT_THREAD();

  /*
   * Cap the stack by zeroing out the saved return address register
   * value. This allows some debugging/profiling tools to know when
   * to stop unwinding the stack. It's a no-op on most platforms.
   */
  MD_CAP_STACK(&thread);

  /* Run thread main */
  thread->retval = (*thread->start)(thread->arg);

  /* All done, time to go away */
  st_thread_exit(thread->retval);
}
Beispiel #10
0
int st_thread_setspecific(int key, void *value)
{
  _st_thread_t *me = _ST_CURRENT_THREAD();

  if (key < 0 || key >= key_max) {
    errno = EINVAL;
    return -1;
  }

  if (value != me->private_data[key]) {
    /* free up previously set non-NULL data value */
    if (me->private_data[key] && _st_destructors[key]) {
      (*_st_destructors[key])(me->private_data[key]);
    }
    me->private_data[key] = value;
  }

  return 0;
}
Beispiel #11
0
/* 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;
}
Beispiel #12
0
/* 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;
}
Beispiel #13
0
int st_thread_join(_st_thread_t *thread, void **retvalp)
{
  _st_cond_t *term = thread->term;

  /* Can't join a non-joinable thread */
  if (term == NULL) {
    errno = EINVAL;
    return -1;
  }
  if (_ST_CURRENT_THREAD() == thread) {
    errno = EDEADLK;
    return -1;
  }

  /* Multiple threads can't wait on the same joinable thread */
  if (term->wait_q.next != &term->wait_q) {
    errno = EINVAL;
    return -1;
  }

  while (thread->state != _ST_ST_ZOMBIE) {
    if (st_cond_timedwait(term, ST_UTIME_NO_TIMEOUT) != 0)
      return -1;
  }

  if (retvalp)
    *retvalp = thread->retval;

  /*
   * Remove target thread from the zombie queue and make it runnable.
   * When it gets scheduled later, it will do the clean up.
   */
  thread->state = _ST_ST_RUNNABLE;
  _ST_DEL_ZOMBIEQ(thread);
  _ST_ADD_RUNQ(thread);

  return 0;
}
Beispiel #14
0
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;
}
Beispiel #15
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;
}
Beispiel #16
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;
}
Beispiel #17
0
_st_thread_t *st_thread_self(void)
{
  return _ST_CURRENT_THREAD();
}