(linenum→info "unix/slp.c:2238")

glibc/2.7/nptl/DESIGN-condvar.txt

    1: Conditional Variable pseudocode.
    2: ================================
    3: 
    4:        int pthread_cond_timedwait (pthread_cond_t *cv, pthread_mutex_t *mutex);
    5:        int pthread_cond_signal    (pthread_cond_t *cv);
    6:        int pthread_cond_broadcast (pthread_cond_t *cv);
    7: 
    8: struct pthread_cond_t {
    9: 
   10:    unsigned int cond_lock;
   11: 
   12:          internal mutex
   13: 
   14:    uint64_t total_seq;
   15: 
   16:      Total number of threads using the conditional variable.
   17: 
   18:    uint64_t wakeup_seq;
   19: 
   20:      sequence number for next wakeup.
   21: 
   22:    uint64_t woken_seq;
   23: 
   24:      sequence number of last woken thread.
   25: 
   26:    uint32_t broadcast_seq;
   27: 
   28: }
   29: 
   30: 
   31: struct cv_data {
   32: 
   33:    pthread_cond_t *cv;
   34: 
   35:    uint32_t bc_seq
   36: 
   37: }
   38: 
   39: 
   40: 
   41: cleanup_handler(cv_data)
   42: {
   43:   cv = cv_data->cv;
   44:   lll_lock(cv->lock);
   45: 
   46:   if (cv_data->bc_seq == cv->broadcast_seq) {
   47:     ++cv->wakeup_seq;
   48:     ++cv->woken_seq;
   49:   }
   50: 
   51:   /* make sure no signal gets lost.  */
   52:   FUTEX_WAKE(cv->wakeup_seq, ALL);
   53: 
   54:   lll_unlock(cv->lock);
   55: }
   56: 
   57: 
   58: cond_timedwait(cv, mutex, timeout):
   59: {
   60:    lll_lock(cv->lock);
   61:    mutex_unlock(mutex);
   62: 
   63:    cleanup_push
   64: 
   65:    ++cv->total_seq;
   66:    val = seq =  cv->wakeup_seq;
   67:    cv_data.bc = cv->broadcast_seq;
   68:    cv_data.cv = cv;
   69: 
   70:    while (1) {
   71: 
   72:      lll_unlock(cv->lock);
   73: 
   74:      enable_async(&cv_data);
   75: 
   76:      ret = FUTEX_WAIT(cv->wakeup_seq, val, timeout);
   77: 
   78:      restore_async
   79: 
   80:      lll_lock(cv->lock);
   81: 
   82:      if (bc != cv->broadcast_seq)
   83:        goto bc_out;
   84: 
   85:      val = cv->wakeup_seq;
   86: 
   87:      if (val != seq && cv->woken_seq != val) {
   88:        ret = 0;
   89:        break;
   90:      }
   91: 
   92:      if (ret == TIMEDOUT) {
   93:        ++cv->wakeup_seq;
   94:        break;
   95:      }
   96:    }
   97: 
   98:    ++cv->woken_seq;
   99: 
  100:  bc_out:
  101:    lll_unlock(cv->lock);
  102: 
  103:    cleanup_pop
  104: 
  105:    mutex_lock(mutex);
  106: 
  107:    return ret;
  108: }
  109: 
  110: cond_signal(cv)
  111: {
  112:    lll_lock(cv->lock);
  113: 
  114:    if (cv->total_seq > cv->wakeup_seq) {
  115:      ++cv->wakeup_seq;
  116:      FUTEX_WAKE(cv->wakeup_seq, 1);
  117:    }
  118: 
  119:    lll_unlock(cv->lock);
  120: }
  121: 
  122: cond_broadcast(cv)
  123: {
  124:    lll_lock(cv->lock);
  125: 
  126:    if (cv->total_seq > cv->wakeup_seq) {
  127:      cv->wakeup_seq = cv->total_seq;
  128:      cv->woken_seq = cv->total_seq;
  129:      ++cv->broadcast_seq;
  130:      FUTEX_WAKE(cv->wakeup_seq, ALL);
  131:    }
  132: 
  133:    lll_unlock(cv->lock);
  134: }
Syntax (Markdown)