diff options
author | Jan Vorlicek <janvorli@microsoft.com> | 2015-11-05 00:23:46 +0300 |
---|---|---|
committer | Jan Vorlicek <janvorli@microsoft.com> | 2015-11-05 11:52:31 +0300 |
commit | cecbc6d2c087febb5850029122c8e27082b5bdcc (patch) | |
tree | 2fac03d2db83af251d8e51bcf2298e200949356e | |
parent | df64a431473ed1a9672e73c7329dd117993d039d (diff) |
Fix few issues in PAL to fix the HelloWorld
With my latest changes, the HelloWorld stopped working. I had two problems
there. One was few simple bugs in the CPU cache details extraction.
The other was the fact that InterlockedXXX operations are implemented like this in PalRedhawk.h:
```C
EXTERN_C long __cdecl _InterlockedIncrement(long volatile *);
Int32 PalInterlockedIncrement(_Inout_ _Interlocked_operand_ Int32 volatile *pDst)
{
return _InterlockedIncrement((long volatile *)pDst);
}
```
The code is using long, which is 64 bits on 64 bit Unix. So it is casting 32 bit
pointer to 64 bit one and performing 64 bit ops. It both corrupts 32 bits after the
location where the pointer points and makes some InterlockedCompareExchange ops
incorrect.
So instead of relying in the _InterlockedXXX intrinsics that can only accept
int or long, I have moved the inline implementations into separate file, one
for windows and one for Unix and implemented all of the PalInterlockedXXX
using __sync_xxxxx functions.
-rw-r--r-- | src/Native/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/Native/Runtime/PalRedhawk.h | 89 | ||||
-rw-r--r-- | src/Native/Runtime/unix/PalRedhawkInline.h | 67 | ||||
-rw-r--r-- | src/Native/Runtime/unix/PalRedhawkUnix.cpp | 63 | ||||
-rw-r--r-- | src/Native/Runtime/windows/PalRedhawkInline.h | 91 |
5 files changed, 196 insertions, 120 deletions
diff --git a/src/Native/CMakeLists.txt b/src/Native/CMakeLists.txt index 5dcb305f5..b5fed91a1 100644 --- a/src/Native/CMakeLists.txt +++ b/src/Native/CMakeLists.txt @@ -19,7 +19,7 @@ function(clr_unknown_arch) endfunction() if (CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL amd64) - add_definitions(-DBIT64=1) + set(IS_64BIT_BUILD 1) elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL armv7l) add_definitions(-DBIT32=1) # Because we don't use CMAKE_C_COMPILER/CMAKE_CXX_COMPILER to use clang @@ -91,6 +91,10 @@ elseif(WIN32) endif() endif() +if(IS_64BIT_BUILD) + add_definitions(-DBIT64=1) +endif(IS_64BIT_BUILD) + if(WIN32) enable_language(ASM_MASM) else() diff --git a/src/Native/Runtime/PalRedhawk.h b/src/Native/Runtime/PalRedhawk.h index 12bdd3aeb..4ab5458e0 100644 --- a/src/Native/Runtime/PalRedhawk.h +++ b/src/Native/Runtime/PalRedhawk.h @@ -705,93 +705,6 @@ inline UInt8 * PalNtCurrentTeb() EXTERN_C void * __cdecl _alloca(size_t); #pragma intrinsic(_alloca) -EXTERN_C long __cdecl _InterlockedIncrement(long volatile *); -#pragma intrinsic(_InterlockedIncrement) -FORCEINLINE Int32 PalInterlockedIncrement(_Inout_ _Interlocked_operand_ Int32 volatile *pDst) -{ - return _InterlockedIncrement((long volatile *)pDst); -} - -EXTERN_C long __cdecl _InterlockedDecrement(long volatile *); -#pragma intrinsic(_InterlockedDecrement) -FORCEINLINE Int32 PalInterlockedDecrement(_Inout_ _Interlocked_operand_ Int32 volatile *pDst) -{ - return _InterlockedDecrement((long volatile *)pDst); -} - -EXTERN_C long _InterlockedOr(long volatile *, long); -#pragma intrinsic(_InterlockedOr) -FORCEINLINE UInt32 PalInterlockedOr(_Inout_ _Interlocked_operand_ UInt32 volatile *pDst, UInt32 iValue) -{ - return _InterlockedOr((long volatile *)pDst, iValue); -} - -EXTERN_C long _InterlockedAnd(long volatile *, long); -#pragma intrinsic(_InterlockedAnd) -FORCEINLINE UInt32 PalInterlockedAnd(_Inout_ _Interlocked_operand_ UInt32 volatile *pDst, UInt32 iValue) -{ - return _InterlockedAnd((long volatile *)pDst, iValue); -} - -EXTERN_C long __PN__MACHINECALL_CDECL_OR_DEFAULT _InterlockedExchange(long volatile *, long); -#pragma intrinsic(_InterlockedExchange) -FORCEINLINE Int32 PalInterlockedExchange(_Inout_ _Interlocked_operand_ Int32 volatile *pDst, Int32 iValue) -{ - return _InterlockedExchange((long volatile *)pDst, iValue); -} - -EXTERN_C long __PN__MACHINECALL_CDECL_OR_DEFAULT _InterlockedCompareExchange(long volatile *, long, long); -#pragma intrinsic(_InterlockedCompareExchange) -FORCEINLINE Int32 PalInterlockedCompareExchange(_Inout_ _Interlocked_operand_ Int32 volatile *pDst, Int32 iValue, Int32 iComperand) -{ - return _InterlockedCompareExchange((long volatile *)pDst, iValue, iComperand); -} - -EXTERN_C Int64 _InterlockedCompareExchange64(Int64 volatile *, Int64, Int64); -#pragma intrinsic(_InterlockedCompareExchange64) -FORCEINLINE Int64 PalInterlockedCompareExchange64(_Inout_ _Interlocked_operand_ Int64 volatile *pDst, Int64 iValue, Int64 iComperand) -{ - return _InterlockedCompareExchange64(pDst, iValue, iComperand); -} - -#if defined(_AMD64_) -EXTERN_C UInt8 _InterlockedCompareExchange128(Int64 volatile *, Int64, Int64, Int64 *); -#pragma intrinsic(_InterlockedCompareExchange128) -FORCEINLINE UInt8 PalInterlockedCompareExchange128(_Inout_ _Interlocked_operand_ Int64 volatile *pDst, Int64 iValueHigh, Int64 iValueLow, Int64 *pComperand) -{ - return _InterlockedCompareExchange128(pDst, iValueHigh, iValueLow, pComperand); -} -#endif // _AMD64_ - -#if defined(_X86_) || defined(_ARM_) - -#define PalInterlockedExchangePointer(_pDst, _pValue) \ - ((void *)_InterlockedExchange((long volatile *)(_pDst), (long)(size_t)(_pValue))) - -#define PalInterlockedCompareExchangePointer(_pDst, _pValue, _pComperand) \ - ((void *)_InterlockedCompareExchange((long volatile *)(_pDst), (long)(size_t)(_pValue), (long)(size_t)(_pComperand))) - -#elif defined(_AMD64_) - -EXTERN_C void * _InterlockedExchangePointer(void * volatile *, void *); -#pragma intrinsic(_InterlockedExchangePointer) -FORCEINLINE void * PalInterlockedExchangePointer(_Inout_ _Interlocked_operand_ void * volatile *pDst, _In_ void *pValue) -{ - return _InterlockedExchangePointer((void * volatile *)pDst, pValue); -} - -EXTERN_C void * _InterlockedCompareExchangePointer(void * volatile *, void *, void *); -#pragma intrinsic(_InterlockedCompareExchangePointer) -FORCEINLINE void * PalInterlockedCompareExchangePointer(_Inout_ _Interlocked_operand_ void * volatile *pDst, _In_ void *pValue, _In_ void *pComperand) -{ - return _InterlockedCompareExchangePointer((void * volatile *)pDst, pValue, pComperand); -} - -#else -#error Unsupported architecture -#endif - - #if defined(_X86_) #define PalYieldProcessor() __asm { rep nop } @@ -895,4 +808,6 @@ REDHAWK_PALIMPORT size_t __cdecl wcslen(const wchar_t *str); REDHAWK_PALIMPORT Int32 __cdecl _wcsicmp(const wchar_t *string1, const wchar_t *string2); #endif // !DACCESS_COMPILE +#include "PalRedhawkInline.h" + #endif // !PAL_REDHAWK_INCLUDED diff --git a/src/Native/Runtime/unix/PalRedhawkInline.h b/src/Native/Runtime/unix/PalRedhawkInline.h new file mode 100644 index 000000000..f5bfc12bc --- /dev/null +++ b/src/Native/Runtime/unix/PalRedhawkInline.h @@ -0,0 +1,67 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// Implementation of Redhawk PAL inline functions + +FORCEINLINE Int32 PalInterlockedIncrement(_Inout_ _Interlocked_operand_ Int32 volatile *pDst) +{ + return __sync_add_and_fetch(pDst, 1); +} + +FORCEINLINE Int32 PalInterlockedDecrement(_Inout_ _Interlocked_operand_ Int32 volatile *pDst) +{ + return __sync_sub_and_fetch(pDst, 1); +} + +FORCEINLINE UInt32 PalInterlockedOr(_Inout_ _Interlocked_operand_ UInt32 volatile *pDst, UInt32 iValue) +{ + return __sync_fetch_and_or(pDst, iValue); +} + +FORCEINLINE UInt32 PalInterlockedAnd(_Inout_ _Interlocked_operand_ UInt32 volatile *pDst, UInt32 iValue) +{ + return __sync_fetch_and_and(pDst, iValue); +} + +FORCEINLINE Int32 PalInterlockedExchange(_Inout_ _Interlocked_operand_ Int32 volatile *pDst, Int32 iValue) +{ + return __sync_swap(pDst, iValue); +} + +FORCEINLINE Int32 PalInterlockedCompareExchange(_Inout_ _Interlocked_operand_ Int32 volatile *pDst, Int32 iValue, Int32 iComperand) +{ + return __sync_val_compare_and_swap(pDst, iComperand, iValue); +} + +FORCEINLINE Int64 PalInterlockedCompareExchange64(_Inout_ _Interlocked_operand_ Int64 volatile *pDst, Int64 iValue, Int64 iComperand) +{ + return __sync_val_compare_and_swap(pDst, iComperand, iValue); +} + +#if defined(_AMD64_) +EXTERN_C UInt8 _InterlockedCompareExchange128(Int64 volatile *, Int64, Int64, Int64 *); +FORCEINLINE UInt8 PalInterlockedCompareExchange128(_Inout_ _Interlocked_operand_ Int64 volatile *pDst, Int64 iValueHigh, Int64 iValueLow, Int64 *pComperand) +{ + return _InterlockedCompareExchange128(pDst, iValueHigh, iValueLow, pComperand); +} +#endif // _AMD64_ + +#ifdef BIT64 + +#define PalInterlockedExchangePointer(_pDst, _pValue) \ + ((void *)PalInterlockedExchange64((Int64 volatile *)(_pDst), (Int64)(size_t)(_pValue))) + +#define PalInterlockedCompareExchangePointer(_pDst, _pValue, _pComperand) \ + ((void *)PalInterlockedCompareExchange64((Int64 volatile *)(_pDst), (Int64)(size_t)(_pValue), (Int64)(size_t)(_pComperand))) + +#else // BIT64 + +#define PalInterlockedExchangePointer(_pDst, _pValue) \ + ((void *)PalInterlockedExchange((Int32 volatile *)(_pDst), (Int32)(size_t)(_pValue))) + +#define PalInterlockedCompareExchangePointer(_pDst, _pValue, _pComperand) \ + ((void *)PalInterlockedCompareExchange((Int32 volatile *)(_pDst), (Int32)(size_t)(_pValue), (Int32)(size_t)(_pComperand))) + +#endif // BIT64 diff --git a/src/Native/Runtime/unix/PalRedhawkUnix.cpp b/src/Native/Runtime/unix/PalRedhawkUnix.cpp index 3ed7e3bb7..df8ac0d91 100644 --- a/src/Native/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/Native/Runtime/unix/PalRedhawkUnix.cpp @@ -28,6 +28,7 @@ #include <dlfcn.h> #include <dirent.h> #include <string.h> +#include <ctype.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/time.h> @@ -609,14 +610,18 @@ REDHAWK_PALEXPORT UInt32_BOOL REDHAWK_PALAPI PalStartBackgroundWork(_In_ Backgro static const int NormalPriority = 0; static const int HighestPriority = -20; + // TODO: Figure out which scheduler to use, the default one doesn't seem to + // support per thread priorities. +#if 0 sched_param params; memset(¶ms, 0, sizeof(params)); + params.sched_priority = highPriority ? HighestPriority : NormalPriority; // Set the priority of the thread st = pthread_attr_setschedparam(&attrs, ¶ms); ASSERT(st == 0); - +#endif // Create the thread as detached, that means not joinable st = pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED); ASSERT(st == 0); @@ -777,11 +782,11 @@ bool QueryCacheSize() // Process entries starting with "cpu" (cpu0, cpu1, ...) in the directory while (success && (cpuEntry = readdir(cpuDir)) != nullptr) { - if (strncmp(cpuEntry->d_name, "cpu", 3) == 0) + if ((strncmp(cpuEntry->d_name, "cpu", 3) == 0) && isdigit(cpuEntry->d_name[3])) { char cpuCachePath[64] = "/sys/devices/system/cpu/"; strcat(cpuCachePath, cpuEntry->d_name); - strcat(cpuCachePath, "cache"); + strcat(cpuCachePath, "/cache"); DIR* cacheDir = opendir(cpuCachePath); if (cacheDir == nullptr) { @@ -796,27 +801,31 @@ bool QueryCacheSize() // For all entries in the directory while ((cacheEntry = readdir(cacheDir)) != nullptr) { - cpuCachePath[cpuCacheBasePathLength] = '\0'; - strcat(cpuCachePath, cpuEntry->d_name); - strcat(cpuCachePath, "/size"); - - int fd = open(cpuCachePath, O_RDONLY); - if (fd < 0) + if (strncmp(cacheEntry->d_name, "index", 5) == 0) { - success = false; - break; + cpuCachePath[cpuCacheBasePathLength] = '\0'; + strcat(cpuCachePath, cacheEntry->d_name); + strcat(cpuCachePath, "/size"); + + int fd = open(cpuCachePath, O_RDONLY); + if (fd < 0) + { + success = false; + break; + } + + char cacheSizeStr[16]; + int bytesRead = read(fd, cacheSizeStr, sizeof(cacheSizeStr) - 1); + cacheSizeStr[bytesRead] = '\0'; + + // Parse the cache size that is formatted as a number followed by the K letter + char* lastChar; + int cacheSize = strtol(cacheSizeStr, &lastChar, 10) * 1024; + ASSERT(*lastChar == 'K'); + g_cbLargestOnDieCache = max(g_cbLargestOnDieCache, cacheSize); + + close(fd); } - - char cacheSizeStr[16]; - int bytesRead = read(fd, cacheSizeStr, sizeof(cacheSizeStr) - 1); - cacheSizeStr[bytesRead] = '\0'; - - // Parse the cache size that is formatted as a number followed by the K letter - ASSERT(cacheSizeStr[bytesRead - 1] == 'K'); - int cacheSize = atoi(cacheSizeStr) * 1024; - g_cbLargestOnDieCache = max(g_cbLargestOnDieCache, cacheSize); - - close(fd); } closedir(cacheDir); @@ -966,16 +975,6 @@ REDHAWK_PALEXPORT _Ret_maybenull_ void* REDHAWK_PALAPI PalSetWerDataBuffer(_In_ return _InterlockedExchangePointer(&pBuffer, pNewBuffer); } -extern "C" UInt32 _InterlockedOr(_Inout_ _Interlocked_operand_ UInt32 volatile *pDst, UInt32 iValue) -{ - return __sync_fetch_and_or(pDst, iValue); -} - -extern "C" UInt32 _InterlockedAnd(_Inout_ _Interlocked_operand_ UInt32 volatile *pDst, UInt32 iValue) -{ - return __sync_fetch_and_and(pDst, iValue); -} - extern "C" HANDLE GetCurrentProcess() { return (HANDLE)-1; diff --git a/src/Native/Runtime/windows/PalRedhawkInline.h b/src/Native/Runtime/windows/PalRedhawkInline.h new file mode 100644 index 000000000..fa4bbdb71 --- /dev/null +++ b/src/Native/Runtime/windows/PalRedhawkInline.h @@ -0,0 +1,91 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +// Implementation of Redhawk PAL inline functions + +EXTERN_C long __cdecl _InterlockedIncrement(long volatile *); +#pragma intrinsic(_InterlockedIncrement) +FORCEINLINE Int32 PalInterlockedIncrement(_Inout_ _Interlocked_operand_ Int32 volatile *pDst) +{ + return _InterlockedIncrement((long volatile *)pDst); +} + +EXTERN_C long __cdecl _InterlockedDecrement(long volatile *); +#pragma intrinsic(_InterlockedDecrement) +FORCEINLINE Int32 PalInterlockedDecrement(_Inout_ _Interlocked_operand_ Int32 volatile *pDst) +{ + return _InterlockedDecrement((long volatile *)pDst); +} + +EXTERN_C long _InterlockedOr(long volatile *, long); +#pragma intrinsic(_InterlockedOr) +FORCEINLINE UInt32 PalInterlockedOr(_Inout_ _Interlocked_operand_ UInt32 volatile *pDst, UInt32 iValue) +{ + return _InterlockedOr((long volatile *)pDst, iValue); +} + +EXTERN_C long _InterlockedAnd(long volatile *, long); +#pragma intrinsic(_InterlockedAnd) +FORCEINLINE UInt32 PalInterlockedAnd(_Inout_ _Interlocked_operand_ UInt32 volatile *pDst, UInt32 iValue) +{ + return _InterlockedAnd((long volatile *)pDst, iValue); +} + +EXTERN_C long __PN__MACHINECALL_CDECL_OR_DEFAULT _InterlockedExchange(long volatile *, long); +#pragma intrinsic(_InterlockedExchange) +FORCEINLINE Int32 PalInterlockedExchange(_Inout_ _Interlocked_operand_ Int32 volatile *pDst, Int32 iValue) +{ + return _InterlockedExchange((long volatile *)pDst, iValue); +} + +EXTERN_C long __PN__MACHINECALL_CDECL_OR_DEFAULT _InterlockedCompareExchange(long volatile *, long, long); +#pragma intrinsic(_InterlockedCompareExchange) +FORCEINLINE Int32 PalInterlockedCompareExchange(_Inout_ _Interlocked_operand_ Int32 volatile *pDst, Int32 iValue, Int32 iComperand) +{ + return _InterlockedCompareExchange((long volatile *)pDst, iValue, iComperand); +} + +EXTERN_C Int64 _InterlockedCompareExchange64(Int64 volatile *, Int64, Int64); +#pragma intrinsic(_InterlockedCompareExchange64) +FORCEINLINE Int64 PalInterlockedCompareExchange64(_Inout_ _Interlocked_operand_ Int64 volatile *pDst, Int64 iValue, Int64 iComperand) +{ + return _InterlockedCompareExchange64(pDst, iValue, iComperand); +} + +#if defined(_AMD64_) +EXTERN_C UInt8 _InterlockedCompareExchange128(Int64 volatile *, Int64, Int64, Int64 *); +#pragma intrinsic(_InterlockedCompareExchange128) +FORCEINLINE UInt8 PalInterlockedCompareExchange128(_Inout_ _Interlocked_operand_ Int64 volatile *pDst, Int64 iValueHigh, Int64 iValueLow, Int64 *pComperand) +{ + return _InterlockedCompareExchange128(pDst, iValueHigh, iValueLow, pComperand); +} +#endif // _AMD64_ + +#ifdef BIT64 + +EXTERN_C void * _InterlockedExchangePointer(void * volatile *, void *); +#pragma intrinsic(_InterlockedExchangePointer) +FORCEINLINE void * PalInterlockedExchangePointer(_Inout_ _Interlocked_operand_ void * volatile *pDst, _In_ void *pValue) +{ + return _InterlockedExchangePointer((void * volatile *)pDst, pValue); +} + +EXTERN_C void * _InterlockedCompareExchangePointer(void * volatile *, void *, void *); +#pragma intrinsic(_InterlockedCompareExchangePointer) +FORCEINLINE void * PalInterlockedCompareExchangePointer(_Inout_ _Interlocked_operand_ void * volatile *pDst, _In_ void *pValue, _In_ void *pComperand) +{ + return _InterlockedCompareExchangePointer((void * volatile *)pDst, pValue, pComperand); +} + +#else // BIT64 + +#define PalInterlockedExchangePointer(_pDst, _pValue) \ + ((void *)_InterlockedExchange((long volatile *)(_pDst), (long)(size_t)(_pValue))) + +#define PalInterlockedCompareExchangePointer(_pDst, _pValue, _pComperand) \ + ((void *)_InterlockedCompareExchange((long volatile *)(_pDst), (long)(size_t)(_pValue), (long)(size_t)(_pComperand))) + +#endif // BIT64 + |