b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/* $Id$ */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/** @file
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * IPRT - Common Termination Code.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2009-2012 Oracle Corporation
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync *
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * available from http://www.virtualbox.org. This file is free software;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * General Public License (GPL) as published by the Free Software
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync *
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * The contents of this file may alternatively be used under the terms
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * of the Common Development and Distribution License Version 1.0
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * VirtualBox OSE distribution, in which case the provisions of the
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * CDDL are applicable instead of those of the GPL.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync *
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * You may elect to license modified versions of this file under the
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * terms and conditions of either the GPL or the CDDL or both.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/*******************************************************************************
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync* Header Files *
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync*******************************************************************************/
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <iprt/initterm.h>
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync#include "internal/iprt.h"
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <iprt/asm.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <iprt/assert.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <iprt/err.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <iprt/mem.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <iprt/once.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <iprt/semaphore.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync#include <iprt/thread.h>
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/*******************************************************************************
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync* Structures and Typedefs *
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync*******************************************************************************/
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/** Pointer to a termination callback record. */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsynctypedef struct RTTERMCALLBACKREC *PRTTERMCALLBACKREC;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/**
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Termination callback record.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsynctypedef struct RTTERMCALLBACKREC
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync{
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /** Pointer to the next record. */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync PRTTERMCALLBACKREC pNext;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /** Pointer to the callback. */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync PFNRTTERMCALLBACK pfnCallback;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /** The user argument. */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync void *pvUser;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync} RTTERMCALLBACKREC;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/*******************************************************************************
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync* Global Variables *
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync*******************************************************************************/
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/** Execute once construct protecting lazy callback initialization. */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsyncstatic RTONCE g_InitTermCallbacksOnce = RTONCE_INITIALIZER;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/** Mutex protecting the callback globals. */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsyncstatic RTSEMFASTMUTEX g_hFastMutex = NIL_RTSEMFASTMUTEX;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/** Number of registered callbacks. */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsyncstatic uint32_t g_cCallbacks = 0;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/** The callback head. */
210e87cc03f92d54681b81a81cc1fdbd48a9d2c8vboxsyncstatic PRTTERMCALLBACKREC g_pCallbackHead = NULL;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync/**
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Initializes the globals.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync *
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * @returns IPRT status code
a438caaf732f7839dc66b4f8dad672527845a003vboxsync * @param pvUser Ignored.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
a438caaf732f7839dc66b4f8dad672527845a003vboxsyncstatic DECLCALLBACK(int32_t) rtTermInitOnce(void *pvUser)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync{
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTSEMFASTMUTEX hFastMutex;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync int rc;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Assert(!g_cCallbacks);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Assert(!g_pCallbackHead);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Assert(g_hFastMutex == NIL_RTSEMFASTMUTEX);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync rc = RTSemFastMutexCreate(&hFastMutex);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (RT_SUCCESS(rc))
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync g_hFastMutex = hFastMutex;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
a438caaf732f7839dc66b4f8dad672527845a003vboxsync NOREF(pvUser);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return rc;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync}
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsyncRTDECL(int) RTTermRegisterCallback(PFNRTTERMCALLBACK pfnCallback, void *pvUser)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync{
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync int rc;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync PRTTERMCALLBACKREC pNew;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /*
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Validation and lazy init.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
a438caaf732f7839dc66b4f8dad672527845a003vboxsync rc = RTOnce(&g_InitTermCallbacksOnce, rtTermInitOnce, NULL);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (RT_FAILURE(rc))
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return rc;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /*
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Allocate and initialize a new callback record.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pNew = (PRTTERMCALLBACKREC)RTMemAlloc(sizeof(*pNew));
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (!pNew)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return VERR_NO_MEMORY;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pNew->pfnCallback = pfnCallback;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pNew->pvUser = pvUser;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /*
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Insert into the list.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync rc = RTSemFastMutexRequest(g_hFastMutex);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (RT_SUCCESS(rc))
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync g_cCallbacks++;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pNew->pNext = g_pCallbackHead;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync g_pCallbackHead = pNew;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTSemFastMutexRelease(g_hFastMutex);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync else
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTMemFree(pNew);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return rc;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync}
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncRT_EXPORT_SYMBOL(RTTermRegisterCallback);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsyncRTDECL(int) RTTermDeregisterCallback(PFNRTTERMCALLBACK pfnCallback, void *pvUser)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync{
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /*
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * g_hFastMutex will be NIL if we're not initialized.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync int rc;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTSEMFASTMUTEX hFastMutex = g_hFastMutex;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (hFastMutex == NIL_RTSEMFASTMUTEX)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return VERR_NOT_FOUND;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync rc = RTSemFastMutexRequest(hFastMutex);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (RT_SUCCESS(rc))
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /*
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Search for the specified pfnCallback/pvUser pair.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
210e87cc03f92d54681b81a81cc1fdbd48a9d2c8vboxsync PRTTERMCALLBACKREC pPrev = NULL;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync PRTTERMCALLBACKREC pCur = g_pCallbackHead;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync while (pCur)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if ( pCur->pfnCallback == pfnCallback
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync && pCur->pvUser == pvUser)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (pPrev)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pPrev->pNext = pCur->pNext;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync else
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync g_pCallbackHead = pCur->pNext;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync g_cCallbacks--;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTSemFastMutexRelease(hFastMutex);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
210e87cc03f92d54681b81a81cc1fdbd48a9d2c8vboxsync pCur->pfnCallback = NULL;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTMemFree(pCur);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return VINF_SUCCESS;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /* next */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pPrev = pCur;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pCur = pCur->pNext;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTSemFastMutexRelease(hFastMutex);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync rc = VERR_NOT_FOUND;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync return rc;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync}
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncRT_EXPORT_SYMBOL(RTTermDeregisterCallback);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsyncRTDECL(void) RTTermRunCallbacks(RTTERMREASON enmReason, int32_t iStatus)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync{
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTSEMFASTMUTEX hFastMutex;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync Assert( enmReason == RTTERMREASON_EXIT
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync || enmReason == RTTERMREASON_ABEND
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync || enmReason == RTTERMREASON_SIGNAL
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync || enmReason == RTTERMREASON_UNLOAD);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /*
ad27e1d5e48ca41245120c331cc88b50464813cevboxsync * Run the callback list. This is a bit paranoid in order to guard against
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * recursive calls to RTTermRunCallbacks.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync while (g_hFastMutex != NIL_RTSEMFASTMUTEX)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync PRTTERMCALLBACKREC pCur;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTTERMCALLBACKREC CurCopy;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync int rc;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /* Unlink the head of the chain. */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync rc = RTSemFastMutexRequest(g_hFastMutex);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync AssertRCReturnVoid(rc);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync pCur = g_pCallbackHead;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (pCur)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync {
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync g_pCallbackHead = pCur->pNext;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync g_cCallbacks--;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTSemFastMutexRelease(g_hFastMutex);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync if (!pCur)
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync break;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /* Copy and free it. */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync CurCopy = *pCur;
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTMemFree(pCur);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /* Make the call. */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync CurCopy.pfnCallback(enmReason, iStatus, CurCopy.pvUser);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync }
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync /*
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync * Free the lock.
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync ASMAtomicXchgHandle(&g_hFastMutex, NIL_RTSEMFASTMUTEX, &hFastMutex);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTSemFastMutexDestroy(hFastMutex);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync RTOnceReset(&g_InitTermCallbacksOnce); /* for the testcase */
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync}
aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32vboxsyncRT_EXPORT_SYMBOL(RTTermRunCallbacks);
b9fc40283b616e122f07c8f48b0bf9c6afc3fab2vboxsync