|
Message-ID: <alpine.LNX.2.11.1503012054440.19651@monopod.intra.ispras.ru> Date: Sun, 1 Mar 2015 21:24:09 +0300 (MSK) From: Alexander Monakov <amonakov@...ras.ru> To: musl@...ts.openwall.com Subject: Re: semaphore redesign On Sun, 1 Mar 2015, Szabolcs Nagy wrote: > * Alexander Monakov <amonakov@...ras.ru> [2015-02-28 02:21:22 +0300]: > > int sem_post(sem_t *sem) > > { > > int val; > > do { > > val = sem->__val[0]; > > if (val == SEM_VALUE_MAX) { > > errno = EOVERFLOW; > > return -1; > > as discussed on irc early return here without a barrier is not ok > (it is a hard to observe corner case, i add the comment here so > it does not get forgotten) We further discussed that to fix it, one can recheck the value after a barrier in the error path, and restart from the beginning if it changed, or always proceed to CAS (with value changed only if not leading to error), and handle errors after the cas-retry loop. The following code implements the latter approach. I strongly prefer it for sem_trywait, where I think EAGAIN is relatively common. For sem_post it's not so clear cut for me, as EOVERFLOW should be extremely rare, but still it helps to get good code layout from the compiler (otherwise GCC lays out error return path inside of the cas loop). int sem_trywait(sem_t *sem) { int val; do val = sem->__val[0]; while (val != a_cas(sem->__val, val, val-!!(val>0))); if (val > 0) return 0; errno = EAGAIN; return -1; } int sem_post(sem_t *sem) { int val; do val = sem->__val[0]; while (val != a_cas(sem->__val, val, val+!!(val<SEM_VALUE_MAX))); if (val < 0) { int priv = sem->__val[2]; a_inc(sem->__val+1); __wake(sem->__val+1, 1, priv); } if (val < SEM_VALUE_MAX) return 0; errno = EOVERFLOW; return -1; }
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.