我在开源EDKII代码库中看到下面的代码片段:
某些背景信息:
#define VOID void
#define SPIN_LOCK_RELEASED ((UINTN) 1)
#define SPIN_LOCK_ACQUIRED ((UINTN) 2)
typedef volatile UINTN SPIN_LOCK;
typedef unsigned __int64 UINTN; //depending on the build options
typedef unsigned __int32 UINTN; //depending on the build options
和
BOOLEAN
EFIAPI
AcquireSpinLockOrFail (
IN OUT SPIN_LOCK *SpinLock
)
{
SPIN_LOCK LockValue;
VOID *Result;
ASSERT (SpinLock != NULL);
LockValue = *SpinLock;
ASSERT (LockValue == SPIN_LOCK_ACQUIRED || LockValue == SPIN_LOCK_RELEASED);
_ReadWriteBarrier ();
Result = InterlockedCompareExchangePointer (
(VOID**)SpinLock, // <============= PLACE A
(VOID*)SPIN_LOCK_RELEASED,
(VOID*)SPIN_LOCK_ACQUIRED
);
_ReadWriteBarrier ();
return (BOOLEAN) (Result == (VOID*) SPIN_LOCK_RELEASED);
}
InterlockedCompareExchangePointer
的实施方式如下:
VOID *
EFIAPI
InterlockedCompareExchangePointer (
IN OUT VOID **Value,
IN VOID *CompareValue,
IN VOID *ExchangeValue
)
{
UINT8 SizeOfValue;
SizeOfValue = (UINT8) sizeof (*Value); // <=========== PLACE B
switch (SizeOfValue) {
case sizeof (UINT32):
return (VOID*)(UINTN)InterlockedCompareExchange32 (
(UINT32*)Value,
(UINT32)(UINTN)CompareValue,
(UINT32)(UINTN)ExchangeValue
);
case sizeof (UINT64):
return (VOID*)(UINTN)InterlockedCompareExchange64 (
(UINT64*)Value,
(UINT64)(UINTN)CompareValue,
(UINT64)(UINTN)ExchangeValue
);
default:
ASSERT (FALSE);
return NULL;
}
}
AFAIK,处理不同的位宽是一些逻辑。
对于地点A,我不知道为什么我们可以将UINTN *
转换为void **
。为什么要明确地将 指针 转换为 指针指向 ?
对于地方B,它是如何运作的?
受@ UnholySheep的评论启发。如果这一切都归结为sizeof(void*)
,为什么不写SizeOfValue = (UINT8) sizeof (void*);
而不是在参数Value
上使用类型转换?