TianoCore EDK2 master
Loading...
Searching...
No Matches
SynchronizationGcc.c
Go to the documentation of this file.
1
11
12//
13// GCC inline assembly for Read Write Barrier
14//
15#define _ReadWriteBarrier() do { __asm__ __volatile__ ("": : : "memory"); } while(0)
16
17#define SPIN_LOCK_RELEASED ((UINTN) 1)
18#define SPIN_LOCK_ACQUIRED ((UINTN) 2)
19
37EFIAPI
39 VOID
40 )
41{
43}
44
62EFIAPI
64 OUT SPIN_LOCK *SpinLock
65 )
66{
67 ASSERT (SpinLock != NULL);
68
69 _ReadWriteBarrier ();
70 *SpinLock = SPIN_LOCK_RELEASED;
71 _ReadWriteBarrier ();
72
73 return SpinLock;
74}
75
97EFIAPI
99 IN OUT SPIN_LOCK *SpinLock
100 )
101{
102 UINT64 Current;
103 UINT64 Previous;
104 UINT64 Total;
105 UINT64 Start;
106 UINT64 End;
107 UINT64 Timeout;
108 INT64 Cycle;
109 INT64 Delta;
110
111 if (PcdGet32 (PcdSpinLockTimeout) == 0) {
112 while (!AcquireSpinLockOrFail (SpinLock)) {
113 CpuPause ();
114 }
115 } else if (!AcquireSpinLockOrFail (SpinLock)) {
116 //
117 // Get the current timer value
118 //
119 Current = GetPerformanceCounter ();
120
121 //
122 // Initialize local variables
123 //
124 Start = 0;
125 End = 0;
126 Total = 0;
127
128 //
129 // Retrieve the performance counter properties and compute the number of performance
130 // counter ticks required to reach the timeout
131 //
132 Timeout = DivU64x32 (
133 MultU64x32 (
134 GetPerformanceCounterProperties (&Start, &End),
135 PcdGet32 (PcdSpinLockTimeout)
136 ),
137 1000000
138 );
139 Cycle = End - Start;
140 if (Cycle < 0) {
141 Cycle = -Cycle;
142 }
143
144 Cycle++;
145
146 while (!AcquireSpinLockOrFail (SpinLock)) {
147 CpuPause ();
148 Previous = Current;
149 Current = GetPerformanceCounter ();
150 Delta = (INT64)(Current - Previous);
151 if (Start > End) {
152 Delta = -Delta;
153 }
154
155 if (Delta < 0) {
156 Delta += Cycle;
157 }
158
159 Total += Delta;
160 ASSERT (Total < Timeout);
161 }
162 }
163
164 return SpinLock;
165}
166
184BOOLEAN
185EFIAPI
187 IN OUT SPIN_LOCK *SpinLock
188 )
189{
190 SPIN_LOCK LockValue;
191 VOID *Result;
192
193 ASSERT (SpinLock != NULL);
194
195 LockValue = *SpinLock;
196 ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED);
197
198 _ReadWriteBarrier ();
200 (VOID **)SpinLock,
201 (VOID *)SPIN_LOCK_RELEASED,
202 (VOID *)SPIN_LOCK_ACQUIRED
203 );
204
205 _ReadWriteBarrier ();
206 return (BOOLEAN)(Result == (VOID *)SPIN_LOCK_RELEASED);
207}
208
223SPIN_LOCK *
224EFIAPI
226 IN OUT SPIN_LOCK *SpinLock
227 )
228{
229 SPIN_LOCK LockValue;
230
231 ASSERT (SpinLock != NULL);
232
233 LockValue = *SpinLock;
234 ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED);
235
236 _ReadWriteBarrier ();
237 *SpinLock = SPIN_LOCK_RELEASED;
238 _ReadWriteBarrier ();
239
240 return SpinLock;
241}
242
257UINT32
258EFIAPI
260 IN volatile UINT32 *Value
261 )
262{
263 ASSERT (Value != NULL);
264 return InternalSyncIncrement (Value);
265}
266
281UINT32
282EFIAPI
284 IN volatile UINT32 *Value
285 )
286{
287 ASSERT (Value != NULL);
288 return InternalSyncDecrement (Value);
289}
290
310UINT16
311EFIAPI
313 IN OUT volatile UINT16 *Value,
314 IN UINT16 CompareValue,
315 IN UINT16 ExchangeValue
316 )
317{
318 ASSERT (Value != NULL);
319 return InternalSyncCompareExchange16 (Value, CompareValue, ExchangeValue);
320}
321
341UINT32
342EFIAPI
344 IN OUT volatile UINT32 *Value,
345 IN UINT32 CompareValue,
346 IN UINT32 ExchangeValue
347 )
348{
349 ASSERT (Value != NULL);
350 return InternalSyncCompareExchange32 (Value, CompareValue, ExchangeValue);
351}
352
371UINT64
372EFIAPI
374 IN OUT volatile UINT64 *Value,
375 IN UINT64 CompareValue,
376 IN UINT64 ExchangeValue
377 )
378{
379 ASSERT (Value != NULL);
380 return InternalSyncCompareExchange64 (Value, CompareValue, ExchangeValue);
381}
382
401VOID *
402EFIAPI
404 IN OUT VOID *volatile *Value,
405 IN VOID *CompareValue,
406 IN VOID *ExchangeValue
407 )
408{
409 UINT8 SizeOfValue;
410
411 SizeOfValue = sizeof (*Value);
412
413 switch (SizeOfValue) {
414 case sizeof (UINT32):
415 return (VOID *)(UINTN)InterlockedCompareExchange32 (
416 (volatile UINT32 *)Value,
417 (UINT32)(UINTN)CompareValue,
418 (UINT32)(UINTN)ExchangeValue
419 );
420 case sizeof (UINT64):
421 return (VOID *)(UINTN)InterlockedCompareExchange64 (
422 (volatile UINT64 *)Value,
423 (UINT64)(UINTN)CompareValue,
424 (UINT64)(UINTN)ExchangeValue
425 );
426 default:
427 ASSERT (FALSE);
428 return NULL;
429 }
430}
UINT64 UINTN
UINT64 EFIAPI GetPerformanceCounterProperties(OUT UINT64 *StartValue OPTIONAL, OUT UINT64 *EndValue OPTIONAL)
UINT64 EFIAPI GetPerformanceCounter(VOID)
UINT64 EFIAPI DivU64x32(IN UINT64 Dividend, IN UINT32 Divisor)
Definition: DivU64x32.c:29
VOID EFIAPI CpuPause(VOID)
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
Definition: MultU64x32.c:27
UINTN InternalGetSpinLockProperties(VOID)
UINT32 EFIAPI InternalSyncDecrement(IN volatile UINT32 *Value)
UINT32 EFIAPI InternalSyncIncrement(IN volatile UINT32 *Value)
UINT64 EFIAPI InternalSyncCompareExchange64(IN volatile UINT64 *Value, IN UINT64 CompareValue, IN UINT64 ExchangeValue)
UINT32 EFIAPI InternalSyncCompareExchange32(IN volatile UINT32 *Value, IN UINT32 CompareValue, IN UINT32 ExchangeValue)
UINT16 EFIAPI InternalSyncCompareExchange16(IN volatile UINT16 *Value, IN UINT16 CompareValue, IN UINT16 ExchangeValue)
#define NULL
Definition: Base.h:319
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
UINT32 EFIAPI InterlockedIncrement(IN volatile UINT32 *Value)
VOID *EFIAPI InterlockedCompareExchangePointer(IN OUT VOID *volatile *Value, IN VOID *CompareValue, IN VOID *ExchangeValue)
SPIN_LOCK *EFIAPI AcquireSpinLock(IN OUT SPIN_LOCK *SpinLock)
UINTN EFIAPI GetSpinLockProperties(VOID)
UINT32 EFIAPI InterlockedCompareExchange32(IN OUT volatile UINT32 *Value, IN UINT32 CompareValue, IN UINT32 ExchangeValue)
UINT16 EFIAPI InterlockedCompareExchange16(IN OUT volatile UINT16 *Value, IN UINT16 CompareValue, IN UINT16 ExchangeValue)
UINT32 EFIAPI InterlockedDecrement(IN volatile UINT32 *Value)
SPIN_LOCK *EFIAPI InitializeSpinLock(OUT SPIN_LOCK *SpinLock)
SPIN_LOCK *EFIAPI ReleaseSpinLock(IN OUT SPIN_LOCK *SpinLock)
BOOLEAN EFIAPI AcquireSpinLockOrFail(IN OUT SPIN_LOCK *SpinLock)
UINT64 EFIAPI InterlockedCompareExchange64(IN OUT volatile UINT64 *Value, IN UINT64 CompareValue, IN UINT64 ExchangeValue)
volatile UINTN SPIN_LOCK