/* Return locked block number {0, 1}, or -1 on error */ static int/*tri-state*/ s_Shmem_RLock(int which) { #ifdef LBSM_DEBUG CORE_LOG(eLOG_Trace, "LBSM R-lock acquire (%d)", which + 1); #endif /*LBSM_DEBUG*/ /* For block 1 then block 0: check [1] first, then continue with [2] */ if (s_Shmem_Lock(which, 1, which/*1:no-wait,0:wait*/) == 0) return which/*block locked*/; return !which || errno == EINVAL ? -1 : s_Shmem_Lock(0, 1, 0/*wait*/); }
/* Return locked block number {0, 1}, or -1 in error */ static int/*tri-state*/ s_Shmem_RLock(void) { #ifdef LBSM_DEBUG CORE_LOG(eLOG_Trace, "LBSM R-lock acquire"); #endif /*LBSM_DEBUG*/ /* For block 1, then block 0: check [1] first, then continue with [2] */ if (s_Shmem_Lock(1, 1, 1/*no-wait*/) == 0) return 1/*block 1 locked*/; return errno == EINVAL ? -1 : s_Shmem_Lock(0, 1, 0/*wait*/); }
static int/*tri-state-bool, inverted*/ s_Shmem_TryWLock(int which) { int semnum = (which << 1) | 1; int/*bool*/ no_undo = 0; struct sembuf rwlock[2]; int i = 0; for (;;) { rwlock[0].sem_num = semnum; rwlock[0].sem_op = 0; /* precondition: [1] == 0 */ rwlock[0].sem_flg = 0; rwlock[1].sem_num = semnum; rwlock[1].sem_op = 1; /* postcondition: [1] == 1 */ rwlock[1].sem_flg = no_undo ? 0 : SEM_UNDO; if (semop(s_Muxid, rwlock, sizeof(rwlock)/sizeof(rwlock[0])) >= 0) { /* No new read accesses are allowed after this point */ s_NoUndo[semnum - 1] = no_undo; /* Look at [2] first, then continue with it */ if (s_Shmem_Lock(which, 2, 0/*wait*/) != 0) return 1/*partially locked*/; return 0/*okay*/; } if (i) break; i = errno; if (i == ENOSPC) { CORE_LOGF_X(8, eLOG_Warning, ("LBSM PreW-locking[%d] w/o undo", which + 1)); no_undo = 1; continue; } if (i == EINTR) continue; if (i != ENOMEM) break; #ifdef LBSM_DEBUG CORE_LOGF(eLOG_Trace, ("LBSM PreW-lock[%d] wait(ENOMEM)", which + 1)); #endif/*LBSM_DEBUG*/ sleep(1); } return -1/*not locked*/; }