VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/misc/term.cpp@ 49329

Last change on this file since 49329 was 44529, checked in by vboxsync, 12 years ago

header (C) fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.8 KB
Line 
1/* $Id: term.cpp 44529 2013-02-04 15:54:15Z vboxsync $ */
2/** @file
3 * IPRT - Common Termination Code.
4 */
5
6/*
7 * Copyright (C) 2009-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#include <iprt/initterm.h>
31#include "internal/iprt.h"
32
33#include <iprt/asm.h>
34#include <iprt/assert.h>
35#include <iprt/err.h>
36#include <iprt/mem.h>
37#include <iprt/once.h>
38#include <iprt/semaphore.h>
39#include <iprt/thread.h>
40
41
42/*******************************************************************************
43* Structures and Typedefs *
44*******************************************************************************/
45/** Pointer to a termination callback record. */
46typedef struct RTTERMCALLBACKREC *PRTTERMCALLBACKREC;
47/**
48 * Termination callback record.
49 */
50typedef struct RTTERMCALLBACKREC
51{
52 /** Pointer to the next record. */
53 PRTTERMCALLBACKREC pNext;
54 /** Pointer to the callback. */
55 PFNRTTERMCALLBACK pfnCallback;
56 /** The user argument. */
57 void *pvUser;
58} RTTERMCALLBACKREC;
59
60
61/*******************************************************************************
62* Global Variables *
63*******************************************************************************/
64/** Execute once construct protecting lazy callback initialization. */
65static RTONCE g_InitTermCallbacksOnce = RTONCE_INITIALIZER;
66/** Mutex protecting the callback globals. */
67static RTSEMFASTMUTEX g_hFastMutex = NIL_RTSEMFASTMUTEX;
68/** Number of registered callbacks. */
69static uint32_t g_cCallbacks = 0;
70/** The callback head. */
71static PRTTERMCALLBACKREC g_pCallbackHead = NULL;
72
73
74
75/**
76 * Initializes the globals.
77 *
78 * @returns IPRT status code
79 * @param pvUser Ignored.
80 */
81static DECLCALLBACK(int32_t) rtTermInitOnce(void *pvUser)
82{
83 RTSEMFASTMUTEX hFastMutex;
84 int rc;
85
86 Assert(!g_cCallbacks);
87 Assert(!g_pCallbackHead);
88 Assert(g_hFastMutex == NIL_RTSEMFASTMUTEX);
89
90 rc = RTSemFastMutexCreate(&hFastMutex);
91 if (RT_SUCCESS(rc))
92 g_hFastMutex = hFastMutex;
93
94 NOREF(pvUser);
95
96 return rc;
97}
98
99
100
101RTDECL(int) RTTermRegisterCallback(PFNRTTERMCALLBACK pfnCallback, void *pvUser)
102{
103 int rc;
104 PRTTERMCALLBACKREC pNew;
105
106 /*
107 * Validation and lazy init.
108 */
109 AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
110
111 rc = RTOnce(&g_InitTermCallbacksOnce, rtTermInitOnce, NULL);
112 if (RT_FAILURE(rc))
113 return rc;
114
115 /*
116 * Allocate and initialize a new callback record.
117 */
118 pNew = (PRTTERMCALLBACKREC)RTMemAlloc(sizeof(*pNew));
119 if (!pNew)
120 return VERR_NO_MEMORY;
121 pNew->pfnCallback = pfnCallback;
122 pNew->pvUser = pvUser;
123
124 /*
125 * Insert into the list.
126 */
127 rc = RTSemFastMutexRequest(g_hFastMutex);
128 if (RT_SUCCESS(rc))
129 {
130 g_cCallbacks++;
131 pNew->pNext = g_pCallbackHead;
132 g_pCallbackHead = pNew;
133
134 RTSemFastMutexRelease(g_hFastMutex);
135 }
136 else
137 RTMemFree(pNew);
138
139 return rc;
140}
141RT_EXPORT_SYMBOL(RTTermRegisterCallback);
142
143
144RTDECL(int) RTTermDeregisterCallback(PFNRTTERMCALLBACK pfnCallback, void *pvUser)
145{
146 /*
147 * g_hFastMutex will be NIL if we're not initialized.
148 */
149 int rc;
150 RTSEMFASTMUTEX hFastMutex = g_hFastMutex;
151 if (hFastMutex == NIL_RTSEMFASTMUTEX)
152 return VERR_NOT_FOUND;
153
154 rc = RTSemFastMutexRequest(hFastMutex);
155 if (RT_SUCCESS(rc))
156 {
157
158 /*
159 * Search for the specified pfnCallback/pvUser pair.
160 */
161 PRTTERMCALLBACKREC pPrev = NULL;
162 PRTTERMCALLBACKREC pCur = g_pCallbackHead;
163 while (pCur)
164 {
165 if ( pCur->pfnCallback == pfnCallback
166 && pCur->pvUser == pvUser)
167 {
168 if (pPrev)
169 pPrev->pNext = pCur->pNext;
170 else
171 g_pCallbackHead = pCur->pNext;
172 g_cCallbacks--;
173 RTSemFastMutexRelease(hFastMutex);
174
175 pCur->pfnCallback = NULL;
176 RTMemFree(pCur);
177 return VINF_SUCCESS;
178 }
179
180 /* next */
181 pPrev = pCur;
182 pCur = pCur->pNext;
183 }
184
185 RTSemFastMutexRelease(hFastMutex);
186 rc = VERR_NOT_FOUND;
187 }
188
189 return rc;
190}
191RT_EXPORT_SYMBOL(RTTermDeregisterCallback);
192
193
194RTDECL(void) RTTermRunCallbacks(RTTERMREASON enmReason, int32_t iStatus)
195{
196 RTSEMFASTMUTEX hFastMutex;
197 Assert( enmReason == RTTERMREASON_EXIT
198 || enmReason == RTTERMREASON_ABEND
199 || enmReason == RTTERMREASON_SIGNAL
200 || enmReason == RTTERMREASON_UNLOAD);
201
202 /*
203 * Run the callback list. This is a bit paranoid in order to guard against
204 * recursive calls to RTTermRunCallbacks.
205 */
206 while (g_hFastMutex != NIL_RTSEMFASTMUTEX)
207 {
208 PRTTERMCALLBACKREC pCur;
209 RTTERMCALLBACKREC CurCopy;
210 int rc;
211
212 /* Unlink the head of the chain. */
213 rc = RTSemFastMutexRequest(g_hFastMutex);
214 AssertRCReturnVoid(rc);
215 pCur = g_pCallbackHead;
216 if (pCur)
217 {
218 g_pCallbackHead = pCur->pNext;
219 g_cCallbacks--;
220 }
221 RTSemFastMutexRelease(g_hFastMutex);
222 if (!pCur)
223 break;
224
225 /* Copy and free it. */
226 CurCopy = *pCur;
227 RTMemFree(pCur);
228
229 /* Make the call. */
230 CurCopy.pfnCallback(enmReason, iStatus, CurCopy.pvUser);
231 }
232
233 /*
234 * Free the lock.
235 */
236 ASMAtomicXchgHandle(&g_hFastMutex, NIL_RTSEMFASTMUTEX, &hFastMutex);
237 RTSemFastMutexDestroy(hFastMutex);
238 RTOnceReset(&g_InitTermCallbacksOnce); /* for the testcase */
239}
240RT_EXPORT_SYMBOL(RTTermRunCallbacks);
241
Note: See TracBrowser for help on using the repository browser.

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