自动档车有没有离合器:【转】关于pthread_cond_wait源码

来源:百度文库 编辑:九乡新闻网 时间:2024/04/27 16:32:15
pthread_cond_wait前面的Mutex是释放了的,只是没有显示的释放,而是在pthread_cond_wait()里面隐式的释放。下面是2.9版本的 pthread_cond_wait()源码,看一下就很清楚了:
int
__pthread_cond_wait (cond, mutex)
pthread_cond_t *cond;
pthread_mutex_t *mutex;
{
struct _pthread_cleanup_buffer buffer;
struct _condvar_cleanup_buffer cbuffer;
int err;
int pshared = (cond->__data.__mutex == (void *) ~0l)
LLL_SHARED : LLL_PRIVATE;

/* Make sure we are along.  */
lll_lock (cond->__data.__lock, pshared);

  /* Now we can release the mutex.  */
err = __pthread_mutex_unlock_usercnt (mutex, 0);

if (__builtin_expect (err, 0))
{
lll_unlock (cond->__data.__lock, pshared);
return err;
}

/* We have one new user of the condvar.  */
++cond->__data.__total_seq;
++cond->__data.__futex;
cond->__data.__nwaiters += 1 < < COND_NWAITERS_SHIFT;

/* Remember the mutex we are using here.  If there is already a
different address store this is a bad user bug.  Do not store
anything for pshared condvars.  */
if (cond->__data.__mutex != (void *) ~0l)
cond->__data.__mutex = mutex;

/* Prepare structure passed to cancellation handler.  */
cbuffer.cond = cond;
cbuffer.mutex = mutex;

/* Before we block we enable cancellation.  Therefore we have to
install a cancellation handler.  */
__pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer);

/* The current values of the wakeup counter.  The "woken" counter
must exceed this value.  */
unsigned long long int val;
unsigned long long int seq;
val = seq = cond->__data.__wakeup_seq;
/* Remember the broadcast counter.  */
cbuffer.bc_seq = cond->__data.__broadcast_seq;

do
{
unsigned int futex_val = cond->__data.__futex;

/* Prepare to wait.  Release the condvar futex.  */
lll_unlock (cond->__data.__lock, pshared);

/* Enable asynchronous cancellation.  Required by the standard.  */
cbuffer.oldtype = __pthread_enable_asynccancel ();

/* Wait until woken by signal or broadcast.  */
lll_futex_wait (&cond->__data.__futex, futex_val, pshared);

/* Disable asynchronous cancellation.  */
__pthread_disable_asynccancel (cbuffer.oldtype);

/* We are going to look at shared data again, so get the lock.  */
lll_lock (cond->__data.__lock, pshared);

/* If a broadcast happened, we are done.  */
if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
goto bc_out;

/* Check whether we are eligible for wakeup.  */
val = cond->__data.__wakeup_seq;
}
while (val == seq || cond->__data.__woken_seq == val);

/* Another thread woken up.  */
++cond->__data.__woken_seq;

bc_out:

cond->__data.__nwaiters -= 1 < < COND_NWAITERS_SHIFT;

/* If pthread_cond_destroy was called on this varaible already,
notify the pthread_cond_destroy caller all waiters have left
and it can be successfully destroyed.  */
if (cond->__data.__total_seq == -1ULL
&& cond->__data.__nwaiters < (1 < < COND_NWAITERS_SHIFT))
lll_futex_wake (&cond->__data.__nwaiters, 1, pshared);

/* We are done with the condvar.  */
lll_unlock (cond->__data.__lock, pshared);

/* The cancellation handling is back to normal, remove the handler.  */
__pthread_cleanup_pop (&buffer, 0);

/* Get the mutex before returning.  */
return __pthread_mutex_cond_lock (mutex);
}