Пример #1
0
/* 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;
}
Пример #2
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;
}