/* TimedWait * block until a count becomes available * * "lock" [ IN ] - externally acquired lock * * "tm" [ IN, NULL OKAY ] - optional timeout where * NULL means timeout value of 0 */ LIB_EXPORT rc_t CC KSemaphoreTimedWait ( KSemaphore *self, struct KLock *lock, struct timeout_t *tm ) { if ( self == NULL ) return RC ( rcPS, rcSemaphore, rcWaiting, rcSelf, rcNull ); if ( self -> avail == 0 ) { SMSG ( "%s[%p]: avail == 0\n", __func__, self ); if ( tm == NULL ) { SMSG ( "%s[%p]: non-blocking mode - return timeout exhausted\n", __func__, self ); return RC ( rcPS, rcSemaphore, rcWaiting, rcTimeout, rcExhausted ); } if ( ++ self -> waiting == 1 ) { SMSG ( "%s[%p]: first waiter\n", __func__, self ); self -> requested = self -> min_requested = 1; self -> uniform = true; } else if ( self -> requested != 1 ) { SMSG ( "%s[%p]: multiple waiters ( %u )\n", __func__, self, self -> waiting ); self -> min_requested = 1; self -> uniform = false; } do { rc_t rc; SMSG ( "%s[%p]: wait on condition...\n", __func__, self ); rc = KConditionTimedWait ( self -> cond, lock, tm ); SMSG ( "%s[%p]:...done, rc = %R\n", __func__, self, rc ); if ( rc != 0 ) { SMSG ( "%s[%p]: timed out - decrementing wait count\n", __func__, self ); -- self -> waiting; return ResetRCContext ( rc, rcPS, rcSemaphore, rcWaiting ); } SMSG ( "%s[%p]: condition signaled - avail = %lu\n", __func__, self, self -> avail ); } while ( self -> avail == 0 ); SMSG ( "%s[%p]: finished waiting\n", __func__, self ); -- self -> waiting; } SMSG ( "%s[%p]: decrementing count from %lu\n", __func__, self, self -> avail ); -- self -> avail; return 0; }
/* TimedAlloc * allocate a count * used for resource metering * * "lock" [ IN ] - externally acquired lock * * "count" [ IN ] - the resource count * * "tm" [ IN, NULL OKAY ] - optional timeout where * NULL means timeout value of 0 */ LIB_EXPORT rc_t CC KSemaphoreTimedAlloc ( KSemaphore *self, struct KLock *lock, uint64_t count, struct timeout_t *tm ) { if ( self == NULL ) return RC ( rcPS, rcSemaphore, rcWaiting, rcSelf, rcNull ); if ( self -> avail < count ) { if ( tm == NULL ) return RC ( rcPS, rcSemaphore, rcWaiting, rcTimeout, rcExhausted ); if ( ++ self -> waiting == 1 ) { self -> requested = self -> min_requested = count; self -> uniform = true; } else if ( self -> requested != count ) { if ( self -> min_requested > count ) self -> min_requested = count; self -> uniform = false; } do { rc_t rc; if ( self -> canceled ) { -- self -> waiting; return RC ( rcPS, rcSemaphore, rcWaiting, rcSemaphore, rcCanceled ); } rc = KConditionTimedWait ( self -> cond, lock, tm ); if ( rc != 0 ) { -- self -> waiting; return ResetRCContext ( rc, rcPS, rcSemaphore, rcWaiting ); } } while ( self -> avail < count ); -- self -> waiting; } self -> avail -= count; return 0; }