]>
git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseLib/Synchronization.c
2 Implementation of synchronization functions.
4 Copyright (c) 2006, Intel Corporation<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 Module Name: Synchronization.c
17 #define SPIN_LOCK_RELEASED ((SPIN_LOCK)1)
18 #define SPIN_LOCK_ACQUIRED ((SPIN_LOCK)2)
21 Performs an atomic increment of an 32-bit unsigned integer.
23 Performs an atomic increment of the 32-bit unsigned integer specified by
24 Value and returns the incremented value. The increment operation must be
25 performed using MP safe mechanisms. The state of the return value is not
26 guaranteed to be MP safe.
28 @param Value A pointer to the 32-bit value to increment.
30 @return The incremented value.
35 InternalSyncIncrement (
36 IN
volatile UINT32
*Value
40 Performs an atomic decrement of an 32-bit unsigned integer.
42 Performs an atomic decrement of the 32-bit unsigned integer specified by
43 Value and returns the decrement value. The decrement operation must be
44 performed using MP safe mechanisms. The state of the return value is not
45 guaranteed to be MP safe.
47 @param Value A pointer to the 32-bit value to decrement.
49 @return The decrement value.
54 InternalSyncDecrement (
55 IN
volatile UINT32
*Value
59 Performs an atomic compare exchange operation on a 32-bit unsigned integer.
61 Performs an atomic compare exchange operation on the 32-bit unsigned integer
62 specified by Value. If Value is equal to CompareValue, then Value is set to
63 ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue,
64 then Value is returned. The compare exchange operation must be performed using
67 @param Value A pointer to the 32-bit value for the compare exchange
69 @param CompareValue 32-bit value used in compare operation.
70 @param ExchangeValue 32-bit value used in exchange operation.
72 @return The original *Value before exchange.
77 InternalSyncCompareExchange32 (
78 IN
volatile UINT32
*Value
,
79 IN UINT32 CompareValue
,
80 IN UINT32 ExchangeValue
84 Performs an atomic compare exchange operation on a 64-bit unsigned integer.
86 Performs an atomic compare exchange operation on the 64-bit unsigned integer specified
87 by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and
88 CompareValue is returned. If Value is not equal to CompareValue, then Value is returned.
89 The compare exchange operation must be performed using MP safe mechanisms.
91 @param Value A pointer to the 64-bit value for the compare exchange
93 @param CompareValue 64-bit value used in compare operation.
94 @param ExchangeValue 64-bit value used in exchange operation.
96 @return The original *Value before exchange.
101 InternalSyncCompareExchange64 (
102 IN
volatile UINT64
*Value
,
103 IN UINT64 CompareValue
,
104 IN UINT64 ExchangeValue
108 Retrieves the architecture specific spin lock alignment requirements for
109 optimal spin lock performance.
111 This function retrieves the spin lock alignment requirements for optimal
112 performance on a given CPU architecture. The spin lock alignment must be a
113 power of two and is returned by this function. If there are no alignment
114 requirements, then 1 must be returned. The spin lock synchronization
115 functions must function correctly if the spin lock size and alignment values
116 returned by this function are not used at all. These values are hints to the
117 consumers of the spin lock synchronization functions to obtain optimal spin
120 @return The architecture specific spin lock alignment.
125 GetSpinLockProperties (
129 // @bug May use a PCD entry to determine this alignment.
134 Initializes a spin lock to the released state and returns the spin lock.
136 This function initializes the spin lock specified by SpinLock to the released
137 state, and returns SpinLock. Optimal performance can be achieved by calling
138 GetSpinLockProperties() to determine the size and alignment requirements for
141 If SpinLock is NULL, then ASSERT().
143 @param SpinLock A pointer to the spin lock to initialize to the released
152 OUT SPIN_LOCK
*SpinLock
155 ASSERT (SpinLock
!= NULL
);
156 *SpinLock
= SPIN_LOCK_RELEASED
;
161 Waits until a spin lock can be placed in the acquired state.
163 This function checks the state of the spin lock specified by SpinLock. If
164 SpinLock is in the released state, then this function places SpinLock in the
165 acquired state and returns SpinLock. Otherwise, this function waits
166 indefinitely for the spin lock to be released, and then places it in the
167 acquired state and returns SpinLock. All state transitions of SpinLock must
168 be performed using MP safe mechanisms.
170 If SpinLock is NULL, then ASSERT().
171 If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().
172 If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in
173 PcdSpinLockTimeout microseconds, then ASSERT().
175 @param SpinLock A pointer to the spin lock to place in the acquired state.
183 IN OUT SPIN_LOCK
*SpinLock
193 if (PcdGet32 (PcdSpinLockTimeout
) > 0) {
194 Tick
= GetPerformanceCounter ();
195 Timeout
= DivU64x32 (
197 GetPerformanceCounterProperties (&Start
, &End
),
198 PcdGet32 (PcdSpinLockTimeout
)
209 while (!AcquireSpinLockOrFail (SpinLock
)) {
211 ASSERT ((Start
< End
) ^ (Tick
<= GetPerformanceCounter ()));
217 Attempts to place a spin lock in the acquired state.
219 This function checks the state of the spin lock specified by SpinLock. If
220 SpinLock is in the released state, then this function places SpinLock in the
221 acquired state and returns TRUE. Otherwise, FALSE is returned. All state
222 transitions of SpinLock must be performed using MP safe mechanisms.
224 If SpinLock is NULL, then ASSERT().
225 If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().
227 @param SpinLock A pointer to the spin lock to place in the acquired state.
229 @retval TRUE SpinLock was placed in the acquired state.
230 @retval FALSE SpinLock could not be acquired.
235 AcquireSpinLockOrFail (
236 IN OUT SPIN_LOCK
*SpinLock
239 ASSERT (SpinLock
!= NULL
);
240 ASSERT (*SpinLock
== SPIN_LOCK_ACQUIRED
|| *SpinLock
== SPIN_LOCK_RELEASED
);
242 InterlockedCompareExchangePointer (
244 (VOID
*)SPIN_LOCK_RELEASED
,
245 (VOID
*)SPIN_LOCK_ACQUIRED
246 ) == (VOID
*)SPIN_LOCK_RELEASED
251 Releases a spin lock.
253 This function places the spin lock specified by SpinLock in the release state
254 and returns SpinLock.
256 If SpinLock is NULL, then ASSERT().
257 If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().
259 @param SpinLock A pointer to the spin lock to release.
267 IN OUT SPIN_LOCK
*SpinLock
270 ASSERT (SpinLock
!= NULL
);
271 ASSERT (*SpinLock
== SPIN_LOCK_ACQUIRED
|| *SpinLock
== SPIN_LOCK_RELEASED
);
272 *SpinLock
= SPIN_LOCK_RELEASED
;
277 Performs an atomic increment of an 32-bit unsigned integer.
279 Performs an atomic increment of the 32-bit unsigned integer specified by
280 Value and returns the incremented value. The increment operation must be
281 performed using MP safe mechanisms. The state of the return value is not
282 guaranteed to be MP safe.
284 If Value is NULL, then ASSERT().
286 @param Value A pointer to the 32-bit value to increment.
288 @return The incremented value.
293 InterlockedIncrement (
297 ASSERT (Value
!= NULL
);
298 return InternalSyncIncrement (Value
);
302 Performs an atomic decrement of an 32-bit unsigned integer.
304 Performs an atomic decrement of the 32-bit unsigned integer specified by
305 Value and returns the decremented value. The decrement operation must be
306 performed using MP safe mechanisms. The state of the return value is not
307 guaranteed to be MP safe.
309 If Value is NULL, then ASSERT().
311 @param Value A pointer to the 32-bit value to decrement.
313 @return The decremented value.
318 InterlockedDecrement (
322 ASSERT (Value
!= NULL
);
323 return InternalSyncDecrement (Value
);
327 Performs an atomic compare exchange operation on a 32-bit unsigned integer.
329 Performs an atomic compare exchange operation on the 32-bit unsigned integer
330 specified by Value. If Value is equal to CompareValue, then Value is set to
331 ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue,
332 then Value is returned. The compare exchange operation must be performed using
335 If Value is NULL, then ASSERT().
337 @param Value A pointer to the 32-bit value for the compare exchange
339 @param CompareValue 32-bit value used in compare operation.
340 @param ExchangeValue 32-bit value used in exchange operation.
342 @return The original *Value before exchange.
347 InterlockedCompareExchange32 (
348 IN OUT UINT32
*Value
,
349 IN UINT32 CompareValue
,
350 IN UINT32 ExchangeValue
353 ASSERT (Value
!= NULL
);
354 return InternalSyncCompareExchange32 (Value
, CompareValue
, ExchangeValue
);
358 Performs an atomic compare exchange operation on a 64-bit unsigned integer.
360 Performs an atomic compare exchange operation on the 64-bit unsigned integer specified
361 by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and
362 CompareValue is returned. If Value is not equal to CompareValue, then Value is returned.
363 The compare exchange operation must be performed using MP safe mechanisms.
365 If Value is NULL, then ASSERT().
367 @param Value A pointer to the 64-bit value for the compare exchange
369 @param CompareValue 64-bit value used in compare operation.
370 @param ExchangeValue 64-bit value used in exchange operation.
372 @return The original *Value before exchange.
377 InterlockedCompareExchange64 (
378 IN OUT UINT64
*Value
,
379 IN UINT64 CompareValue
,
380 IN UINT64 ExchangeValue
383 ASSERT (Value
!= NULL
);
384 return InternalSyncCompareExchange64 (Value
, CompareValue
, ExchangeValue
);
388 Performs an atomic compare exchange operation on a pointer value.
390 Performs an atomic compare exchange operation on the pointer value specified
391 by Value. If Value is equal to CompareValue, then Value is set to
392 ExchangeValue and CompareValue is returned. If Value is not equal to
393 CompareValue, then Value is returned. The compare exchange operation must be
394 performed using MP safe mechanisms.
396 If Value is NULL, then ASSERT().
398 @param Value A pointer to the pointer value for the compare exchange
400 @param CompareValue Pointer value used in compare operation.
401 @param ExchangeValue Pointer value used in exchange operation.
406 InterlockedCompareExchangePointer (
408 IN VOID
*CompareValue
,
409 IN VOID
*ExchangeValue
412 switch (sizeof (*Value
)) {
413 case sizeof (UINT32
):
414 return (VOID
*)(UINTN
)InterlockedCompareExchange32 (
416 (UINT32
)(UINTN
)CompareValue
,
417 (UINT32
)(UINTN
)ExchangeValue
419 case sizeof (UINT64
):
420 return (VOID
*)(UINTN
)InterlockedCompareExchange64 (
422 (UINT64
)(UINTN
)CompareValue
,
423 (UINT64
)(UINTN
)ExchangeValue