setTimeoutの最小時間を調べたときのメモ(断片)

デスクトップの整理でファイルを廃棄するのでこっちにいれとく。

  while (!mShutdown) {
     if (mTimers.Count() > 0) {
        timer = static_cast<nsTimerImpl*>(mTimers[0]);
        if (!TIMER_LESS_THAN(now, timer->mTimeout + mTimeoutAdjustment)) {
	next:
	        timer->PostTimerEvent();
        }

     }

      if (mTimers.Count() > 0) {
        // Don't wait at all (even for PR_INTERVAL_NO_WAIT) if the next timer
        // is due now or overdue.
        if (!TIMER_LESS_THAN(now, timeout))
          goto next;
      }

     mWaiting = PR_TRUE;
     PR_WaitCondVar(mCondVar, waitFor);
     mWaiting = PR_FALSE;
  }

PR_WaitCondVarは環境依存。pthreadの場合

    if (timeout == PR_INTERVAL_NO_TIMEOUT)
        rv = pthread_cond_wait(&cvar->cv, &cvar->lock->mutex);
    else
        rv = pt_TimedWait(&cvar->cv, &cvar->lock->mutex, timeout);

こんなかんじ。1msタイムアウト前提として考えてpt_TimedWaitの中身。数字の操作をして

 rv = pthread_cond_timedwait(cv, ml, &tmo);

を呼んでる。
ここでスレッドはsleepする。pthreadの実装を見ないとわかんない。

http://www.google.com/codesearch?hl=en&q=show:Knhr7NleXX8:yfeqd0kspXs:OFZK7oz2-9U&sa=N&ct=rd&cs_p=http://ftp.gnu.org/gnu/glibc/glibc-linuxthreads-2.2.5.tar.gz&cs_f=linuxthreads/condvar.c&start=1

http://ftp.gnu.org/gnu/glibc/glibc-linuxthreads-2.2.5.tar.gz/linuxthreads/

static int
pthread_cond_timedwait_relative(pthread_cond_t *cond,
                pthread_mutex_t *mutex,
                const struct timespec * abstime)
{
  enqueue(&cond->__c_waiting, self);

condvarのlockが解けた後で指定時間までループ?

  while (1)
    {
      if (!timedsuspend(self, abstime)) {
    int was_on_queue;

    /* __pthread_lock will queue back any spurious restarts that
       may happen to it. */

    __pthread_lock(&cond->__c_lock, self);
    was_on_queue = remove_from_queue(&cond->__c_waiting, self);
    __pthread_unlock(&cond->__c_lock);

    if (was_on_queue) {
      __pthread_set_own_extricate_if(self, 0);
      pthread_mutex_lock(mutex);
      return ETIMEDOUT;
    }

    /* Eat the outstanding restart() from the signaller */
    suspend(self);
      }

      if (THREAD_GETMEM(self, p_condvar_avail) == 0
      && (THREAD_GETMEM(self, p_woken_by_cancel) == 0
          || THREAD_GETMEM(self, p_cancelstate) != PTHREAD_CANCEL_ENABLE))
    {
      /* Count resumes that don't belong to us. */
      spurious_wakeup_count++;
      continue;
    }
      break;
    }

~/linuxthreads/pthread.c

int
__pthread_timedsuspend_new(pthread_descr self, const struct timespec *abstime)
{
  sigset_t unblock, initial_mask;
  int was_signalled = 0;
  sigjmp_buf jmpbuf;

  if (sigsetjmp(jmpbuf, 1) == 0) {
    THREAD_SETMEM(self, p_signal_jmp, &jmpbuf);
    THREAD_SETMEM(self, p_signal, 0);
    /* Unblock the restart signal */
    sigemptyset(&unblock);
    sigaddset(&unblock, __pthread_sig_restart);
    sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);

    while (1) {
      struct timeval now;
      struct timespec reltime;

      /* Compute a time offset relative to now.  */
      __gettimeofday (&now, NULL);
      reltime.tv_nsec = abstime->tv_nsec - now.tv_usec * 1000;
      reltime.tv_sec = abstime->tv_sec - now.tv_sec;
      if (reltime.tv_nsec < 0) {
    reltime.tv_nsec += 1000000000;
    reltime.tv_sec -= 1;
      }

      /* Sleep for the required duration. If woken by a signal,
     resume waiting as required by Single Unix Specification.  */
      if (reltime.tv_sec < 0 || __libc_nanosleep(&reltime, NULL) == 0)
    break;
    }

結局こうなる。__libc_nanosleepまではちょっと追いかける気にならない...