term.cpp revision aa4bcf0a4b2db3ac352b56a291d49cb8d4b66d32
/* $Id$ */
/** @file
* IPRT - Common Termination Code.
*/
/*
* Copyright (C) 2009 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) 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.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <iprt/initterm.h>
#include <iprt/semaphore.h>
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/** Pointer to a termination callback record. */
typedef struct RTTERMCALLBACKREC *PRTTERMCALLBACKREC;
/**
* Termination callback record.
*/
typedef struct RTTERMCALLBACKREC
{
/** Pointer to the next record. */
/** Pointer to the callback. */
/** The user argument. */
void *pvUser;
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/** Execute once construct protecting lazy callback initialization. */
/** Mutex protecting the callback globals. */
/** Number of registered callbacks. */
static uint32_t g_cCallbacks = 0;
/** The callback head. */
/**
* Initializes the globals.
*
* @returns IPRT status code
* @param pvUser1 Ignored.
* @param pvUser2 Ignored.
*/
{
int rc;
if (RT_SUCCESS(rc))
return rc;
}
{
int rc;
/*
* Validation and lazy init.
*/
if (RT_FAILURE(rc))
return rc;
/*
* Allocate and initialize a new callback record.
*/
if (!pNew)
return VERR_NO_MEMORY;
/*
* Insert into the list.
*/
if (RT_SUCCESS(rc))
{
g_cCallbacks++;
}
else
return rc;
}
{
/*
* g_hFastMutex will be NIL if we're not initialized.
*/
int rc;
if (hFastMutex == NIL_RTSEMFASTMUTEX)
return VERR_NOT_FOUND;
if (RT_SUCCESS(rc))
{
/*
* Search for the specified pfnCallback/pvUser pair.
*/
while (pCur)
{
{
if (pPrev)
else
g_cCallbacks--;
return VINF_SUCCESS;
}
/* next */
}
rc = VERR_NOT_FOUND;
}
return rc;
}
{
|| enmReason == RTTERMREASON_ABEND
|| enmReason == RTTERMREASON_SIGNAL
|| enmReason == RTTERMREASON_UNLOAD);
/*
* Run the callback list. This is a bit paranoid in order to guard aginst
* recursive calls to RTTermRunCallbacks.
*/
while (g_hFastMutex != NIL_RTSEMFASTMUTEX)
{
int rc;
/* Unlink the head of the chain. */
if (pCur)
{
g_cCallbacks--;
}
if (!pCur)
break;
/* Copy and free it. */
/* Make the call. */
}
/*
* Free the lock.
*/
}