Logo Search packages:      
Sourcecode: virtualbox-ose version File versions

critsect.h

Go to the documentation of this file.
/** @file
 * innotek Portable Runtime - Critical Sections.
 */

/*
 * Copyright (C) 2006-2007 innotek GmbH
 *
 * This file is part of VirtualBox Open Source Edition (OSE), as
 * available from http://www.virtualbox.org. This file is free software;
 * you can redistribute it and/or modify it under the terms of the GNU
 * General Public License as published by the Free Software Foundation,
 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
 * distribution. VirtualBox OSE is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY of any kind.
 */

#ifndef ___iprt_critsect_h
#define ___iprt_critsect_h

#include <iprt/cdefs.h>
#include <iprt/types.h>
#ifdef IN_RING3
#include <iprt/thread.h>
#endif


__BEGIN_DECLS

/** @defgroup grp_rt_critsect       RTCritSect - Critical Sections
 * @ingroup grp_rt
 * @{
 */

/**
 * Critical section.
 */
00037 typedef struct RTCRITSECT
{
    /** Magic used to validate the section state.
     * RTCRITSECT_MAGIC is the value of an initialized & operational section. */
00041     volatile uint32_t       u32Magic;
    /** Number of lockers.
     * -1 if the section is free. */
00044     volatile int32_t        cLockers;
    /** The owner thread. */
00046     volatile RTNATIVETHREAD NativeThreadOwner;
    /** Number of nested enter operations performed.
     * Greater or equal to 1 if owned, 0 when free.
     */
00050     volatile int32_t        cNestings;
    /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
00052     uint32_t                fFlags;
    /** The semaphore to wait for. */
00054     RTSEMEVENT              EventSem;

    /** Data only used in strict mode for detecting and debugging deadlocks. */
00057     struct RTCRITSECTSTRICT
    {
        /** Strict: The current owner thread. */
00060         RTTHREAD volatile                   ThreadOwner;
        /** Strict: Where the section was entered. */
        HCPTRTYPE(const char * volatile)    pszEnterFile;
        /** Strict: Where the section was entered. */
00064         uint32_t volatile                   u32EnterLine;
#if HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64
        /** Padding for correct alignment. */
        uint32_t                            u32Padding;
#endif
        /** Strict: Where the section was entered. */
00070         RTUINTPTR volatile                  uEnterId;
    } Strict;
} RTCRITSECT;
/** Pointer to a critical section. */
00074 typedef RTCRITSECT *PRTCRITSECT;
/** Pointer to a const critical section. */
00076 typedef const RTCRITSECT *PCRTCRITSECT;

/** RTCRITSECT::u32Magic value. */
00079 #define RTCRITSECT_MAGIC    0x778899aa

/** If set, nesting(/recursion) is not allowed. */
00082 #define RTCRITSECT_FLAGS_NO_NESTING     1

#ifdef IN_RING3

/**
 * Initialize a critical section.
 */
RTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect);

/**
 * Initialize a critical section.
 *
 * @returns iprt status code.
 * @param   pCritSect   Pointer to the critical section structure.
 * @param   fFlags      Flags, any combination of the RTCRITSECT_FLAGS \#defines.
 */
RTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags);

/**
 * Enter a critical section.
 *
 * @returns VINF_SUCCESS on success.
 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
 * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
 * @param   pCritSect   The critical section.
 */
RTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect);

/**
 * Enter a critical section.
 *
 * @returns VINF_SUCCESS on success.
 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
 * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
 * @param   pCritSect   The critical section.
 * @param   pszFile     Where we're entering the section.
 * @param   uLine       Where we're entering the section.
 * @param   uId         Where we're entering the section.
 */
RTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId);

/* in debug mode we'll redefine the enter call. */
#ifdef RT_STRICT
# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, __FILE__,  __LINE__, 0)
#endif

/**
 * Try enter a critical section.
 *
 * @returns VINF_SUCCESS on success.
 * @returns VERR_SEM_BUSY if the critsect was owned.
 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
 * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
 * @param   pCritSect   The critical section.
 */
RTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect);

/**
 * Try enter a critical section.
 *
 * @returns VINF_SUCCESS on success.
 * @returns VERR_SEM_BUSY if the critsect was owned.
 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
 * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
 * @param   pCritSect   The critical section.
 * @param   pszFile     Where we're entering the section.
 * @param   uLine       Where we're entering the section.
 * @param   uId         Where we're entering the section.
 */
RTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId);

/* in debug mode we'll redefine the try-enter call. */
#ifdef RT_STRICT
# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, __FILE__,  __LINE__, 0)
#endif

/**
 * Enter multiple critical sections.
 *
 * This function will enter ALL the specified critical sections before returning.
 *
 * @returns VINF_SUCCESS on success.
 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
 * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
 * @param   cCritSects      Number of critical sections in the array.
 * @param   papCritSects    Array of critical section pointers.
 *
 * @remark  Please note that this function will not necessarily come out favourable in a
 *          fight with other threads which are using the normal RTCritSectEnter() function.
 *          Therefore, avoid having to enter multiple critical sections!
 */
RTDECL(int) RTCritSectEnterMultiple(unsigned cCritSects, PRTCRITSECT *papCritSects);

/**
 * Enter multiple critical sections.
 *
 * This function will enter ALL the specified critical sections before returning.
 *
 * @returns VINF_SUCCESS on success.
 * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
 * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
 *
 * @param   cCritSects      Number of critical sections in the array.
 * @param   papCritSects    Array of critical section pointers.
 * @param   pszFile         Where we're entering the section.
 * @param   uLine           Where we're entering the section.
 * @param   uId             Where we're entering the section.
 *
 * @remark  See RTCritSectEnterMultiple().
 */
RTDECL(int) RTCritSectEnterMultipleDebug(unsigned cCritSects, PRTCRITSECT *papCritSects, const char *pszFile, unsigned uLine, RTUINTPTR uId);

/* in debug mode we'll redefine the enter-multiple call. */
#ifdef RT_STRICT
# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), __FILE__,  __LINE__, 0)
#endif

/**
 * Leave a critical section.
 *
 * @returns VINF_SUCCESS.
 * @param   pCritSect   The critical section.
 */
RTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect);

/**
 * Leave multiple critical sections.
 *
 * @returns VINF_SUCCESS.
 * @param   cCritSects      Number of critical sections in the array.
 * @param   papCritSects    Array of critical section pointers.
 */
RTDECL(int) RTCritSectLeaveMultiple(unsigned cCritSects, PRTCRITSECT *papCritSects);

/**
 * Deletes a critical section.
 *
 * @returns VINF_SUCCESS.
 * @param   pCritSect   The critical section.
 */
RTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect);


/**
 * Checks if a critical section is initialized or not.
 *
 * @returns true if initialized.
 * @returns false if not initialized.
 * @param   pCritSect   The critical section.
 */
DECLINLINE(bool) RTCritSectIsInitialized(PCRTCRITSECT pCritSect)
{
    return pCritSect->u32Magic == RTCRITSECT_MAGIC;
}


/**
 * Checks the caller is the owner of the critical section.
 *
 * @returns true if owner.
 * @returns false if not owner.
 * @param   pCritSect   The critical section.
 */
DECLINLINE(bool) RTCritSectIsOwner(PCRTCRITSECT pCritSect)
{
    return pCritSect->NativeThreadOwner == RTThreadNativeSelf();
}


/**
 * Checks the section is owned by anyone.
 *
 * @returns true if owned.
 * @returns false if not owned.
 * @param   pCritSect   The critical section.
 */
DECLINLINE(bool) RTCritSectIsOwned(PCRTCRITSECT pCritSect)
{
    return pCritSect->NativeThreadOwner != NIL_RTNATIVETHREAD;
}


/**
 * Gets the thread id of the critical section owner.
 *
 * @returns Thread id of the owner thread if owned.
 * @returns NIL_RTNATIVETHREAD is not owned.
 * @param   pCritSect   The critical section.
 */
DECLINLINE(RTNATIVETHREAD) RTCritSectGetOwner(PCRTCRITSECT pCritSect)
{
    return pCritSect->NativeThreadOwner;
}


/**
 * Gets the recursion depth.
 *
 * @returns The recursion depth.
 * @param   pCritSect       The Critical section
 */
DECLINLINE(uint32_t) RTCritSectGetRecursion(PCRTCRITSECT pCritSect)
{
    return pCritSect->cNestings;
}

#endif /* IN_RING3 */
/** @} */

__END_DECLS

#endif


Generated by  Doxygen 1.6.0   Back to index