]>
git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseSynchronizationLib/SynchronizationGcc.c
2 Implementation of synchronization functions.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "BaseSynchronizationLibInternals.h"
13 // GCC inline assembly for Read Write Barrier
15 #define _ReadWriteBarrier() do { __asm__ __volatile__ ("": : : "memory"); } while(0)
17 #define SPIN_LOCK_RELEASED ((UINTN) 1)
18 #define SPIN_LOCK_ACQUIRED ((UINTN) 2)
21 Retrieves the architecture specific spin lock alignment requirements for
22 optimal spin lock performance.
24 This function retrieves the spin lock alignment requirements for optimal
25 performance on a given CPU architecture. The spin lock alignment is byte alignment.
26 It must be a power of two and is returned by this function. If there are no alignment
27 requirements, then 1 must be returned. The spin lock synchronization
28 functions must function correctly if the spin lock size and alignment values
29 returned by this function are not used at all. These values are hints to the
30 consumers of the spin lock synchronization functions to obtain optimal spin
33 @return The architecture specific spin lock alignment.
38 GetSpinLockProperties (
42 return InternalGetSpinLockProperties ();
46 Initializes a spin lock to the released state and returns the spin lock.
48 This function initializes the spin lock specified by SpinLock to the released
49 state, and returns SpinLock. Optimal performance can be achieved by calling
50 GetSpinLockProperties() to determine the size and alignment requirements for
53 If SpinLock is NULL, then ASSERT().
55 @param SpinLock A pointer to the spin lock to initialize to the released
58 @return SpinLock is in release state.
64 OUT SPIN_LOCK
*SpinLock
67 ASSERT (SpinLock
!= NULL
);
70 *SpinLock
= SPIN_LOCK_RELEASED
;
77 Waits until a spin lock can be placed in the acquired state.
79 This function checks the state of the spin lock specified by SpinLock. If
80 SpinLock is in the released state, then this function places SpinLock in the
81 acquired state and returns SpinLock. Otherwise, this function waits
82 indefinitely for the spin lock to be released, and then places it in the
83 acquired state and returns SpinLock. All state transitions of SpinLock must
84 be performed using MP safe mechanisms.
86 If SpinLock is NULL, then ASSERT().
87 If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().
88 If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in
89 PcdSpinLockTimeout microseconds, then ASSERT().
91 @param SpinLock A pointer to the spin lock to place in the acquired state.
93 @return SpinLock acquired the lock.
99 IN OUT SPIN_LOCK
*SpinLock
111 if (PcdGet32 (PcdSpinLockTimeout
) == 0) {
112 while (!AcquireSpinLockOrFail (SpinLock
)) {
115 } else if (!AcquireSpinLockOrFail (SpinLock
)) {
117 // Get the current timer value
119 Current
= GetPerformanceCounter ();
122 // Initialize local variables
129 // Retrieve the performance counter properties and compute the number of performance
130 // counter ticks required to reach the timeout
132 Timeout
= DivU64x32 (
134 GetPerformanceCounterProperties (&Start
, &End
),
135 PcdGet32 (PcdSpinLockTimeout
)
146 while (!AcquireSpinLockOrFail (SpinLock
)) {
149 Current
= GetPerformanceCounter ();
150 Delta
= (INT64
)(Current
- Previous
);
160 ASSERT (Total
< Timeout
);
168 Attempts to place a spin lock in the acquired state.
170 This function checks the state of the spin lock specified by SpinLock. If
171 SpinLock is in the released state, then this function places SpinLock in the
172 acquired state and returns TRUE. Otherwise, FALSE is returned. All state
173 transitions of SpinLock must be performed using MP safe mechanisms.
175 If SpinLock is NULL, then ASSERT().
176 If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().
178 @param SpinLock A pointer to the spin lock to place in the acquired state.
180 @retval TRUE SpinLock was placed in the acquired state.
181 @retval FALSE SpinLock could not be acquired.
186 AcquireSpinLockOrFail (
187 IN OUT SPIN_LOCK
*SpinLock
193 ASSERT (SpinLock
!= NULL
);
195 LockValue
= *SpinLock
;
196 ASSERT (LockValue
== SPIN_LOCK_ACQUIRED
|| LockValue
== SPIN_LOCK_RELEASED
);
198 _ReadWriteBarrier ();
199 Result
= InterlockedCompareExchangePointer (
201 (VOID
*)SPIN_LOCK_RELEASED
,
202 (VOID
*)SPIN_LOCK_ACQUIRED
205 _ReadWriteBarrier ();
206 return (BOOLEAN
)(Result
== (VOID
*)SPIN_LOCK_RELEASED
);
210 Releases a spin lock.
212 This function places the spin lock specified by SpinLock in the release state
213 and returns SpinLock.
215 If SpinLock is NULL, then ASSERT().
216 If SpinLock was not initialized with InitializeSpinLock(), then ASSERT().
218 @param SpinLock A pointer to the spin lock to release.
220 @return SpinLock released the lock.
226 IN OUT SPIN_LOCK
*SpinLock
231 ASSERT (SpinLock
!= NULL
);
233 LockValue
= *SpinLock
;
234 ASSERT (LockValue
== SPIN_LOCK_ACQUIRED
|| LockValue
== SPIN_LOCK_RELEASED
);
236 _ReadWriteBarrier ();
237 *SpinLock
= SPIN_LOCK_RELEASED
;
238 _ReadWriteBarrier ();
244 Performs an atomic increment of an 32-bit unsigned integer.
246 Performs an atomic increment of the 32-bit unsigned integer specified by
247 Value and returns the incremented value. The increment operation must be
248 performed using MP safe mechanisms.
250 If Value is NULL, then ASSERT().
252 @param Value A pointer to the 32-bit value to increment.
254 @return The incremented value.
259 InterlockedIncrement (
260 IN
volatile UINT32
*Value
263 ASSERT (Value
!= NULL
);
264 return InternalSyncIncrement (Value
);
268 Performs an atomic decrement of an 32-bit unsigned integer.
270 Performs an atomic decrement of the 32-bit unsigned integer specified by
271 Value and returns the decremented value. The decrement operation must be
272 performed using MP safe mechanisms.
274 If Value is NULL, then ASSERT().
276 @param Value A pointer to the 32-bit value to decrement.
278 @return The decremented value.
283 InterlockedDecrement (
284 IN
volatile UINT32
*Value
287 ASSERT (Value
!= NULL
);
288 return InternalSyncDecrement (Value
);
292 Performs an atomic compare exchange operation on a 16-bit unsigned integer.
294 Performs an atomic compare exchange operation on the 16-bit unsigned integer
295 specified by Value. If Value is equal to CompareValue, then Value is set to
296 ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue,
297 then Value is returned. The compare exchange operation must be performed using
300 If Value is NULL, then ASSERT().
302 @param Value A pointer to the 16-bit value for the compare exchange
304 @param CompareValue A 16-bit value used in compare operation.
305 @param ExchangeValue A 16-bit value used in exchange operation.
307 @return The original *Value before exchange.
312 InterlockedCompareExchange16 (
313 IN OUT
volatile UINT16
*Value
,
314 IN UINT16 CompareValue
,
315 IN UINT16 ExchangeValue
318 ASSERT (Value
!= NULL
);
319 return InternalSyncCompareExchange16 (Value
, CompareValue
, ExchangeValue
);
323 Performs an atomic compare exchange operation on a 32-bit unsigned integer.
325 Performs an atomic compare exchange operation on the 32-bit unsigned integer
326 specified by Value. If Value is equal to CompareValue, then Value is set to
327 ExchangeValue and CompareValue is returned. If Value is not equal to CompareValue,
328 then Value is returned. The compare exchange operation must be performed using
331 If Value is NULL, then ASSERT().
333 @param Value A pointer to the 32-bit value for the compare exchange
335 @param CompareValue A 32-bit value used in compare operation.
336 @param ExchangeValue A 32-bit value used in exchange operation.
338 @return The original *Value before exchange.
343 InterlockedCompareExchange32 (
344 IN OUT
volatile UINT32
*Value
,
345 IN UINT32 CompareValue
,
346 IN UINT32 ExchangeValue
349 ASSERT (Value
!= NULL
);
350 return InternalSyncCompareExchange32 (Value
, CompareValue
, ExchangeValue
);
354 Performs an atomic compare exchange operation on a 64-bit unsigned integer.
356 Performs an atomic compare exchange operation on the 64-bit unsigned integer specified
357 by Value. If Value is equal to CompareValue, then Value is set to ExchangeValue and
358 CompareValue is returned. If Value is not equal to CompareValue, then Value is returned.
359 The compare exchange operation must be performed using MP safe mechanisms.
361 If Value is NULL, then ASSERT().
363 @param Value A pointer to the 64-bit value for the compare exchange
365 @param CompareValue A 64-bit value used in a compare operation.
366 @param ExchangeValue A 64-bit value used in an exchange operation.
368 @return The original *Value before exchange.
373 InterlockedCompareExchange64 (
374 IN OUT
volatile UINT64
*Value
,
375 IN UINT64 CompareValue
,
376 IN UINT64 ExchangeValue
379 ASSERT (Value
!= NULL
);
380 return InternalSyncCompareExchange64 (Value
, CompareValue
, ExchangeValue
);
384 Performs an atomic compare exchange operation on a pointer value.
386 Performs an atomic compare exchange operation on the pointer value specified
387 by Value. If Value is equal to CompareValue, then Value is set to
388 ExchangeValue and CompareValue is returned. If Value is not equal to
389 CompareValue, then Value is returned. The compare exchange operation must be
390 performed using MP safe mechanisms.
392 If Value is NULL, then ASSERT().
394 @param Value A pointer to the pointer value for the compare exchange
396 @param CompareValue A pointer value used in a compare operation.
397 @param ExchangeValue A pointer value used in an exchange operation.
399 @return The original *Value before exchange.
403 InterlockedCompareExchangePointer (
404 IN OUT VOID
*volatile *Value
,
405 IN VOID
*CompareValue
,
406 IN VOID
*ExchangeValue
411 SizeOfValue
= sizeof (*Value
);
413 switch (SizeOfValue
) {
414 case sizeof (UINT32
):
415 return (VOID
*)(UINTN
)InterlockedCompareExchange32 (
416 (volatile UINT32
*)Value
,
417 (UINT32
)(UINTN
)CompareValue
,
418 (UINT32
)(UINTN
)ExchangeValue
420 case sizeof (UINT64
):
421 return (VOID
*)(UINTN
)InterlockedCompareExchange64 (
422 (volatile UINT64
*)Value
,
423 (UINT64
)(UINTN
)CompareValue
,
424 (UINT64
)(UINTN
)ExchangeValue