📄 readme.cv
字号:
}
if (bAll) {
nWaitersToUnblock += nWaitersBlocked;
nWaitersBlocked = 0;
}
else {
nWaitersToUnblock++;
nWaitersBlocked--;
}
unlock( mtxUnblockLock );
}
else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
sem_wait( semBlockLock ); // close the gate
if ( 0 != nWaitersGone ) {
nWaitersBlocked -= nWaitersGone;
nWaitersGone = 0;
}
if (bAll) {
nWaitersToUnblock = nWaitersBlocked;
nWaitersBlocked = 0;
}
else {
nWaitersToUnblock = 1;
nWaitersBlocked--;
}
unlock( mtxUnblockLock );
sem_post( semBlockQueue );
}
else { // NO-OP
unlock( mtxUnblockLock );
}
return result;
}
---------- Algorithm 8c / IMPL_EVENT,UNBLOCK_STRATEGY == UNBLOCK_ONEBYONE
---------
given:
hevBlockLock - auto-reset event
hevBlockQueue - auto-reset event
mtxExternal - mutex or CS
mtxUnblockLock - mutex or CS
nWaitersGone - int
nWaitersBlocked - int
nWaitersToUnblock - int
wait( timeout ) {
[auto: register int result ] // error checking omitted
[auto: register int nSignalsWasLeft ]
[auto: register int nWaitersWasGone ]
wait( hevBlockLock,INFINITE );
nWaitersBlocked++;
set_event( hevBlockLock );
unlock( mtxExternal );
bTimedOut = wait( hevBlockQueue,timeout );
lock( mtxUnblockLock );
if ( 0 != (SignalsWasLeft = nWaitersToUnblock) ) {
if ( bTimeout ) { // timeout (or canceled)
if ( 0 != nWaitersBlocked ) {
nWaitersBlocked--;
nSignalsWasLeft = 0; // do not unblock next waiter
below (already unblocked)
}
else {
nWaitersGone = 1; // spurious wakeup pending!!
}
}
if ( 0 == --nWaitersToUnblock )
if ( 0 != nWaitersBlocked ) {
set_event( hevBlockLock ); // open the gate
nSignalsWasLeft = 0; // do not open the gate below
again
}
else if ( 0 != (nWaitersWasGone = nWaitersGone) ) {
nWaitersGone = 0;
}
}
}
else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious
event :-)
wait( hevBlockLock,INFINITE );
nWaitersBlocked -= nWaitersGone; // something is going on here -
test of timeouts? :-)
set_event( hevBlockLock );
nWaitersGone = 0;
}
unlock( mtxUnblockLock );
if ( 1 == nSignalsWasLeft ) {
if ( 0 != nWaitersWasGone ) {
reset_event( hevBlockQueue ); // better now than spurious
later
}
set_event( hevBlockLock ); // open the gate
}
else if ( 0 != nSignalsWasLeft ) {
set_event( hevBlockQueue ); // unblock next waiter
}
lock( mtxExternal );
return ( bTimedOut ) ? ETIMEOUT : 0;
}
signal(bAll) {
[auto: register int result ]
lock( mtxUnblockLock );
if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
if ( 0 == nWaitersBlocked ) { // NO-OP
return unlock( mtxUnblockLock );
}
if (bAll) {
nWaitersToUnblock += nWaitersBlocked;
nWaitersBlocked = 0;
}
else {
nWaitersToUnblock++;
nWaitersBlocked--;
}
unlock( mtxUnblockLock );
}
else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
wait( hevBlockLock,INFINITE ); // close the gate
if ( 0 != nWaitersGone ) {
nWaitersBlocked -= nWaitersGone;
nWaitersGone = 0;
}
if (bAll) {
nWaitersToUnblock = nWaitersBlocked;
nWaitersBlocked = 0;
}
else {
nWaitersToUnblock = 1;
nWaitersBlocked--;
}
unlock( mtxUnblockLock );
set_event( hevBlockQueue );
}
else { // NO-OP
unlock( mtxUnblockLock );
}
return result;
}
---------- Algorithm 8d / IMPL_EVENT,UNBLOCK_STRATEGY == UNBLOCK_ALL ------
given:
hevBlockLock - auto-reset event
hevBlockQueueS - auto-reset event // for signals
hevBlockQueueB - manual-reset even // for broadcasts
mtxExternal - mutex or CS
mtxUnblockLock - mutex or CS
eBroadcast - int // 0: no broadcast, 1: broadcast, 2:
broadcast after signal(s)
nWaitersGone - int
nWaitersBlocked - int
nWaitersToUnblock - int
wait( timeout ) {
[auto: register int result ] // error checking omitted
[auto: register int eWasBroadcast ]
[auto: register int nSignalsWasLeft ]
[auto: register int nWaitersWasGone ]
wait( hevBlockLock,INFINITE );
nWaitersBlocked++;
set_event( hevBlockLock );
unlock( mtxExternal );
bTimedOut = waitformultiple( hevBlockQueueS,hevBlockQueueB,timeout,ONE );
lock( mtxUnblockLock );
if ( 0 != (SignalsWasLeft = nWaitersToUnblock) ) {
if ( bTimeout ) { // timeout (or canceled)
if ( 0 != nWaitersBlocked ) {
nWaitersBlocked--;
nSignalsWasLeft = 0; // do not unblock next waiter
below (already unblocked)
}
else if ( 1 != eBroadcast ) {
nWaitersGone = 1;
}
}
if ( 0 == --nWaitersToUnblock ) {
if ( 0 != nWaitersBlocked ) {
set_event( hevBlockLock ); // open the gate
nSignalsWasLeft = 0; // do not open the gate below
again
}
else {
if ( 0 != (eWasBroadcast = eBroadcast) ) {
eBroadcast = 0;
}
if ( 0 != (nWaitersWasGone = nWaitersGone ) {
nWaitersGone = 0;
}
}
}
else if ( 0 != eBroadcast ) {
nSignalsWasLeft = 0; // do not unblock next waiter
below (already unblocked)
}
}
else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious
event :-)
wait( hevBlockLock,INFINITE );
nWaitersBlocked -= nWaitersGone; // something is going on here -
test of timeouts? :-)
set_event( hevBlockLock );
nWaitersGone = 0;
}
unlock( mtxUnblockLock );
if ( 1 == nSignalsWasLeft ) {
if ( 0 != eWasBroadcast ) {
reset_event( hevBlockQueueB );
}
if ( 0 != nWaitersWasGone ) {
reset_event( hevBlockQueueS ); // better now than spurious
later
}
set_event( hevBlockLock ); // open the gate
}
else if ( 0 != nSignalsWasLeft ) {
set_event( hevBlockQueueS ); // unblock next waiter
}
lock( mtxExternal );
return ( bTimedOut ) ? ETIMEOUT : 0;
}
signal(bAll) {
[auto: register int result ]
[auto: register HANDLE hevBlockQueue ]
lock( mtxUnblockLock );
if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
if ( 0 == nWaitersBlocked ) { // NO-OP
return unlock( mtxUnblockLock );
}
if (bAll) {
nWaitersToUnblock += nWaitersBlocked;
nWaitersBlocked = 0;
eBroadcast = 2;
hevBlockQueue = hevBlockQueueB;
}
else {
nWaitersToUnblock++;
nWaitersBlocked--;
return unlock( mtxUnblockLock );
}
}
else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
wait( hevBlockLock,INFINITE ); // close the gate
if ( 0 != nWaitersGone ) {
nWaitersBlocked -= nWaitersGone;
nWaitersGone = 0;
}
if (bAll) {
nWaitersToUnblock = nWaitersBlocked;
nWaitersBlocked = 0;
eBroadcast = 1;
hevBlockQueue = hevBlockQueueB;
}
else {
nWaitersToUnblock = 1;
nWaitersBlocked--;
hevBlockQueue = hevBlockQueueS;
}
}
else { // NO-OP
return unlock( mtxUnblockLock );
}
unlock( mtxUnblockLock );
set_event( hevBlockQueue );
return result;
}
---------------------- Forwarded by Alexander Terekhov/Germany/IBM on
02/21/2001 09:13 AM ---------------------------
Alexander Terekhov
02/20/2001 04:33 PM
To: Louis Thomas <lthomas@arbitrade.com>
cc:
From: Alexander Terekhov/Germany/IBM@IBMDE
Subject: RE: FYI/comp.programming.threads/Re: pthread_cond_* implementatio
n questions
Importance: Normal
>Sorry, gotta take a break and work on something else for a while.
>Real work
>calls, unfortunately. I'll get back to you in two or three days.
ok. no problem. here is some more stuff for pauses you might have
in between :)
---------- Algorithm 7d / IMPL_EVENT,UNBLOCK_STRATEGY == UNBLOCK_ALL ------
given:
hevBlockLock - auto-reset event
hevBlockQueueS - auto-reset event // for signals
hevBlockQueueB - manual-reset even // for broadcasts
mtxExternal - mutex or CS
mtxUnblockLock - mutex or CS
bBroadcast - int
nWaitersGone - int
nWaitersBlocked - int
nWaitersToUnblock - int
wait( timeout ) {
[auto: register int result ] // error checking omitted
[auto: register int bWasBroadcast ]
[auto: register int nSignalsWasLeft ]
wait( hevBlockLock,INFINITE );
nWaitersBlocked++;
set_event( hevBlockLock );
unlock( mtxExternal );
bTimedOut = waitformultiple( hevBlockQueueS,hevBlockQueueB,timeout,ONE );
lock( mtxUnblockLock );
if ( 0 != (SignalsWasLeft = nWaitersToUnblock) ) {
if ( bTimeout ) { // timeout (or canceled)
if ( 0 != nWaitersBlocked ) {
nWaitersBlocked--;
nSignalsWasLeft = 0; // do not unblock next waiter
below (already unblocked)
}
else if ( !bBroadcast ) {
wait( hevBlockQueueS,INFINITE ); // better now than spurious
later
}
}
if ( 0 == --nWaitersToUnblock ) {
if ( 0 != nWaitersBlocked ) {
if ( bBroadcast ) {
reset_event( hevBlockQueueB );
bBroadcast = false;
}
set_event( hevBlockLock ); // open the gate
nSignalsWasLeft = 0; // do not open the gate below
again
}
else if ( false != (bWasBroadcast = bBroadcast) ) {
bBroadcast = false;
}
}
else {
bWasBroadcast = bBroadcast;
}
}
else if ( INT_MAX/2 == ++nWaitersGone ) { // timeout/canceled or spurious
event :-)
wait( hevBlockLock,INFINITE );
nWaitersBlocked -= nWaitersGone; // something is going on here -
test of timeouts? :-)
set_event( hevBlockLock );
nWaitersGone = 0;
}
unlock( mtxUnblockLock );
if ( 1 == nSignalsWasLeft ) {
if ( bWasBroadcast ) {
reset_event( hevBlockQueueB );
}
set_event( hevBlockLock ); // open the gate
}
else if ( 0 != nSignalsWasLeft && !bWasBroadcast ) {
set_event( hevBlockQueueS ); // unblock next waiter
}
lock( mtxExternal );
return ( bTimedOut ) ? ETIMEOUT : 0;
}
signal(bAll) {
[auto: register int result ]
[auto: register HANDLE hevBlockQueue ]
lock( mtxUnblockLock );
if ( 0 != nWaitersToUnblock ) { // the gate is closed!!!
if ( 0 == nWaitersBlocked ) { // NO-OP
return unlock( mtxUnblockLock );
}
if (bAll) {
nWaitersToUnblock += nWaitersBlocked;
nWaitersBlocked = 0;
bBroadcast = true;
hevBlockQueue = hevBlockQueueB;
}
else {
nWaitersToUnblock++;
nWaitersBlocked--;
return unlock( mtxUnblockLock );
}
}
else if ( nWaitersBlocked > nWaitersGone ) { // HARMLESS RACE CONDITION!
wait( hevBlockLock,INFINITE ); // close the gate
if ( 0 != nWaitersGone ) {
nWaitersBlocked -= nWaitersGone;
nWaitersGone = 0;
}
if (bAll) {
nWaitersToUnblock = nWaitersBlocked;
nWaitersBlocked = 0;
bBroadcast = true;
hevBlockQueue = hevBlockQueueB;
}
else {
nWaitersToUnblock = 1;
nWaitersBlocked--;
hevBlockQueue = hevBlockQueueS;
}
}
else { // NO-OP
return unlock( mtxUnblockLock );
}
unlock( mtxUnblockLock );
set_event( hevBlockQueue );
return result;
}
----------------------------------------------------------------------------
Subject: RE: FYI/comp.programming.threads/Re: pthread_cond_* implementatio
n questions
Date: Mon, 26 Feb 2001 22:20:12 -0600
From: Louis Thomas <lthomas@arbitrade.com>
To: "'TEREKHOV@de.ibm.com'" <TEREKHOV@de.ibm.com>
CC: rpj@ise.canberra.edu.au, Thomas Pfaff <tpfaff@gmx.net>,
Nanbor Wang
<nanbor@cs.wustl.edu>
Sorry all. Busy week.
> this insures the fairness
> which POSIX does not (e.g. two subsequent broadcasts - the gate does
insure
> that first wave waiters will start the race for the mutex before waiters
> from the second wave - Linux pthreads process/unblock both waves
> concurrently...)
I'm not sure how we are any more fair about this than Linux. We certainly
don't guarantee that the threads released by the first broadcast will get
the external mutex before the threads of the second wave. In fact, it is
possible that those threads will never get the external mutex if there is
enough contention for it.
> e.g. i was thinking about implementation with a pool of
> N semaphores/counters [...]
I considered that too. The problem is as you mentioned in a). You really
need to assign threads to semaphores once you know how you want to wake them
up, not when they first begin waiting which is the only time you can assign
them.
> well, i am not quite sure that i've fully understood your scenario,
Hmm. Well, it think it's an important example, so I'll try again. First, we
have thread A which we KNOW is waiting on a condition. As soon as it becomes
unblocked for any reason, we will know because it will set a flag. Since the
flag is not set, we are 100% confident that thread A is waiting on the
condition. We have another thread, thread B, which has acquired the mutex
and is about to wait on the condition. Thus it is pretty clear that at any
point, either just A is waiting, or A and B are waiting. Now thread C comes
along. C is about to do a broadcast on the condition. A broadcast is
guaranteed to unblock all threads currently waiting on a condition, right?
Again, we said that either just A is waiti
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -