VirtualBox

source: vbox/trunk/src/VBox/Runtime/generic/spinlock-generic.cpp@ 2981

Last change on this file since 2981 was 2981, checked in by vboxsync, 18 years ago

InnoTek -> innotek: all the headers and comments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.6 KB
Line 
1/* $Id: spinlock-generic.cpp 2981 2007-06-01 16:01:28Z vboxsync $ */
2/** @file
3 * innotek Portable Runtime - Spinlock, generic implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 */
21
22
23/*******************************************************************************
24* Defined Constants And Macros *
25*******************************************************************************/
26/** @def RT_CFG_SPINLOCK_GENERIC_DO_SLEEP
27 * Force cpu yields after spinning the number of times indicated by the define.
28 * If 0 we will spin forever. */
29#define RT_CFG_SPINLOCK_GENERIC_DO_SLEEP 100000
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include <iprt/spinlock.h>
36#include <iprt/alloc.h>
37#include <iprt/asm.h>
38#include <iprt/err.h>
39#include <iprt/assert.h>
40#if RT_CFG_SPINLOCK_GENERIC_DO_SLEEP
41# include <iprt/thread.h>
42#endif
43
44#include "internal/magics.h"
45
46
47/*******************************************************************************
48* Structures and Typedefs *
49*******************************************************************************/
50/**
51 * Generic spinlock structure.
52 */
53typedef struct RTSPINLOCKINTERNAL
54{
55 /** Spinlock magic value (RTSPINLOCK_MAGIC). */
56 uint32_t u32Magic;
57 /** The spinlock. */
58 uint32_t volatile fLocked;
59} RTSPINLOCKINTERNAL, *PRTSPINLOCKINTERNAL;
60
61
62RTDECL(int) RTSpinlockCreate(PRTSPINLOCK pSpinlock)
63{
64 /*
65 * Allocate.
66 */
67 PRTSPINLOCKINTERNAL pSpinlockInt;
68 pSpinlockInt = (PRTSPINLOCKINTERNAL)RTMemAlloc(sizeof(*pSpinlockInt));
69 if (!pSpinlockInt)
70 return VERR_NO_MEMORY;
71
72 /*
73 * Initialize and return.
74 */
75 pSpinlockInt->u32Magic = RTSPINLOCK_MAGIC;
76 ASMAtomicXchgU32(&pSpinlockInt->fLocked, 0);
77
78 *pSpinlock = pSpinlockInt;
79 return VINF_SUCCESS;
80}
81
82
83RTDECL(int) RTSpinlockDestroy(RTSPINLOCK Spinlock)
84{
85 /*
86 * Validate input.
87 */
88 PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
89 if (!pSpinlockInt)
90 return VERR_INVALID_PARAMETER;
91 if (pSpinlockInt->u32Magic != RTSPINLOCK_MAGIC)
92 {
93 AssertMsgFailed(("Invalid spinlock %p magic=%#x\n", pSpinlockInt, pSpinlockInt->u32Magic));
94 return VERR_INVALID_PARAMETER;
95 }
96
97 ASMAtomicIncU32(&pSpinlockInt->u32Magic);
98 RTMemFree(pSpinlockInt);
99 return VINF_SUCCESS;
100}
101
102
103RTDECL(void) RTSpinlockAcquireNoInts(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
104{
105 PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
106 AssertMsg(pSpinlockInt && pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC,
107 ("pSpinlockInt=%p u32Magic=%08x\n", pSpinlockInt, pSpinlockInt ? (int)pSpinlockInt->u32Magic : 0));
108
109 pTmp->uFlags = ASMGetFlags();
110#if RT_CFG_SPINLOCK_GENERIC_DO_SLEEP
111 for (;;)
112 {
113 ASMIntDisable();
114 for (int c = RT_CFG_SPINLOCK_GENERIC_DO_SLEEP; c > 0; c--)
115 if (ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 1, 0))
116 return;
117 RTThreadYield();
118 }
119#else
120 ASMIntDisable();
121 while (!ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 1, 0))
122 /*nothing */;
123#endif
124}
125
126
127RTDECL(void) RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
128{
129 PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
130 AssertMsg(pSpinlockInt && pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC,
131 ("pSpinlockInt=%p u32Magic=%08x\n", pSpinlockInt, pSpinlockInt ? (int)pSpinlockInt->u32Magic : 0));
132 NOREF(pSpinlockInt);
133
134 if (!ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 0, 1))
135 AssertMsgFailed(("Spinlock %p was not locked!\n", pSpinlockInt));
136 ASMSetFlags(pTmp->uFlags);
137}
138
139
140RTDECL(void) RTSpinlockAcquire(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
141{
142 PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
143 AssertMsg(pSpinlockInt && pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC,
144 ("pSpinlockInt=%p u32Magic=%08x\n", pSpinlockInt, pSpinlockInt ? (int)pSpinlockInt->u32Magic : 0));
145 NOREF(pTmp);
146
147#if RT_CFG_SPINLOCK_GENERIC_DO_SLEEP
148 for (;;)
149 {
150 for (int c = RT_CFG_SPINLOCK_GENERIC_DO_SLEEP; c > 0; c--)
151 if (ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 1, 0))
152 return;
153 RTThreadYield();
154 }
155#else
156 while (!ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 1, 0))
157 /*nothing */;
158#endif
159}
160
161
162RTDECL(void) RTSpinlockRelease(RTSPINLOCK Spinlock, PRTSPINLOCKTMP pTmp)
163{
164 PRTSPINLOCKINTERNAL pSpinlockInt = (PRTSPINLOCKINTERNAL)Spinlock;
165 AssertMsg(pSpinlockInt && pSpinlockInt->u32Magic == RTSPINLOCK_MAGIC,
166 ("pSpinlockInt=%p u32Magic=%08x\n", pSpinlockInt, pSpinlockInt ? (int)pSpinlockInt->u32Magic : 0));
167 NOREF(pTmp);
168
169 if (!ASMAtomicCmpXchgU32(&pSpinlockInt->fLocked, 0, 1))
170 AssertMsgFailed(("Spinlock %p was not locked!\n", pSpinlockInt));
171}
172
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