critsect.h revision 78cbab32dbc1ff1bb306f46e347c68adaf19b35e
4518N/A/** @file
4518N/A * IPRT - Critical Sections.
4518N/A */
4518N/A
4518N/A/*
4518N/A * Copyright (C) 2006-2007 Sun Microsystems, Inc.
4518N/A *
4518N/A * This file is part of VirtualBox Open Source Edition (OSE), as
4518N/A * available from http://www.virtualbox.org. This file is free software;
4518N/A * you can redistribute it and/or modify it under the terms of the GNU
4518N/A * General Public License (GPL) as published by the Free Software
4518N/A * Foundation, in version 2 as it comes in the "COPYING" file of the
4518N/A * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
4518N/A * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
4518N/A *
4518N/A * The contents of this file may alternatively be used under the terms
4518N/A * of the Common Development and Distribution License Version 1.0
4518N/A * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
4518N/A * VirtualBox OSE distribution, in which case the provisions of the
4518N/A * CDDL are applicable instead of those of the GPL.
4518N/A *
4518N/A * You may elect to license modified versions of this file under the
4518N/A * terms and conditions of either the GPL or the CDDL or both.
4518N/A *
4518N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
4518N/A * Clara, CA 95054 USA or visit http://www.sun.com if you need
4518N/A * additional information or have any questions.
4518N/A */
4518N/A
4518N/A#ifndef ___iprt_critsect_h
4518N/A#define ___iprt_critsect_h
4518N/A
4518N/A#include <iprt/cdefs.h>
4518N/A#include <iprt/types.h>
4518N/A#ifdef IN_RING3
4518N/A#include <iprt/thread.h>
4518N/A#endif
4518N/A
4518N/A
4518N/ART_BEGIN_DECLS
4518N/A
4518N/A/** @defgroup grp_rt_critsect RTCritSect - Critical Sections
4518N/A * @ingroup grp_rt
4518N/A * @{
4518N/A */
4518N/A
4518N/A/**
4518N/A * Critical section.
4518N/A */
4518N/Atypedef struct RTCRITSECT
4518N/A{
4518N/A /** Magic used to validate the section state.
4518N/A * RTCRITSECT_MAGIC is the value of an initialized & operational section. */
4518N/A volatile uint32_t u32Magic;
4518N/A /** Number of lockers.
4518N/A * -1 if the section is free. */
4518N/A volatile int32_t cLockers;
4518N/A /** The owner thread. */
4518N/A volatile RTNATIVETHREAD NativeThreadOwner;
4518N/A /** Number of nested enter operations performed.
4518N/A * Greater or equal to 1 if owned, 0 when free.
4518N/A */
4518N/A volatile int32_t cNestings;
4518N/A /** Section flags - the RTCRITSECT_FLAGS_* \#defines. */
4518N/A uint32_t fFlags;
4518N/A /** The semaphore to wait for. */
4518N/A RTSEMEVENT EventSem;
4518N/A
4518N/A /** Data only used in strict mode for detecting and debugging deadlocks. */
4518N/A struct RTCRITSECTSTRICT
4518N/A {
4518N/A /** Strict: The current owner thread. */
4518N/A RTTHREAD volatile ThreadOwner;
4518N/A /** Strict: Where the section was entered. */
4518N/A R3PTRTYPE(const char * volatile) pszEnterFile;
4518N/A /** Strict: Where the section was entered. */
4518N/A uint32_t volatile u32EnterLine;
4518N/A#if HC_ARCH_BITS == 64 || GC_ARCH_BITS == 64
4518N/A /** Padding for correct alignment. */
4518N/A uint32_t u32Padding;
4518N/A#endif
4518N/A /** Strict: Where the section was entered. */
4518N/A RTUINTPTR volatile uEnterId;
4518N/A } Strict;
4518N/A} RTCRITSECT;
4518N/A/** Pointer to a critical section. */
4518N/Atypedef RTCRITSECT *PRTCRITSECT;
4518N/A/** Pointer to a const critical section. */
4518N/Atypedef const RTCRITSECT *PCRTCRITSECT;
4518N/A
4518N/A/** RTCRITSECT::u32Magic value. */
4518N/A#define RTCRITSECT_MAGIC 0x778899aa
4518N/A
4518N/A/** If set, nesting(/recursion) is not allowed. */
4518N/A#define RTCRITSECT_FLAGS_NO_NESTING 1
4518N/A
4518N/A#ifdef IN_RING3
4518N/A
4518N/A/**
4518N/A * Initialize a critical section.
4518N/A */
4518N/ARTDECL(int) RTCritSectInit(PRTCRITSECT pCritSect);
4518N/A
4518N/A/**
4518N/A * Initialize a critical section.
4518N/A *
4518N/A * @returns iprt status code.
4518N/A * @param pCritSect Pointer to the critical section structure.
4518N/A * @param fFlags Flags, any combination of the RTCRITSECT_FLAGS \#defines.
4518N/A */
4518N/ARTDECL(int) RTCritSectInitEx(PRTCRITSECT pCritSect, uint32_t fFlags);
4518N/A
4518N/A/**
4518N/A * Enter a critical section.
4518N/A *
4518N/A * @returns VINF_SUCCESS on success.
4518N/A * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
4518N/A * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
4518N/A * @param pCritSect The critical section.
4518N/A */
4518N/ARTDECL(int) RTCritSectEnter(PRTCRITSECT pCritSect);
4518N/A
4518N/A/**
4518N/A * Enter a critical section.
4518N/A *
4518N/A * @returns VINF_SUCCESS on success.
4518N/A * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
4518N/A * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
4518N/A * @param pCritSect The critical section.
4518N/A * @param pszFile Where we're entering the section.
4518N/A * @param uLine Where we're entering the section.
4518N/A * @param uId Where we're entering the section.
4518N/A */
4518N/ARTDECL(int) RTCritSectEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId);
4518N/A
4518N/A/* in debug mode we'll redefine the enter call. */
4518N/A#ifdef RT_STRICT
4518N/A# define RTCritSectEnter(pCritSect) RTCritSectEnterDebug(pCritSect, __FILE__, __LINE__, 0)
4518N/A#endif
4518N/A
4518N/A/**
4518N/A * Try enter a critical section.
4518N/A *
4518N/A * @returns VINF_SUCCESS on success.
4518N/A * @returns VERR_SEM_BUSY if the critsect was owned.
4518N/A * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
4518N/A * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
4518N/A * @param pCritSect The critical section.
4518N/A */
4518N/ARTDECL(int) RTCritSectTryEnter(PRTCRITSECT pCritSect);
4518N/A
4518N/A/**
4518N/A * Try enter a critical section.
4518N/A *
4518N/A * @returns VINF_SUCCESS on success.
4518N/A * @returns VERR_SEM_BUSY if the critsect was owned.
4518N/A * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
4518N/A * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
4518N/A * @param pCritSect The critical section.
4518N/A * @param pszFile Where we're entering the section.
4518N/A * @param uLine Where we're entering the section.
4518N/A * @param uId Where we're entering the section.
4518N/A */
4518N/ARTDECL(int) RTCritSectTryEnterDebug(PRTCRITSECT pCritSect, const char *pszFile, unsigned uLine, RTUINTPTR uId);
4518N/A
4518N/A/* in debug mode we'll redefine the try-enter call. */
4518N/A#ifdef RT_STRICT
4518N/A# define RTCritSectTryEnter(pCritSect) RTCritSectTryEnterDebug(pCritSect, __FILE__, __LINE__, 0)
4518N/A#endif
4518N/A
4518N/A/**
4518N/A * Enter multiple critical sections.
4518N/A *
4518N/A * This function will enter ALL the specified critical sections before returning.
4518N/A *
4518N/A * @returns VINF_SUCCESS on success.
4518N/A * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
4518N/A * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
4518N/A * @param cCritSects Number of critical sections in the array.
4518N/A * @param papCritSects Array of critical section pointers.
4518N/A *
4518N/A * @remark Please note that this function will not necessarily come out favourable in a
4518N/A * fight with other threads which are using the normal RTCritSectEnter() function.
4518N/A * Therefore, avoid having to enter multiple critical sections!
4518N/A */
4518N/ARTDECL(int) RTCritSectEnterMultiple(unsigned cCritSects, PRTCRITSECT *papCritSects);
4518N/A
4518N/A/**
4518N/A * Enter multiple critical sections.
4518N/A *
4518N/A * This function will enter ALL the specified critical sections before returning.
4518N/A *
4518N/A * @returns VINF_SUCCESS on success.
4518N/A * @returns VERR_SEM_NESTED if nested enter on a no nesting section. (Asserted.)
4518N/A * @returns VERR_SEM_DESTROYED if RTCritSectDelete was called while waiting.
4518N/A *
4518N/A * @param cCritSects Number of critical sections in the array.
4518N/A * @param papCritSects Array of critical section pointers.
4518N/A * @param pszFile Where we're entering the section.
4518N/A * @param uLine Where we're entering the section.
4518N/A * @param uId Where we're entering the section.
4518N/A *
4518N/A * @remark See RTCritSectEnterMultiple().
4518N/A */
4518N/ARTDECL(int) RTCritSectEnterMultipleDebug(unsigned cCritSects, PRTCRITSECT *papCritSects, const char *pszFile, unsigned uLine, RTUINTPTR uId);
4518N/A
4518N/A/* in debug mode we'll redefine the enter-multiple call. */
4518N/A#ifdef RT_STRICT
4518N/A# define RTCritSectEnterMultiple(cCritSects, pCritSect) RTCritSectEnterMultipleDebug((cCritSects), (pCritSect), __FILE__, __LINE__, 0)
4518N/A#endif
4518N/A
4518N/A/**
4518N/A * Leave a critical section.
4518N/A *
4518N/A * @returns VINF_SUCCESS.
4518N/A * @param pCritSect The critical section.
4518N/A */
4518N/ARTDECL(int) RTCritSectLeave(PRTCRITSECT pCritSect);
4518N/A
4518N/A/**
4518N/A * Leave multiple critical sections.
4518N/A *
4518N/A * @returns VINF_SUCCESS.
4518N/A * @param cCritSects Number of critical sections in the array.
4518N/A * @param papCritSects Array of critical section pointers.
4518N/A */
4518N/ARTDECL(int) RTCritSectLeaveMultiple(unsigned cCritSects, PRTCRITSECT *papCritSects);
4518N/A
4518N/A/**
4518N/A * Deletes a critical section.
4518N/A *
4518N/A * @returns VINF_SUCCESS.
4518N/A * @param pCritSect The critical section.
4518N/A */
4518N/ARTDECL(int) RTCritSectDelete(PRTCRITSECT pCritSect);
4518N/A
4518N/A/**
4518N/A * Checks the caller is the owner of the critical section.
4518N/A *
4518N/A * @returns true if owner.
4518N/A * @returns false if not owner.
4518N/A * @param pCritSect The critical section.
4518N/A */
4518N/ADECLINLINE(bool) RTCritSectIsOwner(PCRTCRITSECT pCritSect)
4518N/A{
4518N/A return pCritSect->NativeThreadOwner == RTThreadNativeSelf();
4518N/A}
4518N/A
4518N/A#endif /* IN_RING3 */
4518N/A
4518N/A/**
4518N/A * Checks the section is owned by anyone.
4518N/A *
4518N/A * @returns true if owned.
4518N/A * @returns false if not owned.
4518N/A * @param pCritSect The critical section.
4518N/A */
4518N/ADECLINLINE(bool) RTCritSectIsOwned(PCRTCRITSECT pCritSect)
4518N/A{
4518N/A return pCritSect->NativeThreadOwner != NIL_RTNATIVETHREAD;
4518N/A}
4518N/A
4518N/A/**
4518N/A * Gets the thread id of the critical section owner.
4518N/A *
4518N/A * @returns Thread id of the owner thread if owned.
4518N/A * @returns NIL_RTNATIVETHREAD is not owned.
4518N/A * @param pCritSect The critical section.
4518N/A */
4518N/ADECLINLINE(RTNATIVETHREAD) RTCritSectGetOwner(PCRTCRITSECT pCritSect)
4518N/A{
4518N/A return pCritSect->NativeThreadOwner;
4518N/A}
4518N/A
4518N/A/**
4518N/A * Checks if a critical section is initialized or not.
4518N/A *
4518N/A * @returns true if initialized.
4518N/A * @returns false if not initialized.
4518N/A * @param pCritSect The critical section.
4518N/A */
4518N/ADECLINLINE(bool) RTCritSectIsInitialized(PCRTCRITSECT pCritSect)
4518N/A{
4518N/A return pCritSect->u32Magic == RTCRITSECT_MAGIC;
4518N/A}
4518N/A
4518N/A/**
4518N/A * Gets the recursion depth.
4518N/A *
4518N/A * @returns The recursion depth.
4518N/A * @param pCritSect The Critical section
4518N/A */
4518N/ADECLINLINE(uint32_t) RTCritSectGetRecursion(PCRTCRITSECT pCritSect)
4518N/A{
4518N/A return pCritSect->cNestings;
4518N/A}
4518N/A
4518N/A/**
4518N/A * Gets the waiter count
4518N/A *
4518N/A * @returns The waiter count
4518N/A * @param pCritSect The Critical section
4518N/A */
4518N/ADECLINLINE(int32_t) RTCritSectGetWaiters(PCRTCRITSECT pCritSect)
4518N/A{
4518N/A return pCritSect->cLockers;
4518N/A}
4518N/A
4518N/A/** @} */
4518N/A
4518N/ART_END_DECLS
4518N/A
4518N/A#endif
4518N/A
4518N/A