void
semaphore_leave (semaphore_t *sem)
#endif
{
  thread_t *thr;
  int rc;

  rc = pthread_mutex_lock ((pthread_mutex_t*) sem->sem_handle);
  CKRET (rc);

#ifdef SEM_DEBUG
    {
      int inx;
      if (304 == ln && sem->sem_entry_count) GPF_T1 ("should have 0 count when signalling clrg_wait");
      for (inx = MAX_SEM_ENT - 1; inx > 0; inx--)
	{
	  sem->sem_last_left_line[inx] = sem->sem_last_left_line[inx - 1];
	  sem->sem_last_left_file[inx] = sem->sem_last_left_file[inx - 1];
	}
      sem->sem_last_left_line[0] = ln;
      sem->sem_last_left_file[0] = file;
    }
#endif
  if (sem->sem_entry_count)
    sem->sem_entry_count++;
  else
    {
#ifndef SEM_NO_ORDER
      thr = thread_queue_from (&sem->sem_waiting);
      if (thr)
	{
	  _thread_num_wait--;
	  assert (thr->thr_status == WAITSEM);
	  thr->thr_status = RUNNING;
	  pthread_cond_signal ((pthread_cond_t *) thr->thr_cv);
	}
      else
	sem->sem_entry_count++;
#else
      if (sem->sem_waiting.thq_count)
	{
	  _thread_num_wait--;
	  sem->sem_any_signalled = 1;
	  pthread_cond_signal ((pthread_cond_t *) sem->sem_cv);
	}
      else
	sem->sem_entry_count++;
#endif
    }

  rc = pthread_mutex_unlock ((pthread_mutex_t*) sem->sem_handle);
  CKRET (rc);
  return;

failed:
  GPF_T1 ("semaphore_leave() failed");
}
void
semaphore_free (semaphore_t *sem)
{
  thread_t *thr;

  while ((thr = thread_queue_from (&sem->sem_waiting)) != NULL)
    _fiber_status (thr, RUNNABLE);

  dk_free (sem, sizeof (semaphore_t));
}
int
thread_release_dead_threads (int leave_count)
{
  thread_t *thr;
  int rc;
  long thread_killed = 0;
  thread_queue_t term;

  Q_LOCK ();
  if (_deadq.thq_count <= leave_count)
    {
      Q_UNLOCK ();
      return 0;
    }
  thread_queue_init (&term);
  while (_deadq.thq_count > leave_count)
    {
      thr = thread_queue_from (&_deadq);
      if (!thr)
	break;
      _thread_num_dead--;
      thread_queue_to (&term, thr);
    }
  Q_UNLOCK ();

  while (NULL != (thr = thread_queue_from (&term)))
    {
      thr->thr_status = TERMINATE;
      rc = pthread_cond_signal ((pthread_cond_t *) thr->thr_cv);
      CKRET (rc);
      thread_killed++;
    }
#if 0
  if (thread_killed)
    log_info ("%ld OS threads released", thread_killed);
#endif
  return thread_killed;
failed:
  GPF_T1("Thread restart failed");
  return 0;
}
DK_INLINE void
semaphore_leave (semaphore_t *sem)
#endif
{
  thread_t *thr;

  if (sem->sem_entry_count)
    sem->sem_entry_count++;
  else
    {
      thr = thread_queue_from (&sem->sem_waiting);
      if (thr)
	{
	  assert (thr->thr_status == WAITSEM);
	  _fiber_status (thr, RUNNABLE);
	}
      else
	sem->sem_entry_count++;
    }
}
void
mutex_leave (dk_mutex_t *mtx)
#endif
{
#ifndef MTX_DEBUG
  semaphore_leave (mtx->mtx_handle);
#else
  semaphore_t *sem = (semaphore_t *) mtx->mtx_handle;
  thread_t *thr;
#ifdef MALLOC_DEBUG
  if (_current_fiber == NULL)
    {
      assert (mtx == _dbgmal_mtx);
      semaphore_leave (sem);
      return;
    }
#endif
  assert (mtx->mtx_owner == _current_fiber);
  assert (sem->sem_entry_count == 0);
  mtx->mtx_owner = NULL;

  if (sem->sem_entry_count)
    sem->sem_entry_count++;
  else
    {
      thr = thread_queue_from (&sem->sem_waiting);
      if (thr)
	{
	  assert (thr->thr_status == WAITSEM);
	  _fiber_status (thr, RUNNABLE);
	}
      else
	sem->sem_entry_count++;
    }
#endif
}