28
28
* additional information or have any questions.
31
32
/*******************************************************************************
33
34
*******************************************************************************/
34
35
#include <iprt/mp.h>
36
#include "internal/iprt.h"
35
38
#include <iprt/asm.h>
36
39
#include <iprt/assert.h>
37
40
#include <iprt/err.h>
38
41
#include <iprt/mem.h>
39
42
#include <iprt/spinlock.h>
40
43
#include <iprt/string.h>
44
#include <iprt/thread.h>
41
45
#include "r0drv/mp-r0drv.h"
76
80
* This is increased whenever the list has been modified. The callback routine
77
81
* make use of this to avoid having restart at the list head after each callback. */
78
82
static uint32_t volatile g_iRTMpGeneration;
79
/** The number of RTMpNotification users.
80
* This is incremented on init and decremented on termination. */
81
static uint32_t volatile g_cRTMpUsers = 0;
162
163
RTDECL(int) RTMpNotificationRegister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser)
167
RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
171
172
AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
172
173
AssertReturn(g_hRTMpNotifySpinLock != NIL_RTSPINLOCK, VERR_WRONG_ORDER);
174
RT_ASSERT_PREEMPTIBLE();
174
176
RTSpinlockAcquire(g_hRTMpNotifySpinLock, &Tmp);
175
177
for (pCur = g_pRTMpCallbackHead; pCur; pCur = pCur->pNext)
224
226
return VINF_SUCCESS;
228
RT_EXPORT_SYMBOL(RTMpNotificationRegister);
229
231
RTDECL(int) RTMpNotificationDeregister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser)
231
PRTMPNOTIFYREG pPrev;
233
PRTMPNOTIFYREG pPrev;
235
RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
238
240
AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER);
239
241
AssertReturn(g_hRTMpNotifySpinLock != NIL_RTSPINLOCK, VERR_WRONG_ORDER);
242
245
* Find and unlink the record from the list.
273
276
return VINF_SUCCESS;
278
RT_EXPORT_SYMBOL(RTMpNotificationDeregister);
277
281
int rtR0MpNotificationInit(void)
279
int rc = VINF_SUCCESS;
281
if (ASMAtomicIncS32(&g_cRTMpUsers) == 1)
283
int rc = RTSpinlockCreate((PRTSPINLOCK)&g_hRTMpNotifySpinLock);
283
rc = RTSpinlockCreate((PRTSPINLOCK)&g_hRTMpNotifySpinLock);
286
rc = rtR0MpNotificationNativeInit();
284
287
if (RT_SUCCESS(rc))
286
rc = rtR0MpNotificationNativeInit();
290
RTSpinlockDestroy(g_hRTMpNotifySpinLock);
291
g_hRTMpNotifySpinLock = NIL_RTSPINLOCK;
293
ASMAtomicDecS32(&g_cRTMpUsers);
290
RTSpinlockDestroy(g_hRTMpNotifySpinLock);
291
g_hRTMpNotifySpinLock = NIL_RTSPINLOCK;
299
297
void rtR0MpNotificationTerm(void)
301
RTSPINLOCK hSpinlock = g_hRTMpNotifySpinLock;
302
if (hSpinlock != NIL_RTSPINLOCK)
299
PRTMPNOTIFYREG pHead;
300
RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER;
301
RTSPINLOCK hSpinlock = g_hRTMpNotifySpinLock;
302
AssertReturnVoid(hSpinlock != NIL_RTSPINLOCK);
304
rtR0MpNotificationNativeTerm();
306
/* pick up the list and the spinlock. */
307
RTSpinlockAcquire(hSpinlock, &Tmp);
308
ASMAtomicWriteSize(&g_hRTMpNotifySpinLock, NIL_RTSPINLOCK);
309
pHead = g_pRTMpCallbackHead;
310
g_pRTMpCallbackHead = NULL;
311
ASMAtomicIncU32(&g_iRTMpGeneration);
312
RTSpinlockRelease(hSpinlock, &Tmp);
304
AssertMsg(g_cRTMpUsers > 0, ("%d\n", g_cRTMpUsers));
305
if (ASMAtomicDecS32(&g_cRTMpUsers) == 0)
308
PRTMPNOTIFYREG pHead;
311
rtR0MpNotificationNativeTerm();
313
/* pick up the list and the spinlock. */
314
RTSpinlockAcquire(hSpinlock, &Tmp);
315
ASMAtomicWriteSize(&g_hRTMpNotifySpinLock, NIL_RTSPINLOCK);
316
pHead = g_pRTMpCallbackHead;
317
g_pRTMpCallbackHead = NULL;
318
ASMAtomicIncU32(&g_iRTMpGeneration);
319
RTSpinlockRelease(hSpinlock, &Tmp);
324
PRTMPNOTIFYREG pFree = pHead;
325
pHead = pHead->pNext;
328
pFree->pfnCallback = NULL;
332
RTSpinlockDestroy(hSpinlock);
317
PRTMPNOTIFYREG pFree = pHead;
318
pHead = pHead->pNext;
321
pFree->pfnCallback = NULL;
325
RTSpinlockDestroy(hSpinlock);