VirtualBox

Ignore:
Timestamp:
Oct 11, 2010 9:55:12 AM (14 years ago)
Author:
vboxsync
Message:

IPRT: Implemented RTSemEventWaitEx[Debug] for ring-0 linux.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r0drv/linux/semevent-r0drv-linux.c

    r29661 r33033  
    55
    66/*
    7  * Copyright (C) 2006-2007 Oracle Corporation
     7 * Copyright (C) 2006-2010 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3232#include "internal/iprt.h"
    3333#include <iprt/semaphore.h>
    34 #include <iprt/alloc.h>
     34
     35#include <iprt/asm.h>
    3536#include <iprt/assert.h>
    36 #include <iprt/asm.h>
    3737#include <iprt/err.h>
    38 
     38#include <iprt/lockvalidator.h>
     39#include <iprt/mem.h>
     40
     41#include "waitqueue-r0drv-linux.h"
    3942#include "internal/magics.h"
    4043
     
    5255    /** The object status - !0 when signaled and 0 when reset. */
    5356    uint32_t volatile   fState;
     57    /** Reference counter. */
     58    uint32_t volatile   cRefs;
    5459    /** The wait queue. */
    5560    wait_queue_head_t   Head;
     
    7580    pThis->u32Magic = RTSEMEVENT_MAGIC;
    7681    pThis->fState   = 0;
     82    pThis->cRefs    = 1;
    7783    init_waitqueue_head(&pThis->Head);
    7884
     
    8187}
    8288RT_EXPORT_SYMBOL(RTSemEventCreate);
     89
     90
     91/**
     92 * Retains a reference to the event semaphore.
     93 *
     94 * @param   pThis       The event semaphore.
     95 */
     96DECLINLINE(void) rtR0SemEventLnxRetain(PRTSEMEVENTINTERNAL pThis)
     97{
     98    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
     99    Assert(cRefs < 100000); NOREF(cRefs);
     100}
     101
     102
     103/**
     104 * Releases a reference to the event semaphore.
     105 *
     106 * @param   pThis       The event semaphore.
     107 */
     108DECLINLINE(void) rtR0SemEventLnxRelease(PRTSEMEVENTINTERNAL pThis)
     109{
     110    if (RT_UNLIKELY(ASMAtomicDecU32(&pThis->cRefs) == 0))
     111        RTMemFree(pThis);
     112}
    83113
    84114
     
    92122        return VINF_SUCCESS;
    93123    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
     124    Assert(pThis->cRefs > 0);
    94125
    95126    /*
     
    100131    Assert(!waitqueue_active(&pThis->Head));
    101132    wake_up_all(&pThis->Head);
    102     RTMemFree(pThis);
     133    rtR0SemEventLnxRelease(pThis);
    103134    return VINF_SUCCESS;
    104135}
     
    114145    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    115146    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
     147    rtR0SemEventLnxRetain(pThis);
    116148
    117149    /*
     
    121153    wake_up(&pThis->Head);
    122154
     155    rtR0SemEventLnxRelease(pThis);
    123156    return VINF_SUCCESS;
    124157}
     
    127160
    128161/**
    129  * Worker for RTSemEvent and RTSemEventNoResume.
     162 * Worker for RTSemEventWaitEx and RTSemEventWaitExDebug.
    130163 *
    131164 * @returns VBox status code.
    132165 * @param   pThis           The event semaphore.
    133  * @param   cMillies            The number of milliseconds to wait.
    134  * @param   fInterruptible      Whether it's an interruptible wait or not.
    135  */
    136 static int rtSemEventWait(PRTSEMEVENTINTERNAL pThis, RTMSINTERVAL cMillies, bool fInterruptible)
    137 {
    138     /*
    139      * Ok wait for it.
    140      */
    141     DEFINE_WAIT(Wait);
    142     int     rc       = VINF_SUCCESS;
    143     long    lTimeout = cMillies == RT_INDEFINITE_WAIT ? MAX_SCHEDULE_TIMEOUT : msecs_to_jiffies(cMillies);
    144     IPRT_DEBUG_SEMS_STATE(pThis, 'e');
    145     for (;;)
     166 * @param   fFlags          See RTSemEventWaitEx.
     167 * @param   uTimeout        See RTSemEventWaitEx.
     168 * @param   pSrcPos         The source code position of the wait.
     169 */
     170static int rtR0SemEventLnxWait(PRTSEMEVENTINTERNAL pThis, uint32_t fFlags, uint64_t uTimeout,
     171                               PCRTLOCKVALSRCPOS pSrcPos)
     172{
     173    int rc;
     174
     175    /*
     176     * Validate the input.
     177     */
     178    AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
     179    AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("%p u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_PARAMETER);
     180    rtR0SemEventLnxRetain(pThis);
     181
     182    /*
     183     * Try grab the event without setting up the wait.
     184     */
     185    if (   1 /** @todo check if there are someone waiting already - waitqueue_active, but then what do we do below? */
     186        && ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
     187        rc = VINF_SUCCESS;
     188    else
    146189    {
    147         /* make everything thru schedule_timeout() atomic scheduling wise. */
    148         prepare_to_wait(&pThis->Head, &Wait, fInterruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
    149 
    150         /* check the condition. */
    151         if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
    152             break;
    153 
    154         /* check for pending signals. */
    155         if (fInterruptible && signal_pending(current))
     190        /*
     191         * We have to wait.
     192         */
     193        RTR0SEMLNXWAIT Wait;
     194        rc = rtR0SemLnxWaitInit(&Wait, fFlags, uTimeout, &pThis->Head);
     195        if (RT_SUCCESS(rc))
    156196        {
    157             rc = VERR_INTERRUPTED;
    158             break;
    159         }
    160 
    161         /* wait */
    162         lTimeout = schedule_timeout(lTimeout);
    163 
    164         after_wait(&Wait);
    165 
    166         /* Check if someone destroyed the semaphore while we were waiting. */
    167         if (pThis->u32Magic != RTSEMEVENT_MAGIC)
    168         {
    169             rc = VERR_SEM_DESTROYED;
    170             break;
    171         }
    172 
    173         /* check for timeout. */
    174         if (!lTimeout)
    175         {
    176             rc = VERR_TIMEOUT;
    177             break;
     197            IPRT_DEBUG_SEMS_STATE(pThis, 'E');
     198            for (;;)
     199            {
     200                /* The destruction test. */
     201                if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
     202                    rc = VERR_SEM_DESTROYED;
     203                else
     204                {
     205                    rtR0SemLnxWaitPrepare(&Wait);
     206
     207                    /* Check the exit conditions. */
     208                    if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENT_MAGIC))
     209                        rc = VERR_SEM_DESTROYED;
     210                    else if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
     211                        rc = VINF_SUCCESS;
     212                    else if (rtR0SemLnxWaitHasTimedOut(&Wait))
     213                        rc = VERR_TIMEOUT;
     214                    else if (rtR0SemLnxWaitWasInterrupted(&Wait))
     215                        rc = VERR_INTERRUPTED;
     216                    else
     217                    {
     218                        /* Do the wait and then recheck the conditions. */
     219                        rtR0SemLnxWaitDoIt(&Wait);
     220                        continue;
     221                    }
     222                }
     223                break;
     224            }
     225
     226            rtR0SemLnxWaitDelete(&Wait);
     227            IPRT_DEBUG_SEMS_STATE_RC(pThis, 'E', rc);
    178228        }
    179229    }
    180230
    181     finish_wait(&pThis->Head, &Wait);
    182     IPRT_DEBUG_SEMS_STATE_RC(pThis, 'e', rc);
     231    rtR0SemEventLnxRelease(pThis);
    183232    return rc;
    184233}
    185234
    186235
    187 RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
    188 {
    189     PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
    190     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    191     AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
    192 
    193     if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
    194         return VINF_SUCCESS;
    195     return rtSemEventWait(pThis, cMillies, false /* fInterruptible */);
    196 }
    197 RT_EXPORT_SYMBOL(RTSemEventWait);
    198 
    199 
    200 RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies)
    201 {
    202     PRTSEMEVENTINTERNAL pThis = (PRTSEMEVENTINTERNAL)hEventSem;
    203     AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    204     AssertMsgReturn(pThis->u32Magic == RTSEMEVENT_MAGIC, ("pThis->u32Magic=%RX32 pThis=%p\n", pThis->u32Magic, pThis), VERR_INVALID_HANDLE);
    205 
    206     if (ASMAtomicCmpXchgU32(&pThis->fState, 0, 1))
    207         return VINF_SUCCESS;
    208     return rtSemEventWait(pThis, cMillies, true /* fInterruptible */);
    209 }
    210 RT_EXPORT_SYMBOL(RTSemEventWaitNoResume);
    211 
     236#undef RTSemEventWaitEx
     237RTDECL(int)  RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout)
     238{
     239#ifndef RTSEMEVENT_STRICT
     240    return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, NULL);
     241#else
     242    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API();
     243    return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, &SrcPos);
     244#endif
     245}
     246RT_EXPORT_SYMBOL(RTSemEventWaitEx);
     247
     248
     249RTDECL(int)  RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout,
     250                                   RTHCUINTPTR uId, RT_SRC_POS_DECL)
     251{
     252    RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API();
     253    return rtR0SemEventLnxWait(hEventSem, fFlags, uTimeout, &SrcPos);
     254}
     255RT_EXPORT_SYMBOL(RTSemEventWaitExDebug);
     256
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette