diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index d476601bca853a..23fb000ed2c349 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -42,7 +42,7 @@ extern TADDR g_ClrModuleBase; // To include definition of IsThrowableThreadAbortException // #include -CRITICAL_SECTION g_dacCritSec; +minipal_mutex g_dacMutex; ClrDataAccess* g_dacImpl; EXTERN_C BOOL WINAPI DllMain2(HANDLE instance, DWORD reason, LPVOID reserved) @@ -72,7 +72,7 @@ EXTERN_C BOOL WINAPI DllMain2(HANDLE instance, DWORD reason, LPVOID reserved) return FALSE; } #endif - InitializeCriticalSection(&g_dacCritSec); + minipal_mutex_init(&g_dacMutex); g_procInitialized = true; break; @@ -82,7 +82,7 @@ EXTERN_C BOOL WINAPI DllMain2(HANDLE instance, DWORD reason, LPVOID reserved) // It's possible for this to be called without ATTACH completing (eg. if it failed) if (g_procInitialized) { - DeleteCriticalSection(&g_dacCritSec); + minipal_mutex_destroy(&g_dacMutex); } g_procInitialized = false; break; diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index 1f4745a3e1ae4a..16abe8d2826d1b 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -59,7 +59,7 @@ -// Global allocator for DD. Access is protected under the g_dacCritSec lock. +// Global allocator for DD. Access is protected under the g_dacMutex lock. IDacDbiInterface::IAllocator * g_pAllocator = NULL; //--------------------------------------------------------------------------------------- @@ -362,7 +362,7 @@ interface IMDInternalImport* DacDbiInterfaceImpl::GetMDImport( const ReflectionModule * pReflectionModule, bool fThrowEx) { - // Since this is called from an existing DAC-primitive, we already hold the g_dacCritSec lock. + // Since this is called from an existing DAC-primitive, we already hold the g_dacMutex lock. // The lock conveniently protects our cache. SUPPORTS_DAC; diff --git a/src/coreclr/debug/daccess/dacdbiimpl.h b/src/coreclr/debug/daccess/dacdbiimpl.h index d878b0c0255b87..f04504d2ec4d65 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.h +++ b/src/coreclr/debug/daccess/dacdbiimpl.h @@ -1107,7 +1107,7 @@ class DacDbiInterfaceImpl : }; -// Global allocator for DD. Access is protected under the g_dacCritSec lock. +// Global allocator for DD. Access is protected under the g_dacMutex lock. extern "C" IDacDbiInterface::IAllocator * g_pAllocator; @@ -1116,7 +1116,7 @@ class DDHolder public: DDHolder(DacDbiInterfaceImpl* pContainer, bool fAllowReentrant) { - EnterCriticalSection(&g_dacCritSec); + minipal_mutex_enter(&g_dacMutex); // If we're not re-entrant, then assert. if (!fAllowReentrant) @@ -1139,7 +1139,7 @@ class DDHolder g_dacImpl = m_pOldContainer; g_pAllocator = m_pOldAllocator; - LeaveCriticalSection(&g_dacCritSec); + minipal_mutex_leave(&g_dacMutex); } protected: diff --git a/src/coreclr/debug/daccess/dacimpl.h b/src/coreclr/debug/daccess/dacimpl.h index ef4a8246374e56..6d1ad0c16958c0 100644 --- a/src/coreclr/debug/daccess/dacimpl.h +++ b/src/coreclr/debug/daccess/dacimpl.h @@ -13,6 +13,7 @@ #ifndef __DACIMPL_H__ #define __DACIMPL_H__ +#include #include "gcinterface.dac.h" //--------------------------------------------------------------------------------------- // Setting DAC_HASHTABLE tells the DAC to use the hand rolled hashtable for @@ -26,7 +27,7 @@ #include #pragma pop_macro("return") #endif //DAC_HASHTABLE -extern CRITICAL_SECTION g_dacCritSec; +extern minipal_mutex g_dacMutex; // Convert between CLRDATA_ADDRESS and TADDR. // Note that CLRDATA_ADDRESS is sign-extended (for compat with Windbg and OS conventions). Converting @@ -3809,7 +3810,7 @@ class EnumMethodInstances //---------------------------------------------------------------------------- #define DAC_ENTER() \ - EnterCriticalSection(&g_dacCritSec); \ + minipal_mutex_enter(&g_dacMutex); \ ClrDataAccess* __prevDacImpl = g_dacImpl; \ g_dacImpl = this; @@ -3817,10 +3818,10 @@ class EnumMethodInstances // the process's host instance cache hasn't been flushed // since the child was created. #define DAC_ENTER_SUB(dac) \ - EnterCriticalSection(&g_dacCritSec); \ + minipal_mutex_enter(&g_dacMutex); \ if (dac->m_instanceAge != m_instanceAge) \ { \ - LeaveCriticalSection(&g_dacCritSec); \ + minipal_mutex_leave(&g_dacMutex); \ return E_INVALIDARG; \ } \ ClrDataAccess* __prevDacImpl = g_dacImpl; \ @@ -3828,7 +3829,7 @@ class EnumMethodInstances #define DAC_LEAVE() \ g_dacImpl = __prevDacImpl; \ - LeaveCriticalSection(&g_dacCritSec) + minipal_mutex_leave(&g_dacMutex) #define SOSHelperEnter() \ diff --git a/src/coreclr/debug/di/rspriv.h b/src/coreclr/debug/di/rspriv.h index f85bd497e382a3..3185cc0b554302 100644 --- a/src/coreclr/debug/di/rspriv.h +++ b/src/coreclr/debug/di/rspriv.h @@ -15,7 +15,7 @@ #include #include - +#include #ifdef _DEBUG #define LOGGING @@ -798,7 +798,7 @@ class RSLock } - CRITICAL_SECTION m_lock; + minipal_mutex m_lock; #ifdef _DEBUG public: @@ -839,9 +839,8 @@ class RSLock typedef RSLock::RSLockHolder RSLockHolder; typedef RSLock::RSInverseLockHolder RSInverseLockHolder; -// In the RS, we should be using RSLocks instead of raw critical sections. -#define CRITICAL_SECTION USE_RSLOCK_INSTEAD_OF_CRITICAL_SECTION - +// In the RS, we should be using RSLocks instead of raw minipal_mutex. +#define minipal_mutex USE_RSLOCK_INSTEAD_OF_MINIPAL_MUTEX /* ------------------------------------------------------------------------- * * Helper macros. Use the ATT_* macros below instead of these. @@ -11200,7 +11199,7 @@ inline CordbEval * UnwrapCookieCordbEval(CordbProcess *pProc, UINT cookie) // We defined this at the top of the file - undef it now so that we don't pollute other files. -#undef CRITICAL_SECTION +#undef minipal_mutex #ifdef RSCONTRACTS diff --git a/src/coreclr/debug/di/rspriv.inl b/src/coreclr/debug/di/rspriv.inl index d918cae3ee5428..c88416b505c247 100644 --- a/src/coreclr/debug/di/rspriv.inl +++ b/src/coreclr/debug/di/rspriv.inl @@ -528,14 +528,15 @@ inline void RSLock::Init(const char * szTag, int eAttr, ERSLockLevel level) _ASSERTE(IsInit()); - InitializeCriticalSection(&m_lock); + bool init = minipal_mutex_init(&m_lock); + _ASSERTE(init); } // Cleanup a lock. inline void RSLock::Destroy() { CONSISTENCY_CHECK_MSGF(IsInit(), ("RSLock '%s' not inited", m_szTag)); - DeleteCriticalSection(&m_lock); + minipal_mutex_destroy(&m_lock); #ifdef _DEBUG m_eAttr = cLockUninit; // No longer initialized. @@ -549,10 +550,11 @@ inline void RSLock::Lock() #ifdef RSCONTRACTS DbgRSThread * pThread = DbgRSThread::GetThread(); + pThread->NotifyTakeLock(this); #endif - EnterCriticalSection(&m_lock); + minipal_mutex_enter(&m_lock); #ifdef _DEBUG m_tidOwner = ::GetCurrentThreadId(); m_count++; @@ -583,7 +585,7 @@ inline void RSLock::Unlock() pThread->NotifyReleaseLock(this); #endif - LeaveCriticalSection(&m_lock); + minipal_mutex_leave(&m_lock); } template diff --git a/src/coreclr/debug/inc/dbgtransportsession.h b/src/coreclr/debug/inc/dbgtransportsession.h index 7fc6087bed2bda..28f677fdabe014 100644 --- a/src/coreclr/debug/inc/dbgtransportsession.h +++ b/src/coreclr/debug/inc/dbgtransportsession.h @@ -8,9 +8,9 @@ #ifndef RIGHT_SIDE_COMPILE #include #include - #endif // !RIGHT_SIDE_COMPILE +#include #include #if defined(FEATURE_DBGIPC_TRANSPORT_VM) || defined(FEATURE_DBGIPC_TRANSPORT_DI) @@ -271,7 +271,7 @@ inline UINT32 DBGIPC_HTONL(UINT32 x) // Lock abstraction (we can't use the same lock implementation on LS and RS since we really want a Crst on the // LS and this isn't available in the RS environment). -class DbgTransportLock +class DbgTransportLock final { public: void Init(); @@ -281,12 +281,32 @@ class DbgTransportLock private: #ifdef RIGHT_SIDE_COMPILE - CRITICAL_SECTION m_sLock; + minipal_mutex m_sLock; #else // RIGHT_SIDE_COMPILE CrstExplicitInit m_sLock; #endif // RIGHT_SIDE_COMPILE }; +class TransportLockHolder final +{ + DbgTransportLock& _lock; +public: + TransportLockHolder(DbgTransportLock& lock) + : _lock(lock) + { + _lock.Enter(); + } + ~TransportLockHolder() + { + _lock.Leave(); + } + + TransportLockHolder(TransportLockHolder const&) = delete; + TransportLockHolder& operator=(TransportLockHolder const&) = delete; + TransportLockHolder(TransportLockHolder&& other) = delete; + TransportLockHolder&& operator=(TransportLockHolder&&) = delete; +}; + // The transport has only one queue for IPC events, but each IPC event can be marked as one of two types. // The transport will signal the handle corresponding to the type of each IPC event. (See // code:DbgTransportSession::GetIPCEventReadyEvent and code:DbgTransportSession::GetDebugEventReadyEvent.) @@ -555,26 +575,6 @@ class DbgTransportSession } }; - // Holder class used to take a transport lock in a given scope and automatically release it once that - // scope is exited. - class TransportLockHolder - { - public: - TransportLockHolder(DbgTransportLock *pLock) - { - m_pLock = pLock; - m_pLock->Enter(); - } - - ~TransportLockHolder() - { - m_pLock->Leave(); - } - - private: - DbgTransportLock *m_pLock; - }; - #ifdef _DEBUG // Store statistics for various session activities that will be useful for performance analysis and tracking // down bugs. diff --git a/src/coreclr/debug/shared/dbgtransportsession.cpp b/src/coreclr/debug/shared/dbgtransportsession.cpp index 0cce9861b9fc2b..010cb3fa38bb04 100644 --- a/src/coreclr/debug/shared/dbgtransportsession.cpp +++ b/src/coreclr/debug/shared/dbgtransportsession.cpp @@ -80,7 +80,7 @@ HRESULT DbgTransportSession::Init(DebuggerIPCControlBlock *pDCB, AppDomainEnumer // the two way pipe; it expects the in/out handles to be -1 instead of 0. m_ref = 1; m_pipe = TwoWayPipe(); - m_sStateLock = DbgTransportLock(); + m_sStateLock = {}; // Initialize all per-session state variables. InitSessionState(); @@ -187,7 +187,7 @@ void DbgTransportSession::Shutdown() // Must take the state lock to make a state transition. { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); // Remember previous state and transition to SS_Closed. SessionState ePreviousState = m_eState; @@ -271,7 +271,7 @@ bool DbgTransportSession::WaitForSessionToOpen(DWORD dwTimeout) bool DbgTransportSession::UseAsDebugger(DebugTicket * pTicket) { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); if (m_fDebuggerAttached) { if (pTicket->IsValid()) @@ -309,7 +309,7 @@ bool DbgTransportSession::UseAsDebugger(DebugTicket * pTicket) bool DbgTransportSession::StopUsingAsDebugger(DebugTicket * pTicket) { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); if (m_fDebuggerAttached && pTicket->IsValid()) { // The caller is indeed the owner of the debug ticket. @@ -365,7 +365,7 @@ void DbgTransportSession::GetNextEvent(DebuggerIPCEvent *pEvent, DWORD cbEvent) // Must acquire the state lock to synchronize us wrt to the transport thread (clients already guarantee // they serialize calls to this and waiting on m_rghEventReadyEvent). - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); // There must be at least one valid event waiting (this call does not block). _ASSERTE(m_cValidEventBuffers); @@ -607,7 +607,7 @@ HRESULT DbgTransportSession::SendMessage(Message *pMessage, bool fWaitsForReply) // and while determining whether to send immediately or not depending on the session state (to avoid // posting a send on a closed and possibly recycled socket). { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); // Perform any last updates to the header or data block here since we might be about to encrypt them. @@ -939,7 +939,7 @@ void DbgTransportSession::HandleNetworkError(bool fCallerHoldsStateLock) void DbgTransportSession::FlushSendQueue(DWORD dwLastProcessedId) { // Must access the send queue under the state lock. - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); // Note that message headers (and data blocks) may be encrypted. Use the cached fields in the Message // structure to compare message IDs and types. @@ -1030,7 +1030,7 @@ bool DbgTransportSession::ProcessReply(MessageHeader *pHeader) // we don't need to put it on the queue in order (it will never be resent). Easiest just to put it // on the head. { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); pMsg->m_pNext = m_pSendQueueFirst; m_pSendQueueFirst = pMsg; if (m_pSendQueueLast == NULL) @@ -1101,7 +1101,7 @@ DbgTransportSession::Message * DbgTransportSession::RemoveMessageFromSendQueue(D // Locate original message on the send queue. Message *pMsg = NULL; { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); pMsg = m_pSendQueueFirst; Message *pLastMsg = NULL; @@ -1340,7 +1340,7 @@ void DbgTransportSession::TransportWorker() // blocked on a Receive() on the newly formed connection (important if they want to transition the state // to SS_Closed). { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); if (m_eState == SS_Closed) break; @@ -1481,7 +1481,7 @@ void DbgTransportSession::TransportWorker() // Must access the send queue under the state lock. { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); Message *pMsg = m_pSendQueueFirst; while (pMsg) { @@ -1500,7 +1500,7 @@ void DbgTransportSession::TransportWorker() // Finally we can transition to SS_Open. { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); if (m_eState == SS_Closed) break; else if (m_eState == SS_Opening) @@ -1617,7 +1617,7 @@ void DbgTransportSession::TransportWorker() // Must access the send queue under the state lock. { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); Message *pMsg = m_pSendQueueFirst; while (pMsg) @@ -1766,7 +1766,7 @@ void DbgTransportSession::TransportWorker() // We need to do some state cleanup here, since when we reform a connection (if ever, it will // be with a new session). { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); // Check we're still in a good state before a clean restart. if (m_eState != SS_Open) @@ -1815,7 +1815,7 @@ void DbgTransportSession::TransportWorker() // that can expand the array, a client thread may be in GetNextEvent() reading from the // old version. { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); // When we copy old array contents over we place the head of the list at the start of // the new array for simplicity. If the head happened to be at the start of the old @@ -1868,7 +1868,7 @@ void DbgTransportSession::TransportWorker() // We must take the lock to update the count of valid entries though, since clients can // touch this field as well. - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); m_cValidEventBuffers++; DWORD idxCurrentEvent = m_idxEventBufferTail; @@ -2091,7 +2091,7 @@ void DbgTransportSession::TransportWorker() // Drain any remaining entries in the send queue (aborting them when they need completions). { - TransportLockHolder sLockHolder(&m_sStateLock); + TransportLockHolder sLockHolder(m_sStateLock); Message *pMsg; while ((pMsg = m_pSendQueueFirst) != NULL) @@ -2710,27 +2710,28 @@ bool DbgTransportSession::DbgTransportShouldInjectFault(DbgTransportFaultOp eOp, // Lock abstraction code (hides difference in lock implementation between left and right side). #ifdef RIGHT_SIDE_COMPILE -// On the right side we use a CRITICAL_SECTION. +// On the right side we use a minipal_mutex. void DbgTransportLock::Init() { - InitializeCriticalSection(&m_sLock); + minipal_mutex_init(&m_sLock); } void DbgTransportLock::Destroy() { - DeleteCriticalSection(&m_sLock); + minipal_mutex_destroy(&m_sLock); } void DbgTransportLock::Enter() { - EnterCriticalSection(&m_sLock); + minipal_mutex_enter(&m_sLock); } void DbgTransportLock::Leave() { - LeaveCriticalSection(&m_sLock); + minipal_mutex_leave(&m_sLock); } + #else // RIGHT_SIDE_COMPILE // On the left side we use a Crst. diff --git a/src/coreclr/dlls/mscordac/mscordac_unixexports.src b/src/coreclr/dlls/mscordac/mscordac_unixexports.src index 3c307f31531a85..1bafba8c34ac0a 100644 --- a/src/coreclr/dlls/mscordac/mscordac_unixexports.src +++ b/src/coreclr/dlls/mscordac/mscordac_unixexports.src @@ -73,9 +73,7 @@ nativeStringResourceTable_mscorrc #CreateThread #CloseHandle #DebugBreak -#DeleteCriticalSection #DuplicateHandle -#EnterCriticalSection #FlushFileBuffers #FlushInstructionCache #FormatMessageW @@ -101,8 +99,6 @@ nativeStringResourceTable_mscorrc #GetSystemTimeAsFileTime #GetTempPathA #GetTempPathW -#InitializeCriticalSection -#LeaveCriticalSection #LoadLibraryExA #LoadLibraryExW #MapViewOfFile diff --git a/src/coreclr/dlls/mscordbi/CMakeLists.txt b/src/coreclr/dlls/mscordbi/CMakeLists.txt index 87e566175a25c0..01f94c737b4960 100644 --- a/src/coreclr/dlls/mscordbi/CMakeLists.txt +++ b/src/coreclr/dlls/mscordbi/CMakeLists.txt @@ -75,6 +75,7 @@ set(COREDBI_LIBRARIES mdruntimerw-dbi mddatasource_dbi corguids + minipal ) if(CLR_CMAKE_HOST_WIN32) diff --git a/src/coreclr/gc/env/common.h b/src/coreclr/gc/env/common.h index 5d8cff7f779041..d356baa598d1b4 100644 --- a/src/coreclr/gc/env/common.h +++ b/src/coreclr/gc/env/common.h @@ -29,7 +29,9 @@ #include #include -#ifdef TARGET_UNIX +#ifdef TARGET_WINDOWS +#include +#else #include #endif diff --git a/src/coreclr/gc/env/gcenv.base.h b/src/coreclr/gc/env/gcenv.base.h index 2cb1f3bacbcd18..f74a8c466a2ec2 100644 --- a/src/coreclr/gc/env/gcenv.base.h +++ b/src/coreclr/gc/env/gcenv.base.h @@ -45,7 +45,7 @@ #define SSIZE_T_MAX ((ptrdiff_t)(SIZE_T_MAX / 2)) #endif -#ifndef _INC_WINDOWS +#ifdef TARGET_UNIX // ----------------------------------------------------------------------------------------------------------- // // Aliases for Win32 types @@ -80,12 +80,6 @@ inline HRESULT HRESULT_FROM_WIN32(unsigned long x) #define S_OK 0x0 #define E_FAIL 0x80004005 #define E_OUTOFMEMORY 0x8007000E -#define COR_E_EXECUTIONENGINE 0x80131506 -#define CLR_E_GC_BAD_AFFINITY_CONFIG 0x8013200A -#define CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT 0x8013200B -#define CLR_E_GC_BAD_HARD_LIMIT 0x8013200D -#define CLR_E_GC_LARGE_PAGE_MISSING_HARD_LIMIT 0x8013200E -#define CLR_E_GC_BAD_REGION_SIZE 0x8013200F #define NOERROR 0x0 #define ERROR_TIMEOUT 1460 @@ -337,6 +331,14 @@ inline uint8_t BitScanReverse64(uint32_t *bitIndex, uint64_t mask) return mask != 0 ? TRUE : FALSE; #endif // _MSC_VER } +#endif // TARGET_UNIX + +#define COR_E_EXECUTIONENGINE 0x80131506 +#define CLR_E_GC_BAD_AFFINITY_CONFIG 0x8013200A +#define CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT 0x8013200B +#define CLR_E_GC_BAD_HARD_LIMIT 0x8013200D +#define CLR_E_GC_LARGE_PAGE_MISSING_HARD_LIMIT 0x8013200E +#define CLR_E_GC_BAD_REGION_SIZE 0x8013200F // Aligns a size_t to the specified alignment. Alignment must be a power // of two. @@ -383,13 +385,6 @@ inline void* ALIGN_DOWN(void* ptr, size_t alignment) return reinterpret_cast(ALIGN_DOWN(as_size_t, alignment)); } -typedef struct _PROCESSOR_NUMBER { - uint16_t Group; - uint8_t Number; - uint8_t Reserved; -} PROCESSOR_NUMBER, *PPROCESSOR_NUMBER; -#endif // _INC_WINDOWS - // ----------------------------------------------------------------------------------------------------------- // // The subset of the contract code required by the GC/HandleTable sources. If NativeAOT moves to support diff --git a/src/coreclr/gc/env/gcenv.os.h b/src/coreclr/gc/env/gcenv.os.h index aa7223850eaa9b..08e9b39e36eb1a 100644 --- a/src/coreclr/gc/env/gcenv.os.h +++ b/src/coreclr/gc/env/gcenv.os.h @@ -6,27 +6,41 @@ #ifndef __GCENV_OS_H__ #define __GCENV_OS_H__ +#include + #define NUMA_NODE_UNDEFINED UINT16_MAX bool ParseIndexOrRange(const char** config_string, size_t* start_index, size_t* end_index); // Critical section used by the GC -class CLRCriticalSection +class CLRCriticalSection final { - CRITICAL_SECTION m_cs; + minipal_mutex m_cs; public: // Initialize the critical section - bool Initialize(); + bool Initialize() + { + return minipal_mutex_init(&m_cs); + } // Destroy the critical section - void Destroy(); + void Destroy() + { + minipal_mutex_destroy(&m_cs); + } // Enter the critical section. Blocks until the section can be entered. - void Enter(); + void Enter() + { + minipal_mutex_enter(&m_cs); + } // Leave the critical section - void Leave(); + void Leave() + { + minipal_mutex_leave(&m_cs); + } }; // Flags for the GCToOSInterface::VirtualReserve method diff --git a/src/coreclr/gc/env/gcenv.structs.h b/src/coreclr/gc/env/gcenv.structs.h index 9f287ec7bf8c26..f3e30a84930853 100644 --- a/src/coreclr/gc/env/gcenv.structs.h +++ b/src/coreclr/gc/env/gcenv.structs.h @@ -44,10 +44,6 @@ class EEThreadId #else // TARGET_UNIX -#ifndef _INC_WINDOWS -extern "C" uint32_t __stdcall GetCurrentThreadId(); -#endif - class EEThreadId { uint64_t m_uiId; @@ -71,37 +67,4 @@ class EEThreadId #endif // TARGET_UNIX -#ifndef _INC_WINDOWS - -#ifdef TARGET_UNIX - -typedef struct _RTL_CRITICAL_SECTION { - pthread_mutex_t mutex; -} CRITICAL_SECTION, RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION; - -#else - -#pragma pack(push, 8) - -typedef struct _RTL_CRITICAL_SECTION { - void* DebugInfo; - - // - // The following three fields control entering and exiting the critical - // section for the resource - // - - int32_t LockCount; - int32_t RecursionCount; - HANDLE OwningThread; // from the thread's ClientId->UniqueThread - HANDLE LockSemaphore; - uintptr_t SpinCount; // force size on 64-bit systems when packed -} CRITICAL_SECTION, RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION; - -#pragma pack(pop) - -#endif - -#endif // _INC_WINDOWS - #endif // __GCENV_STRUCTS_INCLUDED__ diff --git a/src/coreclr/gc/unix/gcenv.unix.cpp b/src/coreclr/gc/unix/gcenv.unix.cpp index 2eb8e1acdba73d..720828b2565f85 100644 --- a/src/coreclr/gc/unix/gcenv.unix.cpp +++ b/src/coreclr/gc/unix/gcenv.unix.cpp @@ -904,7 +904,7 @@ static void GetLogicalProcessorCacheSizeFromSysFs(size_t* cacheLevel, size_t* ca } } } -#endif +#endif } static void GetLogicalProcessorCacheSizeFromHeuristic(size_t* cacheLevel, size_t* cacheSize) @@ -952,7 +952,7 @@ static size_t GetLogicalProcessorCacheSizeFromOS() GetLogicalProcessorCacheSizeFromSysConf(&cacheLevel, &cacheSize); } - if (cacheSize == 0) + if (cacheSize == 0) { GetLogicalProcessorCacheSizeFromSysFs(&cacheLevel, &cacheSize); if (cacheSize == 0) @@ -1543,43 +1543,3 @@ bool GCToOSInterface::ParseGCHeapAffinitizeRangesEntry(const char** config_strin { return ParseIndexOrRange(config_string, start_index, end_index); } - -// Initialize the critical section -bool CLRCriticalSection::Initialize() -{ - pthread_mutexattr_t mutexAttributes; - int st = pthread_mutexattr_init(&mutexAttributes); - if (st != 0) - { - return false; - } - - st = pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE); - if (st == 0) - { - st = pthread_mutex_init(&m_cs.mutex, &mutexAttributes); - } - - pthread_mutexattr_destroy(&mutexAttributes); - - return (st == 0); -} - -// Destroy the critical section -void CLRCriticalSection::Destroy() -{ - int st = pthread_mutex_destroy(&m_cs.mutex); - assert(st == 0); -} - -// Enter the critical section. Blocks until the section can be entered. -void CLRCriticalSection::Enter() -{ - pthread_mutex_lock(&m_cs.mutex); -} - -// Leave the critical section -void CLRCriticalSection::Leave() -{ - pthread_mutex_unlock(&m_cs.mutex); -} diff --git a/src/coreclr/gc/windows/gcenv.windows.cpp b/src/coreclr/gc/windows/gcenv.windows.cpp index 608751dd169aff..3e8040be0bcbb1 100644 --- a/src/coreclr/gc/windows/gcenv.windows.cpp +++ b/src/coreclr/gc/windows/gcenv.windows.cpp @@ -1319,31 +1319,6 @@ static DWORD GCThreadStub(void* param) return 0; } -// Initialize the critical section -bool CLRCriticalSection::Initialize() -{ - ::InitializeCriticalSection(&m_cs); - return true; -} - -// Destroy the critical section -void CLRCriticalSection::Destroy() -{ - ::DeleteCriticalSection(&m_cs); -} - -// Enter the critical section. Blocks until the section can be entered. -void CLRCriticalSection::Enter() -{ - ::EnterCriticalSection(&m_cs); -} - -// Leave the critical section -void CLRCriticalSection::Leave() -{ - ::LeaveCriticalSection(&m_cs); -} - // WindowsEvent is an implementation of GCEvent that forwards // directly to Win32 APIs. class GCEvent::Impl diff --git a/src/coreclr/inc/crosscomp.h b/src/coreclr/inc/crosscomp.h index f6e65f3f8cf57e..4c30eb01ba8ae9 100644 --- a/src/coreclr/inc/crosscomp.h +++ b/src/coreclr/inc/crosscomp.h @@ -4,13 +4,27 @@ // crosscomp.h - cross-compilation enablement structures. // - #pragma once +#include + #if (!defined(HOST_64BIT) && defined(TARGET_64BIT)) || (defined(HOST_64BIT) && !defined(TARGET_64BIT)) #define CROSSBITNESS_COMPILE + +#ifndef CROSS_COMPILE +#define CROSS_COMPILE +#endif // !CROSS_COMPILE + #endif +#if defined(TARGET_WINDOWS) && !defined(HOST_WINDOWS) && !defined(CROSS_COMPILE) +#define CROSS_COMPILE +#endif // TARGET_WINDOWS && !HOST_WINDOWS && !CROSS_COMPILE + +#if defined(TARGET_UNIX) && !defined(HOST_UNIX) && !defined(CROSS_COMPILE) +#define CROSS_COMPILE +#endif // TARGET_UNIX && !HOST_UNIX && !CROSS_COMPILE + // Target platform-specific library naming // #ifdef TARGET_WINDOWS @@ -705,77 +719,42 @@ typedef struct _KNONVOLATILE_CONTEXT_POINTERS_EX #endif -#if defined(DACCESS_COMPILE) && defined(TARGET_UNIX) -// This is a TARGET oriented copy of CRITICAL_SECTION and PAL_CS_NATIVE_DATA_SIZE -// It is configured based on TARGET configuration rather than HOST configuration -// There is validation code in src/coreclr/vm/crst.cpp to keep these from -// getting out of sync - -#define T_CRITICAL_SECTION_VALIDATION_MESSAGE "T_CRITICAL_SECTION validation failed. It is not in sync with CRITICAL_SECTION" - -#if defined(TARGET_OSX) && defined(TARGET_X86) -#define DAC_CS_NATIVE_DATA_SIZE 76 -#elif defined(TARGET_APPLE) && defined(TARGET_AMD64) -#define DAC_CS_NATIVE_DATA_SIZE 120 -#elif defined(TARGET_APPLE) && defined(TARGET_ARM64) -#define DAC_CS_NATIVE_DATA_SIZE 120 -#elif defined(TARGET_FREEBSD) && defined(TARGET_X86) -#define DAC_CS_NATIVE_DATA_SIZE 12 -#elif defined(TARGET_FREEBSD) && defined(TARGET_AMD64) -#define DAC_CS_NATIVE_DATA_SIZE 24 -#elif defined(TARGET_FREEBSD) && defined(TARGET_ARM64) -#define DAC_CS_NATIVE_DATA_SIZE 24 -#elif (defined(TARGET_LINUX) || defined(TARGET_ANDROID)) && defined(TARGET_ARM) -#define DAC_CS_NATIVE_DATA_SIZE 80 -#elif (defined(TARGET_LINUX) || defined(TARGET_ANDROID)) && defined(TARGET_ARM64) -#define DAC_CS_NATIVE_DATA_SIZE 104 -#elif defined(TARGET_LINUX) && defined(TARGET_LOONGARCH64) -#define DAC_CS_NATIVE_DATA_SIZE 96 -#elif (defined(TARGET_LINUX) || defined(TARGET_ANDROID)) && defined(TARGET_X86) -#define DAC_CS_NATIVE_DATA_SIZE 76 -#elif (defined(TARGET_LINUX) || defined(TARGET_ANDROID)) && defined(TARGET_AMD64) -#define DAC_CS_NATIVE_DATA_SIZE 96 -#elif defined(TARGET_LINUX) && defined(TARGET_S390X) -#define DAC_CS_NATIVE_DATA_SIZE 96 -#elif defined(TARGET_LINUX) && defined(TARGET_RISCV64) -#define DAC_CS_NATIVE_DATA_SIZE 96 -#elif defined(TARGET_LINUX) && defined(TARGET_POWERPC64) -#define DAC_CS_NATIVE_DATA_SIZE 96 -#elif defined(TARGET_NETBSD) && defined(TARGET_AMD64) -#define DAC_CS_NATIVE_DATA_SIZE 96 -#elif defined(TARGET_NETBSD) && defined(TARGET_ARM) -#define DAC_CS_NATIVE_DATA_SIZE 56 -#elif defined(TARGET_NETBSD) && defined(TARGET_X86) -#define DAC_CS_NATIVE_DATA_SIZE 56 -#elif defined(__sun) && defined(TARGET_AMD64) -#define DAC_CS_NATIVE_DATA_SIZE 48 -#elif defined(TARGET_HAIKU) && defined(TARGET_AMD64) -#define DAC_CS_NATIVE_DATA_SIZE 56 -#elif defined(TARGET_WASM) -#define DAC_CS_NATIVE_DATA_SIZE 76 +#if defined(TARGET_APPLE) +#define DAC_MUTEX_MAX_SIZE 96 +#elif defined(TARGET_FREEBSD) +#define DAC_MUTEX_MAX_SIZE 16 +#elif defined(TARGET_LINUX) || defined(TARGET_ANDROID) +#define DAC_MUTEX_MAX_SIZE 64 +#elif defined(TARGET_WINDOWS) +#ifdef TARGET_64BIT +#define DAC_MUTEX_MAX_SIZE 40 +#else +#define DAC_MUTEX_MAX_SIZE 24 +#endif // TARGET_64BIT #else -#warning -#error DAC_CS_NATIVE_DATA_SIZE is not defined for this architecture. This should be same value as PAL_CS_NATIVE_DATA_SIZE (aka sizeof(PAL_CS_NATIVE_DATA)). +// Fallback to a conservative default value +#define DAC_MUTEX_MAX_SIZE 128 #endif -struct T_CRITICAL_SECTION { - PVOID DebugInfo; - LONG LockCount; - LONG RecursionCount; - HANDLE OwningThread; - ULONG_PTR SpinCount; - -#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA - BOOL bInternal; -#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA - volatile DWORD dwInitState; +#ifndef CROSS_COMPILE +static_assert(DAC_MUTEX_MAX_SIZE >= sizeof(minipal_mutex), "DAC_MUTEX_MAX_SIZE must be greater than or equal to the size of minipal_mutex"); +#endif // !CROSS_COMPILE - union CSNativeDataStorage +// This type is used to ensure a consistent size of mutexes +// contained with our Crst types. +// We have this requirement for cross OS compiling the DAC. +struct tgt_minipal_mutex final +{ + union { - BYTE rgNativeDataStorage[DAC_CS_NATIVE_DATA_SIZE]; - PVOID pvAlign; // make sure the storage is machine-pointer-size aligned - } csnds; + // DAC builds want to have the data layout of the target system. + // Make sure that the host minipal_mutex does not influence + // the target data layout +#ifndef DACCESS_COMPILE + minipal_mutex _mtx; +#endif // !DACCESS_COMPILE + + // This is unused padding to ensure struct size. + alignas(void*) BYTE _dacPadding[DAC_MUTEX_MAX_SIZE]; + }; }; -#else -#define T_CRITICAL_SECTION CRITICAL_SECTION -#endif diff --git a/src/coreclr/jit/gcencode.cpp b/src/coreclr/jit/gcencode.cpp index f1eb7cec6b2250..cf7933ff8d3dc7 100644 --- a/src/coreclr/jit/gcencode.cpp +++ b/src/coreclr/jit/gcencode.cpp @@ -17,6 +17,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #pragma hdrstop #endif +#include #include "gcinfotypes.h" #include "patchpointinfo.h" @@ -374,8 +375,8 @@ void GCInfo::gcDumpVarPtrDsc(varPtrDsc* desc) // find . -name regen.txt | xargs cat | grep CallSite | sort | uniq -c | sort -r | head -80 #if REGEN_SHORTCUTS || REGEN_CALLPAT -static FILE* logFile = NULL; -CRITICAL_SECTION logFileLock; +static FILE* logFile = NULL; +minipal_mutex logFileLock; #endif #if REGEN_CALLPAT @@ -398,12 +399,12 @@ static void regenLog(unsigned codeDelta, if (logFile == NULL) { logFile = fopen_utf8("regen.txt", "a"); - InitializeCriticalSection(&logFileLock); + minipal_mutex_init(&logFileLock); } assert(((enSize > 0) && (enSize < 256)) && ((pat.val & 0xffffff) != 0xffffff)); - EnterCriticalSection(&logFileLock); + minipal_mutex_enter(&logFileLock); fprintf(logFile, "CallSite( 0x%08x, 0x%02x%02x, 0x", pat.val, byrefArgMask, byrefRegMask); @@ -415,7 +416,7 @@ static void regenLog(unsigned codeDelta, fprintf(logFile, "),\n"); fflush(logFile); - LeaveCriticalSection(&logFileLock); + minipal_mutex_leave(&logFileLock); } #endif @@ -425,10 +426,10 @@ static void regenLog(unsigned encoding, InfoHdr* header, InfoHdr* state) if (logFile == NULL) { logFile = fopen_utf8("regen.txt", "a"); - InitializeCriticalSection(&logFileLock); + minipal_mutex_init(&logFileLock); } - EnterCriticalSection(&logFileLock); + minipal_mutex_enter(&logFileLock); fprintf(logFile, "InfoHdr( %2d, %2d, %1d, %1d, %1d," @@ -451,7 +452,7 @@ static void regenLog(unsigned encoding, InfoHdr* header, InfoHdr* state) fflush(logFile); - LeaveCriticalSection(&logFileLock); + minipal_mutex_leave(&logFileLock); } #endif diff --git a/src/coreclr/nativeaot/Runtime/CachedInterfaceDispatch_Aot.cpp b/src/coreclr/nativeaot/Runtime/CachedInterfaceDispatch_Aot.cpp index 8eb16e8b630983..9a8be1bfd69e29 100644 --- a/src/coreclr/nativeaot/Runtime/CachedInterfaceDispatch_Aot.cpp +++ b/src/coreclr/nativeaot/Runtime/CachedInterfaceDispatch_Aot.cpp @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. #include "common.h" +#include #include "CachedInterfaceDispatchPal.h" #include "CachedInterfaceDispatch.h" diff --git a/src/coreclr/nativeaot/Runtime/CommonMacros.h b/src/coreclr/nativeaot/Runtime/CommonMacros.h index c174b06f17ccd4..a7e3dbd57cf651 100644 --- a/src/coreclr/nativeaot/Runtime/CommonMacros.h +++ b/src/coreclr/nativeaot/Runtime/CommonMacros.h @@ -341,22 +341,6 @@ extern uint64_t g_startupTimelineEvents[NUM_STARTUP_TIMELINE_EVENTS]; #define DECLSPEC_THREAD __thread #endif // !_MSC_VER -#ifndef __GCENV_BASE_INCLUDED__ -#if !defined(_INC_WINDOWS) -#ifdef _WIN32 -// this must exactly match the typedef used by windows.h -typedef long HRESULT; -#else -typedef int32_t HRESULT; -#endif - -#define S_OK 0x0 -#define E_FAIL 0x80004005 - -#define UNREFERENCED_PARAMETER(P) (void)(P) -#endif // !defined(_INC_WINDOWS) -#endif // __GCENV_BASE_INCLUDED__ - // PAL Numbers // Used to ensure cross-compiler compatibility when declaring large // integer constants. 64-bit integer constants should be wrapped in the diff --git a/src/coreclr/nativeaot/Runtime/Crst.cpp b/src/coreclr/nativeaot/Runtime/Crst.cpp index 48a3ee7fde0312..e7779a6ad8fb23 100644 --- a/src/coreclr/nativeaot/Runtime/Crst.cpp +++ b/src/coreclr/nativeaot/Runtime/Crst.cpp @@ -16,14 +16,14 @@ void CrstStatic::Init(CrstType eType, CrstFlags eFlags) #if defined(_DEBUG) m_uiOwnerId.Clear(); #endif // _DEBUG - PalInitializeCriticalSectionEx(&m_sCritSec, 0, 0); + minipal_mutex_init(&m_Lock); #endif // !DACCESS_COMPILE } void CrstStatic::Destroy() { #ifndef DACCESS_COMPILE - PalDeleteCriticalSection(&m_sCritSec); + minipal_mutex_destroy(&m_Lock); #endif // !DACCESS_COMPILE } @@ -31,7 +31,7 @@ void CrstStatic::Destroy() void CrstStatic::Enter(CrstStatic *pCrst) { #ifndef DACCESS_COMPILE - PalEnterCriticalSection(&pCrst->m_sCritSec); + minipal_mutex_enter(&pCrst->m_Lock); #if defined(_DEBUG) pCrst->m_uiOwnerId.SetToCurrentThread(); #endif // _DEBUG @@ -47,7 +47,7 @@ void CrstStatic::Leave(CrstStatic *pCrst) #if defined(_DEBUG) pCrst->m_uiOwnerId.Clear(); #endif // _DEBUG - PalLeaveCriticalSection(&pCrst->m_sCritSec); + minipal_mutex_leave(&pCrst->m_Lock); #else UNREFERENCED_PARAMETER(pCrst); #endif // !DACCESS_COMPILE diff --git a/src/coreclr/nativeaot/Runtime/Crst.h b/src/coreclr/nativeaot/Runtime/Crst.h index 4ab9db08e0f5e3..13e2177afb77bd 100644 --- a/src/coreclr/nativeaot/Runtime/Crst.h +++ b/src/coreclr/nativeaot/Runtime/Crst.h @@ -4,7 +4,7 @@ // // ----------------------------------------------------------------------------------------------------------- // -// Minimal Crst implementation based on CRITICAL_SECTION. Doesn't support much except for the basic locking +// Minimal Crst implementation. Doesn't support much except for the basic locking // functionality (in particular there is no rank violation checking). // @@ -51,7 +51,7 @@ class CrstStatic #endif // _DEBUG private: - CRITICAL_SECTION m_sCritSec; + minipal_mutex m_Lock; #if defined(_DEBUG) EEThreadId m_uiOwnerId; #endif // _DEBUG diff --git a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp index ad8e2f4cccb1f8..c400bd021b983d 100644 --- a/src/coreclr/nativeaot/Runtime/EHHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/EHHelpers.cpp @@ -1,9 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #include "common.h" -#ifdef HOST_WINDOWS -#include -#endif #ifndef DACCESS_COMPILE #include "CommonTypes.h" #include "CommonMacros.h" @@ -350,7 +347,7 @@ static uintptr_t UnwindSimpleHelperToCaller( #ifdef TARGET_UNIX -int32_t __stdcall RhpHardwareExceptionHandler(uintptr_t faultCode, uintptr_t faultAddress, +int32_t RhpHardwareExceptionHandler(uintptr_t faultCode, uintptr_t faultAddress, PAL_LIMITED_CONTEXT* palContext, uintptr_t* arg0Reg, uintptr_t* arg1Reg) { uintptr_t faultingIP = palContext->GetIp(); diff --git a/src/coreclr/nativeaot/Runtime/PalRedhawk.h b/src/coreclr/nativeaot/Runtime/PalRedhawk.h index 167570b165d199..1c65ece5a185f4 100644 --- a/src/coreclr/nativeaot/Runtime/PalRedhawk.h +++ b/src/coreclr/nativeaot/Runtime/PalRedhawk.h @@ -17,13 +17,15 @@ #include #include -#ifdef TARGET_UNIX +#ifdef HOST_WINDOWS +#include +#else #include #endif #include "CommonTypes.h" #include "CommonMacros.h" -#include "gcenv.structs.h" // CRITICAL_SECTION +#include "gcenv.structs.h" // EEThreadId #include "PalRedhawkCommon.h" #ifndef PAL_REDHAWK_INCLUDED @@ -61,10 +63,11 @@ #define DIRECTORY_SEPARATOR_CHAR '\\' #endif // TARGET_UNIX -#ifndef _INC_WINDOWS - +#ifdef TARGET_UNIX // There are some fairly primitive type definitions below but don't pull them into the rest of Redhawk unless // we have to (in which case these definitions will move to CommonTypes.h). +typedef int32_t HRESULT; + typedef WCHAR * LPWSTR; typedef const WCHAR * LPCWSTR; typedef char * LPSTR; @@ -74,14 +77,7 @@ typedef void * HINSTANCE; typedef void * LPSECURITY_ATTRIBUTES; typedef void * LPOVERLAPPED; -#ifdef TARGET_UNIX -#define __stdcall -typedef char TCHAR; -#define _T(s) s -#else -typedef wchar_t TCHAR; -#define _T(s) L##s -#endif +#define UNREFERENCED_PARAMETER(P) (void)(P) typedef union _LARGE_INTEGER { struct { @@ -133,7 +129,7 @@ typedef enum _EXCEPTION_DISPOSITION { #define STATUS_ACCESS_VIOLATION ((uint32_t )0xC0000005L) #define STATUS_STACK_OVERFLOW ((uint32_t )0xC00000FDL) -#endif // !_INC_WINDOWS +#endif // TARGET_UNIX #define STATUS_REDHAWK_NULL_REFERENCE ((uint32_t )0x00000000L) #define STATUS_REDHAWK_UNMANAGED_HELPER_NULL_REFERENCE ((uint32_t )0x00000042L) @@ -144,9 +140,16 @@ typedef enum _EXCEPTION_DISPOSITION { #define NULL_AREA_SIZE (64*1024) #endif +#ifdef TARGET_UNIX +#define _T(s) s +typedef char TCHAR; +#else +// Avoid including tchar.h on Windows. +#define _T(s) L ## s +#endif // TARGET_UNIX #ifndef DACCESS_COMPILE -#ifndef _INC_WINDOWS +#ifdef TARGET_UNIX #ifndef TRUE #define TRUE 1 @@ -178,7 +181,7 @@ typedef enum _EXCEPTION_DISPOSITION { #define WAIT_TIMEOUT 258 #define WAIT_FAILED 0xFFFFFFFF -#endif // !_INC_WINDOWS +#endif // TARGET_UNIX #endif // !DACCESS_COMPILE extern uint32_t g_RhNumberOfProcessors; @@ -193,16 +196,7 @@ extern uint32_t g_RhNumberOfProcessors; #endif // TARGET_UNIX #ifndef DACCESS_COMPILE - -#ifdef _DEBUG -#define CaptureStackBackTrace RtlCaptureStackBackTrace -#endif - -#ifndef _INC_WINDOWS -// Include the list of external functions we wish to access. If we do our job 100% then it will be -// possible to link without any direct reference to any Win32 library. #include "PalRedhawkFunctions.h" -#endif // !_INC_WINDOWS #endif // !DACCESS_COMPILE // The Redhawk PAL must be initialized before any of its exports can be called. Returns true for a successful @@ -290,9 +284,9 @@ REDHAWK_PALIMPORT uint32_t REDHAWK_PALAPI PalGetOsPageSize(); REDHAWK_PALIMPORT void REDHAWK_PALAPI PalSetHardwareExceptionHandler(PHARDWARE_EXCEPTION_HANDLER handler); #endif -typedef uint32_t (__stdcall *BackgroundCallback)(_In_opt_ void* pCallbackContext); +typedef uint32_t (*BackgroundCallback)(_In_opt_ void* pCallbackContext); REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalSetCurrentThreadName(const char* name); -#ifdef TARGET_WINDOWS +#ifdef HOST_WINDOWS REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalSetCurrentThreadNameW(const WCHAR* name); REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalInitComAndFlsSlot(); #endif diff --git a/src/coreclr/nativeaot/Runtime/PalRedhawkFunctions.h b/src/coreclr/nativeaot/Runtime/PalRedhawkFunctions.h index 05d59f10d817d8..271cad80fab970 100644 --- a/src/coreclr/nativeaot/Runtime/PalRedhawkFunctions.h +++ b/src/coreclr/nativeaot/Runtime/PalRedhawkFunctions.h @@ -1,98 +1,21 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -extern "C" uint16_t __stdcall CaptureStackBackTrace(uint32_t, uint32_t, void*, uint32_t*); -inline uint16_t PalCaptureStackBackTrace(uint32_t arg1, uint32_t arg2, void* arg3, uint32_t* arg4) -{ - return CaptureStackBackTrace(arg1, arg2, arg3, arg4); -} - -extern "C" UInt32_BOOL __stdcall CloseHandle(HANDLE); -inline UInt32_BOOL PalCloseHandle(HANDLE arg1) -{ - return CloseHandle(arg1); -} - -extern "C" void __stdcall DeleteCriticalSection(CRITICAL_SECTION *); -inline void PalDeleteCriticalSection(CRITICAL_SECTION * arg1) -{ - DeleteCriticalSection(arg1); -} - -extern "C" void __stdcall EnterCriticalSection(CRITICAL_SECTION *); -inline void PalEnterCriticalSection(CRITICAL_SECTION * arg1) -{ - EnterCriticalSection(arg1); -} - -extern "C" void __stdcall FlushProcessWriteBuffers(); -inline void PalFlushProcessWriteBuffers() -{ - FlushProcessWriteBuffers(); -} - -extern "C" uint32_t __stdcall GetCurrentProcessId(); -inline uint32_t PalGetCurrentProcessId() -{ - return GetCurrentProcessId(); -} +uint16_t PalCaptureStackBackTrace(uint32_t arg1, uint32_t arg2, void* arg3, uint32_t* arg4); +UInt32_BOOL PalCloseHandle(HANDLE arg1); +void PalFlushProcessWriteBuffers(); +uint32_t PalGetCurrentProcessId(); #ifdef UNICODE -_Success_(return != 0 && return < nSize) -extern "C" uint32_t __stdcall GetEnvironmentVariableW(_In_opt_ LPCWSTR lpName, _Out_writes_to_opt_(nSize, return + 1) LPWSTR lpBuffer, _In_ uint32_t nSize); -inline uint32_t PalGetEnvironmentVariable(_In_opt_ LPCWSTR lpName, _Out_writes_to_opt_(nSize, return + 1) LPWSTR lpBuffer, _In_ uint32_t nSize) -{ - return GetEnvironmentVariableW(lpName, lpBuffer, nSize); -} +uint32_t PalGetEnvironmentVariable(_In_opt_ LPCWSTR lpName, _Out_writes_to_opt_(nSize, return + 1) LPWSTR lpBuffer, _In_ uint32_t nSize); #else -_Success_(return != 0 && return < nSize) -extern "C" uint32_t __stdcall GetEnvironmentVariableA(_In_opt_ LPCSTR lpName, _Out_writes_to_opt_(nSize, return + 1) LPSTR lpBuffer, _In_ uint32_t nSize); -inline uint32_t PalGetEnvironmentVariable(_In_opt_ LPCSTR lpName, _Out_writes_to_opt_(nSize, return + 1) LPSTR lpBuffer, _In_ uint32_t nSize) -{ - return GetEnvironmentVariableA(lpName, lpBuffer, nSize); -} +uint32_t PalGetEnvironmentVariable(_In_opt_ LPCSTR lpName, _Out_writes_to_opt_(nSize, return + 1) LPSTR lpBuffer, _In_ uint32_t nSize); #endif -extern "C" UInt32_BOOL __stdcall InitializeCriticalSectionEx(CRITICAL_SECTION *, uint32_t, uint32_t); -inline UInt32_BOOL PalInitializeCriticalSectionEx(CRITICAL_SECTION * arg1, uint32_t arg2, uint32_t arg3) -{ - return InitializeCriticalSectionEx(arg1, arg2, arg3); -} - -extern "C" void __stdcall LeaveCriticalSection(CRITICAL_SECTION *); -inline void PalLeaveCriticalSection(CRITICAL_SECTION * arg1) -{ - LeaveCriticalSection(arg1); -} - -extern "C" UInt32_BOOL __stdcall ResetEvent(HANDLE); -inline UInt32_BOOL PalResetEvent(HANDLE arg1) -{ - return ResetEvent(arg1); -} - -extern "C" UInt32_BOOL __stdcall SetEvent(HANDLE); -inline UInt32_BOOL PalSetEvent(HANDLE arg1) -{ - return SetEvent(arg1); -} - -extern "C" uint32_t __stdcall WaitForSingleObjectEx(HANDLE, uint32_t, UInt32_BOOL); -inline uint32_t PalWaitForSingleObjectEx(HANDLE arg1, uint32_t arg2, UInt32_BOOL arg3) -{ - return WaitForSingleObjectEx(arg1, arg2, arg3); -} +UInt32_BOOL PalResetEvent(HANDLE arg1); +UInt32_BOOL PalSetEvent(HANDLE arg1); +uint32_t PalWaitForSingleObjectEx(HANDLE arg1, uint32_t arg2, UInt32_BOOL arg3); #ifdef PAL_REDHAWK_INCLUDED -extern "C" void __stdcall GetSystemTimeAsFileTime(FILETIME *); -inline void PalGetSystemTimeAsFileTime(FILETIME * arg1) -{ - GetSystemTimeAsFileTime(arg1); -} - -extern "C" void __stdcall RaiseFailFastException(PEXCEPTION_RECORD, PCONTEXT, uint32_t); -inline void PalRaiseFailFastException(PEXCEPTION_RECORD arg1, PCONTEXT arg2, uint32_t arg3) -{ - RaiseFailFastException(arg1, arg2, arg3); -} +void PalGetSystemTimeAsFileTime(FILETIME * arg1); #endif diff --git a/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp b/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp index cbb72fd1aead03..9bdc8ac5ce9079 100644 --- a/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp +++ b/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp @@ -215,7 +215,7 @@ void RuntimeInstance::RegisterCodeManager(ICodeManager * pCodeManager, PTR_VOID m_cbManagedCodeRange = cbRange; } -extern "C" void __stdcall RegisterCodeManager(ICodeManager * pCodeManager, PTR_VOID pvStartRange, uint32_t cbRange) +extern "C" void RegisterCodeManager(ICodeManager * pCodeManager, PTR_VOID pvStartRange, uint32_t cbRange) { GetRuntimeInstance()->RegisterCodeManager(pCodeManager, pvStartRange, cbRange); } @@ -255,7 +255,7 @@ bool RuntimeInstance::IsUnboxingStub(uint8_t* pCode) return false; } -extern "C" bool __stdcall RegisterUnboxingStubs(PTR_VOID pvStartRange, uint32_t cbRange) +extern "C" bool RegisterUnboxingStubs(PTR_VOID pvStartRange, uint32_t cbRange) { return GetRuntimeInstance()->RegisterUnboxingStubs(pvStartRange, cbRange); } diff --git a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp index 59b828ab28e85d..764e503af34896 100644 --- a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp +++ b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp @@ -2,9 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. #include "common.h" -#ifdef HOST_WINDOWS -#include -#endif #include "gcenv.h" #include "CommonTypes.h" #include "CommonMacros.h" diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp index 20d557ec6f8e81..f79ca41ce654a3 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp @@ -9,7 +9,7 @@ #include #include -#ifdef TARGET_WINDOWS +#ifdef HOST_WINDOWS #include #else #include @@ -398,7 +398,7 @@ uint32_t ep_rt_aot_current_process_get_id (void) { STATIC_CONTRACT_NOTHROW; - return static_cast(GetCurrentProcessId ()); + return PalGetCurrentProcessId (); } ep_rt_thread_id_t @@ -432,7 +432,7 @@ ep_rt_aot_system_timestamp_get (void) STATIC_CONTRACT_NOTHROW; FILETIME value; - GetSystemTimeAsFileTime (&value); + PalGetSystemTimeAsFileTime (&value); return static_cast(((static_cast(value.dwHighDateTime)) << 32) | static_cast(value.dwLowDateTime)); } diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h index 207637bf3b9a00..d1206ab16455b5 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h @@ -830,7 +830,7 @@ uint32_t ep_rt_processors_get_count (void) { STATIC_CONTRACT_NOTHROW; -#ifdef _INC_WINDOWS +#ifdef HOST_WINDOWS SYSTEM_INFO sys_info = {}; GetSystemInfo (&sys_info); return static_cast(sys_info.dwNumberOfProcessors); @@ -882,7 +882,7 @@ ep_rt_system_time_get (EventPipeSystemTime *system_time) { STATIC_CONTRACT_NOTHROW; -#ifdef _INC_WINDOWS +#ifdef HOST_WINDOWS SYSTEMTIME value; GetSystemTime (&value); @@ -897,7 +897,7 @@ ep_rt_system_time_get (EventPipeSystemTime *system_time) value.wMinute, value.wSecond, value.wMilliseconds); -#elif TARGET_UNIX +#else time_t tt; struct tm *ut_ptr; struct timeval time_val; diff --git a/src/coreclr/nativeaot/Runtime/gcenv.ee.cpp b/src/coreclr/nativeaot/Runtime/gcenv.ee.cpp index 767375e6af4d8f..9285e676354434 100644 --- a/src/coreclr/nativeaot/Runtime/gcenv.ee.cpp +++ b/src/coreclr/nativeaot/Runtime/gcenv.ee.cpp @@ -63,7 +63,7 @@ void GCToEEInterface::RestartEE(bool /*bFinishedGC*/) // This is needed to synchronize threads that were running in preemptive mode while // the runtime was suspended and that will return to cooperative mode after the runtime // is restarted. - ::FlushProcessWriteBuffers(); + PalFlushProcessWriteBuffers(); #endif // !defined(TARGET_X86) && !defined(TARGET_AMD64) SyncClean::CleanUp(); @@ -404,7 +404,7 @@ void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args) { // If runtime is not suspended, force all threads to see the changed table before seeing updated heap boundaries. // See: http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/346765 - FlushProcessWriteBuffers(); + PalFlushProcessWriteBuffers(); } #endif @@ -415,7 +415,7 @@ void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args) if (!is_runtime_suspended) { // If runtime is not suspended, force all threads to see the changed state before observing future allocations. - FlushProcessWriteBuffers(); + PalFlushProcessWriteBuffers(); } #endif return; @@ -574,7 +574,7 @@ static bool CreateNonSuspendableThread(void (*threadStart)(void*), void* arg, co // Helper used to wrap the start routine of GC threads so we can do things like initialize the // thread state which requires running in the new thread's context. - auto threadStub = [](void* argument) -> DWORD + auto threadStub = [](void* argument) -> uint32_t { ThreadStore::RawGetCurrentThread()->SetGCSpecial(); @@ -618,7 +618,7 @@ bool GCToEEInterface::CreateThread(void (*threadStart)(void*), void* arg, bool i // Helper used to wrap the start routine of background GC threads so we can do things like initialize the // thread state which requires running in the new thread's context. - auto threadStub = [](void* argument) -> DWORD + auto threadStub = [](void* argument) -> uint32_t { ThreadStubArguments* pStartContext = (ThreadStubArguments*)argument; diff --git a/src/coreclr/nativeaot/Runtime/gcenv.h b/src/coreclr/nativeaot/Runtime/gcenv.h index 06e65edb71801f..da485d2ef0c532 100644 --- a/src/coreclr/nativeaot/Runtime/gcenv.h +++ b/src/coreclr/nativeaot/Runtime/gcenv.h @@ -14,6 +14,8 @@ #include #include +#include + #ifdef TARGET_UNIX #include #endif diff --git a/src/coreclr/nativeaot/Runtime/inc/CommonTypes.h b/src/coreclr/nativeaot/Runtime/inc/CommonTypes.h index e77e9878e3ebd2..7776c909c9457b 100644 --- a/src/coreclr/nativeaot/Runtime/inc/CommonTypes.h +++ b/src/coreclr/nativeaot/Runtime/inc/CommonTypes.h @@ -10,6 +10,12 @@ #include #include +#ifdef HOST_WINDOWS +#include +#endif // HOST_WINDOWS + +#include + // Implement pure virtual for Unix (for -p:LinkStandardCPlusPlusLibrary=false the default), // to avoid linker requiring __cxa_pure_virtual. #ifdef TARGET_WINDOWS @@ -29,7 +35,7 @@ using std::intptr_t; typedef wchar_t WCHAR; #define W(str) L##str #else -typedef char16_t WCHAR; +typedef char16_t WCHAR; #define W(str) u##str #endif typedef void * HANDLE; @@ -38,22 +44,18 @@ typedef uint32_t UInt32_BOOL; // windows 4-byte BOOL, 0 -> false, #define UInt32_FALSE 0 #define UInt32_TRUE 1 -#if defined(FEATURE_EVENT_TRACE) && !defined(_INC_WINDOWS) +#if defined(FEATURE_EVENT_TRACE) && defined(TARGET_UNIX) typedef int BOOL; typedef void* LPVOID; typedef uint32_t UINT; typedef void* PVOID; typedef uint64_t ULONGLONG; typedef uintptr_t ULONG_PTR; -#ifdef _MSC_VER -typedef unsigned long ULONG; -#else typedef uint32_t ULONG; -#endif typedef int64_t LONGLONG; typedef uint8_t BYTE; typedef uint16_t UINT16; -#endif // FEATURE_EVENT_TRACE && !_INC_WINDOWS +#endif // FEATURE_EVENT_TRACE && TARGET_UNIX // Hijack funcs are not called, they are "returned to". And when done, they return to the actual caller. // Thus they cannot have any parameters or return anything. diff --git a/src/coreclr/nativeaot/Runtime/rhassert.cpp b/src/coreclr/nativeaot/Runtime/rhassert.cpp index 970a0b025700da..f66ec3f7d02a3b 100644 --- a/src/coreclr/nativeaot/Runtime/rhassert.cpp +++ b/src/coreclr/nativeaot/Runtime/rhassert.cpp @@ -31,7 +31,7 @@ void Assert(const char * expr, const char * file, uint32_t line_num, const char // If there's no debugger attached, we just FailFast if (!minipal_is_native_debugger_present()) - PalRaiseFailFastException(NULL, NULL, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS); + RhFailFast(); // If there is a debugger attached, we break and then allow continuation. PalDebugBreak(); diff --git a/src/coreclr/nativeaot/Runtime/rhassert.h b/src/coreclr/nativeaot/Runtime/rhassert.h index 34403e216f5b16..de725ae26bdafa 100644 --- a/src/coreclr/nativeaot/Runtime/rhassert.h +++ b/src/coreclr/nativeaot/Runtime/rhassert.h @@ -60,8 +60,10 @@ void Assert(const char * expr, const char * file, unsigned int line_num, const c ASSERT_UNCONDITIONALLY(message); \ ASSUME(0); \ -#define FAIL_FAST_GENERATE_EXCEPTION_ADDRESS 0x1 - -#define RhFailFast() RaiseFailFastException(NULL, NULL, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS) +#ifdef HOST_WINDOWS +#define RhFailFast() ::RaiseFailFastException(NULL, NULL, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS) +#else +void RhFailFast(); +#endif // HOST_WINDOWS #endif // __RHASSERT_H__ diff --git a/src/coreclr/nativeaot/Runtime/startup.cpp b/src/coreclr/nativeaot/Runtime/startup.cpp index 78c6429944df78..bfc9fe189e886b 100644 --- a/src/coreclr/nativeaot/Runtime/startup.cpp +++ b/src/coreclr/nativeaot/Runtime/startup.cpp @@ -1,9 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #include "common.h" -#ifdef HOST_WINDOWS -#include -#endif #include "CommonTypes.h" #include "CommonMacros.h" #include "daccess.h" diff --git a/src/coreclr/nativeaot/Runtime/thread.cpp b/src/coreclr/nativeaot/Runtime/thread.cpp index d4ed62a1881c5a..8fbf8a8e20fd78 100644 --- a/src/coreclr/nativeaot/Runtime/thread.cpp +++ b/src/coreclr/nativeaot/Runtime/thread.cpp @@ -2,9 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. #include "common.h" -#ifdef HOST_WINDOWS -#include -#endif #include "gcenv.h" #include "gcheaputilities.h" @@ -906,19 +903,19 @@ void Thread::Unhijack() } // This unhijack routine is called to undo a hijack, that is potentially on a different thread. -// +// // Although there are many code sequences (here and in asm) to // perform an unhijack operation, they will never execute concurrently: -// +// // - A thread may unhijack itself at any time so long as it does that from unmanaged code while in coop mode. // This ensures that coop thread can access its stack synchronously. // Unhijacking from unmanaged code ensures that another thread will not attempt to hijack it, // since we only hijack threads that are executing managed code. -// +// // - A GC thread may access a thread asynchronously, including unhijacking it. // Asynchronously accessed thread must be in preemptive mode and should not // access the managed portion of its stack. -// +// // - A thread that owns the suspension can access another thread as long as the other thread is // in preemptive mode or suspended in managed code. // Either way the other thread cannot be accessing its hijack. diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index 5a7435a5df7528..d8f94c513ee3dc 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -68,8 +68,6 @@ using std::nullptr_t; -#define PalRaiseFailFastException RaiseFailFastException - #define INVALID_HANDLE_VALUE ((HANDLE)(intptr_t)-1) #define PAGE_NOACCESS 0x01 @@ -88,7 +86,7 @@ static const int tccMilliSecondsToMicroSeconds = 1000; static const int tccMilliSecondsToNanoSeconds = 1000000; static const int tccMicroSecondsToNanoSeconds = 1000; -extern "C" void RaiseFailFastException(PEXCEPTION_RECORD arg1, PCONTEXT arg2, uint32_t arg3) +void RhFailFast() { // Causes creation of a crash dump if enabled PalCreateCrashDumpIfEnabled(); @@ -632,7 +630,7 @@ REDHAWK_PALEXPORT UInt32_BOOL REDHAWK_PALAPI PalAreShadowStacksEnabled() return false; } -extern "C" UInt32_BOOL CloseHandle(HANDLE handle) +UInt32_BOOL PalCloseHandle(HANDLE handle) { if ((handle == NULL) || (handle == INVALID_HANDLE_VALUE)) { @@ -868,67 +866,26 @@ REDHAWK_PALEXPORT void PalFlushInstructionCache(_In_ void* pAddress, size_t size #endif } -extern "C" uint32_t GetCurrentProcessId() +uint32_t PalGetCurrentProcessId() { return getpid(); } -extern "C" UInt32_BOOL InitializeCriticalSection(CRITICAL_SECTION * lpCriticalSection) -{ - pthread_mutexattr_t mutexAttributes; - int st = pthread_mutexattr_init(&mutexAttributes); - if (st != 0) - { - return false; - } - - st = pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE); - if (st == 0) - { - st = pthread_mutex_init(&lpCriticalSection->mutex, &mutexAttributes); - } - - pthread_mutexattr_destroy(&mutexAttributes); - - return (st == 0); -} - -extern "C" UInt32_BOOL InitializeCriticalSectionEx(CRITICAL_SECTION * lpCriticalSection, uint32_t arg2, uint32_t arg3) -{ - return InitializeCriticalSection(lpCriticalSection); -} - - -extern "C" void DeleteCriticalSection(CRITICAL_SECTION * lpCriticalSection) -{ - pthread_mutex_destroy(&lpCriticalSection->mutex); -} - -extern "C" void EnterCriticalSection(CRITICAL_SECTION * lpCriticalSection) -{ - pthread_mutex_lock(&lpCriticalSection->mutex);; -} - -extern "C" void LeaveCriticalSection(CRITICAL_SECTION * lpCriticalSection) -{ - pthread_mutex_unlock(&lpCriticalSection->mutex); -} - -extern "C" UInt32_BOOL SetEvent(HANDLE event) +UInt32_BOOL PalSetEvent(HANDLE event) { UnixEvent* unixEvent = (UnixEvent*)event; unixEvent->Set(); return UInt32_TRUE; } -extern "C" UInt32_BOOL ResetEvent(HANDLE event) +UInt32_BOOL PalResetEvent(HANDLE event) { UnixEvent* unixEvent = (UnixEvent*)event; unixEvent->Reset(); return UInt32_TRUE; } -extern "C" uint32_t GetEnvironmentVariableA(const char * name, char * buffer, uint32_t size) +uint32_t PalGetEnvironmentVariable(const char * name, char * buffer, uint32_t size) { const char* value = getenv(name); if (value == NULL) @@ -947,7 +904,7 @@ extern "C" uint32_t GetEnvironmentVariableA(const char * name, char * buffer, ui return (valueLen < UINT32_MAX) ? (valueLen + 1) : 0; } -extern "C" uint16_t RtlCaptureStackBackTrace(uint32_t arg1, uint32_t arg2, void* arg3, uint32_t* arg4) +uint16_t PalCaptureStackBackTrace(uint32_t arg1, uint32_t arg2, void* arg3, uint32_t* arg4) { // UNIXTODO: Implement this function return 0; @@ -1062,7 +1019,7 @@ REDHAWK_PALEXPORT void REDHAWK_PALAPI PalHijack(Thread* pThreadToHijack) } #endif // FEATURE_HIJACK -extern "C" uint32_t WaitForSingleObjectEx(HANDLE handle, uint32_t milliseconds, UInt32_BOOL alertable) +uint32_t PalWaitForSingleObjectEx(HANDLE handle, uint32_t milliseconds, UInt32_BOOL alertable) { UnixEvent* unixEvent = (UnixEvent*)handle; return unixEvent->Wait(milliseconds); @@ -1073,7 +1030,7 @@ REDHAWK_PALEXPORT uint32_t REDHAWK_PALAPI PalCompatibleWaitAny(UInt32_BOOL alert // Only a single handle wait for event is supported ASSERT(handleCount == 1); - return WaitForSingleObjectEx(pHandles[0], timeout, alertable); + return PalWaitForSingleObjectEx(pHandles[0], timeout, alertable); } REDHAWK_PALEXPORT HANDLE PalCreateLowMemoryResourceNotification() @@ -1178,7 +1135,7 @@ REDHAWK_PALEXPORT int32_t PalGetModuleFileName(_Out_ const TCHAR** pModuleNameOu #endif // defined(HOST_WASM) } -extern "C" void FlushProcessWriteBuffers() +void PalFlushProcessWriteBuffers() { GCToOSInterface::FlushProcessWriteBuffers(); } @@ -1186,7 +1143,7 @@ extern "C" void FlushProcessWriteBuffers() static const int64_t SECS_BETWEEN_1601_AND_1970_EPOCHS = 11644473600LL; static const int64_t SECS_TO_100NS = 10000000; /* 10^7 */ -extern "C" void GetSystemTimeAsFileTime(FILETIME *lpSystemTimeAsFileTime) +void PalGetSystemTimeAsFileTime(FILETIME *lpSystemTimeAsFileTime) { struct timeval time = { 0 }; gettimeofday(&time, NULL); diff --git a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp index 26df766b18b4a8..531e6db8904fab 100644 --- a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp @@ -966,7 +966,7 @@ bool CoffNativeCodeManager::GetReturnAddressHijackInfo(MethodInfo * pMethodIn *ppvRetAddrLocation = (PTR_PTR_VOID)registerSet.PCTAddr; return true; -#endif +#endif } #ifdef TARGET_X86 @@ -1146,8 +1146,8 @@ PTR_VOID CoffNativeCodeManager::GetAssociatedData(PTR_VOID ControlPC) return dac_cast(m_moduleBase + dataRVA); } -extern "C" void __stdcall RegisterCodeManager(ICodeManager * pCodeManager, PTR_VOID pvStartRange, uint32_t cbRange); -extern "C" bool __stdcall RegisterUnboxingStubs(PTR_VOID pvStartRange, uint32_t cbRange); +extern "C" void RegisterCodeManager(ICodeManager * pCodeManager, PTR_VOID pvStartRange, uint32_t cbRange); +extern "C" bool RegisterUnboxingStubs(PTR_VOID pvStartRange, uint32_t cbRange); extern "C" bool RhRegisterOSModule(void * pModule, diff --git a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp index fbab660b11f6f3..56a088f524ae60 100644 --- a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp @@ -21,8 +21,6 @@ #define _T(s) L##s #include "RhConfig.h" -#define PalRaiseFailFastException RaiseFailFastException - #include "gcenv.h" #include "gcenv.ee.h" #include "gcconfig.h" @@ -1038,3 +1036,51 @@ void SetSSP(CONTEXT *pContext, uintptr_t ssp) } } #endif // TARGET_AMD64 + +uint16_t PalCaptureStackBackTrace(uint32_t arg1, uint32_t arg2, void* arg3, uint32_t* arg4) +{ + DWORD backTraceHash; + WORD res = ::RtlCaptureStackBackTrace(arg1, arg2, (PVOID*)arg3, &backTraceHash); + *arg4 = backTraceHash; + return res; +} + +UInt32_BOOL PalCloseHandle(HANDLE arg1) +{ + return ::CloseHandle(arg1); +} + +void PalFlushProcessWriteBuffers() +{ + ::FlushProcessWriteBuffers(); +} + +uint32_t PalGetCurrentProcessId() +{ + return static_cast(::GetCurrentProcessId()); +} + +uint32_t PalGetEnvironmentVariable(_In_opt_ LPCWSTR lpName, _Out_writes_to_opt_(nSize, return + 1) LPWSTR lpBuffer, _In_ uint32_t nSize) +{ + return ::GetEnvironmentVariableW(lpName, lpBuffer, nSize); +} + +UInt32_BOOL PalResetEvent(HANDLE arg1) +{ + return ::ResetEvent(arg1); +} + +UInt32_BOOL PalSetEvent(HANDLE arg1) +{ + return ::SetEvent(arg1); +} + +uint32_t PalWaitForSingleObjectEx(HANDLE arg1, uint32_t arg2, UInt32_BOOL arg3) +{ + return ::WaitForSingleObjectEx(arg1, arg2, arg3); +} + +void PalGetSystemTimeAsFileTime(FILETIME * arg1) +{ + ::GetSystemTimeAsFileTime(arg1); +} diff --git a/src/coreclr/pal/inc/pal.h b/src/coreclr/pal/inc/pal.h index 3c450af44d7659..a2c3c285a85f60 100644 --- a/src/coreclr/pal/inc/pal.h +++ b/src/coreclr/pal/inc/pal.h @@ -2545,77 +2545,6 @@ PALIMPORT BOOL PALAPI PAL_VirtualUnwindOutOfProc(CONTEXT *context, KNONVOLATILE_ PALIMPORT BOOL PALAPI PAL_GetUnwindInfoSize(SIZE_T baseAddress, ULONG64 ehFrameHdrAddr, UnwindReadMemoryCallback readMemoryCallback, PULONG64 ehFrameStart, PULONG64 ehFrameSize); -/* PAL_CS_NATIVE_DATA_SIZE is defined as sizeof(PAL_CRITICAL_SECTION_NATIVE_DATA) */ - -#if defined(__APPLE__) && defined(__i386__) -#define PAL_CS_NATIVE_DATA_SIZE 76 -#elif defined(__APPLE__) && defined(HOST_AMD64) -#define PAL_CS_NATIVE_DATA_SIZE 120 -#elif defined(__APPLE__) && defined(HOST_ARM64) -#define PAL_CS_NATIVE_DATA_SIZE 120 -#elif defined(__FreeBSD__) && defined(HOST_X86) -#define PAL_CS_NATIVE_DATA_SIZE 12 -#elif defined(__FreeBSD__) && defined(__x86_64__) -#define PAL_CS_NATIVE_DATA_SIZE 24 -#elif defined(__FreeBSD__) && defined(HOST_ARM64) -#define PAL_CS_NATIVE_DATA_SIZE 24 -#elif defined(__linux__) && defined(HOST_ARM) -#define PAL_CS_NATIVE_DATA_SIZE 80 -#elif defined(__linux__) && defined(HOST_ARM64) -#define PAL_CS_NATIVE_DATA_SIZE 104 -#elif defined(__linux__) && defined(__i386__) -#define PAL_CS_NATIVE_DATA_SIZE 76 -#elif defined(__linux__) && defined(__x86_64__) -#define PAL_CS_NATIVE_DATA_SIZE 96 -#elif defined(__linux__) && defined(HOST_S390X) -#define PAL_CS_NATIVE_DATA_SIZE 96 -#elif defined(__linux__) && defined(HOST_POWERPC64) -#define PAL_CS_NATIVE_DATA_SIZE 96 -#elif defined(__NetBSD__) && defined(__amd64__) -#define PAL_CS_NATIVE_DATA_SIZE 96 -#elif defined(__NetBSD__) && defined(__earm__) -#define PAL_CS_NATIVE_DATA_SIZE 56 -#elif defined(__NetBSD__) && defined(__i386__) -#define PAL_CS_NATIVE_DATA_SIZE 56 -#elif defined(__sun) && defined(__x86_64__) -#define PAL_CS_NATIVE_DATA_SIZE 48 -#elif defined(__linux__) && defined(__loongarch64) -#define PAL_CS_NATIVE_DATA_SIZE 96 -#elif defined(__linux__) && defined(__riscv) && __riscv_xlen == 64 -#define PAL_CS_NATIVE_DATA_SIZE 96 -#elif defined(__HAIKU__) && defined(__x86_64__) -#define PAL_CS_NATIVE_DATA_SIZE 56 -#elif defined(HOST_WASM) -#define PAL_CS_NATIVE_DATA_SIZE 76 -#else -#error PAL_CS_NATIVE_DATA_SIZE is not defined for this architecture -#endif - -// -typedef struct _CRITICAL_SECTION { - PVOID DebugInfo; - LONG LockCount; - LONG RecursionCount; - HANDLE OwningThread; - ULONG_PTR SpinCount; - -#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA - BOOL bInternal; -#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA - volatile DWORD dwInitState; - - union CSNativeDataStorage - { - BYTE rgNativeDataStorage[PAL_CS_NATIVE_DATA_SIZE]; - PVOID pvAlign; // make sure the storage is machine-pointer-size aligned - } csnds; -} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION; - -PALIMPORT VOID PALAPI EnterCriticalSection(IN OUT LPCRITICAL_SECTION lpCriticalSection); -PALIMPORT VOID PALAPI LeaveCriticalSection(IN OUT LPCRITICAL_SECTION lpCriticalSection); -PALIMPORT VOID PALAPI InitializeCriticalSection(OUT LPCRITICAL_SECTION lpCriticalSection); -PALIMPORT VOID PALAPI DeleteCriticalSection(IN OUT LPCRITICAL_SECTION lpCriticalSection); - #define PAGE_NOACCESS 0x01 #define PAGE_READONLY 0x02 #define PAGE_READWRITE 0x04 diff --git a/src/coreclr/pal/src/CMakeLists.txt b/src/coreclr/pal/src/CMakeLists.txt index 34461f79c9ae5c..a850607a20c359 100644 --- a/src/coreclr/pal/src/CMakeLists.txt +++ b/src/coreclr/pal/src/CMakeLists.txt @@ -201,7 +201,6 @@ set(SOURCES safecrt/wcsncpy_s.cpp safecrt/wmakepath_s.cpp sharedmemory/sharedmemory.cpp - sync/cs.cpp synchobj/event.cpp synchobj/semaphore.cpp synchobj/mutex.cpp diff --git a/src/coreclr/pal/src/exception/machexception.cpp b/src/coreclr/pal/src/exception/machexception.cpp index cfa8269cc86a3c..f52519959a8736 100644 --- a/src/coreclr/pal/src/exception/machexception.cpp +++ b/src/coreclr/pal/src/exception/machexception.cpp @@ -21,7 +21,6 @@ SET_DEFAULT_DEBUG_CHANNEL(EXCEPT); // some headers have code with asserts, so do #include "pal/palinternal.h" #if HAVE_MACH_EXCEPTIONS #include "machexception.h" -#include "pal/critsect.h" #include "pal/debug.h" #include "pal/init.h" #include "pal/utils.h" diff --git a/src/coreclr/pal/src/exception/remote-unwind.cpp b/src/coreclr/pal/src/exception/remote-unwind.cpp index 67ab6c644389d0..0ea3787210ef06 100644 --- a/src/coreclr/pal/src/exception/remote-unwind.cpp +++ b/src/coreclr/pal/src/exception/remote-unwind.cpp @@ -43,7 +43,6 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "config.h" #include "pal/palinternal.h" #include "pal/dbgmsg.h" -#include "pal/critsect.h" #include "pal/debug.h" #include "pal_endian.h" #include "pal.h" @@ -2329,7 +2328,7 @@ find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pip, int nee return unw_get_proc_info_in_range(start_ip, end_ip, ehFrameHdrAddr, ehFrameHdrLen, exidxFrameHdrAddr, exidxFrameHdrLen, as, ip, pip, need_unwind_info, arg); #else // HAVE_GET_PROC_INFO_IN_RANGE || !defined(HOST_UNIX) - // This branch is executed when using llvm-libunwind (macOS and similar platforms) + // This branch is executed when using llvm-libunwind (macOS and similar platforms) // or HP-libunwind version 1.6 and earlier. if (ehFrameHdrAddr == 0) { diff --git a/src/coreclr/pal/src/exception/seh.cpp b/src/coreclr/pal/src/exception/seh.cpp index edee8bd071fc62..c2f28cff936c96 100644 --- a/src/coreclr/pal/src/exception/seh.cpp +++ b/src/coreclr/pal/src/exception/seh.cpp @@ -21,7 +21,6 @@ Module Name: #include "pal/handleapi.hpp" #include "pal/seh.hpp" #include "pal/dbgmsg.h" -#include "pal/critsect.h" #include "pal/debug.h" #include "pal/init.h" #include "pal/process.h" diff --git a/src/coreclr/pal/src/handlemgr/handlemgr.cpp b/src/coreclr/pal/src/handlemgr/handlemgr.cpp index 7a3b5c20912aa7..da7d72036ba154 100644 --- a/src/coreclr/pal/src/handlemgr/handlemgr.cpp +++ b/src/coreclr/pal/src/handlemgr/handlemgr.cpp @@ -19,7 +19,6 @@ Module Name: #include "pal/thread.hpp" #include "pal/handlemgr.hpp" -#include "pal/cs.hpp" #include "pal/dbgmsg.h" using namespace CorUnix; @@ -41,7 +40,7 @@ CSimpleHandleManager::Initialize( { PAL_ERROR palError = NO_ERROR; - InternalInitializeCriticalSection(&m_csLock); + minipal_mutex_init(&m_mtxLock); m_fLockInitialized = TRUE; m_dwTableGrowthRate = c_BasicGrowthRate; diff --git a/src/coreclr/pal/src/include/pal/critsect.h b/src/coreclr/pal/src/include/pal/critsect.h deleted file mode 100644 index c14baf20a1e4c5..00000000000000 --- a/src/coreclr/pal/src/include/pal/critsect.h +++ /dev/null @@ -1,44 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*++ - - - -Module Name: - - include/pal/critsect.h - -Abstract: - - Header file for the critical sections functions. - - - ---*/ - -#ifndef _PAL_CRITSECT_H_ -#define _PAL_CRITSECT_H_ - -#ifdef __cplusplus -extern "C" -{ -#endif // __cplusplus - -VOID InternalInitializeCriticalSection(CRITICAL_SECTION *pcs); -VOID InternalDeleteCriticalSection(CRITICAL_SECTION *pcs); - -/* The following PALCEnterCriticalSection and PALCLeaveCriticalSection - functions are intended to provide CorUnix's InternalEnterCriticalSection - and InternalLeaveCriticalSection functionalities to legacy C code, - which has no knowledge of CPalThread, classes and namespaces. -*/ -VOID PALCEnterCriticalSection(CRITICAL_SECTION *pcs); -VOID PALCLeaveCriticalSection(CRITICAL_SECTION *pcs); - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif /* _PAL_CRITSECT_H_ */ - diff --git a/src/coreclr/pal/src/include/pal/cs.hpp b/src/coreclr/pal/src/include/pal/cs.hpp deleted file mode 100644 index cb374ffa1ec0ff..00000000000000 --- a/src/coreclr/pal/src/include/pal/cs.hpp +++ /dev/null @@ -1,49 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/////////////////////////////////////////////////////////////////////////////// -// -// File: -// cs.cpp -// -// Purpose: -// Header file for critical sections implementation -// - -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _PAL_CS_HPP -#define _PAL_CS_HPP - -#include "corunix.hpp" -#include "critsect.h" - -namespace CorUnix -{ - void CriticalSectionSubSysInitialize(void); - - void InternalInitializeCriticalSectionAndSpinCount( - PCRITICAL_SECTION pCriticalSection, - DWORD dwSpinCount, - bool fInternal); - - void InternalEnterCriticalSection( - CPalThread *pThread, - CRITICAL_SECTION *pcs - ); - - void InternalLeaveCriticalSection( - CPalThread *pThread, - CRITICAL_SECTION *pcs - ); - -#ifdef _DEBUG - void PALCS_ReportStatisticalData(void); - void PALCS_DumpCSList(); -#endif // _DEBUG - -} - -#endif // _PAL_CS_HPP - diff --git a/src/coreclr/pal/src/include/pal/environ.h b/src/coreclr/pal/src/include/pal/environ.h index 226279c0425b58..14262470c4474d 100644 --- a/src/coreclr/pal/src/include/pal/environ.h +++ b/src/coreclr/pal/src/include/pal/environ.h @@ -18,6 +18,8 @@ Module Name: #ifndef __ENVIRON_H_ #define __ENVIRON_H_ +#include + #ifdef __cplusplus extern "C" { @@ -32,7 +34,7 @@ Variables : gcsEnvironment: critical section to synchronize access to palEnvironment --*/ extern char **palEnvironment; -extern CRITICAL_SECTION gcsEnvironment; +extern minipal_mutex gcsEnvironment; /*++ diff --git a/src/coreclr/pal/src/include/pal/handlemgr.hpp b/src/coreclr/pal/src/include/pal/handlemgr.hpp index f6a3b5d1637476..1e00a647357392 100644 --- a/src/coreclr/pal/src/include/pal/handlemgr.hpp +++ b/src/coreclr/pal/src/include/pal/handlemgr.hpp @@ -22,9 +22,8 @@ Module Name: #include "corunix.hpp" -#include "cs.hpp" #include "pal/thread.hpp" - +#include /* Pseudo handles constant for current thread and process */ extern const HANDLE hPseudoCurrentProcess; @@ -72,7 +71,7 @@ namespace CorUnix DWORD m_dwTableGrowthRate; HANDLE_TABLE_ENTRY* m_rghteHandleTable; - CRITICAL_SECTION m_csLock; + minipal_mutex m_mtxLock; bool m_fLockInitialized; bool ValidateHandle(HANDLE h); @@ -95,7 +94,7 @@ namespace CorUnix { if (m_fLockInitialized) { - DeleteCriticalSection(&m_csLock); + minipal_mutex_destroy(&m_mtxLock); } if (NULL != m_rghteHandleTable) @@ -138,7 +137,7 @@ namespace CorUnix CPalThread *pThread ) { - InternalEnterCriticalSection(pThread, &m_csLock); + minipal_mutex_enter(&m_mtxLock); }; void @@ -146,7 +145,7 @@ namespace CorUnix CPalThread *pThread ) { - InternalLeaveCriticalSection(pThread, &m_csLock); + minipal_mutex_leave(&m_mtxLock); }; }; diff --git a/src/coreclr/pal/src/include/pal/palinternal.h b/src/coreclr/pal/src/include/pal/palinternal.h index 75ec473e8e8872..073d8435e24c91 100644 --- a/src/coreclr/pal/src/include/pal/palinternal.h +++ b/src/coreclr/pal/src/include/pal/palinternal.h @@ -164,6 +164,7 @@ function_name() to call the system's implementation #undef __real_type_class #endif +#include #include "pal.h" #include "palprivate.h" diff --git a/src/coreclr/pal/src/include/pal/sharedmemory.h b/src/coreclr/pal/src/include/pal/sharedmemory.h index c1ec1b9b6ae2d3..84a35d2b237dd6 100644 --- a/src/coreclr/pal/src/include/pal/sharedmemory.h +++ b/src/coreclr/pal/src/include/pal/sharedmemory.h @@ -259,7 +259,7 @@ class SharedMemoryProcessDataHeader class SharedMemoryManager { private: - static CRITICAL_SECTION s_creationDeletionProcessLock; + static minipal_mutex s_creationDeletionProcessLock; static int s_creationDeletionLockFileDescriptor; struct UserScopeUidAndFileDescriptor diff --git a/src/coreclr/pal/src/include/pal/synchcache.hpp b/src/coreclr/pal/src/include/pal/synchcache.hpp index b2020d4ad2630f..81ecec769a3114 100644 --- a/src/coreclr/pal/src/include/pal/synchcache.hpp +++ b/src/coreclr/pal/src/include/pal/synchcache.hpp @@ -30,7 +30,7 @@ namespace CorUnix static const int MaxDepth = 256; Volatile m_pHead; - CRITICAL_SECTION m_cs; + minipal_mutex m_cs; Volatile m_iDepth; int m_iMaxDepth; #ifdef _DEBUG @@ -38,9 +38,9 @@ namespace CorUnix #endif void Lock(CPalThread * pthrCurrent) - { InternalEnterCriticalSection(pthrCurrent, &m_cs); } + { minipal_mutex_enter(&m_cs); } void Unlock(CPalThread * pthrCurrent) - { InternalLeaveCriticalSection(pthrCurrent, &m_cs); } + { minipal_mutex_leave(&m_cs); } public: CSynchCache(int iMaxDepth = MaxDepth) : @@ -51,7 +51,7 @@ namespace CorUnix ,m_iMaxTrackedDepth(0) #endif { - InternalInitializeCriticalSection(&m_cs); + minipal_mutex_init(&m_cs); if (m_iMaxDepth < 0) { m_iMaxDepth = 0; @@ -61,7 +61,7 @@ namespace CorUnix ~CSynchCache() { Flush(NULL, true); - InternalDeleteCriticalSection(&m_cs); + minipal_mutex_destroy(&m_cs); } #ifdef _DEBUG @@ -205,7 +205,7 @@ namespace CorUnix // cache before continuing Volatile m_pHead; - CRITICAL_SECTION m_cs; + minipal_mutex m_cs; Volatile m_iDepth; int m_iMaxDepth; #ifdef _DEBUG @@ -213,9 +213,9 @@ namespace CorUnix #endif void Lock(CPalThread * pthrCurrent) - { InternalEnterCriticalSection(pthrCurrent, &m_cs); } + { minipal_mutex_enter(&m_cs); } void Unlock(CPalThread * pthrCurrent) - { InternalLeaveCriticalSection(pthrCurrent, &m_cs); } + { minipal_mutex_leave(&m_cs); } public: CSHRSynchCache(int iMaxDepth = MaxDepth) : @@ -226,7 +226,7 @@ namespace CorUnix ,m_iMaxTrackedDepth(0) #endif { - InternalInitializeCriticalSection(&m_cs); + minipal_mutex_init(&m_cs); if (m_iMaxDepth < 0) { m_iMaxDepth = 0; @@ -236,7 +236,7 @@ namespace CorUnix ~CSHRSynchCache() { Flush(NULL, true); - InternalDeleteCriticalSection(&m_cs); + minipal_mutex_destroy(&m_cs); } #ifdef _DEBUG diff --git a/src/coreclr/pal/src/include/pal/thread.hpp b/src/coreclr/pal/src/include/pal/thread.hpp index 66776300e01581..236bb6d49d9d84 100644 --- a/src/coreclr/pal/src/include/pal/thread.hpp +++ b/src/coreclr/pal/src/include/pal/thread.hpp @@ -20,7 +20,6 @@ Module Name: #define _PAL_THREAD_HPP_ #include "corunix.hpp" -#include "cs.hpp" #include #if HAVE_MACH_EXCEPTIONS @@ -32,6 +31,7 @@ Module Name: #include "synchobjects.hpp" #include #include +#include namespace CorUnix { @@ -203,7 +203,7 @@ namespace CorUnix CPalThread *m_pNext; DWORD m_dwExitCode; BOOL m_fExitCodeSet; - CRITICAL_SECTION m_csLock; + minipal_mutex m_mtxLock; bool m_fLockInitialized; bool m_fIsDummy; @@ -372,7 +372,7 @@ namespace CorUnix CPalThread *pThread ) { - InternalEnterCriticalSection(pThread, &m_csLock); + minipal_mutex_enter(&m_mtxLock); }; void @@ -380,7 +380,7 @@ namespace CorUnix CPalThread *pThread ) { - InternalLeaveCriticalSection(pThread, &m_csLock); + minipal_mutex_leave(&m_mtxLock); }; // diff --git a/src/coreclr/pal/src/init/pal.cpp b/src/coreclr/pal/src/init/pal.cpp index c1d7984ca927b3..6811690132daed 100644 --- a/src/coreclr/pal/src/init/pal.cpp +++ b/src/coreclr/pal/src/init/pal.cpp @@ -19,7 +19,6 @@ SET_DEFAULT_DEBUG_CHANNEL(PAL); // some headers have code with asserts, so do th #include "pal/thread.hpp" #include "pal/synchobjects.hpp" #include "pal/procobj.hpp" -#include "pal/cs.hpp" #include "pal/file.hpp" #include "pal/map.hpp" #include "../objmgr/listedobjectmanager.hpp" @@ -111,7 +110,7 @@ BOOL g_useDefaultBaseAddr = FALSE; /* critical section to protect access to init_count. This is allocated on the very first PAL_Initialize call, and is freed afterward. */ -static PCRITICAL_SECTION init_critsec = NULL; +static minipal_mutex* init_critsec = NULL; static DWORD g_initializeDLLFlags = PAL_INITIALIZE_DLL; @@ -311,31 +310,29 @@ Initialize( /*Firstly initiate a lastError */ SetLastError(ERROR_GEN_FAILURE); - CriticalSectionSubSysInitialize(); - if(nullptr == init_critsec) { pthread_mutex_lock(&init_critsec_mutex); // prevents race condition of two threads // initializing the critical section. if(nullptr == init_critsec) { - static CRITICAL_SECTION temp_critsec; + static minipal_mutex temp_critsec; // Want this critical section to NOT be internal to avoid the use of unsafe region markers. - InternalInitializeCriticalSectionAndSpinCount(&temp_critsec, 0, false); + minipal_mutex_init(&temp_critsec); if(nullptr != InterlockedCompareExchangePointer(&init_critsec, &temp_critsec, nullptr)) { // Another thread got in before us! shouldn't happen, if the PAL // isn't initialized there shouldn't be any other threads WARN("Another thread initialized the critical section\n"); - InternalDeleteCriticalSection(&temp_critsec); + minipal_mutex_destroy(&temp_critsec); } } pthread_mutex_unlock(&init_critsec_mutex); } - InternalEnterCriticalSection(pThread, init_critsec); // here pThread is always nullptr + minipal_mutex_enter(init_critsec); if (init_count == 0) { @@ -670,7 +667,7 @@ Initialize( ERROR("PAL_Initialize failed\n"); SetLastError(palError); done: - InternalLeaveCriticalSection(pThread, init_critsec); + minipal_mutex_leave(init_critsec); if (fFirstTimeInit && 0 == retval) { @@ -882,10 +879,7 @@ BOOL PALInitLock(void) return FALSE; } - CPalThread * pThread = - (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : nullptr); - - InternalEnterCriticalSection(pThread, init_critsec); + minipal_mutex_enter(init_critsec); return TRUE; } @@ -904,10 +898,7 @@ void PALInitUnlock(void) return; } - CPalThread * pThread = - (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : nullptr); - - InternalLeaveCriticalSection(pThread, init_critsec); + minipal_mutex_leave(init_critsec); } /* Internal functions *********************************************************/ diff --git a/src/coreclr/pal/src/loader/module.cpp b/src/coreclr/pal/src/loader/module.cpp index a81fa0664d631f..d7cff970a0b02e 100644 --- a/src/coreclr/pal/src/loader/module.cpp +++ b/src/coreclr/pal/src/loader/module.cpp @@ -24,7 +24,6 @@ SET_DEFAULT_DEBUG_CHANNEL(LOADER); // some headers have code with asserts, so do #include "pal/file.hpp" #include "pal/palinternal.h" #include "pal/module.h" -#include "pal/cs.hpp" #include "pal/process.h" #include "pal/file.h" #include "pal/utils.h" @@ -74,7 +73,7 @@ using namespace CorUnix; /* static variables ***********************************************************/ /* critical section that regulates access to the module list */ -CRITICAL_SECTION module_critsec; +minipal_mutex module_critsec; /* always the first, in the in-load-order list */ MODSTRUCT exe_module; @@ -1010,7 +1009,7 @@ BOOL LOADInitializeModules() { _ASSERTE(exe_module.prev == nullptr); - InternalInitializeCriticalSection(&module_critsec); + minipal_mutex_init(&module_critsec); // Initialize module for main executable TRACE("Initializing module for main executable\n"); @@ -1864,7 +1863,7 @@ void LockModuleList() CPalThread * pThread = (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : nullptr); - InternalEnterCriticalSection(pThread, &module_critsec); + minipal_mutex_enter(&module_critsec); } /*++ @@ -1886,5 +1885,5 @@ void UnlockModuleList() CPalThread * pThread = (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : nullptr); - InternalLeaveCriticalSection(pThread, &module_critsec); + minipal_mutex_leave(&module_critsec); } diff --git a/src/coreclr/pal/src/map/map.cpp b/src/coreclr/pal/src/map/map.cpp index 35909bd54f8356..8900ccd1058c01 100644 --- a/src/coreclr/pal/src/map/map.cpp +++ b/src/coreclr/pal/src/map/map.cpp @@ -21,7 +21,6 @@ Module Name: #include "pal/palinternal.h" #include "pal/dbgmsg.h" #include "pal/init.h" -#include "pal/critsect.h" #include "pal/virtual.h" #include "pal/environ.h" #include "common.h" @@ -55,7 +54,7 @@ SET_DEFAULT_DEBUG_CHANNEL(VIRTUAL); // this critical section. // -CRITICAL_SECTION mapping_critsec; +minipal_mutex mapping_critsec; LIST_ENTRY MappedViewList; #ifndef CORECLR @@ -920,7 +919,7 @@ CorUnix::InternalMapViewOfFile( goto InternalMapViewOfFileExit; } - InternalEnterCriticalSection(pThread, &mapping_critsec); + minipal_mutex_enter(&mapping_critsec); if (FILE_MAP_COPY == dwDesiredAccess) { @@ -1116,7 +1115,7 @@ CorUnix::InternalMapViewOfFile( InternalMapViewOfFileLeaveCriticalSection: - InternalLeaveCriticalSection(pThread, &mapping_critsec); + minipal_mutex_leave(&mapping_critsec); InternalMapViewOfFileExit: @@ -1144,7 +1143,7 @@ CorUnix::InternalUnmapViewOfFile( PMAPPED_VIEW_LIST pView = NULL; IPalObject *pMappingObject = NULL; - InternalEnterCriticalSection(pThread, &mapping_critsec); + minipal_mutex_enter(&mapping_critsec); pView = MAPGetViewForAddress(lpBaseAddress); if (NULL == pView) @@ -1177,7 +1176,7 @@ CorUnix::InternalUnmapViewOfFile( InternalUnmapViewOfFileExit: - InternalLeaveCriticalSection(pThread, &mapping_critsec); + minipal_mutex_leave(&mapping_critsec); // // We can't dereference the file mapping object until after @@ -1209,7 +1208,7 @@ MAPInitialize( void ) { TRACE( "Initialising the critical section.\n" ); - InternalInitializeCriticalSection(&mapping_critsec); + minipal_mutex_init(&mapping_critsec); InitializeListHead(&MappedViewList); @@ -1231,7 +1230,7 @@ Function : void MAPCleanup( void ) { TRACE( "Deleting the critical section.\n" ); - InternalDeleteCriticalSection(&mapping_critsec); + minipal_mutex_destroy(&mapping_critsec); } /*++ @@ -1665,9 +1664,8 @@ BOOL MAPGetRegionInfo(LPVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer) { BOOL fFound = FALSE; - CPalThread * pThread = InternalGetCurrentThread(); - InternalEnterCriticalSection(pThread, &mapping_critsec); + minipal_mutex_enter(&mapping_critsec); for(LIST_ENTRY *pLink = MappedViewList.Flink; pLink != &MappedViewList; @@ -1708,7 +1706,7 @@ BOOL MAPGetRegionInfo(LPVOID lpAddress, } } - InternalLeaveCriticalSection(pThread, &mapping_critsec); + minipal_mutex_leave(&mapping_critsec); return fFound; } @@ -2166,7 +2164,7 @@ void * MAPMapPEFile(HANDLE hFile, off_t offset) // and each of the sections, as well as all the space between them that we give PROT_NONE protections. // We're going to start adding mappings to the mapping list, so take the critical section - InternalEnterCriticalSection(pThread, &mapping_critsec); + minipal_mutex_enter(&mapping_critsec); reserveSize = RoundToPage(virtualSize, offset); if ((ntHeader.OptionalHeader.SectionAlignment) > GetVirtualPageSize()) @@ -2416,7 +2414,7 @@ void * MAPMapPEFile(HANDLE hFile, off_t offset) doneReleaseMappingCriticalSection: - InternalLeaveCriticalSection(pThread, &mapping_critsec); + minipal_mutex_leave(&mapping_critsec); done: @@ -2468,7 +2466,7 @@ BOOL MAPUnmapPEFile(LPCVOID lpAddress) BOOL retval = TRUE; CPalThread * pThread = InternalGetCurrentThread(); - InternalEnterCriticalSection(pThread, &mapping_critsec); + minipal_mutex_enter(&mapping_critsec); PLIST_ENTRY pLink, pLinkNext, pLinkLocal = NULL; unsigned nPESections = 0; @@ -2506,7 +2504,7 @@ BOOL MAPUnmapPEFile(LPCVOID lpAddress) } #endif // _DEBUG - InternalLeaveCriticalSection(pThread, &mapping_critsec); + minipal_mutex_leave(&mapping_critsec); // Now, outside the critical section, do the actual unmapping work @@ -2555,8 +2553,7 @@ BOOL MAPMarkSectionAsNotNeeded(LPCVOID lpAddress) BOOL retval = TRUE; #ifndef TARGET_ANDROID - CPalThread * pThread = InternalGetCurrentThread(); - InternalEnterCriticalSection(pThread, &mapping_critsec); + minipal_mutex_enter(&mapping_critsec); PLIST_ENTRY pLink, pLinkNext = NULL; // Look through the entire MappedViewList for all mappings associated with the @@ -2584,7 +2581,7 @@ BOOL MAPMarkSectionAsNotNeeded(LPCVOID lpAddress) } } - InternalLeaveCriticalSection(pThread, &mapping_critsec); + minipal_mutex_leave(&mapping_critsec); #endif // TARGET_ANDROID TRACE_(LOADER)("MAPMarkSectionAsNotNeeded returning %d\n", retval); diff --git a/src/coreclr/pal/src/map/virtual.cpp b/src/coreclr/pal/src/map/virtual.cpp index e5e67e18c3b4f6..dcf3fd5c51c852 100644 --- a/src/coreclr/pal/src/map/virtual.cpp +++ b/src/coreclr/pal/src/map/virtual.cpp @@ -22,7 +22,6 @@ Module Name: SET_DEFAULT_DEBUG_CHANNEL(VIRTUAL); // some headers have code with asserts, so do this first #include "pal/thread.hpp" -#include "pal/cs.hpp" #include "pal/file.hpp" #include "pal/seh.hpp" #include "pal/virtual.h" @@ -48,7 +47,7 @@ SET_DEFAULT_DEBUG_CHANNEL(VIRTUAL); // some headers have code with asserts, so d using namespace CorUnix; -CRITICAL_SECTION virtual_critsec; +minipal_mutex virtual_critsec; // The first node in our list of allocated blocks. static PCMI pVirtualMemory; @@ -175,7 +174,7 @@ VIRTUALInitialize(bool initializeExecutableMemoryAllocator) TRACE("Initializing the Virtual Critical Sections. \n"); - InternalInitializeCriticalSection(&virtual_critsec); + minipal_mutex_init(&virtual_critsec); pVirtualMemory = NULL; @@ -207,9 +206,7 @@ void VIRTUALCleanup() { PCMI pEntry; PCMI pTempEntry; - CPalThread * pthrCurrent = InternalGetCurrentThread(); - - InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_enter(&virtual_critsec); // Clean up the allocated memory. pEntry = pVirtualMemory; @@ -223,10 +220,10 @@ void VIRTUALCleanup() } pVirtualMemory = NULL; - InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_leave(&virtual_critsec); TRACE( "Deleting the Virtual Critical Sections. \n" ); - DeleteCriticalSection( &virtual_critsec ); + minipal_mutex_destroy( &virtual_critsec ); } /*** @@ -344,9 +341,7 @@ static void VIRTUALDisplayList( void ) PCMI p; SIZE_T count; SIZE_T index; - CPalThread * pthrCurrent = InternalGetCurrentThread(); - - InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_enter(&virtual_critsec); p = pVirtualMemory; count = 0; @@ -365,7 +360,7 @@ static void VIRTUALDisplayList( void ) p = p->pNext; } - InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_leave(&virtual_critsec); } #endif @@ -817,8 +812,7 @@ PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange( // ExecutableMemoryAllocator::AllocateMemory() for the reason why it is done SIZE_T reservationSize = ALIGN_UP(dwSize, VIRTUAL_64KB); - CPalThread *currentThread = InternalGetCurrentThread(); - InternalEnterCriticalSection(currentThread, &virtual_critsec); + minipal_mutex_enter(&virtual_critsec); void *address = g_executableMemoryAllocator.AllocateMemoryWithinRange(lpBeginAddress, lpEndAddress, reservationSize); if (address != nullptr) @@ -841,7 +835,7 @@ PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange( address, TRUE); - InternalLeaveCriticalSection(currentThread, &virtual_critsec); + minipal_mutex_leave(&virtual_critsec); LOGEXIT("PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange returning %p\n", address); PERF_EXIT(PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange); @@ -939,9 +933,9 @@ VirtualAlloc( if ( flAllocationType & MEM_RESERVE ) { - InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_enter(&virtual_critsec); pRetVal = VIRTUALReserveMemory( pthrCurrent, lpAddress, dwSize, flAllocationType, flProtect ); - InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_leave(&virtual_critsec); if ( !pRetVal ) { @@ -952,7 +946,7 @@ VirtualAlloc( if ( flAllocationType & MEM_COMMIT ) { - InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_enter(&virtual_critsec); if ( pRetVal != NULL ) { /* We are reserving and committing. */ @@ -965,7 +959,7 @@ VirtualAlloc( pRetVal = VIRTUALCommitMemory( pthrCurrent, lpAddress, dwSize, flAllocationType, flProtect ); } - InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_leave(&virtual_critsec); } done: @@ -998,7 +992,7 @@ VirtualFree( lpAddress, dwSize, dwFreeType); pthrCurrent = InternalGetCurrentThread(); - InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_enter(&virtual_critsec); /* Sanity Checks. */ if ( !lpAddress ) @@ -1157,7 +1151,7 @@ VirtualFree( NULL, bRetVal); - InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_leave(&virtual_critsec); LOGEXIT( "VirtualFree returning %s.\n", bRetVal == TRUE ? "TRUE" : "FALSE" ); PERF_EXIT(VirtualFree); return bRetVal; @@ -1185,15 +1179,13 @@ VirtualProtect( SIZE_T Index = 0; SIZE_T NumberOfPagesToChange = 0; SIZE_T OffSet = 0; - CPalThread * pthrCurrent; PERF_ENTRY(VirtualProtect); ENTRY("VirtualProtect(lpAddress=%p, dwSize=%u, flNewProtect=%#x, " "flOldProtect=%p)\n", lpAddress, dwSize, flNewProtect, lpflOldProtect); - pthrCurrent = InternalGetCurrentThread(); - InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_enter(&virtual_critsec); StartBoundary = (UINT_PTR) ALIGN_DOWN(lpAddress, GetVirtualPageSize()); MemSize = ALIGN_UP((UINT_PTR)lpAddress + dwSize, GetVirtualPageSize()) - StartBoundary; @@ -1249,7 +1241,7 @@ VirtualProtect( } } ExitVirtualProtect: - InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_leave(&virtual_critsec); #if defined _DEBUG VIRTUALDisplayList(); @@ -1444,7 +1436,7 @@ VirtualQuery( lpAddress, lpBuffer, dwLength); pthrCurrent = InternalGetCurrentThread(); - InternalEnterCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_enter(&virtual_critsec); if ( !lpBuffer) { @@ -1525,7 +1517,7 @@ VirtualQuery( ExitVirtualQuery: - InternalLeaveCriticalSection(pthrCurrent, &virtual_critsec); + minipal_mutex_leave(&virtual_critsec); LOGEXIT( "VirtualQuery returning %d.\n", sizeof( *lpBuffer ) ); PERF_EXIT(VirtualQuery); @@ -1549,9 +1541,9 @@ Function : void* ReserveMemoryFromExecutableAllocator(CPalThread* pThread, SIZE_T allocationSize) { #ifdef HOST_64BIT - InternalEnterCriticalSection(pThread, &virtual_critsec); + minipal_mutex_enter(&virtual_critsec); void* mem = g_executableMemoryAllocator.AllocateMemory(allocationSize); - InternalLeaveCriticalSection(pThread, &virtual_critsec); + minipal_mutex_leave(&virtual_critsec); return mem; #else // !HOST_64BIT diff --git a/src/coreclr/pal/src/misc/dbgmsg.cpp b/src/coreclr/pal/src/misc/dbgmsg.cpp index 3a1da44c9b79c1..cc1213e8e73a6d 100644 --- a/src/coreclr/pal/src/misc/dbgmsg.cpp +++ b/src/coreclr/pal/src/misc/dbgmsg.cpp @@ -21,7 +21,6 @@ Module Name: #include "config.h" #include "pal/dbgmsg.h" #include "pal/cruntime.h" -#include "pal/critsect.h" #include "pal/file.h" #include "pal/environ.h" @@ -126,7 +125,7 @@ static const char INDENT_CHAR = '.'; static BOOL DBG_get_indent(DBG_LEVEL_ID level, const char *format, char *indent_string); -static CRITICAL_SECTION fprintf_crit_section; +static minipal_mutex fprintf_crit_section; /* Function definitions */ @@ -361,7 +360,7 @@ BOOL DBG_init_channels(void) } } - InternalInitializeCriticalSection(&fprintf_crit_section); + minipal_mutex_init(&fprintf_crit_section); return TRUE; } @@ -387,7 +386,7 @@ void DBG_close_channels() output_file = NULL; - DeleteCriticalSection(&fprintf_crit_section); + minipal_mutex_destroy(&fprintf_crit_section); /* if necessary, release TLS key for entry nesting level */ if(0 != max_entry_level) @@ -539,9 +538,9 @@ int DBG_printf(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader, avoid holding a libc lock while another thread is calling SuspendThread on this one. */ - InternalEnterCriticalSection(NULL, &fprintf_crit_section); + minipal_mutex_enter(&fprintf_crit_section); fprintf( output_file, "%s%s", indent, buffer ); - InternalLeaveCriticalSection(NULL, &fprintf_crit_section); + minipal_mutex_leave(&fprintf_crit_section); /* flush the output to file */ if ( fflush(output_file) != 0 ) diff --git a/src/coreclr/pal/src/misc/environ.cpp b/src/coreclr/pal/src/misc/environ.cpp index 53729118a89218..4a9eb640e2e64a 100644 --- a/src/coreclr/pal/src/misc/environ.cpp +++ b/src/coreclr/pal/src/misc/environ.cpp @@ -20,7 +20,6 @@ Revision History: --*/ #include "pal/palinternal.h" -#include "pal/critsect.h" #include "pal/dbgmsg.h" #include "pal/environ.h" @@ -38,7 +37,7 @@ char **palEnvironment = nullptr; int palEnvironmentCount = 0; int palEnvironmentCapacity = 0; -CRITICAL_SECTION gcsEnvironment; +minipal_mutex gcsEnvironment; /*++ Function: @@ -114,7 +113,7 @@ GetEnvironmentVariableA( // the environment variable value without EnvironGetenv making an // intermediate copy. We will just copy the string to the output // buffer anyway, so just stay in the critical section until then. - InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_enter(&gcsEnvironment); value = EnvironGetenv(lpName, /* copyValue */ FALSE); @@ -134,7 +133,7 @@ GetEnvironmentVariableA( SetLastError(ERROR_SUCCESS); } - InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_leave(&gcsEnvironment); } if (value == nullptr) @@ -401,7 +400,7 @@ GetEnvironmentStringsW( ENTRY("GetEnvironmentStringsW()\n"); CPalThread * pthrCurrent = InternalGetCurrentThread(); - InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_enter(&gcsEnvironment); envNum = 0; len = 0; @@ -433,7 +432,7 @@ GetEnvironmentStringsW( *tempEnviron = 0; /* Put an extra null at the end */ EXIT: - InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_leave(&gcsEnvironment); LOGEXIT("GetEnvironmentStringsW returning %p\n", wenviron); PERF_EXIT(GetEnvironmentStringsW); @@ -610,7 +609,7 @@ Return Values BOOL ResizeEnvironment(int newSize) { CPalThread * pthrCurrent = InternalGetCurrentThread(); - InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_enter(&gcsEnvironment); BOOL ret = FALSE; if (newSize >= palEnvironmentCount) @@ -630,7 +629,7 @@ BOOL ResizeEnvironment(int newSize) ASSERT("ResizeEnvironment: newSize < current palEnvironmentCount!\n"); } - InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_leave(&gcsEnvironment); return ret; } @@ -652,7 +651,7 @@ void EnvironUnsetenv(const char *name) int nameLength = strlen(name); CPalThread * pthrCurrent = InternalGetCurrentThread(); - InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_enter(&gcsEnvironment); for (int i = 0; palEnvironment[i] != nullptr; ++i) { @@ -680,7 +679,7 @@ void EnvironUnsetenv(const char *name) } } - InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_leave(&gcsEnvironment); } /*++ @@ -746,7 +745,7 @@ BOOL EnvironPutenv(const char* entry, BOOL deleteIfEmpty) { // See if we are replacing an item or adding one. - InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_enter(&gcsEnvironment); fOwningCS = true; int i; @@ -801,7 +800,7 @@ BOOL EnvironPutenv(const char* entry, BOOL deleteIfEmpty) if (fOwningCS) { - InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_leave(&gcsEnvironment); } return result; @@ -883,7 +882,7 @@ Return Value char* EnvironGetenv(const char* name, BOOL copyValue) { CPalThread * pthrCurrent = InternalGetCurrentThread(); - InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_enter(&gcsEnvironment); char* retValue = FindEnvVarValue(name); @@ -892,7 +891,7 @@ char* EnvironGetenv(const char* name, BOOL copyValue) retValue = strdup(retValue); } - InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_leave(&gcsEnvironment); return retValue; } @@ -939,10 +938,10 @@ EnvironInitialize(void) { BOOL ret = FALSE; - InternalInitializeCriticalSection(&gcsEnvironment); + minipal_mutex_init(&gcsEnvironment); CPalThread * pthrCurrent = InternalGetCurrentThread(); - InternalEnterCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_enter(&gcsEnvironment); char** sourceEnviron = EnvironGetSystemEnvironment(); @@ -974,7 +973,7 @@ EnvironInitialize(void) palEnvironment[variableCount] = nullptr; } - InternalLeaveCriticalSection(pthrCurrent, &gcsEnvironment); + minipal_mutex_leave(&gcsEnvironment); return ret; } diff --git a/src/coreclr/pal/src/misc/fmtmessage.cpp b/src/coreclr/pal/src/misc/fmtmessage.cpp index cfedd815da3cae..f096156f23847e 100644 --- a/src/coreclr/pal/src/misc/fmtmessage.cpp +++ b/src/coreclr/pal/src/misc/fmtmessage.cpp @@ -21,7 +21,6 @@ Revision History: #include "pal/palinternal.h" #include "pal/dbgmsg.h" -#include "pal/critsect.h" #include "pal/module.h" #include "errorstrings.h" diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index 67dc6cbbdd1318..b9afb95a574052 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -184,14 +184,13 @@ struct PerfJitDumpState { int result = 0; - // On platforms where JITDUMP is used, the PAL QueryPerformanceFrequency - // returns tccSecondsToNanoSeconds, meaning QueryPerformanceCounter - // will return a direct nanosecond value. If this isn't true, + // On platforms where JITDUMP is used, minipal_hires_tick_frequency() + // returns tccSecondsToNanoSeconds. If this isn't true, // then some other method will need to be used to implement GetTimeStampNS. // Validate this is true once in Start here. if (minipal_hires_tick_frequency() != tccSecondsToNanoSeconds) { - _ASSERTE(!"QueryPerformanceFrequency does not return tccSecondsToNanoSeconds. Implement JITDUMP GetTimeStampNS directly for this platform.\n"); + _ASSERTE(!"minipal_hires_tick_frequency() does not return tccSecondsToNanoSeconds. Implement JITDUMP GetTimeStampNS directly for this platform.\n"); FatalError(); } diff --git a/src/coreclr/pal/src/objmgr/listedobject.cpp b/src/coreclr/pal/src/objmgr/listedobject.cpp index 1f15fba2052923..349c76cdf62599 100644 --- a/src/coreclr/pal/src/objmgr/listedobject.cpp +++ b/src/coreclr/pal/src/objmgr/listedobject.cpp @@ -17,7 +17,6 @@ Module Name: --*/ #include "listedobject.hpp" -#include "pal/cs.hpp" #include "pal/dbgmsg.h" #include @@ -158,7 +157,7 @@ CListedObject::AcquireObjectDestructionLock( pthr ); - InternalEnterCriticalSection(pthr, m_pcsObjListLock); + minipal_mutex_enter(m_pcsObjListLock); LOGEXIT("CListedObject::AcquireObjectDestructionLock\n"); } @@ -196,7 +195,7 @@ CListedObject::ReleaseObjectDestructionLock( RemoveEntryList(&m_le); } - InternalLeaveCriticalSection(pthr, m_pcsObjListLock); + minipal_mutex_leave(m_pcsObjListLock); } /*++ diff --git a/src/coreclr/pal/src/objmgr/listedobject.hpp b/src/coreclr/pal/src/objmgr/listedobject.hpp index a75bb54af28b02..11e346e4c3979f 100644 --- a/src/coreclr/pal/src/objmgr/listedobject.hpp +++ b/src/coreclr/pal/src/objmgr/listedobject.hpp @@ -42,7 +42,7 @@ namespace CorUnix // The lock that guards access to that list // - CRITICAL_SECTION *m_pcsObjListLock; + minipal_mutex *m_pcsObjListLock; virtual void @@ -67,7 +67,7 @@ namespace CorUnix CListedObject( CObjectType *pot, - CRITICAL_SECTION *pcsObjListLock + minipal_mutex *pcsObjListLock ) : CPalObjectBase(pot), @@ -144,7 +144,7 @@ namespace CorUnix CSharedMemoryWaitableObject( CObjectType *pot, - CRITICAL_SECTION *pcsObjListLock + minipal_mutex *pcsObjListLock ) : CListedObject(pot, pcsObjListLock) diff --git a/src/coreclr/pal/src/objmgr/listedobjectmanager.cpp b/src/coreclr/pal/src/objmgr/listedobjectmanager.cpp index e058c60211f965..5e00282c0a4a5e 100644 --- a/src/coreclr/pal/src/objmgr/listedobjectmanager.cpp +++ b/src/coreclr/pal/src/objmgr/listedobjectmanager.cpp @@ -18,7 +18,6 @@ Module Name: #include "listedobjectmanager.hpp" #include "listedobject.hpp" -#include "pal/cs.hpp" #include "pal/thread.hpp" #include "pal/procobj.hpp" #include "pal/dbgmsg.h" @@ -60,7 +59,7 @@ CListedObjectManager::Initialize( InitializeListHead(&m_leNamedObjects); InitializeListHead(&m_leAnonymousObjects); - InternalInitializeCriticalSection(&m_csListLock); + minipal_mutex_init(&m_csListLock); m_fListLockInitialized = TRUE; palError = m_HandleManager.Initialize(); @@ -97,7 +96,7 @@ CListedObjectManager::Shutdown( pthr ); - InternalEnterCriticalSection(pthr, &m_csListLock); + minipal_mutex_enter(&m_csListLock); while (!IsListEmpty(&m_leAnonymousObjects)) { @@ -113,7 +112,7 @@ CListedObjectManager::Shutdown( pshmobj->CleanupForProcessShutdown(pthr); } - InternalLeaveCriticalSection(pthr, &m_csListLock); + minipal_mutex_leave(&m_csListLock); LOGEXIT("CListedObjectManager::Shutdown returns %d\n", NO_ERROR); @@ -246,7 +245,7 @@ CListedObjectManager::RegisterObject( potObj = pobjToRegister->GetObjectType(); - InternalEnterCriticalSection(pthr, &m_csListLock); + minipal_mutex_enter(&m_csListLock); if (0 != poa->sObjectName.GetStringLength()) { @@ -336,7 +335,7 @@ CListedObjectManager::RegisterObject( RegisterObjectExit: - InternalLeaveCriticalSection(pthr, &m_csListLock); + minipal_mutex_leave(&m_csListLock); if (NULL != pobjToRegister) { @@ -397,7 +396,7 @@ CListedObjectManager::LocateObject( TRACE("Searching for object name %S\n", psObjectToLocate->GetString()); - InternalEnterCriticalSection(pthr, &m_csListLock); + minipal_mutex_enter(&m_csListLock); // // Search the local named object list for this object @@ -462,7 +461,7 @@ CListedObjectManager::LocateObject( LocateObjectExit: - InternalLeaveCriticalSection(pthr, &m_csListLock); + minipal_mutex_leave(&m_csListLock); LOGEXIT("CListedObjectManager::LocateObject returns %d\n", palError); diff --git a/src/coreclr/pal/src/objmgr/listedobjectmanager.hpp b/src/coreclr/pal/src/objmgr/listedobjectmanager.hpp index e893d2e6a15bc9..ffe98cb04d4c18 100644 --- a/src/coreclr/pal/src/objmgr/listedobjectmanager.hpp +++ b/src/coreclr/pal/src/objmgr/listedobjectmanager.hpp @@ -30,7 +30,7 @@ namespace CorUnix { protected: - CRITICAL_SECTION m_csListLock; + minipal_mutex m_csListLock; bool m_fListLockInitialized; LIST_ENTRY m_leNamedObjects; LIST_ENTRY m_leAnonymousObjects; diff --git a/src/coreclr/pal/src/objmgr/palobjbase.hpp b/src/coreclr/pal/src/objmgr/palobjbase.hpp index ceb49ca79b41e0..866c26747122a6 100644 --- a/src/coreclr/pal/src/objmgr/palobjbase.hpp +++ b/src/coreclr/pal/src/objmgr/palobjbase.hpp @@ -20,7 +20,6 @@ Module Name: #define _PALOBJBASE_HPP_ #include "pal/corunix.hpp" -#include "pal/cs.hpp" #include "pal/thread.hpp" namespace CorUnix @@ -29,7 +28,7 @@ namespace CorUnix { private: - CRITICAL_SECTION m_cs; + minipal_mutex m_cs; bool m_fInitialized; public: @@ -44,7 +43,7 @@ namespace CorUnix { if (m_fInitialized) { - InternalDeleteCriticalSection(&m_cs); + minipal_mutex_destroy(&m_cs); } }; @@ -55,7 +54,7 @@ namespace CorUnix { PAL_ERROR palError = NO_ERROR; - InternalInitializeCriticalSection(&m_cs); + minipal_mutex_init(&m_cs); m_fInitialized = TRUE; return palError; @@ -67,7 +66,7 @@ namespace CorUnix IDataLock **pDataLock ) { - InternalEnterCriticalSection(pthr, &m_cs); + minipal_mutex_enter(&m_cs); *pDataLock = static_cast(this); }; @@ -78,7 +77,7 @@ namespace CorUnix bool fDataChanged ) { - InternalLeaveCriticalSection(pthr, &m_cs); + minipal_mutex_leave(&m_cs); }; }; diff --git a/src/coreclr/pal/src/safecrt/internal.h b/src/coreclr/pal/src/safecrt/internal.h deleted file mode 100644 index 8c1a6e57243667..00000000000000 --- a/src/coreclr/pal/src/safecrt/internal.h +++ /dev/null @@ -1,1066 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*** -*internal.h - contains declarations of internal routines and variables -* - -* -*Purpose: -* Declares routines and variables used internally by the C run-time. -* -* [Internal] -* -****/ - -#if _MSC_VER > 1000 -#pragma once -#endif /* _MSC_VER > 1000 */ - -#ifndef _INC_INTERNAL -#define _INC_INTERNAL - -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -/* - * Conditionally include windows.h to pick up the definition of - * CRITICAL_SECTION. - */ -#include - -#ifdef _MSC_VER -#pragma pack(push,_CRT_PACKING) -#endif /* _MSC_VER */ - -/* Define function types used in several startup sources */ - -typedef void (__cdecl *_PVFV)(void); -typedef int (__cdecl *_PIFV)(void); -typedef void (__cdecl *_PVFI)(int); - -#if _MSC_VER >= 1400 && defined(_M_CEE) -typedef const void* (__clrcall *_PVFVM)(void); -typedef int (__clrcall *_PIFVM)(void); -typedef void (__clrcall *_CPVFV)(void); -#endif /* _MSC_VER >= 1400 && defined(_M_CEE) */ - -#if defined (_M_CEE_PURE) || (defined (_DLL) && defined (_M_IX86)) -/* Retained for compatibility with VC++ 5.0 and earlier versions */ -_CRTIMP int * __cdecl __p__commode(void); -#endif /* defined (_M_CEE_PURE) || (defined (_DLL) && defined (_M_IX86)) */ -#if defined (SPECIAL_CRTEXE) && defined (_DLL) - extern int _commode; -#else /* defined (SPECIAL_CRTEXE) && defined (_DLL) */ -#ifndef _M_CEE_PURE -_CRTIMP extern int _commode; -#else /* _M_CEE_PURE */ -#define _commode (*__p___commode()) -#endif /* _M_CEE_PURE */ -#endif /* defined (SPECIAL_CRTEXE) && defined (_DLL) */ - -#define __IOINFO_TM_ANSI 0 /* Regular Text */ -#define __IOINFO_TM_UTF8 1 /* UTF8 Encoded */ -#define __IOINFO_TM_UTF16LE 2 /* UTF16 Little Endian Encoded */ - -/* - * Control structure for lowio file handles - */ -typedef struct { - intptr_t osfhnd; /* underlying OS file HANDLE */ - char osfile; /* attributes of file (e.g., open in text mode?) */ - char pipech; /* one char buffer for handles opened on pipes */ - int lockinitflag; - CRITICAL_SECTION lock; -#ifndef _SAFECRT_IMPL - /* Not used in the safecrt downlevel. We do not define them, so we cannot use them accidentally */ - char textmode : 7; /* __IOINFO_TM_ANSI or __IOINFO_TM_UTF8 or __IOINFO_TM_UTF16LE */ - char unicode : 1; /* Was the file opened as unicode? */ - char pipech2[2]; /* 2 more peak ahead chars for UNICODE mode */ -#endif /* _SAFECRT_IMPL */ - } ioinfo; - -/* - * Definition of IOINFO_L2E, the log base 2 of the number of elements in each - * array of ioinfo structs. - */ -#define IOINFO_L2E 5 - -/* - * Definition of IOINFO_ARRAY_ELTS, the number of elements in ioinfo array - */ -#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) - -/* - * Definition of IOINFO_ARRAYS, maximum number of supported ioinfo arrays. - */ -#define IOINFO_ARRAYS 64 - -#define _NHANDLE_ (IOINFO_ARRAYS * IOINFO_ARRAY_ELTS) - -#define _TZ_STRINGS_SIZE 64 - -/* - * Access macros for getting at an ioinfo struct and its fields from a - * file handle - */ -#define _pioinfo(i) ( __pioinfo[(i) >> IOINFO_L2E] + ((i) & (IOINFO_ARRAY_ELTS - \ - 1)) ) -#define _osfhnd(i) ( _pioinfo(i)->osfhnd ) - -#define _osfile(i) ( _pioinfo(i)->osfile ) - -#define _pipech(i) ( _pioinfo(i)->pipech ) - -#define _pipech2(i) ( _pioinfo(i)->pipech2 ) - -#define _textmode(i) ( _pioinfo(i)->textmode ) - -#define _tm_unicode(i) ( _pioinfo(i)->unicode ) - -/* - * Safer versions of the above macros. Currently, only _osfile_safe is - * used. - */ -#define _pioinfo_safe(i) ( (((i) != -1) && ((i) != -2)) ? _pioinfo(i) : &__badioinfo ) - -#define _osfhnd_safe(i) ( _pioinfo_safe(i)->osfhnd ) - -#define _osfile_safe(i) ( _pioinfo_safe(i)->osfile ) - -#define _pipech_safe(i) ( _pioinfo_safe(i)->pipech ) - -#define _pipech2_safe(i) ( _pioinfo_safe(i)->pipech2 ) - -#ifdef _SAFECRT_IMPL -/* safecrt does not have support for textmode, so we always return __IOINFO_TM_ANSI */ -#define _textmode_safe(i) __IOINFO_TM_ANSI -#define _tm_unicode_safe(i) 0 -#else /* _SAFECRT_IMPL */ -#define _textmode_safe(i) ( _pioinfo_safe(i)->textmode ) -#define _tm_unicode_safe(i) ( _pioinfo_safe(i)->unicode ) -#endif /* _SAFECRT_IMPL */ - -#ifndef _M_CEE_PURE -#ifdef _SAFECRT_IMPL -/* We need to get this from the downlevel DLL, even when we build safecrt.lib */ -extern __declspec(dllimport) ioinfo __badioinfo; -extern __declspec(dllimport) ioinfo * __pioinfo[]; -#else /* _SAFECRT_IMPL */ -/* - * Special, static ioinfo structure used only for more graceful handling - * of a C file handle value of -1 (results from common errors at the stdio - * level). - */ -extern _CRTIMP ioinfo __badioinfo; - -/* - * Array of arrays of control structures for lowio files. - */ -extern _CRTIMP ioinfo * __pioinfo[]; -#endif /* _SAFECRT_IMPL */ -#endif /* _M_CEE_PURE */ - -/* - * Current number of allocated ioinfo structures (_NHANDLE_ is the upper - * limit). - */ -extern int _nhandle; - -int __cdecl _alloc_osfhnd(void); -int __cdecl _free_osfhnd(int); -int __cdecl _set_osfhnd(int, intptr_t); - -/* - fileno for stdout, stdin & stderr when there is no console -*/ -#define _NO_CONSOLE_FILENO (intptr_t)-2 - - -extern const char __dnames[]; -extern const char __mnames[]; - -extern int _days[]; -extern int _lpdays[]; - -extern __time32_t __cdecl __loctotime32_t(int, int, int, int, int, int, int); -extern __time64_t __cdecl __loctotime64_t(int, int, int, int, int, int, int); - -extern void __cdecl __tzset(void); - -extern int __cdecl _validdrive(unsigned); - -/* - * If we are only interested in years between 1901 and 2099, we could use this: - * - * #define IS_LEAP_YEAR(y) (y % 4 == 0) - */ - -#define IS_LEAP_YEAR(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0) - -/* - * This variable is in the C start-up; the length must be kept synchronized - * It is used by the *cenvarg.c modules - */ - -extern char _acfinfo[]; /* "_C_FILE_INFO=" */ - -#define CFI_LENGTH 12 /* "_C_FILE_INFO" is 12 bytes long */ - - -/* - * stdio internals - */ -#ifndef _FILE_DEFINED -struct _iobuf { - char *_ptr; - int _cnt; - char *_base; - int _flag; - int _file; - int _charbuf; - int _bufsiz; - char *_tmpfname; - }; -typedef struct _iobuf FILE; -#define _FILE_DEFINED -#endif /* _FILE_DEFINED */ - -#if !defined (_FILEX_DEFINED) && defined (_WINDOWS_) - -/* - * Variation of FILE type used for the dynamically allocated portion of - * __piob[]. For single thread, _FILEX is the same as FILE. For multithread - * models, _FILEX has two fields: the FILE struct and the CRITICAL_SECTION - * struct used to serialize access to the FILE. - */ - -typedef struct { - FILE f; - CRITICAL_SECTION lock; - } _FILEX; - - -#define _FILEX_DEFINED -#endif /* !defined (_FILEX_DEFINED) && defined (_WINDOWS_) */ - -/* - * Number of entries supported in the array pointed to by __piob[]. That is, - * the number of stdio-level files which may be open simultaneously. This - * is normally set to _NSTREAM_ by the stdio initialization code. - */ -extern int _nstream; - -/* - * Pointer to the array of pointers to FILE/_FILEX structures that are used - * to manage stdio-level files. - */ -extern void **__piob; - -FILE * __cdecl _getstream(void); -FILE * __cdecl _openfile(_In_z_ const char * _Filename, _In_z_ const char * _Mode, _In_ int _ShFlag, _Out_ FILE * _File); -FILE * __cdecl _wopenfile(_In_z_ const char16_t * _Filename, _In_z_ const char16_t * _Mode, _In_ int _ShFlag, _Out_ FILE * _File); -void __cdecl _getbuf(_Out_ FILE * _File); -int __cdecl _filwbuf (__inout FILE * _File); -int __cdecl _flswbuf(_In_ int _Ch, __inout FILE * _File); -void __cdecl _freebuf(__inout FILE * _File); -int __cdecl _stbuf(__inout FILE * _File); -void __cdecl _ftbuf(int _Flag, __inout FILE * _File); - -#ifdef _SAFECRT_IMPL - -int __cdecl _output(__inout FILE * _File, _In_z_ __format_string const char *_Format, va_list _ArgList); -int __cdecl _woutput(__inout FILE * _File, _In_z_ __format_string const char16_t *_Format, va_list _ArgList); -int __cdecl _output_s(__inout FILE * _File, _In_z_ __format_string const char *_Format, va_list _ArgList); -int __cdecl _output_p(__inout FILE * _File, _In_z_ __format_string const char *_Format, va_list _ArgList); -typedef int (*OUTPUTFN)(FILE *, const char *, va_list); - -#else /* _SAFECRT_IMPL */ - -int __cdecl _output_l(__inout FILE * _File, _In_z_ __format_string const char *_Format, _In_opt_ _locale_t _Locale, va_list _ArgList); -int __cdecl _woutput_l(__inout FILE * _File, _In_z_ __format_string const char16_t *_Format, _In_opt_ _locale_t _Locale, va_list _ArgList); -int __cdecl _output_s_l(__inout FILE * _File, _In_z_ __format_string const char *_Format, _In_opt_ _locale_t _Locale, va_list _ArgList); -int __cdecl _output_p_l(__inout FILE * _File, _In_z_ __format_string const char *_Format, _In_opt_ _locale_t _Locale, va_list _ArgList); -typedef int (*OUTPUTFN)(__inout FILE * _File, const char *, _locale_t, va_list); - -#endif /* _SAFECRT_IMPL */ - -#ifdef _SAFECRT_IMPL - -int __cdecl _input(_In_ FILE * _File, _In_z_ __format_string const unsigned char * _Format, va_list _ArgList); -int __cdecl _winput(_In_ FILE * _File, _In_z_ __format_string const char16_t * _Format, va_list _ArgList); -int __cdecl _input_s(_In_ FILE * _File, _In_z_ __format_string const unsigned char * _Format, va_list _ArgList); -typedef int (*INPUTFN)(FILE *, const unsigned char *, va_list); -typedef int (*WINPUTFN)(FILE *, const char16_t *, va_list); - -#else /* _SAFECRT_IMPL */ - -int __cdecl _input_l(__inout FILE * _File, _In_z_ __format_string const unsigned char *, _In_opt_ _locale_t _Locale, va_list _ArgList); -int __cdecl _winput_l(__inout FILE * _File, _In_z_ __format_string const char16_t *, _In_opt_ _locale_t _Locale, va_list _ArgList); -int __cdecl _input_s_l(__inout FILE * _File, _In_z_ __format_string const unsigned char *, _In_opt_ _locale_t _Locale, va_list _ArgList); -int __cdecl _winput_s_l(__inout FILE * _File, _In_z_ __format_string const char16_t *, _In_opt_ _locale_t _Locale, va_list _ArgList); -typedef int (*INPUTFN)(FILE *, const unsigned char *, _locale_t, va_list); -typedef int (*WINPUTFN)(FILE *, const char16_t *, _locale_t, va_list); - -#ifdef _UNICODE -#define TINPUTFN WINPUTFN -#else /* _UNICODE */ -#define TINPUTFN INPUTFN -#endif /* _UNICODE */ - -#endif /* _SAFECRT_IMPL */ - -int __cdecl _flush(__inout FILE * _File); -void __cdecl _endstdio(void); - -errno_t __cdecl _sopen_helper(_In_z_ const char * _Filename, - _In_ int _OFlag, _In_ int _ShFlag, _In_ int _PMode, - _Out_ int * _PFileHandle, int _BSecure); -errno_t __cdecl _wsopen_helper(_In_z_ const char16_t * _Filename, - _In_ int _OFlag, _In_ int _ShFlag, _In_ int _PMode, - _Out_ int * _PFileHandle, int _BSecure); - -#ifndef CRTDLL -extern int _cflush; -#endif /* CRTDLL */ - -extern unsigned int _tempoff; - -extern unsigned int _old_pfxlen; - -extern int _umaskval; /* the umask value */ - -extern char _pipech[]; /* pipe lookahead */ - -extern char _exitflag; /* callable termination flag */ - -extern int _C_Termination_Done; /* termination done flag */ - -char * __cdecl _getpath(_In_z_ const char * _Src, _Out_writes_z_(_SizeInChars) char * _Dst, _In_ size_t _SizeInChars); -char16_t * __cdecl _wgetpath(_In_z_ const char16_t * _Src, _Out_writes_z_(_SizeInWords) char16_t * _Dst, _In_ size_t _SizeInWords); - -extern int _dowildcard; /* flag to enable argv[] wildcard expansion */ - -#ifndef _PNH_DEFINED -typedef int (__cdecl * _PNH)( size_t ); -#define _PNH_DEFINED -#endif /* _PNH_DEFINED */ - -#if _MSC_VER >= 1400 && defined(_M_CEE) -#ifndef __MPNH_DEFINED -typedef int (__clrcall * __MPNH)( size_t ); -#define __MPNH_DEFINED -#endif /* __MPNH_DEFINED */ -#endif /* _MSC_VER >= 1400 && defined(_M_CEE) */ - - -/* calls the currently installed new handler */ -int __cdecl _callnewh(_In_ size_t _Size); - -extern int _newmode; /* malloc new() handler mode */ - -/* pointer to initial environment block that is passed to [w]main */ -#ifndef _M_CEE_PURE -extern _CRTIMP char16_t **__winitenv; -extern _CRTIMP char **__initenv; -#endif /* _M_CEE_PURE */ - -/* _calloca helper */ -#define _calloca(count, size) ((count<=0 || size<=0 || ((((size_t)_HEAP_MAXREQ) / ((size_t)count)) < ((size_t)size)))? NULL : _malloca(count * size)) - -/* startup set values */ -extern char *_aenvptr; /* environment ptr */ -extern char16_t *_wenvptr; /* wide environment ptr */ - -/* command line */ - -#if defined (_DLL) -_CRTIMP char ** __cdecl __p__acmdln(void); -_CRTIMP char16_t ** __cdecl __p__wcmdln(void); -#endif /* defined (_DLL) */ -#ifndef _M_CEE_PURE -_CRTIMP extern char *_acmdln; -_CRTIMP extern char16_t *_wcmdln; -#else /* _M_CEE_PURE */ -#define _acmdln (*__p__acmdln()) -#define _wcmdln (*__p__wcmdln()) -#endif /* _M_CEE_PURE */ - -/* - * prototypes for internal startup functions - */ -int __cdecl _cwild(void); /* wild.c */ -int __cdecl _wcwild(void); /* wwild.c */ -int __cdecl _mtinit(void); /* tidtable.c */ -void __cdecl _mtterm(void); /* tidtable.c */ -int __cdecl _mtinitlocks(void); /* mlock.c */ -void __cdecl _mtdeletelocks(void); /* mlock.c */ -int __cdecl _mtinitlocknum(int); /* mlock.c */ - -/* Wrapper for InitializeCriticalSection API, with default spin count */ -int __cdecl __crtInitCritSecAndSpinCount(PCRITICAL_SECTION, DWORD); -#define _CRT_SPINCOUNT 4000 - -/* - * C source build only!!!! - * - * more prototypes for internal startup functions - */ -void __cdecl _amsg_exit(int); /* crt0.c */ -void __cdecl __crtExitProcess(int); /* crt0dat.c */ -void __cdecl __crtCorExitProcess(int); /* crt0dat.c */ -void __cdecl __crtdll_callstaticterminators(void); /* crt0dat.c */ - -/* -_cinit now allows the caller to suppress floating point precision init -This allows the DLLs that use the CRT to not initialise FP precision, -allowing the EXE's setting to persist even when a DLL is loaded -*/ -int __cdecl _cinit(int /* initFloatingPrecision */); /* crt0dat.c */ -void __cdecl __doinits(void); /* astart.asm */ -void __cdecl __doterms(void); /* astart.asm */ -void __cdecl __dopreterms(void); /* astart.asm */ -void __cdecl _FF_MSGBANNER(void); -void __cdecl _fpmath(int /*initPrecision*/); -void __cdecl _fpclear(void); -void __cdecl _fptrap(void); /* crt0fp.c */ -int __cdecl _heap_init(int); -void __cdecl _heap_term(void); -void __cdecl _heap_abort(void); -void __cdecl __initconin(void); /* initcon.c */ -void __cdecl __initconout(void); /* initcon.c */ -int __cdecl _ioinit(void); /* crt0.c, crtlib.c */ -void __cdecl _ioterm(void); /* crt0.c, crtlib.c */ -char * __cdecl _GET_RTERRMSG(int); -void __cdecl _NMSG_WRITE(int); -int __CRTDECL _setargv(void); /* setargv.c, stdargv.c */ -int __CRTDECL __setargv(void); /* stdargv.c */ -int __CRTDECL _wsetargv(void); /* wsetargv.c, wstdargv.c */ -int __CRTDECL __wsetargv(void); /* wstdargv.c */ -int __cdecl _setenvp(void); /* stdenvp.c */ -int __cdecl _wsetenvp(void); /* wstdenvp.c */ -void __cdecl __setmbctable(unsigned int); /* mbctype.c */ - -#ifdef MRTDLL -_MRTIMP int __cdecl _onexit_process(_CPVFV); -_MRTIMP int __cdecl _onexit_app_domain(_CPVFV); -#endif /* MRTDLL */ - -#ifndef _MANAGED_MAIN -int __CRTDECL main(_In_ int _Argc, _In_reads_z_(_Argc) char ** _Argv, _In_z_ char ** _Env); -int __CRTDECL wmain(_In_ int _Argc, _In_reads_z_(_Argc) char16_t ** _Argv, _In_z_ char16_t ** _Env); -#endif /* _MANAGED_MAIN */ - -/* helper functions for wide/multibyte environment conversion */ -int __cdecl __mbtow_environ (void); -int __cdecl __wtomb_environ (void); - -/* These two functions take a char ** for the environment option - At some point during their execution, they take ownership of the - memory block passed in using option. At this point, they - NULL out the incoming char * / char16_t * to ensure there is no - double-free -*/ -int __cdecl __crtsetenv(_Outptr_opt_ char ** _POption, _In_ const int _Primary); -int __cdecl __crtwsetenv(_Outptr_opt_ char16_t ** _POption, _In_ const int _Primary); - -#ifndef _M_CEE_PURE -_CRTIMP extern void (__cdecl * _aexit_rtn)(int); -#endif /* _M_CEE_PURE */ - -#if defined (_DLL) || defined (CRTDLL) - -#ifndef _STARTUP_INFO_DEFINED -typedef struct -{ - int newmode; -} _startupinfo; -#define _STARTUP_INFO_DEFINED -#endif /* _STARTUP_INFO_DEFINED */ - -_CRTIMP int __cdecl __getmainargs(_Out_ int * _Argc, _Outptr_result_buffer_(*_Argc) char *** _Argv, - _Outptr_opt_ char *** _Env, _In_ int _DoWildCard, - _In_ _startupinfo * _StartInfo); - -_CRTIMP int __cdecl __wgetmainargs(_Out_ int * _Argc, _Outptr_result_buffer_(*_Argc)char16_t *** _Argv, - _Outptr_opt_ char16_t *** _Env, _In_ int _DoWildCard, - _In_ _startupinfo * _StartInfo); - -#endif /* defined (_DLL) || defined (CRTDLL) */ - -/* - * Prototype, variables and constants which determine how error messages are - * written out. - */ -#define _UNKNOWN_APP 0 -#define _CONSOLE_APP 1 -#define _GUI_APP 2 - -extern int __app_type; - -#if !defined (_M_CEE_PURE) - -extern Volatile __native_startup_lock; - -#define __NO_REASON UINT_MAX -extern Volatile __native_dllmain_reason; -extern Volatile __native_vcclrit_reason; - -#if defined (__cplusplus) - -#pragma warning(push) -#pragma warning(disable: 4483) -#if _MSC_FULL_VER >= 140050415 -#define _NATIVE_STARTUP_NAMESPACE __identifier("") -#else /* _MSC_FULL_VER >= 140050415 */ -#define _NATIVE_STARTUP_NAMESPACE __CrtImplementationDetails -#endif /* _MSC_FULL_VER >= 140050415 */ - -namespace _NATIVE_STARTUP_NAMESPACE -{ - class NativeDll - { - private: - static const unsigned int ProcessDetach = 0; - static const unsigned int ProcessAttach = 1; - static const unsigned int ThreadAttach = 2; - static const unsigned int ThreadDetach = 3; - static const unsigned int ProcessVerifier = 4; - - public: - - inline static bool IsInDllMain() - { - return (__native_dllmain_reason != __NO_REASON); - } - - inline static bool IsInProcessAttach() - { - return (__native_dllmain_reason == ProcessAttach); - } - - inline static bool IsInProcessDetach() - { - return (__native_dllmain_reason == ProcessDetach); - } - - inline static bool IsInVcclrit() - { - return (__native_vcclrit_reason != __NO_REASON); - } - - inline static bool IsSafeForManagedCode() - { - if (!IsInDllMain()) - { - return true; - } - - if (IsInVcclrit()) - { - return true; - } - - return !IsInProcessAttach() && !IsInProcessDetach(); - } - }; -} -#pragma warning(pop) - -#endif /* defined (__cplusplus) */ - -#endif /* !defined (_M_CEE_PURE) */ - -extern int __error_mode; - -_CRTIMP void __cdecl __set_app_type(int); -#if defined (CRTDLL) && !defined (_SYSCRT) -/* - * All these function pointer are used for creating global state of CRT - * functions. Either all of them will be set or all of them will be NULL - */ -typedef void (__cdecl *_set_app_type_function)(int); -typedef int (__cdecl *_get_app_type_function)(); -extern _set_app_type_function __set_app_type_server; -extern _get_app_type_function __get_app_type_server; -#endif /* defined (CRTDLL) && !defined (_SYSCRT) */ - -/* - * C source build only!!!! - * - * map Win32 errors into Xenix errno values -- for modules written in C - */ -_CRTIMP void __cdecl _dosmaperr(unsigned long); -extern int __cdecl _get_errno_from_oserr(unsigned long); - -/* - * internal routines used by the exec/spawn functions - */ - -extern intptr_t __cdecl _dospawn(_In_ int _Mode, _In_opt_z_ const char * _Name, __inout_z char * _Cmd, _In_opt_z_ char * _Env); -extern intptr_t __cdecl _wdospawn(_In_ int _Mode, _In_opt_z_ const char16_t * _Name, __inout_z char16_t * _Cmd, _In_opt_z_ char16_t * _Env); -extern int __cdecl _cenvarg(_In_z_ const char * const * _Argv, _In_opt_z_ const char * const * _Env, - _Outptr_opt_ char ** _ArgBlk, _Outptr_opt_ char ** _EnvBlk, _In_z_ const char *_Name); -extern int __cdecl _wcenvarg(_In_z_ const char16_t * const * _Argv, _In_opt_z_ const char16_t * const * _Env, - _Outptr_opt_ char16_t ** _ArgBlk, _Outptr_opt_ char16_t ** _EnvBlk, _In_z_ const char16_t * _Name); -#ifndef _M_IX86 -extern char ** _capture_argv(_In_ va_list *, _In_z_ const char * _FirstArg, _Out_writes_z_(_MaxCount) char ** _Static_argv, _In_ size_t _MaxCount); -extern char16_t ** _wcapture_argv(_In_ va_list *, _In_z_ const char16_t * _FirstArg, _Out_writes_z_(_MaxCount) char16_t ** _Static_argv, _In_ size_t _MaxCount); -#endif /* _M_IX86 */ - -/* - * internal routine used by the abort - */ - -extern _PHNDLR __cdecl __get_sigabrt(void); - -/* - * Type from ntdef.h - */ - -typedef LONG NTSTATUS; - -/* - * Exception code used in _invalid_parameter - */ - -#ifndef STATUS_INVALID_PARAMETER -#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL) -#endif /* STATUS_INVALID_PARAMETER */ - -/* - * Exception code used for abort and _CALL_REPORTFAULT - */ - -#ifndef STATUS_FATAL_APP_EXIT -#define STATUS_FATAL_APP_EXIT ((NTSTATUS)0x40000015L) -#endif /* STATUS_FATAL_APP_EXIT */ - -/* - * Validate functions - */ -#include /* _ASSERTE */ -#include - -#define __STR2WSTR(str) L##str - -#define _STR2WSTR(str) __STR2WSTR(str) - -#define __FILEW__ _STR2WSTR(__FILE__) -#define __FUNCTIONW__ _STR2WSTR(__FUNCTION__) - -/* We completely fill the buffer only in debug (see _SECURECRT__FILL_STRING - * and _SECURECRT__FILL_BYTE macros). - */ -#if !defined (_SECURECRT_FILL_BUFFER) -#ifdef _DEBUG -#define _SECURECRT_FILL_BUFFER 1 -#else /* _DEBUG */ -#define _SECURECRT_FILL_BUFFER 0 -#endif /* _DEBUG */ -#endif /* !defined (_SECURECRT_FILL_BUFFER) */ - -#ifndef _SAFECRT_IMPL -/* _invalid_parameter is already defined in safecrt.h and safecrt.lib */ -#if !defined (_NATIVE_char16_t_DEFINED) && defined (_M_CEE_PURE) -extern "C++" -#endif /* !defined (_NATIVE_char16_t_DEFINED) && defined (_M_CEE_PURE) */ -_CRTIMP -#endif /* _SAFECRT_IMPL */ -void __cdecl _invalid_parameter(_In_opt_z_ const char16_t *, _In_opt_z_ const char16_t *, _In_opt_z_ const char16_t *, unsigned int, uintptr_t); - -#if !defined (_NATIVE_char16_t_DEFINED) && defined (_M_CEE_PURE) -extern "C++" -#endif /* !defined (_NATIVE_char16_t_DEFINED) && defined (_M_CEE_PURE) */ -_CRTIMP -void __cdecl _invoke_watson(_In_opt_z_ const char16_t *, _In_opt_z_ const char16_t *, _In_opt_z_ const char16_t *, unsigned int, uintptr_t); - -#ifndef _DEBUG -#if !defined (_NATIVE_char16_t_DEFINED) && defined (_M_CEE_PURE) -extern "C++" -#endif /* !defined (_NATIVE_char16_t_DEFINED) && defined (_M_CEE_PURE) */ -_CRTIMP -void __cdecl _invalid_parameter_noinfo(void); -#endif /* _DEBUG */ - -/* Invoke Watson if _ExpressionError is not 0; otherwise simply return _ExpressionError */ -__forceinline -void _invoke_watson_if_error( - errno_t _ExpressionError, - const char16_t *_Expression, - const char16_t *_Function, - const char16_t *_File, - unsigned int _Line, - uintptr_t _Reserved - ) -{ - if (_ExpressionError == 0) - { - return; - } - _invoke_watson(_Expression, _Function, _File, _Line, _Reserved); -} - -/* Invoke Watson if _ExpressionError is not 0 and equal to _ErrorValue1 or _ErrorValue2; otherwise simply return _ExpressionError */ -__forceinline -errno_t _invoke_watson_if_oneof( - errno_t _ExpressionError, - errno_t _ErrorValue1, - errno_t _ErrorValue2, - const char16_t *_Expression, - const char16_t *_Function, - const char16_t *_File, - unsigned int _Line, - uintptr_t _Reserved - ) -{ - if (_ExpressionError == 0 || (_ExpressionError != _ErrorValue1 && _ExpressionError != _ErrorValue2)) - { - return _ExpressionError; - } - _invoke_watson(_Expression, _Function, _File, _Line, _Reserved); - return _ExpressionError; -} - -/* - * Assert in debug builds. - * set errno and return - * - */ -#ifdef _DEBUG -#define _CALL_INVALID_PARAMETER_FUNC(funcname, expr) funcname(expr, __FUNCTIONW__, __FILEW__, __LINE__, 0) -#define _INVOKE_WATSON_IF_ERROR(expr) _invoke_watson_if_error((expr), __STR2WSTR(#expr), __FUNCTIONW__, __FILEW__, __LINE__, 0) -#define _INVOKE_WATSON_IF_ONEOF(expr, errvalue1, errvalue2) _invoke_watson_if_oneof(expr, (errvalue1), (errvalue2), __STR2WSTR(#expr), __FUNCTIONW__, __FILEW__, __LINE__, 0) -#else /* _DEBUG */ -#define _CALL_INVALID_PARAMETER_FUNC(funcname, expr) funcname(NULL, NULL, NULL, 0, 0) -#define _INVOKE_WATSON_IF_ERROR(expr) _invoke_watson_if_error(expr, NULL, NULL, NULL, 0, 0) -#define _INVOKE_WATSON_IF_ONEOF(expr, errvalue1, errvalue2) _invoke_watson_if_oneof((expr), (errvalue1), (errvalue2), NULL, NULL, NULL, 0, 0) -#endif /* _DEBUG */ - -#define _INVALID_PARAMETER(expr) _CALL_INVALID_PARAMETER_FUNC(_invalid_parameter, expr) - -#define _VALIDATE_RETURN_VOID( expr, errorcode ) \ - { \ - int _Expr_val=!!(expr); \ - _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ - if ( !( _Expr_val ) ) \ - { \ - errno = errorcode; \ - _INVALID_PARAMETER(_CRT_WIDE(#expr)); \ - return; \ - } \ - } - -/* - * Assert in debug builds. - * set errno and return value - */ - -#ifndef _VALIDATE_RETURN -#define _VALIDATE_RETURN( expr, errorcode, retexpr ) \ - { \ - int _Expr_val=!!(expr); \ - _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ - if ( !( _Expr_val ) ) \ - { \ - errno = errorcode; \ - _INVALID_PARAMETER(_CRT_WIDE(#expr) ); \ - return ( retexpr ); \ - } \ - } -#endif /* _VALIDATE_RETURN */ - -#ifndef _VALIDATE_RETURN_NOEXC -#define _VALIDATE_RETURN_NOEXC( expr, errorcode, retexpr ) \ - { \ - if ( !(expr) ) \ - { \ - errno = errorcode; \ - return ( retexpr ); \ - } \ - } -#endif /* _VALIDATE_RETURN_NOEXC */ - -/* - * Assert in debug builds. - * set errno and set retval for later usage - */ - -#define _VALIDATE_SETRET( expr, errorcode, retval, retexpr ) \ - { \ - int _Expr_val=!!(expr); \ - _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ - if ( !( _Expr_val ) ) \ - { \ - errno = errorcode; \ - _INVALID_PARAMETER(_CRT_WIDE(#expr)); \ - retval=( retexpr ); \ - } \ - } - -#define _CHECK_FH_RETURN( handle, errorcode, retexpr ) \ - { \ - if(handle == _NO_CONSOLE_FILENO) \ - { \ - errno = errorcode; \ - return ( retexpr ); \ - } \ - } - -/* - We use _VALIDATE_STREAM_ANSI_RETURN to ensure that ANSI file operations( - fprintf etc) aren't called on files opened as UNICODE. We do this check - only if it's an actual FILE pointer & not a string -*/ - -#define _VALIDATE_STREAM_ANSI_RETURN( stream, errorcode, retexpr ) \ - { \ - FILE *_Stream=stream; \ - _VALIDATE_RETURN(( (_Stream->_flag & _IOSTRG) || \ - ( (_textmode_safe(_fileno(_Stream)) == __IOINFO_TM_ANSI) && \ - !_tm_unicode_safe(_fileno(_Stream)))), \ - errorcode, retexpr) \ - } - -/* - We use _VALIDATE_STREAM_ANSI_SETRET to ensure that ANSI file operations( - fprintf etc) aren't called on files opened as UNICODE. We do this check - only if it's an actual FILE pointer & not a string. It doesn't actually return - immediately -*/ - -#define _VALIDATE_STREAM_ANSI_SETRET( stream, errorcode, retval, retexpr) \ - { \ - FILE *_Stream=stream; \ - _VALIDATE_SETRET(( (_Stream->_flag & _IOSTRG) || \ - ( (_textmode_safe(_fileno(_Stream)) == __IOINFO_TM_ANSI) && \ - !_tm_unicode_safe(_fileno(_Stream)))), \ - errorcode, retval, retexpr) \ - } - -/* - * Assert in debug builds. - * Return value (do not set errno) - */ - -#define _VALIDATE_RETURN_NOERRNO( expr, retexpr ) \ - { \ - int _Expr_val=!!(expr); \ - _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ - if ( !( _Expr_val ) ) \ - { \ - _INVALID_PARAMETER(_CRT_WIDE(#expr)); \ - return ( retexpr ); \ - } \ - } - -/* - * Assert in debug builds. - * set errno and return errorcode - */ - -#define _VALIDATE_RETURN_ERRCODE( expr, errorcode ) \ - { \ - int _Expr_val=!!(expr); \ - _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ - if ( !( _Expr_val ) ) \ - { \ - errno = errorcode; \ - _INVALID_PARAMETER(_CRT_WIDE(#expr)); \ - return ( errorcode ); \ - } \ - } - -#define _VALIDATE_RETURN_ERRCODE_NOEXC( expr, errorcode ) \ - { \ - if (!(expr)) \ - { \ - errno = errorcode; \ - return ( errorcode ); \ - } \ - } - -#define _VALIDATE_CLEAR_OSSERR_RETURN( expr, errorcode, retexpr ) \ - { \ - int _Expr_val=!!(expr); \ - _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ - if ( !( _Expr_val ) ) \ - { \ - _doserrno = 0L; \ - errno = errorcode; \ - _INVALID_PARAMETER(_CRT_WIDE(#expr) ); \ - return ( retexpr ); \ - } \ - } - -#define _CHECK_FH_CLEAR_OSSERR_RETURN( handle, errorcode, retexpr ) \ - { \ - if(handle == _NO_CONSOLE_FILENO) \ - { \ - _doserrno = 0L; \ - errno = errorcode; \ - return ( retexpr ); \ - } \ - } - -#define _VALIDATE_CLEAR_OSSERR_RETURN_ERRCODE( expr, errorcode ) \ - { \ - int _Expr_val=!!(expr); \ - _ASSERT_EXPR( ( _Expr_val ), _CRT_WIDE(#expr) ); \ - if ( !( _Expr_val ) ) \ - { \ - _doserrno = 0L; \ - errno = errorcode; \ - _INVALID_PARAMETER(_CRT_WIDE(#expr)); \ - return ( errorcode ); \ - } \ - } - -#define _CHECK_FH_CLEAR_OSSERR_RETURN_ERRCODE( handle, retexpr ) \ - { \ - if(handle == _NO_CONSOLE_FILENO) \ - { \ - _doserrno = 0L; \ - return ( retexpr ); \ - } \ - } - -#ifdef _DEBUG -extern size_t __crtDebugFillThreshold; -#endif /* _DEBUG */ - -#if !defined (_SECURECRT_FILL_BUFFER_THRESHOLD) -#ifdef _DEBUG -#define _SECURECRT_FILL_BUFFER_THRESHOLD __crtDebugFillThreshold -#else /* _DEBUG */ -#define _SECURECRT_FILL_BUFFER_THRESHOLD ((size_t)0) -#endif /* _DEBUG */ -#endif /* !defined (_SECURECRT_FILL_BUFFER_THRESHOLD) */ - -#if _SECURECRT_FILL_BUFFER -#define _SECURECRT__FILL_STRING(_String, _Size, _Offset) \ - if ((_Size) != ((size_t)-1) && (_Size) != INT_MAX && \ - ((size_t)(_Offset)) < (_Size)) \ - { \ - memset((_String) + (_Offset), \ - _SECURECRT_FILL_BUFFER_PATTERN, \ - (_SECURECRT_FILL_BUFFER_THRESHOLD < ((size_t)((_Size) - (_Offset))) ? \ - _SECURECRT_FILL_BUFFER_THRESHOLD : \ - ((_Size) - (_Offset))) * sizeof(*(_String))); \ - } -#else /* _SECURECRT_FILL_BUFFER */ -#define _SECURECRT__FILL_STRING(_String, _Size, _Offset) -#endif /* _SECURECRT_FILL_BUFFER */ - -#if _SECURECRT_FILL_BUFFER -#define _SECURECRT__FILL_BYTE(_Position) \ - if (_SECURECRT_FILL_BUFFER_THRESHOLD > 0) \ - { \ - (_Position) = _SECURECRT_FILL_BUFFER_PATTERN; \ - } -#else /* _SECURECRT_FILL_BUFFER */ -#define _SECURECRT__FILL_BYTE(_Position) -#endif /* _SECURECRT_FILL_BUFFER */ - -#ifdef __cplusplus -#define _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE extern "C" -#else /* __cplusplus */ -#define _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE -#endif /* __cplusplus */ - -/* helper macros to redirect an mbs function to the corresponding _l version */ -#define _REDIRECT_TO_L_VERSION_1(_ReturnType, _FunctionName, _Type1) \ - _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE \ - _ReturnType __cdecl _FunctionName(_Type1 _Arg1) \ - { \ - return _FunctionName##_l(_Arg1, NULL); \ - } - -#define _REDIRECT_TO_L_VERSION_2(_ReturnType, _FunctionName, _Type1, _Type2) \ - _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE \ - _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2) \ - { \ - return _FunctionName##_l(_Arg1, _Arg2, NULL); \ - } - -#define _REDIRECT_TO_L_VERSION_3(_ReturnType, _FunctionName, _Type1, _Type2, _Type3) \ - _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE \ - _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2, _Type3 _Arg3) \ - { \ - return _FunctionName##_l(_Arg1, _Arg2, _Arg3, NULL); \ - } - -#define _REDIRECT_TO_L_VERSION_4(_ReturnType, _FunctionName, _Type1, _Type2, _Type3, _Type4) \ - _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE \ - _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2, _Type3 _Arg3, _Type4 _Arg4) \ - { \ - return _FunctionName##_l(_Arg1, _Arg2, _Arg3, _Arg4, NULL); \ - } - -#define _REDIRECT_TO_L_VERSION_5(_ReturnType, _FunctionName, _Type1, _Type2, _Type3, _Type4, _Type5) \ - _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE \ - _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2, _Type3 _Arg3, _Type4 _Arg4, _Type5 _Arg5) \ - { \ - return _FunctionName##_l(_Arg1, _Arg2, _Arg3, _Arg4, _Arg5, NULL); \ - } - -#define _REDIRECT_TO_L_VERSION_6(_ReturnType, _FunctionName, _Type1, _Type2, _Type3, _Type4, _Type5, _Type6) \ - _REDIRECT_TO_L_VERSION_FUNC_PROLOGUE \ - _ReturnType __cdecl _FunctionName(_Type1 _Arg1, _Type2 _Arg2, _Type3 _Arg3, _Type4 _Arg4, _Type5 _Arg5, _Type6 _Arg6) \ - { \ - return _FunctionName##_l(_Arg1, _Arg2, _Arg3, _Arg4, _Arg5, _Arg6, NULL); \ - } - -/* internal helper functions for encoding and decoding pointers */ -void __cdecl _init_pointers(); -_CRTIMP void * __cdecl _encode_pointer(void *); -_CRTIMP void * __cdecl _encoded_null(); -_CRTIMP void * __cdecl _decode_pointer(void *); - -/* internal helper function for communicating with the debugger */ -BOOL DebuggerKnownHandle(); - -#define _ERRCHECK(e) \ - _INVOKE_WATSON_IF_ERROR(e) - -#define _ERRCHECK_EINVAL(e) \ - _INVOKE_WATSON_IF_ONEOF(e, EINVAL, EINVAL) - -#define _ERRCHECK_EINVAL_ERANGE(e) \ - _INVOKE_WATSON_IF_ONEOF(e, EINVAL, ERANGE) - -#define _ERRCHECK_SPRINTF(_PrintfCall) \ - { \ - errno_t _SaveErrno = errno; \ - errno = 0; \ - if ( ( _PrintfCall ) < 0) \ - { \ - _ERRCHECK_EINVAL_ERANGE(errno); \ - } \ - errno = _SaveErrno; \ - } - -/* internal helper function to access environment variable in read-only mode */ -const char16_t * __cdecl _wgetenv_helper_nolock(const char16_t *); -const char * __cdecl _getenv_helper_nolock(const char *); - -/* internal helper routines used to query a PE image header. */ -BOOL __cdecl _ValidateImageBase(PBYTE pImageBase); -PIMAGE_SECTION_HEADER __cdecl _FindPESection(PBYTE pImageBase, DWORD_PTR rva); -BOOL __cdecl _IsNonwritableInCurrentImage(PBYTE pTarget); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#ifdef _MSC_VER -#pragma pack(pop) -#endif /* _MSC_VER */ - -#endif /* _INC_INTERNAL */ diff --git a/src/coreclr/pal/src/safecrt/internal_securecrt.h b/src/coreclr/pal/src/safecrt/internal_securecrt.h index f5117457c5d81b..1c323efe0084d2 100644 --- a/src/coreclr/pal/src/safecrt/internal_securecrt.h +++ b/src/coreclr/pal/src/safecrt/internal_securecrt.h @@ -71,8 +71,6 @@ #define _TRUNCATE ((size_t)-1) #endif /* !defined (_TRUNCATE) */ -/* #include */ - #define _VALIDATE_RETURN_VOID( expr, errorcode ) \ { \ int _Expr_val=!!(expr); \ diff --git a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp index 368dbfa4950f10..5d12b850f9b9bc 100644 --- a/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp +++ b/src/coreclr/pal/src/sharedmemory/sharedmemory.cpp @@ -1481,7 +1481,7 @@ void SharedMemoryProcessDataHeader::DecRefCount() //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // SharedMemoryManager -CRITICAL_SECTION SharedMemoryManager::s_creationDeletionProcessLock; +minipal_mutex SharedMemoryManager::s_creationDeletionProcessLock; int SharedMemoryManager::s_creationDeletionLockFileDescriptor = -1; SharedMemoryManager::UserScopeUidAndFileDescriptor *SharedMemoryManager::s_userScopeUidToCreationDeletionLockFDs; @@ -1497,7 +1497,7 @@ SIZE_T SharedMemoryManager::s_creationDeletionFileLockOwnerThreadId = SharedMemo void SharedMemoryManager::StaticInitialize() { - InitializeCriticalSection(&s_creationDeletionProcessLock); + minipal_mutex_init(&s_creationDeletionProcessLock); } void SharedMemoryManager::StaticClose() @@ -1522,7 +1522,7 @@ void SharedMemoryManager::AcquireCreationDeletionProcessLock() _ASSERTE(!IsCreationDeletionProcessLockAcquired()); _ASSERTE(!IsCreationDeletionFileLockAcquired()); - EnterCriticalSection(&s_creationDeletionProcessLock); + minipal_mutex_enter(&s_creationDeletionProcessLock); #ifdef _DEBUG s_creationDeletionProcessLockOwnerThreadId = THREADSilentGetCurrentThreadId(); #endif // _DEBUG @@ -1536,7 +1536,7 @@ void SharedMemoryManager::ReleaseCreationDeletionProcessLock() #ifdef _DEBUG s_creationDeletionProcessLockOwnerThreadId = SharedMemoryHelpers::InvalidThreadId; #endif // _DEBUG - LeaveCriticalSection(&s_creationDeletionProcessLock); + minipal_mutex_leave(&s_creationDeletionProcessLock); } void SharedMemoryManager::AcquireCreationDeletionFileLock(SharedMemorySystemCallErrors *errors, const SharedMemoryId *id) diff --git a/src/coreclr/pal/src/sync/cs.cpp b/src/coreclr/pal/src/sync/cs.cpp deleted file mode 100644 index 032ff1c189f3cf..00000000000000 --- a/src/coreclr/pal/src/sync/cs.cpp +++ /dev/null @@ -1,1457 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/////////////////////////////////////////////////////////////////////////////// -// -// File: -// cs.cpp -// -// Purpose: -// Implementation of critical sections -// -/////////////////////////////////////////////////////////////////////////////// - -#include "pal/thread.hpp" -#include "pal/cs.hpp" -#include "pal/list.h" -#include "pal/dbgmsg.h" -#include "pal/init.h" -#include "pal/process.h" - -#include -#include - -using namespace CorUnix; - -// -// Uncomment the following line to turn CS behavior from -// unfair to fair lock -// -// #define PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - -// -// Uncomment the following line to enable simple mutex based CSs -// Note: when MUTEX_BASED_CSS is defined, PALCS_TRANSFER_OWNERSHIP_ON_RELEASE -// has no effect -// -// #define MUTEX_BASED_CSS - -// -// Important notes on critical sections layout/semantics on Unix -// -// 1) The PAL_CRITICAL_SECTION structure below must match the size of the -// CRITICAL_SECTION defined in pal.h. Besides the "windows part" -// of both the structures must be identical. -// 2) Both PAL_CRITICAL_SECTION and CRITICAL_SECTION currently do not match -// the size of the Windows' CRITICAL_SECTION. -// - From unmanaged code point of view, one should never make assumptions -// on the size and layout of the CRITICAL_SECTION structure, and anyway -// on Unix PAL's CRITICAL_SECTION extends the Windows one, so that some -// assumptions may still work. -// - From managed code point of view, one could try to interop directly -// to unmanaged critical sections APIs (though that would be quite -// meaningless). In order to do that, one would need to define a copy -// of the CRITICAL_SECTION structure in one's code, and that may lead -// to access random data beyond the structure limit, if that managed -// code is compiled on Unix. -// In case such scenario should be supported, the current implementation -// will have to be modified in a way to go back to the original Windows -// CRITICAL_SECTION layout. That would require to dynamically allocate -// the native data and use LockSemaphore as a pointer to it. The current -// solution intentionally avoids that since an effort has been made to -// make CSs objects completely independent from any other PAL subsystem, -// so that they can be used during initialization and shutdown. -// In case the "dynamically allocate native data" solution should be -// implemented, CSs would acquire a dependency on memory allocation and -// thread suspension subsystems, since the first contention on a specific -// CS would trigger the native data allocation. -// 3) The semantics of the LockCount field has not been kept compatible with -// the Windows implementation. -// Both on Windows and Unix the lower bit of LockCount indicates -// whether or not the CS is locked (for both fair and unfair lock -// solution), the second bit indicates whether or not currently there is a -// waiter that has been awakened and that is trying to acquire the CS -// (only unfair lock solution, unused in the fair one); starting from the -// third bit, LockCount represents the number of waiter threads currently -// waiting on the CS. -// Windows, anyway, implements this semantics in negative logic, so that -// an unlocked CS is represented by a LockCount == -1 (i.e. 0xFFFFFFFF, -// all the bits set), while on Unix an unlocked CS has LockCount == 0. -// Windows needs to use negative logic to support legacy code bad enough -// to directly access CS's fields making the assumption that -// LockCount == -1 means CS unlocked. Unix will not support that, and -// it uses positive logic. -// 4) The CRITICAL_SECTION_DEBUG_INFO layout on Unix is intentionally not -// compatible with the Windows layout. -// 5) For legacy code dependencies issues similar to those just described for -// the LockCount field, Windows CS code maintains a per-process list of -// debug info for all the CSs, both on debug and free/retail builds. On -// Unix such a list is maintained only on debug builds, and no debug -// info structure is allocated on free/retail builds -// - -SET_DEFAULT_DEBUG_CHANNEL(CRITSEC); - -#ifdef TRACE_CS_LOGIC -#define CS_TRACE TRACE -#else -#ifdef __GNUC__ -#define CS_TRACE(args...) -#else -#define CS_TRACE(...) -#endif -#endif // TRACE_CS_LOGIC - -// -// Note: PALCS_LOCK_WAITER_INC must be 2 * PALCS_LOCK_AWAKENED_WAITER -// -#define PALCS_LOCK_INIT 0 -#define PALCS_LOCK_BIT 1 -#define PALCS_LOCK_AWAKENED_WAITER 2 -#define PALCS_LOCK_WAITER_INC 4 - -#define PALCS_GETLBIT(val) ((int)(0!=(PALCS_LOCK_BIT&val))) -#define PALCS_GETAWBIT(val) ((int)(0!=(PALCS_LOCK_AWAKENED_WAITER&val))) -#define PALCS_GETWCOUNT(val) (val/PALCS_LOCK_WAITER_INC) - -enum PalCsInitState -{ - PalCsNotInitialized, // Critical section not initialized (InitializedCriticalSection - // has not yet been called, or DeleteCriticalsection has been - // called). - PalCsUserInitialized, // Critical section initialized from the user point of view, - // i.e. InitializedCriticalSection has been called. - PalCsFullyInitializing, // A thread found the CS locked, this is the first contention on - // this CS, and the thread is initializing the CS's native data. - PalCsFullyInitialized // Internal CS's native data has been fully initialized. -}; - -enum PalCsWaiterReturnState -{ - PalCsReturnWaiterAwakened, - PalCsWaiterDidntWait -}; - -struct _PAL_CRITICAL_SECTION; // fwd declaration - -typedef struct _CRITICAL_SECTION_DEBUG_INFO -{ - LIST_ENTRY Link; - struct _PAL_CRITICAL_SECTION * pOwnerCS; - Volatile lAcquireCount; - Volatile lEnterCount; - Volatile lContentionCount; -} CRITICAL_SECTION_DEBUG_INFO, *PCRITICAL_SECTION_DEBUG_INFO; - -typedef struct _PAL_CRITICAL_SECTION_NATIVE_DATA -{ - pthread_mutex_t mutex; - pthread_cond_t condition; - int iPredicate; -} PAL_CRITICAL_SECTION_NATIVE_DATA, *PPAL_CRITICAL_SECTION_NATIVE_DATA; - -typedef struct _PAL_CRITICAL_SECTION { - // Windows part - PCRITICAL_SECTION_DEBUG_INFO DebugInfo; - Volatile LockCount; - LONG RecursionCount; - SIZE_T OwningThread; - ULONG_PTR SpinCount; - // Private Unix part -#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA - BOOL fInternal; -#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA - Volatile cisInitState; - PAL_CRITICAL_SECTION_NATIVE_DATA csndNativeData; -} PAL_CRITICAL_SECTION, *PPAL_CRITICAL_SECTION, *LPPAL_CRITICAL_SECTION; - -#ifdef _DEBUG -namespace CorUnix -{ - PAL_CRITICAL_SECTION g_csPALCSsListLock; - LIST_ENTRY g_PALCSList = { &g_PALCSList, &g_PALCSList}; -} -#endif // _DEBUG - -#define ObtainCurrentThreadId(thread) ObtainCurrentThreadIdImpl(thread, __func__) -static SIZE_T ObtainCurrentThreadIdImpl(CPalThread *pCurrentThread, const char *callingFuncName) -{ - SIZE_T threadId; - if(pCurrentThread) - { - threadId = pCurrentThread->GetThreadId(); - _ASSERTE(threadId == THREADSilentGetCurrentThreadId()); - } - else - { - threadId = THREADSilentGetCurrentThreadId(); - CS_TRACE("Early %s, no pthread data, getting TID internally\n", callingFuncName); - } - _ASSERTE(0 != threadId); - - return threadId; -} - - -/*++ -Function: - InitializeCriticalSection - -See MSDN doc. ---*/ -void InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - PERF_ENTRY(InitializeCriticalSection); - ENTRY("InitializeCriticalSection(lpCriticalSection=%p)\n", - lpCriticalSection); - - InternalInitializeCriticalSectionAndSpinCount(lpCriticalSection, - 0, false); - - LOGEXIT("InitializeCriticalSection returns void\n"); - PERF_EXIT(InitializeCriticalSection); -} - -/*++ -Function: - InitializeCriticalSectionAndSpinCount - -See MSDN doc. ---*/ -BOOL InitializeCriticalSectionAndSpinCount(LPCRITICAL_SECTION lpCriticalSection, - DWORD dwSpinCount) -{ - BOOL bRet = TRUE; - PERF_ENTRY(InitializeCriticalSectionAndSpinCount); - ENTRY("InitializeCriticalSectionAndSpinCount(lpCriticalSection=%p, " - "dwSpinCount=%u)\n", lpCriticalSection, dwSpinCount); - - InternalInitializeCriticalSectionAndSpinCount(lpCriticalSection, - dwSpinCount, false); - - LOGEXIT("InitializeCriticalSectionAndSpinCount returns BOOL %d\n", - bRet); - PERF_EXIT(InitializeCriticalSectionAndSpinCount); - return bRet; -} - -/*++ -Function: - DeleteCriticalSection - -See MSDN doc. ---*/ -void DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - PERF_ENTRY(DeleteCriticalSection); - ENTRY("DeleteCriticalSection(lpCriticalSection=%p)\n", lpCriticalSection); - - InternalDeleteCriticalSection(lpCriticalSection); - - LOGEXIT("DeleteCriticalSection returns void\n"); - PERF_EXIT(DeleteCriticalSection); -} - -/*++ -Function: - EnterCriticalSection - -See MSDN doc. ---*/ -void EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - PERF_ENTRY(EnterCriticalSection); - ENTRY("EnterCriticalSection(lpCriticalSection=%p)\n", lpCriticalSection); - - CPalThread * pThread = InternalGetCurrentThread(); - - InternalEnterCriticalSection(pThread, lpCriticalSection); - - LOGEXIT("EnterCriticalSection returns void\n"); - PERF_EXIT(EnterCriticalSection); -} - -/*++ -Function: - LeaveCriticalSection - -See MSDN doc. ---*/ -VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - PERF_ENTRY(LeaveCriticalSection); - ENTRY("LeaveCriticalSection(lpCriticalSection=%p)\n", lpCriticalSection); - - CPalThread * pThread = InternalGetCurrentThread(); - - InternalLeaveCriticalSection(pThread, lpCriticalSection); - - LOGEXIT("LeaveCriticalSection returns void\n"); - PERF_EXIT(LeaveCriticalSection); -} - -/*++ -Function: - InternalInitializeCriticalSection - -Initializes a critical section. It assumes the CS is an internal one, -i.e. thread entering it will be marked unsafe for suspension ---*/ -VOID InternalInitializeCriticalSection(CRITICAL_SECTION *pcs) -{ - InternalInitializeCriticalSectionAndSpinCount(pcs, 0, true); -} - -/*++ -Function: - InternalDeleteCriticalSection - -Deletes a critical section ---*/ -VOID InternalDeleteCriticalSection( - PCRITICAL_SECTION pCriticalSection) -{ - PAL_CRITICAL_SECTION * pPalCriticalSection = - reinterpret_cast(pCriticalSection); - - _ASSERT_MSG(PalCsUserInitialized == pPalCriticalSection->cisInitState || - PalCsFullyInitialized == pPalCriticalSection->cisInitState, - "CS %p is not initialized", pPalCriticalSection); - -#ifdef _DEBUG - CPalThread * pThread = - (PALIsThreadDataInitialized() ? GetCurrentPalThread() : NULL); - - if (0 != pPalCriticalSection->LockCount) - { - SIZE_T tid; - tid = ObtainCurrentThreadId(pThread); - int iWaiterCount = (int)PALCS_GETWCOUNT(pPalCriticalSection->LockCount); - - if (0 != (PALCS_LOCK_BIT & pPalCriticalSection->LockCount)) - { - // CS is locked - if (tid != pPalCriticalSection->OwningThread) - { - // not owner - ASSERT("Thread tid=%u deleting a CS owned by thread tid=%u\n", - tid, pPalCriticalSection->OwningThread); - } - else - { - // owner - if (0 != iWaiterCount) - { - ERROR("Thread tid=%u is deleting a CS with %d threads waiting on it\n", - tid, iWaiterCount); - } - else - { - WARN("Thread tid=%u is deleting a critical section it still owns\n", - tid); - } - } - } - else - { - // CS is not locked - if (0 != iWaiterCount) - { - ERROR("Deleting a CS with %d threads waiting on it\n", - iWaiterCount); - } - else - { - ERROR("Thread tid=%u is deleting a critical section currently not " - "owned, but with one waiter awakened\n", tid); - } - } - } - - if (NULL != pPalCriticalSection->DebugInfo) - { - if (pPalCriticalSection != &CorUnix::g_csPALCSsListLock) - { - InternalEnterCriticalSection(pThread, - reinterpret_cast(&g_csPALCSsListLock)); - RemoveEntryList(&pPalCriticalSection->DebugInfo->Link); - InternalLeaveCriticalSection(pThread, - reinterpret_cast(&g_csPALCSsListLock)); - } - else - { - RemoveEntryList(&pPalCriticalSection->DebugInfo->Link); - } - -#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA - LONG lVal, lNewVal; - Volatile * plDest; - - // Update delete count - InterlockedIncrement(pPalCriticalSection->fInternal ? - &g_lPALCSInternalDeleteCount : &g_lPALCSDeleteCount); - - // Update acquire count - plDest = pPalCriticalSection->fInternal ? - &g_lPALCSInternalAcquireCount : &g_lPALCSAcquireCount; - do { - lVal = *plDest; - lNewVal = lVal + pPalCriticalSection->DebugInfo->lAcquireCount; - lNewVal = InterlockedCompareExchange(plDest, lNewVal, lVal); - } while (lVal != lNewVal); - - // Update enter count - plDest = pPalCriticalSection->fInternal ? - &g_lPALCSInternalEnterCount : &g_lPALCSEnterCount; - do { - lVal = *plDest; - lNewVal = lVal + pPalCriticalSection->DebugInfo->lEnterCount; - lNewVal = InterlockedCompareExchange(plDest, lNewVal, lVal); - } while (lVal != lNewVal); - - // Update contention count - plDest = pPalCriticalSection->fInternal ? - &g_lPALCSInternalContentionCount : &g_lPALCSContentionCount; - do { - lVal = *plDest; - lNewVal = lVal + pPalCriticalSection->DebugInfo->lContentionCount; - lNewVal = InterlockedCompareExchange(plDest, lNewVal, lVal); - } while (lVal != lNewVal); - -#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA - - delete pPalCriticalSection->DebugInfo; - pPalCriticalSection->DebugInfo = NULL; - } -#endif // _DEBUG - - if (PalCsFullyInitialized == pPalCriticalSection->cisInitState) - { - int iRet; - - // destroy condition - iRet = pthread_cond_destroy(&pPalCriticalSection->csndNativeData.condition); - _ASSERT_MSG(0 == iRet, "Failed destroying condition in CS @ %p " - "[err=%d]\n", pPalCriticalSection, iRet); - - // destroy mutex - iRet = pthread_mutex_destroy(&pPalCriticalSection->csndNativeData.mutex); - _ASSERT_MSG(0 == iRet, "Failed destroying mutex in CS @ %p " - "[err=%d]\n", pPalCriticalSection, iRet); - } - - // Reset critical section state - pPalCriticalSection->cisInitState = PalCsNotInitialized; -} - -// The following PALCEnterCriticalSection and PALCLeaveCriticalSection -// functions are intended to provide CorUnix's InternalEnterCriticalSection -// and InternalLeaveCriticalSection functionalities to legacy C code, -// which has no knowledge of CPalThread, classes and namespaces. - -/*++ -Function: - PALCEnterCriticalSection - -Provides CorUnix's InternalEnterCriticalSection functionality to legacy C code, -which has no knowledge of CPalThread, classes and namespaces. ---*/ -VOID PALCEnterCriticalSection(CRITICAL_SECTION * pcs) -{ - CPalThread * pThread = - (PALIsThreadDataInitialized() ? GetCurrentPalThread() : NULL); - CorUnix::InternalEnterCriticalSection(pThread, pcs); -} - -/*++ -Function: - PALCLeaveCriticalSection - -Provides CorUnix's InternalLeaveCriticalSection functionality to legacy C code, -which has no knowledge of CPalThread, classes and namespaces. ---*/ -VOID PALCLeaveCriticalSection(CRITICAL_SECTION * pcs) -{ - CPalThread * pThread = - (PALIsThreadDataInitialized() ? GetCurrentPalThread() : NULL); - CorUnix::InternalLeaveCriticalSection(pThread, pcs); -} - -namespace CorUnix -{ - static PalCsWaiterReturnState PALCS_WaitOnCS( - PAL_CRITICAL_SECTION * pPalCriticalSection, - LONG lInc); - static PAL_ERROR PALCS_DoActualWait(PAL_CRITICAL_SECTION * pPalCriticalSection); - static PAL_ERROR PALCS_WakeUpWaiter(PAL_CRITICAL_SECTION * pPalCriticalSection); - static bool PALCS_FullyInitialize(PAL_CRITICAL_SECTION * pPalCriticalSection); - -#ifdef _DEBUG - enum CSSubSysInitState - { - CSSubSysNotInitialized, - CSSubSysInitializing, - CSSubSysInitialized - }; - static Volatile csssInitState = CSSubSysNotInitialized; - -#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA - static Volatile g_lPALCSInitializeCount = 0; - static Volatile g_lPALCSDeleteCount = 0; - static Volatile g_lPALCSAcquireCount = 0; - static Volatile g_lPALCSEnterCount = 0; - static Volatile g_lPALCSContentionCount = 0; - static Volatile g_lPALCSInternalInitializeCount = 0; - static Volatile g_lPALCSInternalDeleteCount = 0; - static Volatile g_lPALCSInternalAcquireCount = 0; - static Volatile g_lPALCSInternalEnterCount = 0; - static Volatile g_lPALCSInternalContentionCount = 0; -#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA -#endif // _DEBUG - - - /*++ - Function: - CorUnix::CriticalSectionSubSysInitialize - - Initializes CS subsystem - --*/ - void CriticalSectionSubSysInitialize() - { - static_assert(sizeof(CRITICAL_SECTION) >= sizeof(PAL_CRITICAL_SECTION), - "PAL fatal internal error: sizeof(CRITICAL_SECTION) is " - "smaller than sizeof(PAL_CRITICAL_SECTION)"); - -#ifdef _DEBUG - LONG lRet = InterlockedCompareExchange((LONG *)&csssInitState, - (LONG)CSSubSysInitializing, - (LONG)CSSubSysNotInitialized); - if ((LONG)CSSubSysNotInitialized == lRet) - { - InitializeListHead(&g_PALCSList); - - InternalInitializeCriticalSectionAndSpinCount( - reinterpret_cast(&g_csPALCSsListLock), - 0, true); - InterlockedExchange((LONG *)&csssInitState, - (LONG)CSSubSysInitialized); - } - else - { - while (csssInitState != CSSubSysInitialized) - { - sched_yield(); - } - } -#endif // _DEBUG - } - - /*++ - Function: - CorUnix::InternalInitializeCriticalSectionAndSpinCount - - Initializes a CS with the given spin count. If 'fInternal' is true - the CS will be treatead as an internal one for its whole lifetime, - i.e. any thread that will enter it will be marked as unsafe for - suspension as long as it holds the CS - --*/ - void InternalInitializeCriticalSectionAndSpinCount( - PCRITICAL_SECTION pCriticalSection, - DWORD dwSpinCount, - bool fInternal) - { - PAL_CRITICAL_SECTION * pPalCriticalSection = - reinterpret_cast(pCriticalSection); - -#ifndef PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - // Make sure bits are defined in a usable way - _ASSERTE(PALCS_LOCK_AWAKENED_WAITER * 2 == PALCS_LOCK_WAITER_INC); -#endif // !PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - - // Make sure structure sizes are compatible - _ASSERTE(sizeof(CRITICAL_SECTION) >= sizeof(PAL_CRITICAL_SECTION)); - -#ifdef _DEBUG - if (sizeof(CRITICAL_SECTION) > sizeof(PAL_CRITICAL_SECTION)) - { - WARN("PAL_CS_NATIVE_DATA_SIZE appears to be defined to a value (%d) " - "larger than needed on this platform (%d).\n", - sizeof(CRITICAL_SECTION), sizeof(PAL_CRITICAL_SECTION)); - } -#endif // _DEBUG - - // Init CS data - pPalCriticalSection->DebugInfo = NULL; - pPalCriticalSection->LockCount = 0; - pPalCriticalSection->RecursionCount = 0; - pPalCriticalSection->SpinCount = dwSpinCount; - pPalCriticalSection->OwningThread = 0; - -#ifdef _DEBUG - CPalThread * pThread = - (PALIsThreadDataInitialized() ? GetCurrentPalThread() : NULL); - - pPalCriticalSection->DebugInfo = new(std::nothrow) CRITICAL_SECTION_DEBUG_INFO(); - _ASSERT_MSG(NULL != pPalCriticalSection->DebugInfo, - "Failed to allocate debug info for new CS\n"); - - // Init debug info data - pPalCriticalSection->DebugInfo->lAcquireCount = 0; - pPalCriticalSection->DebugInfo->lEnterCount = 0; - pPalCriticalSection->DebugInfo->lContentionCount = 0; - pPalCriticalSection->DebugInfo->pOwnerCS = pPalCriticalSection; - - // Insert debug info struct in global list - if (pPalCriticalSection != &g_csPALCSsListLock) - { - InternalEnterCriticalSection(pThread, - reinterpret_cast(&g_csPALCSsListLock)); - InsertTailList(&g_PALCSList, &pPalCriticalSection->DebugInfo->Link); - InternalLeaveCriticalSection(pThread, - reinterpret_cast(&g_csPALCSsListLock)); - } - else - { - InsertTailList(&g_PALCSList, &pPalCriticalSection->DebugInfo->Link); - } - -#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA - pPalCriticalSection->fInternal = fInternal; - InterlockedIncrement(fInternal ? - &g_lPALCSInternalInitializeCount : &g_lPALCSInitializeCount); -#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA -#endif // _DEBUG - - // Set initializazion state - pPalCriticalSection->cisInitState = PalCsUserInitialized; - -#ifdef MUTEX_BASED_CSS - bool fInit; - do - { - fInit = PALCS_FullyInitialize(pPalCriticalSection); - _ASSERTE(fInit); - } while (!fInit && 0 == sched_yield()); - - if (fInit) - { - // Set initializazion state - pPalCriticalSection->cisInitState = PalCsFullyInitialized; - } -#endif // MUTEX_BASED_CSS - } - -#ifndef MUTEX_BASED_CSS - /*++ - Function: - CorUnix::InternalEnterCriticalSection - - Enters a CS, causing the thread to block if the CS is owned by - another thread - --*/ - void InternalEnterCriticalSection( - CPalThread * pThread, - PCRITICAL_SECTION pCriticalSection) - { - PAL_CRITICAL_SECTION * pPalCriticalSection = - reinterpret_cast(pCriticalSection); - - LONG lSpinCount; - LONG lVal, lNewVal; - LONG lBitsToChange, lWaitInc; - PalCsWaiterReturnState cwrs; - SIZE_T threadId; - - _ASSERTE(PalCsNotInitialized != pPalCriticalSection->cisInitState); - - threadId = ObtainCurrentThreadId(pThread); - - - // Check if the current thread already owns the CS - // - // Note: there is no need for this double check to be atomic. In fact - // if the first check fails, the second doesn't count (and it's not - // even executed). If the first one succeeds and the second one - // doesn't, it doesn't matter if LockCount has already changed by the - // time OwningThread is tested. Instead, if the first one succeeded, - // and the second also succeeds, LockCount cannot have changed in the - // meanwhile, since this is the owning thread and only the owning - // thread can change the lock bit when the CS is owned. - if ((pPalCriticalSection->LockCount & PALCS_LOCK_BIT) && - (pPalCriticalSection->OwningThread == threadId)) - { - pPalCriticalSection->RecursionCount += 1; -#ifdef _DEBUG - if (NULL != pPalCriticalSection->DebugInfo) - { - pPalCriticalSection->DebugInfo->lEnterCount += 1; - } -#endif // _DEBUG - goto IECS_exit; - } - - // Set bits to change and waiter increment for an incoming thread - lBitsToChange = PALCS_LOCK_BIT; - lWaitInc = PALCS_LOCK_WAITER_INC; - lSpinCount = pPalCriticalSection->SpinCount; - - while (TRUE) - { - // Either this is an incoming thread, and therefore lBitsToChange - // is just PALCS_LOCK_BIT, or this is an awakened waiter - _ASSERTE(PALCS_LOCK_BIT == lBitsToChange || - (PALCS_LOCK_BIT | PALCS_LOCK_AWAKENED_WAITER) == lBitsToChange); - - // Make sure the waiter increment is in a valid range - _ASSERTE(PALCS_LOCK_WAITER_INC == lWaitInc || - PALCS_LOCK_AWAKENED_WAITER == lWaitInc); - - do { - lVal = pPalCriticalSection->LockCount; - - while (0 == (lVal & PALCS_LOCK_BIT)) - { - // CS is not locked: try lo lock it - - // Make sure that whether we are an incoming thread - // or the PALCS_LOCK_AWAKENED_WAITER bit is set - _ASSERTE((PALCS_LOCK_BIT == lBitsToChange) || - (PALCS_LOCK_AWAKENED_WAITER & lVal)); - - lNewVal = lVal ^ lBitsToChange; - - // Make sure we are actually trying to lock - _ASSERTE(lNewVal & PALCS_LOCK_BIT); - - CS_TRACE("[ECS %p] Switching from {%d, %d, %d} to " - "{%d, %d, %d} ==>\n", pPalCriticalSection, - PALCS_GETWCOUNT(lVal), PALCS_GETAWBIT(lVal), PALCS_GETLBIT(lVal), - PALCS_GETWCOUNT(lNewVal), PALCS_GETAWBIT(lNewVal), PALCS_GETLBIT(lNewVal)); - - // Try to switch the value - lNewVal = InterlockedCompareExchange (&pPalCriticalSection->LockCount, - lNewVal, lVal); - - CS_TRACE("[ECS %p] ==> %s LockCount={%d, %d, %d} " - "lVal={%d, %d, %d}\n", pPalCriticalSection, - (lNewVal == lVal) ? "OK" : "NO", - PALCS_GETWCOUNT(pPalCriticalSection->LockCount), - PALCS_GETAWBIT(pPalCriticalSection->LockCount), - PALCS_GETLBIT(pPalCriticalSection->LockCount), - PALCS_GETWCOUNT(lVal), PALCS_GETAWBIT(lVal), PALCS_GETLBIT(lVal)); - - if (lNewVal == lVal) - { - // CS successfully acquired - goto IECS_set_ownership; - } - - // Acquisition failed, some thread raced with us; - // update value for next loop - lVal = lNewVal; - } - - if (0 < lSpinCount) - { - sched_yield(); - } - } while (0 <= --lSpinCount); - - cwrs = PALCS_WaitOnCS(pPalCriticalSection, lWaitInc); - - if (PalCsReturnWaiterAwakened == cwrs) - { -#ifdef PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - // - // Fair Critical Sections - // - // In the fair lock case, when a waiter wakes up the CS - // must be locked (i.e. ownership passed on to the waiter) - _ASSERTE(0 != (PALCS_LOCK_BIT & pPalCriticalSection->LockCount)); - - // CS successfully acquired - goto IECS_set_ownership; - -#else // PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - // - // Unfair Critical Sections - // - _ASSERTE(PALCS_LOCK_AWAKENED_WAITER & pPalCriticalSection->LockCount); - - lBitsToChange = PALCS_LOCK_BIT | PALCS_LOCK_AWAKENED_WAITER; - lWaitInc = PALCS_LOCK_AWAKENED_WAITER; -#endif // PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - } - } - - IECS_set_ownership: - // Critical section acquired: set ownership data - pPalCriticalSection->OwningThread = threadId; - pPalCriticalSection->RecursionCount = 1; -#ifdef _DEBUG - if (NULL != pPalCriticalSection->DebugInfo) - { - pPalCriticalSection->DebugInfo->lAcquireCount += 1; - pPalCriticalSection->DebugInfo->lEnterCount += 1; - } -#endif // _DEBUG - - IECS_exit: - return; - } - - /*++ - Function: - CorUnix::InternalLeaveCriticalSection - - Leaves a currently owned CS - --*/ - void InternalLeaveCriticalSection(CPalThread * pThread, - PCRITICAL_SECTION pCriticalSection) - { - PAL_CRITICAL_SECTION * pPalCriticalSection = - reinterpret_cast(pCriticalSection); - LONG lVal, lNewVal; - -#ifdef _DEBUG - SIZE_T threadId; - - _ASSERTE(PalCsNotInitialized != pPalCriticalSection->cisInitState); - - threadId = ObtainCurrentThreadId(pThread); - _ASSERTE(threadId == pPalCriticalSection->OwningThread); -#endif // _DEBUG - - _ASSERT_MSG(PALCS_LOCK_BIT & pPalCriticalSection->LockCount, - "Trying to release an unlocked CS\n"); - _ASSERT_MSG(0 < pPalCriticalSection->RecursionCount, - "Trying to release an unlocked CS\n"); - - if (--pPalCriticalSection->RecursionCount > 0) - { - // Recursion was > 1, still owning the CS - goto ILCS_cs_exit; - } - - // Reset CS ownership - pPalCriticalSection->OwningThread = 0; - - // Load the current LockCount value - lVal = pPalCriticalSection->LockCount; - - while (true) - { - _ASSERT_MSG(0 != (PALCS_LOCK_BIT & lVal), - "Trying to release an unlocked CS\n"); - - // NB: In the fair lock case (PALCS_TRANSFER_OWNERSHIP_ON_RELEASE) the - // PALCS_LOCK_AWAKENED_WAITER bit is not used - if ( (PALCS_LOCK_BIT == lVal) -#ifndef PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - || (PALCS_LOCK_AWAKENED_WAITER & lVal) -#endif // !PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - ) - { - // Whether there are no waiters (PALCS_LOCK_BIT == lVal) - // or a waiter has already been awakened, therefore we - // just need to reset the lock bit and return - lNewVal = lVal & ~PALCS_LOCK_BIT; - CS_TRACE("[LCS-UN %p] Switching from {%d, %d, %d} to " - "{%d, %d, %d} ==>\n", pPalCriticalSection, - PALCS_GETWCOUNT(lVal), PALCS_GETAWBIT(lVal), PALCS_GETLBIT(lVal), - PALCS_GETWCOUNT(lNewVal), PALCS_GETAWBIT(lNewVal), PALCS_GETLBIT(lNewVal)); - - lNewVal = InterlockedCompareExchange(&pPalCriticalSection->LockCount, - lNewVal, lVal); - - CS_TRACE("[LCS-UN %p] ==> %s\n", pPalCriticalSection, - (lNewVal == lVal) ? "OK" : "NO"); - - if (lNewVal == lVal) - { - goto ILCS_cs_exit; - } - } - else - { - // There is at least one waiter, we need to wake it up - -#ifdef PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - // Fair lock case: passing ownership on to the first waiter. - // Here we need only to decrement the waiters count. CS will - // remain locked and ownership will be passed to the waiter, - // which will take care of setting ownership data as soon as - // it wakes up - lNewVal = lVal - PALCS_LOCK_WAITER_INC; -#else // PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - // Unfair lock case: we need to atomically decrement the waiters - // count (we are about ot wake up one of them), set the - // "waiter awakened" bit and to reset the "CS locked" bit. - // Note that, since we know that at this time PALCS_LOCK_BIT - // is set and PALCS_LOCK_AWAKENED_WAITER is not set, none of - // the addenda will affect bits other than its target bit(s), - // i.e. PALCS_LOCK_BIT will not affect PALCS_LOCK_AWAKENED_WAITER, - // PALCS_LOCK_AWAKENED_WAITER will not affect the actual - // count of waiters, and the latter will not change the two - // former ones - lNewVal = lVal - PALCS_LOCK_WAITER_INC + - PALCS_LOCK_AWAKENED_WAITER - PALCS_LOCK_BIT; -#endif // PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - CS_TRACE("[LCS-CN %p] Switching from {%d, %d, %d} to {%d, %d, %d} ==>\n", - pPalCriticalSection, - PALCS_GETWCOUNT(lVal), PALCS_GETAWBIT(lVal), PALCS_GETLBIT(lVal), - PALCS_GETWCOUNT(lNewVal), PALCS_GETAWBIT(lNewVal), PALCS_GETLBIT(lNewVal)); - - lNewVal = InterlockedCompareExchange(&pPalCriticalSection->LockCount, - lNewVal, lVal); - - CS_TRACE("[LCS-CN %p] ==> %s\n", pPalCriticalSection, - (lNewVal == lVal) ? "OK" : "NO"); - - if (lNewVal == lVal) - { - // Wake up the waiter - PALCS_WakeUpWaiter (pPalCriticalSection); - -#ifdef PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - // In the fair lock case, we need to yield here to defeat - // the inherently unfair nature of the condition/predicate - // construct - sched_yield(); -#endif // PALCS_TRANSFER_OWNERSHIP_ON_RELEASE - - goto ILCS_cs_exit; - } - } - - // CS unlock failed due to race with another thread trying to - // register as waiter on it. We need to keep on looping. We - // intentionally do not yield here in order to reserve higher - // priority for the releasing thread. - // - // At this point lNewVal contains the latest LockCount value - // retrieved by one of the two InterlockedCompareExchange above; - // we can use this value as expected LockCount for the next loop, - // without the need to fetch it again. - lVal = lNewVal; - } - - ILCS_cs_exit: - return; - } - -#endif // MUTEX_BASED_CSS - - /*++ - Function: - CorUnix::PALCS_FullyInitialize - - Fully initializes a CS which was previously initialized in InitializeCriticalSection. - This method is called at the first contention on the target CS - --*/ - bool PALCS_FullyInitialize(PAL_CRITICAL_SECTION * pPalCriticalSection) - { - LONG lVal, lNewVal; - bool fRet = true; - - lVal = pPalCriticalSection->cisInitState; - if (PalCsFullyInitialized == lVal) - { - goto PCDI_exit; - } - if (PalCsUserInitialized == lVal) - { - int iRet; - lNewVal = (LONG)PalCsFullyInitializing; - lNewVal = InterlockedCompareExchange( - (LONG *)&pPalCriticalSection->cisInitState, lNewVal, lVal); - if (lNewVal != lVal) - { - if (PalCsFullyInitialized == lNewVal) - { - // Another thread did initialize this CS: we can - // safely return 'true' - goto PCDI_exit; - } - - // Another thread is still initializing this CS: yield and - // spin by returning 'false' - sched_yield(); - fRet = false; - goto PCDI_exit; - } - - // - // Actual native initialization - // - // Mutex - iRet = pthread_mutex_init(&pPalCriticalSection->csndNativeData.mutex, NULL); - if (0 != iRet) - { - ASSERT("Failed initializing mutex in CS @ %p [err=%d]\n", - pPalCriticalSection, iRet); - pPalCriticalSection->cisInitState = PalCsUserInitialized; - fRet = false; - goto PCDI_exit; - } -#ifndef MUTEX_BASED_CSS - // Condition - iRet = pthread_cond_init(&pPalCriticalSection->csndNativeData.condition, NULL); - if (0 != iRet) - { - ASSERT("Failed initializing condition in CS @ %p [err=%d]\n", - pPalCriticalSection, iRet); - pthread_mutex_destroy(&pPalCriticalSection->csndNativeData.mutex); - pPalCriticalSection->cisInitState = PalCsUserInitialized; - fRet = false; - goto PCDI_exit; - } - // Predicate - pPalCriticalSection->csndNativeData.iPredicate = 0; -#endif - - pPalCriticalSection->cisInitState = PalCsFullyInitialized; - } - else if (PalCsFullyInitializing == lVal) - { - // Another thread is still initializing this CS: yield and - // spin by returning 'false' - sched_yield(); - fRet = false; - goto PCDI_exit; - } - else - { - ASSERT("CS %p is not initialized", pPalCriticalSection); - fRet = false; - goto PCDI_exit; - } - - PCDI_exit: - return fRet; - } - - - /*++ - Function: - CorUnix::PALCS_WaitOnCS - - Waits on a CS owned by another thread. It returns PalCsReturnWaiterAwakened - if the thread actually waited on the CS and it has been awakened on CS - release. It returns PalCsWaiterDidntWait if another thread is currently - fully-initializing the CS and therefore the current thread couldn't wait - on it - --*/ - PalCsWaiterReturnState PALCS_WaitOnCS(PAL_CRITICAL_SECTION * pPalCriticalSection, - LONG lInc) - { - DWORD lVal, lNewVal; - PAL_ERROR palErr = NO_ERROR; - - if (PalCsFullyInitialized != pPalCriticalSection->cisInitState) - { - // First contention, the CS native wait support need to be - // initialized at this time - if (!PALCS_FullyInitialize(pPalCriticalSection)) - { - // The current thread failed the full initialization of the CS, - // whether because another thread is race-initializing it, or - // there are no enough memory/resources at this time, or - // InitializeCriticalSection has never been called. By - // returning we will cause the thread to spin on CS trying - // again until the CS is initialized - return PalCsWaiterDidntWait; - } - } - - // Make sure we have a valid waiter increment - _ASSERTE(PALCS_LOCK_WAITER_INC == lInc || - PALCS_LOCK_AWAKENED_WAITER == lInc); - - do { - lVal = pPalCriticalSection->LockCount; - - // Make sure the waiter increment is compatible with the - // awakened waiter bit value - _ASSERTE(PALCS_LOCK_WAITER_INC == lInc || - PALCS_LOCK_AWAKENED_WAITER & lVal); - - if (0 == (lVal & PALCS_LOCK_BIT)) - { - // the CS is no longer locked, let's bail out - return PalCsWaiterDidntWait; - } - - lNewVal = lVal + lInc; - - // Make sure that this thread was whether an incoming one or it - // was an awakened waiter and, in this case, we are now going to - // turn off the awakened waiter bit - _ASSERT_MSG(PALCS_LOCK_WAITER_INC == lInc || - 0 == (PALCS_LOCK_AWAKENED_WAITER & lNewVal)); - - CS_TRACE("[WCS %p] Switching from {%d, %d, %d} to " - "{%d, %d, %d} ==> ", pPalCriticalSection, - PALCS_GETWCOUNT(lVal), PALCS_GETAWBIT(lVal), PALCS_GETLBIT(lVal), - PALCS_GETWCOUNT(lNewVal), PALCS_GETAWBIT(lNewVal), PALCS_GETLBIT(lNewVal)); - - lNewVal = InterlockedCompareExchange (&pPalCriticalSection->LockCount, - lNewVal, lVal); - - CS_TRACE("[WCS %p] ==> %s\n", pPalCriticalSection, - (lNewVal == lVal) ? "OK" : "NO"); - - } while (lNewVal != lVal); - -#ifdef _DEBUG - if (NULL != pPalCriticalSection->DebugInfo) - { - pPalCriticalSection->DebugInfo->lContentionCount += 1; - } -#endif // _DEBUG - - // Do the actual native wait - palErr = PALCS_DoActualWait(pPalCriticalSection); - _ASSERT_MSG(NO_ERROR == palErr, "Native CS wait failed\n"); - - return PalCsReturnWaiterAwakened; - } - - /*++ - Function: - CorUnix::PALCS_DoActualWait - - Performs the actual native wait on the CS - --*/ - PAL_ERROR PALCS_DoActualWait(PAL_CRITICAL_SECTION * pPalCriticalSection) - { - int iRet; - PAL_ERROR palErr = NO_ERROR; - - CS_TRACE("Trying to go to sleep [CS=%p]\n", pPalCriticalSection); - - // Lock the mutex - iRet = pthread_mutex_lock(&pPalCriticalSection->csndNativeData.mutex); - if (0 != iRet) - { - palErr = ERROR_INTERNAL_ERROR; - goto PCDAW_exit; - } - - CS_TRACE("Actually Going to sleep [CS=%p]\n", pPalCriticalSection); - - while (0 == pPalCriticalSection->csndNativeData.iPredicate) - { - // Wait on the condition - iRet = pthread_cond_wait(&pPalCriticalSection->csndNativeData.condition, - &pPalCriticalSection->csndNativeData.mutex); - - CS_TRACE("Got a signal on condition [pred=%d]!\n", - pPalCriticalSection->csndNativeData.iPredicate); - if (0 != iRet) - { - // Failed: unlock the mutex and bail out - ASSERT("Failed waiting on condition in CS %p [err=%d]\n", - pPalCriticalSection, iRet); - pthread_mutex_unlock(&pPalCriticalSection->csndNativeData.mutex); - palErr = ERROR_INTERNAL_ERROR; - goto PCDAW_exit; - } - } - - // Reset the predicate - pPalCriticalSection->csndNativeData.iPredicate = 0; - - // Unlock the mutex - iRet = pthread_mutex_unlock(&pPalCriticalSection->csndNativeData.mutex); - if (0 != iRet) - { - palErr = ERROR_INTERNAL_ERROR; - goto PCDAW_exit; - } - - PCDAW_exit: - - CS_TRACE("Just woken up [CS=%p]\n", pPalCriticalSection); - - return palErr; - } - - /*++ - Function: - CorUnix::PALCS_WakeUpWaiter - - Wakes up the first thread waiting on the CS - --*/ - PAL_ERROR PALCS_WakeUpWaiter(PAL_CRITICAL_SECTION * pPalCriticalSection) - { - int iRet; - PAL_ERROR palErr = NO_ERROR; - - _ASSERT_MSG(PalCsFullyInitialized == pPalCriticalSection->cisInitState, - "Trying to wake up a waiter on CS not fully initialized\n"); - - // Lock the mutex - iRet = pthread_mutex_lock(&pPalCriticalSection->csndNativeData.mutex); - if (0 != iRet) - { - palErr = ERROR_INTERNAL_ERROR; - goto PCWUW_exit; - } - - // Set the predicate - pPalCriticalSection->csndNativeData.iPredicate = 1; - - CS_TRACE("Signaling condition/predicate [pred=%d]!\n", - pPalCriticalSection->csndNativeData.iPredicate); - - // Signal the condition - iRet = pthread_cond_signal(&pPalCriticalSection->csndNativeData.condition); - if (0 != iRet) - { - // Failed: set palErr, but continue in order to unlock - // the mutex anyway - ASSERT("Failed setting condition in CS %p [ret=%d]\n", - pPalCriticalSection, iRet); - palErr = ERROR_INTERNAL_ERROR; - } - - // Unlock the mutex - iRet = pthread_mutex_unlock(&pPalCriticalSection->csndNativeData.mutex); - if (0 != iRet) - { - palErr = ERROR_INTERNAL_ERROR; - goto PCWUW_exit; - } - - PCWUW_exit: - return palErr; - } - -#ifdef _DEBUG - /*++ - Function: - CorUnix::PALCS_ReportStatisticalData - - Report creation/acquisition/contention statistical data for the all the - CSs so far existed and no longer existing in the current process - --*/ - void PALCS_ReportStatisticalData() - { -#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA - CPalThread * pThread = InternalGetCurrentThread(); - - if (NULL == pThread) DebugBreak(); - - // Take the lock for the global list of CS debug infos - InternalEnterCriticalSection(pThread, (CRITICAL_SECTION*)&g_csPALCSsListLock); - - LONG lPALCSInitializeCount = g_lPALCSInitializeCount; - LONG lPALCSDeleteCount = g_lPALCSDeleteCount; - LONG lPALCSAcquireCount = g_lPALCSAcquireCount; - LONG lPALCSEnterCount = g_lPALCSEnterCount; - LONG lPALCSContentionCount = g_lPALCSContentionCount; - LONG lPALCSInternalInitializeCount = g_lPALCSInternalInitializeCount; - LONG lPALCSInternalDeleteCount = g_lPALCSInternalDeleteCount; - LONG lPALCSInternalAcquireCount = g_lPALCSInternalAcquireCount; - LONG lPALCSInternalEnterCount = g_lPALCSInternalEnterCount; - LONG lPALCSInternalContentionCount = g_lPALCSInternalContentionCount; - - PLIST_ENTRY pItem = g_PALCSList.Flink; - while (&g_PALCSList != pItem) - { - PCRITICAL_SECTION_DEBUG_INFO pDebugInfo = - (PCRITICAL_SECTION_DEBUG_INFO)pItem; - - if (pDebugInfo->pOwnerCS->fInternal) - { - lPALCSInternalAcquireCount += pDebugInfo->lAcquireCount; - lPALCSInternalEnterCount += pDebugInfo->lEnterCount; - lPALCSInternalContentionCount += pDebugInfo->lContentionCount; - } - else - { - lPALCSAcquireCount += pDebugInfo->lAcquireCount; - lPALCSEnterCount += pDebugInfo->lEnterCount; - lPALCSContentionCount += pDebugInfo->lContentionCount; - } - - pItem = pItem->Flink; - } - - // Release the lock for the global list of CS debug infos - InternalLeaveCriticalSection(pThread, (CRITICAL_SECTION*)&g_csPALCSsListLock); - - TRACE("Critical Sections Statistical Data:\n"); - TRACE("{\n"); - TRACE(" Client code CSs:\n"); - TRACE(" {\n"); - TRACE(" Initialize Count: %d\n", lPALCSInitializeCount); - TRACE(" Delete Count: %d\n", lPALCSDeleteCount); - TRACE(" Acquire Count: %d\n", lPALCSAcquireCount); - TRACE(" Enter Count: %d\n", lPALCSEnterCount); - TRACE(" Contention Count: %d\n", lPALCSContentionCount); - TRACE(" }\n"); - TRACE(" Internal PAL CSs:\n"); - TRACE(" {\n"); - TRACE(" Initialize Count: %d\n", lPALCSInternalInitializeCount); - TRACE(" Delete Count: %d\n", lPALCSInternalDeleteCount); - TRACE(" Acquire Count: %d\n", lPALCSInternalAcquireCount); - TRACE(" Enter Count: %d\n", lPALCSInternalEnterCount); - TRACE(" Contention Count: %d\n", lPALCSInternalContentionCount); - TRACE(" }\n"); - TRACE("}\n"); -#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA - } - - /*++ - Function: - CorUnix::PALCS_DumpCSList - - Dumps the list of all the CS currently existing in this process. - --*/ - void PALCS_DumpCSList() - { - CPalThread * pThread = InternalGetCurrentThread(); - - // Take the lock for the global list of CS debug infos - InternalEnterCriticalSection(pThread, (CRITICAL_SECTION*)&g_csPALCSsListLock); - - PLIST_ENTRY pItem = g_PALCSList.Flink; - while (&g_PALCSList != pItem) - { - PCRITICAL_SECTION_DEBUG_INFO pDebugInfo = - (PCRITICAL_SECTION_DEBUG_INFO)pItem; - PPAL_CRITICAL_SECTION pCS = pDebugInfo->pOwnerCS; - - printf("CS @ %p \n" - "{\tDebugInfo = %p -> \n", - pCS, pDebugInfo); - - printf("\t{\n\t\t[Link]\n\t\tpOwnerCS = %p\n" - "\t\tAcquireCount \t= %d\n" - "\t\tEnterCount \t= %d\n" - "\t\tContentionCount = %d\n", - pDebugInfo->pOwnerCS, pDebugInfo->lAcquireCount.Load(), - pDebugInfo->lEnterCount.Load(), pDebugInfo->lContentionCount.Load()); - printf("\t}\n"); - - printf("\tLockCount \t= %#x\n" - "\tRecursionCount \t= %d\n" - "\tOwningThread \t= %p\n" - "\tSpinCount \t= %u\n" - "\tfInternal \t= %d\n" - "\teInitState \t= %u\n" - "\tpNativeData \t= %p ->\n", - pCS->LockCount.Load(), pCS->RecursionCount, (void *)pCS->OwningThread, - (unsigned)pCS->SpinCount, -#ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA - (int)pCS->fInternal, -#else - (int)0, -#endif // PAL_TRACK_CRITICAL_SECTIONS_DATA - pCS->cisInitState.Load(), &pCS->csndNativeData); - - printf("\t{\n\t\t[mutex]\n\t\t[condition]\n" - "\t\tPredicate \t= %d\n" - "\t}\n}\n",pCS->csndNativeData.iPredicate); - - printf("}\n"); - - pItem = pItem->Flink; - } - - // Release the lock for the global list of CS debug infos - InternalLeaveCriticalSection(pThread, (CRITICAL_SECTION*)&g_csPALCSsListLock); - } -#endif // _DEBUG - - -#if defined(MUTEX_BASED_CSS) || defined(_DEBUG) - /*++ - Function: - CorUnix::InternalEnterCriticalSection - - Enters a CS, causing the thread to block if the CS is owned by - another thread - --*/ -#ifdef MUTEX_BASED_CSS - void InternalEnterCriticalSection( - CPalThread * pThread, - PCRITICAL_SECTION pCriticalSection) -#else // MUTEX_BASED_CSS - void MTX_InternalEnterCriticalSection( - CPalThread * pThread, - PCRITICAL_SECTION pCriticalSection) -#endif // MUTEX_BASED_CSS - - { - PAL_CRITICAL_SECTION * pPalCriticalSection = - reinterpret_cast(pCriticalSection); - int iRet; - SIZE_T threadId; - - _ASSERTE(PalCsNotInitialized != pPalCriticalSection->cisInitState); - - threadId = ObtainCurrentThreadId(pThread); - - /* check if the current thread already owns the criticalSection */ - if (pPalCriticalSection->OwningThread == threadId) - { - _ASSERTE(0 < pPalCriticalSection->RecursionCount); - pPalCriticalSection->RecursionCount += 1; - return; - } - - iRet = pthread_mutex_lock(&pPalCriticalSection->csndNativeData.mutex); - _ASSERTE(0 == iRet); - - pPalCriticalSection->OwningThread = threadId; - pPalCriticalSection->RecursionCount = 1; - } - - - /*++ - Function: - CorUnix::InternalLeaveCriticalSection - - Leaves a currently owned CS - --*/ -#ifdef MUTEX_BASED_CSS - void InternalLeaveCriticalSection( - CPalThread * pThread, - PCRITICAL_SECTION pCriticalSection) -#else // MUTEX_BASED_CSS - void MTX_InternalLeaveCriticalSection( - CPalThread * pThread, - PCRITICAL_SECTION pCriticalSection) -#endif // MUTEX_BASED_CSS - { - PAL_CRITICAL_SECTION * pPalCriticalSection = - reinterpret_cast(pCriticalSection); - int iRet; -#ifdef _DEBUG - SIZE_T threadId; - - _ASSERTE(PalCsNotInitialized != pPalCriticalSection->cisInitState); - - threadId = ObtainCurrentThreadId(pThread); - _ASSERTE(threadId == pPalCriticalSection->OwningThread); - - if (0 >= pPalCriticalSection->RecursionCount) - DebugBreak(); - - _ASSERTE(0 < pPalCriticalSection->RecursionCount); -#endif // _DEBUG - - if (0 < --pPalCriticalSection->RecursionCount) - return; - - pPalCriticalSection->OwningThread = 0; - - iRet = pthread_mutex_unlock(&pPalCriticalSection->csndNativeData.mutex); - _ASSERTE(0 == iRet); - } - -#endif // MUTEX_BASED_CSS || _DEBUG -} diff --git a/src/coreclr/pal/src/synchmgr/synchmanager.cpp b/src/coreclr/pal/src/synchmgr/synchmanager.cpp index 50446fdf1e775b..8e6723ea77d1af 100644 --- a/src/coreclr/pal/src/synchmgr/synchmanager.cpp +++ b/src/coreclr/pal/src/synchmgr/synchmanager.cpp @@ -141,8 +141,8 @@ namespace CorUnix CPalSynchronizationManager * CPalSynchronizationManager::s_pObjSynchMgr = NULL; Volatile CPalSynchronizationManager::s_lInitStatus = SynchMgrStatusIdle; - CRITICAL_SECTION CPalSynchronizationManager::s_csSynchProcessLock; - CRITICAL_SECTION CPalSynchronizationManager::s_csMonitoredProcessesLock; + minipal_mutex CPalSynchronizationManager::s_csSynchProcessLock; + minipal_mutex CPalSynchronizationManager::s_csMonitoredProcessesLock; CPalSynchronizationManager::CPalSynchronizationManager() : m_dwWorkerThreadTid(0), @@ -1298,8 +1298,8 @@ namespace CorUnix goto I_exit; } - InternalInitializeCriticalSection(&s_csSynchProcessLock); - InternalInitializeCriticalSection(&s_csMonitoredProcessesLock); + minipal_mutex_init(&s_csSynchProcessLock); + minipal_mutex_init(&s_csMonitoredProcessesLock); pSynchManager = new(std::nothrow) CPalSynchronizationManager(); if (NULL == pSynchManager) @@ -2343,7 +2343,7 @@ namespace CorUnix VALIDATEOBJECT(psdSynchData); - InternalEnterCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + minipal_mutex_enter(&s_csMonitoredProcessesLock); fMonitoredProcessesLock = true; @@ -2392,7 +2392,7 @@ namespace CorUnix } // Unlock - InternalLeaveCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + minipal_mutex_leave(&s_csMonitoredProcessesLock); fMonitoredProcessesLock = false; if (fWakeUpWorker) @@ -2412,8 +2412,7 @@ namespace CorUnix RPFM_exit: if (fMonitoredProcessesLock) { - InternalLeaveCriticalSection(pthrCurrent, - &s_csMonitoredProcessesLock); + minipal_mutex_leave(&s_csMonitoredProcessesLock); } return palErr; @@ -2438,7 +2437,7 @@ namespace CorUnix VALIDATEOBJECT(psdSynchData); - InternalEnterCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + minipal_mutex_enter(&s_csMonitoredProcessesLock); pmpln = m_pmplnMonitoredProcesses; while (pmpln) @@ -2477,7 +2476,7 @@ namespace CorUnix palErr = ERROR_NOT_FOUND; } - InternalLeaveCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + minipal_mutex_leave(&s_csMonitoredProcessesLock); return palErr; } @@ -2536,7 +2535,7 @@ namespace CorUnix // lock is needed in order to support object promotion. // Grab the monitored processes lock - InternalEnterCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + minipal_mutex_enter(&s_csMonitoredProcessesLock); fMonitoredProcessesLock = true; lInitialNodeCount = m_lMonitoredProcessesCount; @@ -2581,7 +2580,7 @@ namespace CorUnix } // Release the monitored processes lock - InternalLeaveCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + minipal_mutex_leave(&s_csMonitoredProcessesLock); fMonitoredProcessesLock = false; if (lRemovingCount > 0) @@ -2591,7 +2590,7 @@ namespace CorUnix fLocalSynchLock = true; // Acquire the monitored processes lock - InternalEnterCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + minipal_mutex_enter(&s_csMonitoredProcessesLock); fMonitoredProcessesLock = true; // Start from the beginning of the exited processes list @@ -2651,7 +2650,7 @@ namespace CorUnix if (fMonitoredProcessesLock) { - InternalLeaveCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + minipal_mutex_leave(&s_csMonitoredProcessesLock); } if (fLocalSynchLock) @@ -2677,7 +2676,7 @@ namespace CorUnix MonitoredProcessesListNode * pNode; // Grab the monitored processes lock - InternalEnterCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + minipal_mutex_enter(&s_csMonitoredProcessesLock); while (m_pmplnMonitoredProcesses) { @@ -2689,7 +2688,7 @@ namespace CorUnix } // Release the monitored processes lock - InternalLeaveCriticalSection(pthrCurrent, &s_csMonitoredProcessesLock); + minipal_mutex_leave(&s_csMonitoredProcessesLock); } /*++ diff --git a/src/coreclr/pal/src/synchmgr/synchmanager.hpp b/src/coreclr/pal/src/synchmgr/synchmanager.hpp index 83a3ee6ca30431..7d86ab6fb12d4d 100644 --- a/src/coreclr/pal/src/synchmgr/synchmanager.hpp +++ b/src/coreclr/pal/src/synchmgr/synchmanager.hpp @@ -21,7 +21,6 @@ Module Name: #include "pal/synchobjects.hpp" #include "pal/synchcache.hpp" -#include "pal/cs.hpp" #include "pal/corunix.hpp" #include "pal/thread.hpp" #include "pal/procobj.hpp" @@ -523,8 +522,8 @@ namespace CorUnix // static members static CPalSynchronizationManager * s_pObjSynchMgr; static Volatile s_lInitStatus; - static CRITICAL_SECTION s_csSynchProcessLock; - static CRITICAL_SECTION s_csMonitoredProcessesLock; + static minipal_mutex s_csSynchProcessLock; + static minipal_mutex s_csMonitoredProcessesLock; // members DWORD m_dwWorkerThreadTid; @@ -590,7 +589,7 @@ namespace CorUnix if (1 == ++pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount) { - InternalEnterCriticalSection(pthrCurrent, &s_csSynchProcessLock); + minipal_mutex_enter(&s_csSynchProcessLock); } } static void ReleaseLocalSynchLock(CPalThread * pthrCurrent) @@ -598,7 +597,7 @@ namespace CorUnix _ASSERTE(0 < pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount); if (0 == --pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount) { - InternalLeaveCriticalSection(pthrCurrent, &s_csSynchProcessLock); + minipal_mutex_leave(&s_csSynchProcessLock); #if SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING pthrCurrent->synchronizationInfo.RunDeferredThreadConditionSignalings(); @@ -613,7 +612,7 @@ namespace CorUnix if (0 < lRet) { pthrCurrent->synchronizationInfo.m_lLocalSynchLockCount = 0; - InternalLeaveCriticalSection(pthrCurrent, &s_csSynchProcessLock); + minipal_mutex_leave(&s_csSynchProcessLock); #if SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING pthrCurrent->synchronizationInfo.RunDeferredThreadConditionSignalings(); diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index cac8ac04a1fb08..c56cc0637dcd2f 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -25,7 +25,6 @@ SET_DEFAULT_DEBUG_CHANNEL(PROCESS); // some headers have code with asserts, so d #include "pal/palinternal.h" #include "pal/process.h" #include "pal/init.h" -#include "pal/critsect.h" #include "pal/debug.h" #include "pal/utils.h" #include "pal/environ.h" @@ -158,7 +157,7 @@ IPalObject* CorUnix::g_pobjProcess; // Critical section that protects process data (e.g., the // list of active threads)/ // -CRITICAL_SECTION g_csProcess; +minipal_mutex g_csProcess; // // List and count of active threads @@ -2787,14 +2786,14 @@ CorUnix::InitializeProcessData( pGThreadList = NULL; g_dwThreadCount = 0; - InternalInitializeCriticalSection(&g_csProcess); + minipal_mutex_init(&g_csProcess); fLockInitialized = TRUE; if (NO_ERROR != palError) { if (fLockInitialized) { - InternalDeleteCriticalSection(&g_csProcess); + minipal_mutex_destroy(&g_csProcess); } } @@ -2840,7 +2839,7 @@ CorUnix::InitializeProcessCommandLine( ERROR("Invalid full path\n"); palError = ERROR_INTERNAL_ERROR; goto exit; - } + } lpwstr[0] = '\0'; size_t n = PAL_wcslen(lpwstrFullPath) + 1; @@ -3011,7 +3010,7 @@ PROCCleanupInitialProcess(VOID) { CPalThread *pThread = InternalGetCurrentThread(); - InternalEnterCriticalSection(pThread, &g_csProcess); + minipal_mutex_enter(&g_csProcess); /* Free the application directory */ free(g_lpwstrAppDir); @@ -3019,7 +3018,7 @@ PROCCleanupInitialProcess(VOID) /* Free the stored command line */ free(g_lpwstrCmdLine); - InternalLeaveCriticalSection(pThread, &g_csProcess); + minipal_mutex_leave(&g_csProcess); // // Object manager shutdown will handle freeing the underlying @@ -3047,7 +3046,7 @@ CorUnix::PROCAddThread( { /* protect the access of the thread list with critical section for mutithreading access */ - InternalEnterCriticalSection(pCurrentThread, &g_csProcess); + minipal_mutex_enter(&g_csProcess); pTargetThread->SetNext(pGThreadList); pGThreadList = pTargetThread; @@ -3056,7 +3055,7 @@ CorUnix::PROCAddThread( TRACE("Thread 0x%p (id %#x) added to the process thread list\n", pTargetThread, pTargetThread->GetThreadId()); - InternalLeaveCriticalSection(pCurrentThread, &g_csProcess); + minipal_mutex_leave(&g_csProcess); } @@ -3082,7 +3081,7 @@ CorUnix::PROCRemoveThread( /* protect the access of the thread list with critical section for mutithreading access */ - InternalEnterCriticalSection(pCurrentThread, &g_csProcess); + minipal_mutex_enter(&g_csProcess); curThread = pGThreadList; @@ -3123,7 +3122,7 @@ CorUnix::PROCRemoveThread( WARN("Thread %p not removed (it wasn't found in the list)\n", pTargetThread); EXIT: - InternalLeaveCriticalSection(pCurrentThread, &g_csProcess); + minipal_mutex_leave(&g_csProcess); } @@ -3168,7 +3167,7 @@ PROCProcessLock( CPalThread * pThread = (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : NULL); - InternalEnterCriticalSection(pThread, &g_csProcess); + minipal_mutex_enter(&g_csProcess); } @@ -3192,7 +3191,7 @@ PROCProcessUnlock( CPalThread * pThread = (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : NULL); - InternalLeaveCriticalSection(pThread, &g_csProcess); + minipal_mutex_leave(&g_csProcess); } #if USE_SYSV_SEMAPHORES diff --git a/src/coreclr/pal/src/thread/thread.cpp b/src/coreclr/pal/src/thread/thread.cpp index d4b3e723a70f4f..fe48f04dfe639b 100644 --- a/src/coreclr/pal/src/thread/thread.cpp +++ b/src/coreclr/pal/src/thread/thread.cpp @@ -17,7 +17,6 @@ SET_DEFAULT_DEBUG_CHANNEL(THREAD); // some headers have code with asserts, so do #include "pal/thread.hpp" #include "pal/mutex.hpp" #include "pal/handlemgr.hpp" -#include "pal/cs.hpp" #include "pal/seh.hpp" #include "pal/signal.hpp" @@ -2040,7 +2039,7 @@ CPalThread::RunPreCreateInitializers( // First, perform initialization of CPalThread private members // - InternalInitializeCriticalSection(&m_csLock); + minipal_mutex_init(&m_mtxLock); m_fLockInitialized = TRUE; iError = pthread_mutex_init(&m_startMutex, NULL); @@ -2099,7 +2098,7 @@ CPalThread::~CPalThread() if (m_fLockInitialized) { - InternalDeleteCriticalSection(&m_csLock); + minipal_mutex_destroy(&m_mtxLock); } if (m_fStartItemsInitialized) diff --git a/src/coreclr/pal/tests/palsuite/CMakeLists.txt b/src/coreclr/pal/tests/palsuite/CMakeLists.txt index b143c3f90baf19..705e5b107230e3 100644 --- a/src/coreclr/pal/tests/palsuite/CMakeLists.txt +++ b/src/coreclr/pal/tests/palsuite/CMakeLists.txt @@ -48,15 +48,6 @@ add_executable_clr(paltests #composite/object_management/semaphore/nonshared/semaphore.cpp #composite/object_management/semaphore/shared/main.cpp #composite/object_management/semaphore/shared/semaphore.cpp - #composite/synchronization/criticalsection/criticalsection.cpp - #composite/synchronization/criticalsection/mainWrapper.cpp - #composite/synchronization/nativecriticalsection/mtx_critsect.cpp - #composite/synchronization/nativecriticalsection/pal_composite_native_cs.cpp - #composite/synchronization/nativecriticalsection/resultbuffer.cpp - #composite/synchronization/nativecs_interlocked/interlocked.cpp - #composite/synchronization/nativecs_interlocked/mtx_critsect.cpp - #composite/synchronization/nativecs_interlocked/pal_composite_native_cs.cpp - #composite/synchronization/nativecs_interlocked/resultbuffer.cpp #composite/wfmo/main.cpp #composite/wfmo/mutex.cpp c_runtime/atof/test1/test1.cpp @@ -405,13 +396,6 @@ add_executable_clr(paltests threading/CreateThread/test1/test1.cpp threading/CreateThread/test2/test2.cpp threading/CreateThread/test3/test3.cpp - threading/CriticalSectionFunctions/test1/InitializeCriticalSection.cpp - threading/CriticalSectionFunctions/test2/test2.cpp - threading/CriticalSectionFunctions/test4/test4.cpp - threading/CriticalSectionFunctions/test5/test5.cpp - threading/CriticalSectionFunctions/test6/test6.cpp - threading/CriticalSectionFunctions/test7/test7.cpp - threading/CriticalSectionFunctions/test8/test8.cpp threading/DuplicateHandle/test1/test1.cpp threading/DuplicateHandle/test10/test10.cpp threading/DuplicateHandle/test11/childprocess.cpp diff --git a/src/coreclr/pal/tests/palsuite/common/palsuite.cpp b/src/coreclr/pal/tests/palsuite/common/palsuite.cpp index fcb5701e3f8864..50c07a490a9637 100644 --- a/src/coreclr/pal/tests/palsuite/common/palsuite.cpp +++ b/src/coreclr/pal/tests/palsuite/common/palsuite.cpp @@ -17,7 +17,6 @@ const char* szTextFile = "text.txt"; HANDLE hToken[NUM_TOKENS]; -CRITICAL_SECTION CriticalSection; WCHAR* convert(const char * aString) { @@ -185,8 +184,8 @@ mkAbsoluteFilenameA ( sizeFN = strlen( fileName ); sizeAPN = (sizeDN + 1 + sizeFN + 1); - /* ensure ((dirName + DELIM + fileName + \0) =< MAX_PATH ) */ - if ( sizeAPN > MAX_PATH ) + /* ensure ((dirName + DELIM + fileName + \0) =< _MAX_PATH ) */ + if ( sizeAPN > _MAX_PATH ) { return ( 0 ); } diff --git a/src/coreclr/pal/tests/palsuite/common/palsuite.h b/src/coreclr/pal/tests/palsuite/common/palsuite.h index 2b79dc74d1036b..8e7336ca8e596c 100644 --- a/src/coreclr/pal/tests/palsuite/common/palsuite.h +++ b/src/coreclr/pal/tests/palsuite/common/palsuite.h @@ -118,7 +118,6 @@ BOOL Cleanup(HANDLE *hArray, DWORD dwIndex); #define NUM_TOKENS 3 extern HANDLE hToken[NUM_TOKENS]; -extern CRITICAL_SECTION CriticalSection; /* * Take two wide strings representing file and directory names diff --git a/src/coreclr/pal/tests/palsuite/compilableTests.txt b/src/coreclr/pal/tests/palsuite/compilableTests.txt index be031d7214969e..6b74e5bea269cc 100644 --- a/src/coreclr/pal/tests/palsuite/compilableTests.txt +++ b/src/coreclr/pal/tests/palsuite/compilableTests.txt @@ -296,13 +296,6 @@ threading/CreateSemaphoreW_ReleaseSemaphore/test3/paltest_createsemaphorew_relea threading/CreateThread/test1/paltest_createthread_test1 threading/CreateThread/test2/paltest_createthread_test2 threading/CreateThread/test3/paltest_createthread_test3 -threading/CriticalSectionFunctions/test1/paltest_criticalsectionfunctions_test1 -threading/CriticalSectionFunctions/test2/paltest_criticalsectionfunctions_test2 -threading/CriticalSectionFunctions/test4/paltest_criticalsectionfunctions_test4 -threading/CriticalSectionFunctions/test5/paltest_criticalsectionfunctions_test5 -threading/CriticalSectionFunctions/test6/paltest_criticalsectionfunctions_test6 -threading/CriticalSectionFunctions/test7/paltest_criticalsectionfunctions_test7 -threading/CriticalSectionFunctions/test8/paltest_criticalsectionfunctions_test8 threading/DuplicateHandle/test1/paltest_duplicatehandle_test1 threading/DuplicateHandle/test10/paltest_duplicatehandle_test10 threading/DuplicateHandle/test11/paltest_duplicatehandle_test11 diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.cpp b/src/coreclr/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.cpp deleted file mode 100644 index 5935e46f028fae..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/criticalsection/criticalsection.cpp +++ /dev/null @@ -1,417 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** Source: criticalsection.c -** -** Purpose: Test Critical Section Reengineering PAL Effort -** -** PseudoCode: - Preparation: - Create PROCESS_COUNT processes. - In each process create a Critical Section - - Test: - Create THREAD_COUNT threads. - In a loop repeated REPEAT_COUNT times: - Enter Critical Section - Do Work - Leave Critical Section - The main thread waits for all of the created threads to exit (WFMO wait all on the created thread handles) and call DeleteCriticalSection - - Parameters: - PROCESS_COUNT: Number of processes - THREAD_COUNT: Number of threads in each process - REPEAT_COUNT: The number of times to execute the loop.. - - Statistics Captured: - Total elapsed time - MTBF - - Scenario: - Single Process with Multiple threads. Main thread creates critical section. - All other threads call EnterCriticalSection. When thread enters critical section - it does some work and leaves critical section. - -** Dependencies: - CreateThread -** InitializeCriticalSection -** EnterCriticalSection -** LeaveCriticalSection -** DeleteCriticalSection -** WaitForSingleObject -** -** Author: rameshg -** -** -**=========================================================*/ - -#include -#include "resultbuffer.h" - -//Global Variables -DWORD dwThreadId; -long long GLOBAL_COUNTER ; -HANDLE g_hEvent; - -/* Test Input Variables */ -unsigned int USE_PROCESS_COUNT = 0; -unsigned int THREAD_COUNT = 0; -unsigned int REPEAT_COUNT = 0; -unsigned int SLEEP_LENGTH = 0; -unsigned int RELATION_ID = 0; - - -CRITICAL_SECTION CriticalSectionM; /* Critical Section Object (used as mutex) */ - - -/* Capture statistics for each worker thread */ -struct statistics{ - unsigned int processId; - unsigned int operationsFailed; - unsigned int operationsPassed; - unsigned int operationsTotal; - DWORD operationTime; //Milliseconds - unsigned int relationId; -}; - - -/*Capture Statistics at a Process level*/ -struct processStatistics{ - unsigned int processId; - DWORD operationTime; //Milliseconds - unsigned int relationId; -}; - - -ResultBuffer *resultBuffer; - -//function declarations -int GetParameters( int , char **); -void setup (void); -void cleanup(void); -void incrementCounter(void); -DWORD PALAPI enterandleavecs( LPVOID ); - - -/* -*Setup for the test case -*/ - -VOID -setup(VOID) -{ - -g_hEvent = CreateEvent(NULL,TRUE,FALSE, NULL); -if(g_hEvent == NULL) -{ - Fail("Create Event Failed\n" - "GetLastError returned %d\n", GetLastError()); -} - -GLOBAL_COUNTER=0; -/* -* Create mutual exclusion mechanisms -*/ -InitializeCriticalSection ( &CriticalSectionM ); - -} - - -/* -* Cleanup for the test case -*/ -VOID -cleanup(VOID) -{ - /* - * Clean up Critical Section object - */ - DeleteCriticalSection(&CriticalSectionM); - PAL_Terminate(); -} - - -/*function that increments a counter*/ -VOID -incrementCounter(VOID) -{ - - if (INT_MAX==GLOBAL_COUNTER) - GLOBAL_COUNTER=0; - - GLOBAL_COUNTER++; - -} - -/* - * Enter and Leave Critical Section - */ -DWORD -PALAPI -enterandleavecs( LPVOID lpParam ) -{ - - struct statistics stats; - int loopcount = REPEAT_COUNT; - int i; - DWORD dwStart =0; - - int Id=(int)lpParam; - - //initialize structure to hold thread level statistics - stats.relationId = RELATION_ID; - stats.processId = USE_PROCESS_COUNT; - stats.operationsFailed = 0; - stats.operationsPassed = 0; - stats.operationsTotal = 0; - stats.operationTime = 0; - - //Wait for main thread to signal event - if (WAIT_OBJECT_0 != WaitForSingleObject(g_hEvent,INFINITE)) - { - Fail ("readfile: Wait for Single Object (g_hEvent) failed. Failing test.\n" - "GetLastError returned %d\n", GetLastError()); - } - - //Collect operation start time - dwStart = (DWORD)minipal_lowres_ticks(); - - //Operation starts loopcount times - for(i = 0; i < loopcount; i++) - { - - EnterCriticalSection(&CriticalSectionM); - /* - *Do Some Thing once you enter critical section - */ - incrementCounter(); - LeaveCriticalSection(&CriticalSectionM); - - stats.operationsPassed++; - stats.operationsTotal++; - } - //collect operation end time - stats.operationTime = (DWORD)minipal_lowres_ticks() - dwStart; - - /*Trace("\n\n\n\nOperation Time %d\n", stats.operationTime); - Trace("Operation Passed %d\n", stats.operationsPassed); - Trace("Operation Total %d\n", stats.operationsTotal); - Trace("Operation Failed %d\n", stats.operationsFailed); */ - - if(resultBuffer->LogResult(Id, (char *)&stats)) - { - Fail("Error while writing to shared memory, Thread Id is[%d] and Process id is [%d]\n", Id, USE_PROCESS_COUNT); - } - - - return 0; -} - - -PALTEST(composite_synchronization_criticalsection_paltest_synchronization_criticalsection, "composite/synchronization/criticalsection/paltest_synchronization_criticalsection") -{ - -/* -* Parameter to the threads that will be created -*/ -DWORD dwThrdParam = 0; -HANDLE hThread[64]; -unsigned int i = 0; -DWORD dwStart; - -/* Variables to capture the file name and the file pointer*/ -char fileName[MAX_PATH_FNAME]; -char processFileName[MAX_PATH_FNAME]; -FILE *hFile,*hProcessFile; -struct processStatistics processStats; - -struct statistics* buffer; -int statisticsSize = 0; - -/* -* PAL Initialize -*/ -if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - -if(GetParameters(argc, argv)) - { - Fail("Error in obtaining the parameters\n"); - } - - -/*setup file for process result collection */ -_snprintf(processFileName, MAX_PATH_FNAME, "%d_process_criticalsection_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); -hProcessFile = fopen(processFileName, "w+"); -if(hProcessFile == NULL) - { - Fail("Error in opening file to write process results for process [%d]\n", USE_PROCESS_COUNT); - } - -//Initialize Process Stats Variables -processStats.operationTime = 0; -processStats.processId = USE_PROCESS_COUNT; -processStats.relationId = RELATION_ID; //Will change later - -//Start Process Time Capture -dwStart = (DWORD)minipal_lowres_ticks(); - -//setup file for thread result collection -statisticsSize = sizeof(struct statistics); -_snprintf(fileName, MAX_PATH_FNAME, "%d_thread_criticalsection_%d_.txt", USE_PROCESS_COUNT, RELATION_ID); -hFile = fopen(fileName, "w+"); -if(hFile == NULL) -{ - Fail("Error in opening file for write for process [%d]\n", USE_PROCESS_COUNT); -} - -// For each thread we will log operations failed (int), passed (int), total (int) -// and number of ticks (DWORD) for the operations -resultBuffer = new ResultBuffer( THREAD_COUNT, statisticsSize); - -/* -* Call the Setup Routine -*/ -setup(); - -//Create Thread Count Worker Threads - -while (i< THREAD_COUNT) -{ - dwThrdParam = i; - - hThread[i] = CreateThread( - NULL, - 0, - enterandleavecs, - (LPVOID)dwThrdParam, - 0, - &dwThreadId); - - if ( NULL == hThread[i] ) - { - Fail ( "CreateThread() returned NULL. Failing test.\n" - "GetLastError returned %d\n", GetLastError()); - } - i++; -} - -/* -* Set Event to signal all threads to start using the CS -*/ - -if (0==SetEvent(g_hEvent)) -{ - Fail ( "SetEvent returned Zero. Failing test.\n" - "GetLastError returned %d\n", GetLastError()); -} - -/* - * Wait for worker threads to complete - * - */ -if ( WAIT_OBJECT_0 != WaitForMultipleObjects (THREAD_COUNT,hThread,TRUE, INFINITE)) -{ - Fail ( "WaitForMultipleObject Failed. Failing test.\n" - "GetLastError returned %d\n", GetLastError()); -} - - -//Get the end time of the process -processStats.operationTime = (DWORD)minipal_lowres_ticks() - dwStart; - -//Write Process Result Contents to File -if(hProcessFile!= NULL) - { - fprintf(hProcessFile, "%d,%lu,%d\n", processStats.processId, processStats.operationTime, processStats.relationId ); - } - -if (0!=fclose(hProcessFile)) -{ - Fail("Unable to write process results to file" - "GetLastError returned %d\n", GetLastError()); -} - - -/*Write Threads Results to a file*/ -if(hFile!= NULL) -{ - for( i = 0; i < THREAD_COUNT; i++ ) - { - buffer = (struct statistics *)resultBuffer->getResultBuffer(i); - fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); - //Trace("Iteration %d over\n", i); - } -} - -if (0!=fclose(hFile)) -{ - Fail("Unable to write thread results to file" - "GetLastError returned %d\n", GetLastError()); -} - - /* Logging for the test case over, clean up the handles */ - //Trace("Contents of the buffer are [%s]\n", resultBuffer->getResultBuffer()); - - -//Call Cleanup for Test Case -cleanup(); - -//Trace("Value of GLOBAL COUNTER %d \n", GLOBAL_COUNTER); -return (PASS); - -} - - -int GetParameters( int argc, char **argv) -{ - - if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) - || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) - { - printf("PAL -Composite Critical Section Test\n"); - printf("Usage:\n"); - printf("\t[PROCESS_COUNT] Greater than or Equal to 1 \n"); - printf("\t[WORKER_THREAD_MULTIPLIER_COUNT] Greater than or Equal to 1 and Less than or Equal to 64 \n"); - printf("\t[REPEAT_COUNT] Greater than or Equal to 1\n"); - printf("\t[RELATION_ID [Greater than or Equal to 1]\n"); - return -1; - } - -// Trace("Args 1 is [%s], Arg 2 is [%s], Arg 3 is [%s]\n", argv[1], argv[2], argv[3]); - - USE_PROCESS_COUNT = atoi(argv[1]); - if( USE_PROCESS_COUNT < 0) - { - printf("\nPROCESS_COUNT to greater than or equal to 1\n"); - return -1; - } - - THREAD_COUNT = atoi(argv[2]); - if( THREAD_COUNT < 1 || THREAD_COUNT > 64) - { - printf("\nTHREAD_COUNT to be greater than or equal to 1 or less than or equal to 64\n"); - return -1; - } - - REPEAT_COUNT = atoi(argv[3]); - if( REPEAT_COUNT < 1) - { - printf("\nREPEAT_COUNT to greater than or equal to 1\n"); - return -1; - } - - RELATION_ID = atoi(argv[4]); - if( RELATION_ID < 1) - { - printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); - return -1; - } - - return 0; -} - diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.cpp b/src/coreclr/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.cpp deleted file mode 100644 index 99a1d0c5dad7f3..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/criticalsection/mainWrapper.cpp +++ /dev/null @@ -1,254 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/* -Source Code: mainWrapper.c - -mainWrapper.c creates Composite Test Case Processes and waits for all processes to get over - -Algorithm -o Create PROCESS_COUNT processes. - -Author: RameshG -*/ - -#include -#include "resulttime.h" - -/* Test Input Variables */ -unsigned int USE_PROCESS_COUNT = 0; //default -unsigned int THREAD_COUNT = 0; //default -unsigned int REPEAT_COUNT = 0; //default -unsigned int SLEEP_LENGTH = 0; //default -unsigned int RELATION_ID = 1001; - - -//Structure to capture application wide statistics -struct applicationStatistics{ - DWORD operationTime; - unsigned int relationId; - unsigned int processCount; - unsigned int threadCount; - unsigned int repeatCount; - char* buildNumber; - -}; - - -//Get parameters from the commandline -int GetParameters( int argc, char **argv) -{ - - if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) - || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) - { - printf("Main Wrapper PAL -Composite Critical Section Test\n"); - printf("Usage:\n"); - printf("\t[PROCESS_COUNT] Greater than or Equal to 1 \n"); - printf("\t[THREAD_COUNT] Greater than or Equal to 1 and Less than or Equal to 64 \n"); - printf("\t[REPEAT_COUNT] Greater than or Equal to 1\n"); - printf("\t[RELATION_ID [Greater than or Equal to 1]\n"); - - return -1; - } - - USE_PROCESS_COUNT = atoi(argv[1]); - if( USE_PROCESS_COUNT < 0) - { - printf("\nPROCESS_COUNT to greater than or equal to 1\n"); - return -1; - } - - THREAD_COUNT = atoi(argv[2]); - if( THREAD_COUNT < 1 || THREAD_COUNT > 64) - { - printf("\nTHREAD_COUNT to be greater than or equal to 1 or less than or equal to 64\n"); - return -1; - } - - REPEAT_COUNT = atoi(argv[3]); - if( REPEAT_COUNT < 1) - { - printf("\nREPEAT_COUNT to greater than or equal to 1\n"); - return -1; - } - - RELATION_ID = atoi(argv[4]); - if( RELATION_ID < 1) - { - printf("\nMain Process:Invalid RELATION_ID number, Pass greater than 1\n"); - return -1; - } - - - - - return 0; -} - -//Main entry point for the application -PALTEST(composite_synchronization_criticalsection_paltest_synchronization_criticalsection, "composite/synchronization/criticalsection/paltest_synchronization_criticalsection") -{ - unsigned int i = 0; - HANDLE hProcess[MAXIMUM_WAIT_OBJECTS]; //Array to hold Process handles - DWORD processReturnCode = 0; - int testReturnCode = PASS; - STARTUPINFO si[MAXIMUM_WAIT_OBJECTS]; - PROCESS_INFORMATION pi[MAXIMUM_WAIT_OBJECTS]; - FILE *hFile; //handle to application results file - char fileName[MAX_PATH]; //file name of the application results file - struct applicationStatistics appStats; - DWORD dwStart=0; //to store the tick count - char lpCommandLine[MAX_PATH] = ""; - int returnCode = 0; - - if(0 != (PAL_Initialize(argc, argv))) - { - return ( FAIL ); - } - - - - - if(GetParameters(argc, argv)) - { - Fail("Error in obtaining the parameters\n"); - } - - //Initialize Application Statistics Structure - appStats.operationTime=0; - appStats.relationId = RELATION_ID; - appStats.processCount = USE_PROCESS_COUNT; - appStats.threadCount = THREAD_COUNT; - appStats.repeatCount = REPEAT_COUNT; - appStats.buildNumber = getBuildNumber(); - - -_snprintf(fileName, MAX_PATH, "main_criticalsection_%d_.txt", RELATION_ID); - -hFile = fopen(fileName, "w+"); - -if(hFile == NULL) - { - Fail("Error in opening file to write application results for Critical Section Test, and error code is %d\n", GetLastError()); - } - -//Start Process Time Capture -dwStart = (DWORD)minipal_lowres_ticks(); - -for( i = 0; i < USE_PROCESS_COUNT; i++ ) - { - - ZeroMemory( lpCommandLine, MAX_PATH ); - if ( _snprintf( lpCommandLine, MAX_PATH-1, "criticalsection %d %d %d %d", i, THREAD_COUNT, REPEAT_COUNT, RELATION_ID) < 0 ) - { - Trace ("Error: Insufficient commandline string length for iteration [%d]\n", i); - } - - /* Zero the data structure space */ - ZeroMemory ( &pi[i], sizeof(pi[i]) ); - ZeroMemory ( &si[i], sizeof(si[i]) ); - - /* Set the process flags and standard io handles */ - si[i].cb = sizeof(si[i]); - - //Printing the Command Line - //Trace("Command Line \t %s \n", lpCommandLine); - - //Create Process - if(!CreateProcess( NULL, /* lpApplicationName*/ - lpCommandLine, /* lpCommandLine */ - NULL, /* lpProcessAttributes */ - NULL, /* lpThreadAttributes */ - TRUE, /* bInheritHandles */ - 0, /* dwCreationFlags, */ - NULL, /* lpEnvironment */ - NULL, /* pCurrentDirectory */ - &si[i], /* lpStartupInfo */ - &pi[i] /* lpProcessInformation */ - )) - { - Fail("Process Not created for [%d] and failed with error code %d\n", i, GetLastError()); - } - else - { - hProcess[i] = pi[i].hProcess; - //Trace("Process created for [%d]\n", i); - } - - } - - returnCode = WaitForMultipleObjects( USE_PROCESS_COUNT, hProcess, TRUE, INFINITE); - if( WAIT_OBJECT_0 != returnCode ) - { - Trace("Wait for Object(s) @ Main thread for %d processes returned %d, and GetLastError value is %d\n", USE_PROCESS_COUNT, returnCode, GetLastError()); - testReturnCode = FAIL; - } - - for( i = 0; i < USE_PROCESS_COUNT; i++ ) - { - /* check the exit code from the process */ - if( ! GetExitCodeProcess( pi[i].hProcess, &processReturnCode ) ) - { - Trace( "GetExitCodeProcess call failed for iteration %d with error code %u\n", - i, GetLastError() ); - - testReturnCode = FAIL; - } - - if(processReturnCode == FAIL) - { - Trace( "Process [%d] failed and returned FAIL\n", i); - testReturnCode = FAIL; - } - - if(!CloseHandle(pi[i].hThread)) - { - Trace("Error:%d: CloseHandle failed for Process [%d] hThread\n", GetLastError(), i); - testReturnCode = FAIL; - } - - if(!CloseHandle(pi[i].hProcess) ) - { - Trace("Error:%d: CloseHandle failed for Process [%d] hProcess\n", GetLastError(), i); - testReturnCode = FAIL; - } - } - -//Get the end time of the process -appStats.operationTime = (DWORD)minipal_lowres_ticks() - dwStart; - -if( testReturnCode == PASS) - { - Trace("Test Passed\n"); - - } - else - { - Fail("Test Failed\n"); - - } - -//Write Process Result Contents to File -if(hFile!= NULL) - { - fprintf(hFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId,appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber); - } - -if (0!=fclose(hFile)) -{ - Trace("Error:%d: fclose failed for file %s\n", GetLastError(), fileName); -} - - PAL_Terminate(); - -if( testReturnCode == PASS) -{ - return PASS; -} -else -{ - return FAIL; -} - -} diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/criticalsection/readme.txt b/src/coreclr/pal/tests/palsuite/composite/synchronization/criticalsection/readme.txt deleted file mode 100644 index 974497cfaff94e..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/criticalsection/readme.txt +++ /dev/null @@ -1,11 +0,0 @@ -To compile: - -1) create a dat file (say criticalsection.dat) with contents: -PAL,Composite,palsuite\composite\synchronization\criticalsection,criticalsection=mainWrapper.c,criticalsection.c,,, - -2) perl rrunmod.pl -r criticalsection.dat - - -To execute: -mainwrapper [PROCESS_COUNT] [WORKER_THREAD_MULTIPLIER_COUNT] [REPEAT_COUNT] - diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.cpp b/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.cpp deleted file mode 100644 index 6f5a032a62cdbf..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -//#include -#include -#include "mtx_critsect.h" - -CsWaiterReturnState MTXWaitOnCS(LPCRITICAL_SECTION lpCriticalSection); -void MTXDoActualWait(LPCRITICAL_SECTION lpCriticalSection); -void MTXWakeUpWaiter(LPCRITICAL_SECTION lpCriticalSection); - -/*extern "C" { - LONG InterlockedCompareExchange( - LONG volatile *Destination, - LONG Exchange, - LONG Comperand); -} -*/ -int MTXInitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - int retcode = 0; - - lpCriticalSection->DebugInfo = NULL; - lpCriticalSection->LockCount = 0; - lpCriticalSection->RecursionCount = 0; - lpCriticalSection->SpinCount = 0; - lpCriticalSection->OwningThread = NULL; - - lpCriticalSection->LockSemaphore = (HANDLE)&lpCriticalSection->NativeData; - - if (0!= pthread_mutex_init(&lpCriticalSection->NativeData.Mutex, NULL)) - { - printf("Error Initializing Critical Section\n"); - retcode = -1; - } - - - lpCriticalSection->InitCount = CS_INITIALIZED; - return retcode; -} - -int MTXDeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - int retcode = 0; - - if (lpCriticalSection->InitCount == CS_INITIALIZED) - { - - if (0!=pthread_mutex_destroy(&lpCriticalSection->NativeData.Mutex)) - { - printf("Error Deleting Critical Section\n"); - retcode = -1; - } - } - - lpCriticalSection->InitCount = CS_NOT_INIZIALIZED; - return retcode; -} - -int MTXEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - - DWORD thread_id; - int retcode = 0; - - thread_id = (DWORD)THREADSilentGetCurrentThreadId(); - - /* check if the current thread already owns the criticalSection */ - if (lpCriticalSection->OwningThread == (HANDLE)thread_id) - { - lpCriticalSection->RecursionCount++; - //Check if this is a failure condition - return 0; - } - - if (0!= pthread_mutex_lock(&lpCriticalSection->NativeData.Mutex)) - { - //Error Condition - printf("Error Entering Critical Section\n"); - retcode = -1; - } - else - { - lpCriticalSection->OwningThread = (HANDLE)thread_id; - lpCriticalSection->RecursionCount = 1; - } - - return retcode; -} - -int MTXLeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - int retcode = 0; - - if (--lpCriticalSection->RecursionCount > 0) - //*****check this ***** - return 0; - - lpCriticalSection->OwningThread = 0; - - if (0!= pthread_mutex_unlock(&lpCriticalSection->NativeData.Mutex)) - { - //Error Condition - printf("Error Leaving Critical Section\n"); - retcode = -1; - } - - return retcode; -} - diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.h b/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.h deleted file mode 100644 index 90c36cc61cdc7a..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/mtx_critsect.h +++ /dev/null @@ -1,50 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include - -typedef void VOID; -typedef unsigned long DWORD; -typedef long LONG; -typedef unsigned long ULONG; -typedef void* HANDLE; -typedef unsigned long ULONG_PTR; - -#define FALSE 0 -#define TRUE 1 - -#define CSBIT_CS_IS_LOCKED 1 -#define CSBIT_NEW_WAITER 2 - -typedef enum CsInitState { CS_NOT_INIZIALIZED, CS_INITIALIZED, CS_FULLY_INITIALIZED } CsInitState; -typedef enum _CsWaiterReturnState { CS_WAITER_WOKEN_UP, CS_WAITER_DIDNT_WAIT } CsWaiterReturnState; - -typedef struct _CRITICAL_SECTION_DEBUG_INFO { - LONG volatile ContentionCount; - LONG volatile InternalContentionCount; - ULONG volatile AcquireCount; - ULONG volatile EnterCount; -} CRITICAL_SECTION_DEBUG_INFO, *PCRITICAL_SECTION_DEBUG_INFO; - -typedef struct _CRITICAL_SECTION_NATIVE_DATA { - pthread_mutex_t Mutex; -} CRITICAL_SECTION_NATIVE_DATA, *PCRITICAL_SECTION_NATIVE_DATA; - -typedef struct _CRITICAL_SECTION { - - CsInitState InitCount; - PCRITICAL_SECTION_DEBUG_INFO DebugInfo; - LONG LockCount; - LONG RecursionCount; - HANDLE OwningThread; - HANDLE LockSemaphore; - ULONG_PTR SpinCount; - CRITICAL_SECTION_NATIVE_DATA NativeData; - -} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION; - -int MTXInitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); -int MTXDeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection); -int MTXEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); -int MTXLeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection); - diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.cpp b/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.cpp deleted file mode 100644 index 5cee88142c467d..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/pal_composite_native_cs.cpp +++ /dev/null @@ -1,466 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include -#include -#include -#include -#include -//#include -#include "mtx_critsect.cpp" -//#include "mtx_critsect.h" -#include "resultbuffer.h" - - - -#define LONGLONG long long -#define ULONGLONG unsigned LONGLONG -/*Defining Global Variables*/ - -int THREAD_COUNT=0; -int REPEAT_COUNT=0; -int GLOBAL_COUNTER=0; -int USE_PROCESS_COUNT = 0; -int RELATION_ID =0; -int g_counter = 0; -int MAX_PATH = 256; -LONGLONG calibrationValue = 0; - -pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t g_cv = PTHREAD_COND_INITIALIZER; -pthread_cond_t g_cv2 = PTHREAD_COND_INITIALIZER; -CRITICAL_SECTION g_cs; - -/* Capture statistics for each worker thread */ -struct statistics{ - unsigned int processId; - unsigned int operationsFailed; - unsigned int operationsPassed; - unsigned int operationsTotal; - DWORD operationTime; - unsigned int relationId; -}; - - -struct applicationStatistics{ - DWORD operationTime; - unsigned int relationId; - unsigned int processCount; - unsigned int threadCount; - unsigned int repeatCount; - char* buildNumber; - -}; - -ResultBuffer *resultBuffer; - - -void* waitforworkerthreads(void*); -void starttests(int); -int setuptest(void); -int cleanuptest(void); -int GetParameters( int , char **); -void incrementCounter(void); -ULONGLONG GetTicks(void); -ULONGLONG getPerfCalibrationValue(void); - - - -PALTEST(composite_synchronization_nativecriticalsection_paltest_synchronization_nativecriticalsection, "composite/synchronization/nativecriticalsection/paltest_synchronization_nativecriticalsection") - { - //Variable Declaration - pthread_t pthreads[640]; - int threadID[640]; - int i=0; - int j=0; - int rtn=0; - ULONGLONG startTicks = 0; - - /* Variables to capture the file name and the file pointer*/ - char fileName[MAX_PATH]; - FILE *hFile; - struct statistics* buffer; - int statisticsSize = 0; - - /*Variable to Captutre Information at the Application Level*/ - struct applicationStatistics appStats; - char mainFileName[MAX_PATH]; - FILE *hMainFile; - - //Get perfCalibrationValue - - calibrationValue = getPerfCalibrationValue(); - printf("Calibration Value for this Platform %llu \n", calibrationValue); - - - //Get Parameters - if(GetParameters(argc, argv)) - { - printf("Error in obtaining the parameters\n"); - exit(-1); - } - - //Assign Values to Application Statistics Members - appStats.relationId=RELATION_ID; - appStats.operationTime=0; - appStats.buildNumber = "999.99"; - appStats.processCount = USE_PROCESS_COUNT; - appStats.threadCount = THREAD_COUNT; - appStats.repeatCount = REPEAT_COUNT; - - printf("RELATION ID : %d\n", appStats.relationId); - printf("Process Count : %d\n", appStats.processCount); - printf("Thread Count : %d\n", appStats.threadCount); - printf("Repeat Count : %d\n", appStats.repeatCount); - - - //Open file for Application Statistics Collection - snprintf(mainFileName, MAX_PATH, "main_nativecriticalsection_%d_.txt",appStats.relationId); - hMainFile = fopen(mainFileName, "w+"); - - if(hMainFile == NULL) - { - printf("Error in opening main file for write\n"); - } - - - for (i=0;igetResultBuffer(i); - fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); - //printf("Iteration %d over\n", i); - } - } - fclose(hFile); - - - - //Call Test Case Cleanup Routine - if (0!=cleanuptest()) - { - //Error Condition - printf("Error Cleaning up Test Case"); - exit(-1); - } - - - if(hMainFile!= NULL) - { - printf("Writing to Main File \n"); - fprintf(hMainFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId, appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber); - - } - fclose(hMainFile); - return 0; - } - -void * waitforworkerthreads(void * threadId) -{ - - int *threadParam = (int*) threadId; - -// printf("Thread ID : %d \n", *threadParam); - - //Acquire Lock - if (0!=pthread_mutex_lock(&g_mutex)) - { - //Error Condition - printf("Error Acquiring Mutex Lock in Wait for Worker Thread\n"); - exit(-1); - } - - //Increment Global Counter - GLOBAL_COUNTER++; - - - //If global counter is equal to thread count then signal main thread - if (GLOBAL_COUNTER == THREAD_COUNT) - { - if (0!=pthread_cond_signal(&g_cv2)) - { - //Error Condition - printf("Error in setting conditional variable\n"); - exit(-1); - } - } - - //Wait for main thread to signal - if (0!=pthread_cond_wait(&g_cv,&g_mutex)) - { - //Error Condition - printf("Error waiting on conditional variable in Worker Thread\n"); - exit(-1); - } - - //Release the mutex lock - if (0!=pthread_mutex_unlock(&g_mutex)) - { - //Error Condition - printf("Error Releasing Mutex Lock in Worker Thread\n"); - exit(-1); - } - - //Start the test - starttests(*threadParam); - -} - -void starttests(int threadID) -{ - /*All threads beign executing tests cases*/ - int i = 0; - int Id = threadID; - struct statistics stats; - ULONGLONG startTime = 0; - ULONGLONG endTime = 0; - - - stats.relationId = RELATION_ID; - stats.processId = USE_PROCESS_COUNT; - stats.operationsFailed = 0; - stats.operationsPassed = 0; - stats.operationsTotal = 0; - stats.operationTime = 0; - - //Enter and Leave Critical Section in a loop REPEAT_COUNT Times - - startTime = GetTicks(); - - for (i=0;iLogResult(Id, (char *)&stats)) - { - printf("Error while writing to shared memory, Thread Id is[??] and Process id is [%d]\n", USE_PROCESS_COUNT); - } - -} - -int setuptest(void) -{ - - //Initialize Critical Section - if (0!=MTXInitializeCriticalSection( &g_cs)) - { - return -1; - } - return 0; -} - -int cleanuptest(void) -{ - - //Delete Critical Section - if (0!=MTXDeleteCriticalSection(&g_cs)) - { - return -1; - } - return 0; -} - -int GetParameters( int argc, char **argv) -{ - - if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) - || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) - { - printf("PAL -Composite Native Critical Section Test\n"); - printf("Usage:\n"); - printf("\t[PROCESS_ID ( greater than 1] \n"); - printf("\t[THREAD_COUNT ( greater than 1] \n"); - printf("\t[REPEAT_COUNT ( greater than 1]\n"); - printf("\t[RELATION_ID [greater than or Equal to 1]\n"); - return -1; - } - - - USE_PROCESS_COUNT = atoi(argv[1]); - if( USE_PROCESS_COUNT < 0) - { - printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n"); - return -1; - } - - THREAD_COUNT = atoi(argv[2]); - if( THREAD_COUNT < 1) - { - printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n"); - return -1; - } - - REPEAT_COUNT = atoi(argv[3]); - if( REPEAT_COUNT < 1) - { - printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n"); - return -1; - } - - RELATION_ID = atoi(argv[4]); - if( RELATION_ID < 1) - { - printf("\nInvalid RELATION_ID number, Pass greater than 1\n"); - return -1; - } - - - return 0; -} - -void incrementCounter(void) -{ - g_counter ++; -} - - -//Implementation borrowed from pertrace.c -ULONGLONG GetTicks(void) -{ -#ifdef i386 - unsigned long a, d; - asm volatile("rdtsc":"=a" (a), "=d" (d)); - return ((ULONGLONG)((unsigned int)(d)) << 32) | (unsigned int)(a); -#else - // #error Don''t know how to get ticks on this platform - return (ULONGLONG)gethrtime(); -#endif // i386 -} - - -/**/ -ULONGLONG getPerfCalibrationValue(void) -{ - ULONGLONG startTicks; - ULONGLONG endTicks; - - startTicks = GetTicks(); - sleep(1); - endTicks = GetTicks(); - - return ((endTicks-startTicks)/1000); //Return number of Ticks in One Milliseconds - -} - diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/readme.txt b/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/readme.txt deleted file mode 100644 index 8d83bf794cdb90..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/readme.txt +++ /dev/null @@ -1,19 +0,0 @@ -To compile: - -For FReeBSD Platform use the following to compile: -gcc -pthread -lm -lgcc -lstdc++ -xc++ -Di386 pal_composite_native_cs.c - -For Solaris Platform use the following to compile: -gcc -lpthread -lm -lgcc -lstdc++ -xc++ -D__sparc__ pal_composite_native_cs.c - -For HPUX Platform use the following to compile: -gcc -lpthread -mlp64 -lm -lgcc -lstdc++ -xc++ -D_HPUX_ -D__ia64__ pal_composite_native_cs.c - -To execute: -./a.out [PROCESS_COUNT] [THREAD_COUNT] [REPEAT_COUNT] - - - ./a.out 1 32 1000000 4102406 - - - diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.cpp b/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.cpp deleted file mode 100644 index 9988a49f9c509c..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -//#include "stdafx.h" -#include "resultbuffer.h" - -ResultBuffer:: ResultBuffer(int ThreadCount, int ThreadLogSize) - { - // Declare an internal status variable - int Status=0; - - // Update the maximum thread count - MaxThreadCount = ThreadCount; - - // Allocate the memory buffer based on the passed in thread and process counts - // and the specified size of the thread specific buffer - buffer = NULL; - buffer = (char*)malloc(ThreadCount*ThreadLogSize); - // Check to see if the buffer memory was allocated - if (buffer == NULL) - Status = -1; - // Initialize the buffer to 0 to prevent bogus data - memset(buffer,0,ThreadCount*ThreadLogSize); - - // The ThreadOffset is equal to the total number of bytes that will be stored per thread - ThreadOffset = ThreadLogSize; - - } - - - int ResultBuffer::LogResult(int Thread, char* Data) - { - // Declare an internal status flad - int status = 0; - - // Declare an object to store the offset address into the buffer - int Offset; - - // Check to make sure the Thread index is not out of range - if(Thread > MaxThreadCount) - { - printf("Thread index is out of range, Value of Thread[%d], Value of MaxThreadCount[%d]\n", Thread, MaxThreadCount); - status = -1; - return(status); - } - - // Calculate the offset into the shared buffer based on the process and thread indices - Offset = (Thread)*ThreadOffset; - - // Write the passed in data to the reserved buffer - memcpy(buffer+Offset,Data,ThreadOffset); - - return(status); - } - - - char* ResultBuffer::getResultBuffer(int threadId) - { - - return (buffer + threadId*ThreadOffset); - - } - diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.h b/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.h deleted file mode 100644 index c3d9a27fdb782c..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecriticalsection/resultbuffer.h +++ /dev/null @@ -1,42 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include -#include -//#include -#ifndef _RESULT_BUFFER_H_ -#define _RESULT_BUFFER_H_ - -//#include - -struct ResultData -{ - int value; - int size; -// ResultData* NextResult; -}; - - class ResultBuffer -{ - // Declare a pointer to a memory buffer to store the logged results - char* buffer; - // Declare an object to store the maximum Thread count - int MaxThreadCount; - // Declare and internal data object to store the calculated offset between adjacent threads data sets - int ThreadOffset; - - // Declare a linked list object to store the parameter values -public: - - // Declare a constructor for the single process case - ResultBuffer(int ThreadCount, int ThreadLogSize); - // Declare a method to log data for the single process instance - int LogResult(int Thread, char* Data); - - char* getResultBuffer(int threadId); -}; - -#include "resultbuffer.cpp" -#endif // _RESULT_BUFFER_H_ - - diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/interlocked.cpp b/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/interlocked.cpp deleted file mode 100644 index a87b6c4a28428e..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/interlocked.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - - -typedef long LONG; - -extern "C" { -LONG InterlockedCompareExchange( - LONG volatile *Destination, - LONG Exchange, - LONG Comperand) -{ -#ifdef i386 - LONG result; - - __asm__ __volatile__( - "lock; cmpxchgl %2,(%1)" - : "=a" (result) - : "r" (Destination), "r" (Exchange), "0" (Comperand) - : "memory" - ); - - return result; -#endif -} -} diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.cpp b/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.cpp deleted file mode 100644 index cd62a7840a1c18..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.cpp +++ /dev/null @@ -1,111 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include - -#include -#include "mtx_critsect.h" - -CsWaiterReturnState MTXWaitOnCS(LPCRITICAL_SECTION lpCriticalSection); -void MTXDoActualWait(LPCRITICAL_SECTION lpCriticalSection); -void MTXWakeUpWaiter(LPCRITICAL_SECTION lpCriticalSection); - -/*extern "C" { - LONG InterlockedCompareExchange( - LONG volatile *Destination, - LONG Exchange, - LONG Comperand); -} -*/ -int MTXInitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - int retcode = 0; - - lpCriticalSection->DebugInfo = NULL; - lpCriticalSection->LockCount = 0; - lpCriticalSection->RecursionCount = 0; - lpCriticalSection->SpinCount = 0; - lpCriticalSection->OwningThread = NULL; - - lpCriticalSection->LockSemaphore = (HANDLE)&lpCriticalSection->NativeData; - - if (0!= pthread_mutex_init(&lpCriticalSection->NativeData.Mutex, NULL)) - { - printf("Error Initializing Critical Section\n"); - retcode = -1; - } - - - lpCriticalSection->InitCount = CS_INITIALIZED; - return retcode; -} - -int MTXDeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - int retcode = 0; - - if (lpCriticalSection->InitCount == CS_INITIALIZED) - { - - if (0!=pthread_mutex_destroy(&lpCriticalSection->NativeData.Mutex)) - { - printf("Error Deleting Critical Section\n"); - retcode = -1; - } - } - - lpCriticalSection->InitCount = CS_NOT_INIZIALIZED; - return retcode; -} - -int MTXEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - - DWORD thread_id; - int retcode = 0; - - thread_id = (DWORD)THREADSilentGetCurrentThreadId(); - - /* check if the current thread already owns the criticalSection */ - if (lpCriticalSection->OwningThread == (HANDLE)thread_id) - { - lpCriticalSection->RecursionCount++; - //Check if this is a failure condition - return 0; - } - - if (0!= pthread_mutex_lock(&lpCriticalSection->NativeData.Mutex)) - { - //Error Condition - printf("Error Entering Critical Section\n"); - retcode = -1; - } - else - { - lpCriticalSection->OwningThread = (HANDLE)thread_id; - lpCriticalSection->RecursionCount = 1; - } - - return retcode; -} - -int MTXLeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection) -{ - int retcode = 0; - - if (--lpCriticalSection->RecursionCount > 0) - //*****check this ***** - return 0; - - lpCriticalSection->OwningThread = 0; - - if (0!= pthread_mutex_unlock(&lpCriticalSection->NativeData.Mutex)) - { - //Error Condition - printf("Error Leaving Critical Section\n"); - retcode = -1; - } - - return retcode; -} - diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.h b/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.h deleted file mode 100644 index 16e9eb9cbb39f5..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/mtx_critsect.h +++ /dev/null @@ -1,66 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include - -typedef void VOID; -typedef void* HANDLE; -typedef unsigned long ULONG_PTR; - -#ifdef HPUX - typedef unsigned int DWORD; - typedef int LONG; - typedef unsigned int ULONG; -#else - typedef unsigned long DWORD; - typedef long LONG; - typedef unsigned long ULONG; -#endif - - - - -#define FALSE 0 -#define TRUE 1 - -#define CSBIT_CS_IS_LOCKED 1 -#define CSBIT_NEW_WAITER 2 - -typedef enum CsInitState { CS_NOT_INIZIALIZED, CS_INITIALIZED, CS_FULLY_INITIALIZED } CsInitState; -typedef enum _CsWaiterReturnState { CS_WAITER_WOKEN_UP, CS_WAITER_DIDNT_WAIT } CsWaiterReturnState; - -typedef struct _CRITICAL_SECTION_DEBUG_INFO { - LONG volatile ContentionCount; - LONG volatile InternalContentionCount; - ULONG volatile AcquireCount; - ULONG volatile EnterCount; -} CRITICAL_SECTION_DEBUG_INFO, *PCRITICAL_SECTION_DEBUG_INFO; - -typedef struct _CRITICAL_SECTION_NATIVE_DATA { - pthread_mutex_t Mutex; -} CRITICAL_SECTION_NATIVE_DATA, *PCRITICAL_SECTION_NATIVE_DATA; - -typedef struct _CRITICAL_SECTION { - - CsInitState InitCount; - PCRITICAL_SECTION_DEBUG_INFO DebugInfo; - LONG LockCount; - LONG RecursionCount; - HANDLE OwningThread; - HANDLE LockSemaphore; - ULONG_PTR SpinCount; - CRITICAL_SECTION_NATIVE_DATA NativeData; - -} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION; - -int MTXInitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); -int MTXDeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection); -int MTXEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); -int MTXLeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection); - -extern "C" { - LONG InterlockedCompareExchange( - LONG volatile *Destination, - LONG Exchange, - LONG Comperand); -} diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.cpp b/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.cpp deleted file mode 100644 index d98669c2b28346..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/pal_composite_native_cs.cpp +++ /dev/null @@ -1,470 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include -#include -#include -#include -#include -//#include -//#include "mtx_critsect.cpp" -#include "mtx_critsect.h" -#include "resultbuffer.h" - - - -#define LONGLONG long long -#define ULONGLONG unsigned LONGLONG -/*Defining Global Variables*/ - -int THREAD_COUNT=0; -int REPEAT_COUNT=0; -int GLOBAL_COUNTER=0; -int USE_PROCESS_COUNT = 0; -int RELATION_ID =0; -int g_counter = 0; -int MAX_PATH = 256; -LONGLONG calibrationValue = 0; - -pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t g_cv = PTHREAD_COND_INITIALIZER; -pthread_cond_t g_cv2 = PTHREAD_COND_INITIALIZER; -CRITICAL_SECTION g_cs; - -/* Capture statistics for each worker thread */ -struct statistics{ - unsigned int processId; - unsigned int operationsFailed; - unsigned int operationsPassed; - unsigned int operationsTotal; - DWORD operationTime; - unsigned int relationId; -}; - - -struct applicationStatistics{ - DWORD operationTime; - unsigned int relationId; - unsigned int processCount; - unsigned int threadCount; - unsigned int repeatCount; - char* buildNumber; - -}; - -ResultBuffer *resultBuffer; - - -void* waitforworkerthreads(void*); -void starttests(int); -int setuptest(void); -int cleanuptest(void); -int GetParameters( int , char **); -void incrementCounter(void); -ULONGLONG GetTicks(void); -ULONGLONG getPerfCalibrationValue(void); - - - -PALTEST(composite_synchronization_nativecs_interlocked_paltest_synchronization_nativecs_interlocked, "composite/synchronization/nativecs_interlocked/paltest_synchronization_nativecs_interlocked") - { - //Variable Declaration - pthread_t pthreads[640]; - int threadID[640]; - int i=0; - int j=0; - int rtn=0; - ULONGLONG startTicks = 0; - - /* Variables to capture the file name and the file pointer*/ - char fileName[MAX_PATH]; - FILE *hFile; - struct statistics* buffer; - int statisticsSize = 0; - - /*Variable to Captutre Information at the Application Level*/ - struct applicationStatistics appStats; - char mainFileName[MAX_PATH]; - FILE *hMainFile; - - //Get perfCalibrationValue - - calibrationValue = getPerfCalibrationValue(); - printf("Calibration Value for this Platform %llu \n", calibrationValue); - - - //Get Parameters - if(GetParameters(argc, argv)) - { - printf("Error in obtaining the parameters\n"); - exit(-1); - } - - //Assign Values to Application Statistics Members - appStats.relationId=RELATION_ID; - appStats.operationTime=0; - appStats.buildNumber = "999.99"; - appStats.processCount = USE_PROCESS_COUNT; - appStats.threadCount = THREAD_COUNT; - appStats.repeatCount = REPEAT_COUNT; - - printf("RELATION ID : %d\n", appStats.relationId); - printf("Process Count : %d\n", appStats.processCount); - printf("Thread Count : %d\n", appStats.threadCount); - printf("Repeat Count : %d\n", appStats.repeatCount); - - - //Open file for Application Statistics Collection - snprintf(mainFileName, MAX_PATH, "main_nativecriticalsection_%d_.txt",appStats.relationId); - hMainFile = fopen(mainFileName, "w+"); - - if(hMainFile == NULL) - { - printf("Error in opening main file for write\n"); - } - - - for (i=0;igetResultBuffer(i); - fprintf(hFile, "%d,%d,%d,%d,%lu,%d\n", buffer->processId, buffer->operationsFailed, buffer->operationsPassed, buffer->operationsTotal, buffer->operationTime, buffer->relationId ); - //printf("Iteration %d over\n", i); - } - } - fclose(hFile); - - - - //Call Test Case Cleanup Routine - if (0!=cleanuptest()) - { - //Error Condition - printf("Error Cleaning up Test Case"); - exit(-1); - } - - - if(hMainFile!= NULL) - { - printf("Writing to Main File \n"); - fprintf(hMainFile, "%lu,%d,%d,%d,%d,%s\n", appStats.operationTime, appStats.relationId, appStats.processCount, appStats.threadCount, appStats.repeatCount, appStats.buildNumber); - - } - fclose(hMainFile); - return 0; - } - -void * waitforworkerthreads(void * threadId) -{ - - int *threadParam = (int*) threadId; - -// printf("Thread ID : %d \n", *threadParam); - - //Acquire Lock - if (0!=pthread_mutex_lock(&g_mutex)) - { - //Error Condition - printf("Error Acquiring Mutex Lock in Wait for Worker Thread\n"); - exit(-1); - } - - //Increment Global Counter - GLOBAL_COUNTER++; - - - //If global counter is equal to thread count then signal main thread - if (GLOBAL_COUNTER == THREAD_COUNT) - { - if (0!=pthread_cond_signal(&g_cv2)) - { - //Error Condition - printf("Error in setting conditional variable\n"); - exit(-1); - } - } - - //Wait for main thread to signal - if (0!=pthread_cond_wait(&g_cv,&g_mutex)) - { - //Error Condition - printf("Error waiting on conditional variable in Worker Thread\n"); - exit(-1); - } - - //Release the mutex lock - if (0!=pthread_mutex_unlock(&g_mutex)) - { - //Error Condition - printf("Error Releasing Mutex Lock in Worker Thread\n"); - exit(-1); - } - - //Start the test - starttests(*threadParam); - -} - -void starttests(int threadID) -{ - /*All threads beign executing tests cases*/ - int i = 0; - int Id = threadID; - struct statistics stats; - ULONGLONG startTime = 0; - ULONGLONG endTime = 0; - - LONG volatile Destination; - LONG Exchange; - LONG Comperand; - LONG result; - - stats.relationId = RELATION_ID; - stats.processId = USE_PROCESS_COUNT; - stats.operationsFailed = 0; - stats.operationsPassed = 0; - stats.operationsTotal = 0; - stats.operationTime = 0; - - //Enter and Leave Critical Section in a loop REPEAT_COUNT Times - - - startTime = GetTicks(); - - for (i=0;iLogResult(Id, (char *)&stats)) - { - printf("Error while writing to shared memory, Thread Id is[??] and Process id is [%d]\n", USE_PROCESS_COUNT); - } - -} - -int setuptest(void) -{ - - //Initialize Critical Section - /* - if (0!=MTXInitializeCriticalSection( &g_cs)) - { - return -1; - } - */ - return 0; -} - -int cleanuptest(void) -{ - - //Delete Critical Section - /* - if (0!=MTXDeleteCriticalSection(&g_cs)) - { - return -1; - } - */ - return 0; -} - -int GetParameters( int argc, char **argv) -{ - - if( (argc != 5) || ((argc == 1) && !strcmp(argv[1],"/?")) - || !strcmp(argv[1],"/h") || !strcmp(argv[1],"/H")) - { - printf("PAL -Composite Native Critical Section Test\n"); - printf("Usage:\n"); - printf("\t[PROCESS_ID ( greater than 1] \n"); - printf("\t[THREAD_COUNT ( greater than 1] \n"); - printf("\t[REPEAT_COUNT ( greater than 1]\n"); - printf("\t[RELATION_ID [greater than or Equal to 1]\n"); - return -1; - } - - - USE_PROCESS_COUNT = atoi(argv[1]); - if( USE_PROCESS_COUNT < 0) - { - printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n"); - return -1; - } - - THREAD_COUNT = atoi(argv[2]); - if( THREAD_COUNT < 1) - { - printf("\nInvalid THREAD_COUNT number, Pass greater than 1\n"); - return -1; - } - - REPEAT_COUNT = atoi(argv[3]); - if( REPEAT_COUNT < 1) - { - printf("\nInvalid REPEAT_COUNT number, Pass greater than 1\n"); - return -1; - } - - RELATION_ID = atoi(argv[4]); - if( RELATION_ID < 1) - { - printf("\nInvalid RELATION_ID number, Pass greater than 1\n"); - return -1; - } - - - return 0; -} - -void incrementCounter(void) -{ - g_counter ++; -} - - -//Implementation borrowed from pertrace.c -ULONGLONG GetTicks(void) -{ -#ifdef i386 - unsigned long a, d; - asm volatile("rdtsc":"=a" (a), "=d" (d)); - return ((ULONGLONG)((unsigned int)(d)) << 32) | (unsigned int)(a); -#else - // #error Don''t know how to get ticks on this platform - return (ULONGLONG)gethrtime(); -#endif // i386 -} - - -/**/ -ULONGLONG getPerfCalibrationValue(void) -{ - ULONGLONG startTicks; - ULONGLONG endTicks; - - startTicks = GetTicks(); - sleep(1); - endTicks = GetTicks(); - - return ((endTicks-startTicks)/1000); //Return number of Ticks in One Milliseconds - -} - diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.cpp b/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.cpp deleted file mode 100644 index 9988a49f9c509c..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -//#include "stdafx.h" -#include "resultbuffer.h" - -ResultBuffer:: ResultBuffer(int ThreadCount, int ThreadLogSize) - { - // Declare an internal status variable - int Status=0; - - // Update the maximum thread count - MaxThreadCount = ThreadCount; - - // Allocate the memory buffer based on the passed in thread and process counts - // and the specified size of the thread specific buffer - buffer = NULL; - buffer = (char*)malloc(ThreadCount*ThreadLogSize); - // Check to see if the buffer memory was allocated - if (buffer == NULL) - Status = -1; - // Initialize the buffer to 0 to prevent bogus data - memset(buffer,0,ThreadCount*ThreadLogSize); - - // The ThreadOffset is equal to the total number of bytes that will be stored per thread - ThreadOffset = ThreadLogSize; - - } - - - int ResultBuffer::LogResult(int Thread, char* Data) - { - // Declare an internal status flad - int status = 0; - - // Declare an object to store the offset address into the buffer - int Offset; - - // Check to make sure the Thread index is not out of range - if(Thread > MaxThreadCount) - { - printf("Thread index is out of range, Value of Thread[%d], Value of MaxThreadCount[%d]\n", Thread, MaxThreadCount); - status = -1; - return(status); - } - - // Calculate the offset into the shared buffer based on the process and thread indices - Offset = (Thread)*ThreadOffset; - - // Write the passed in data to the reserved buffer - memcpy(buffer+Offset,Data,ThreadOffset); - - return(status); - } - - - char* ResultBuffer::getResultBuffer(int threadId) - { - - return (buffer + threadId*ThreadOffset); - - } - diff --git a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.h b/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.h deleted file mode 100644 index c3d9a27fdb782c..00000000000000 --- a/src/coreclr/pal/tests/palsuite/composite/synchronization/nativecs_interlocked/resultbuffer.h +++ /dev/null @@ -1,42 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#include -#include -//#include -#ifndef _RESULT_BUFFER_H_ -#define _RESULT_BUFFER_H_ - -//#include - -struct ResultData -{ - int value; - int size; -// ResultData* NextResult; -}; - - class ResultBuffer -{ - // Declare a pointer to a memory buffer to store the logged results - char* buffer; - // Declare an object to store the maximum Thread count - int MaxThreadCount; - // Declare and internal data object to store the calculated offset between adjacent threads data sets - int ThreadOffset; - - // Declare a linked list object to store the parameter values -public: - - // Declare a constructor for the single process case - ResultBuffer(int ThreadCount, int ThreadLogSize); - // Declare a method to log data for the single process instance - int LogResult(int Thread, char* Data); - - char* getResultBuffer(int threadId); -}; - -#include "resultbuffer.cpp" -#endif // _RESULT_BUFFER_H_ - - diff --git a/src/coreclr/pal/tests/palsuite/paltestlist.txt b/src/coreclr/pal/tests/palsuite/paltestlist.txt index 318009912c975c..73da31d6db66a8 100644 --- a/src/coreclr/pal/tests/palsuite/paltestlist.txt +++ b/src/coreclr/pal/tests/palsuite/paltestlist.txt @@ -261,11 +261,6 @@ threading/CreateSemaphoreW_ReleaseSemaphore/test1/paltest_createsemaphorew_relea threading/CreateSemaphoreW_ReleaseSemaphore/test2/paltest_createsemaphorew_releasesemaphore_test2 threading/CreateThread/test1/paltest_createthread_test1 threading/CreateThread/test3/paltest_createthread_test3 -threading/CriticalSectionFunctions/test1/paltest_criticalsectionfunctions_test1 -threading/CriticalSectionFunctions/test2/paltest_criticalsectionfunctions_test2 -threading/CriticalSectionFunctions/test4/paltest_criticalsectionfunctions_test4 -threading/CriticalSectionFunctions/test7/paltest_criticalsectionfunctions_test7 -threading/CriticalSectionFunctions/test8/paltest_criticalsectionfunctions_test8 threading/DuplicateHandle/test10/paltest_duplicatehandle_test10 threading/DuplicateHandle/test2/paltest_duplicatehandle_test2 threading/DuplicateHandle/test4/paltest_duplicatehandle_test4 diff --git a/src/coreclr/pal/tests/palsuite/paltestlist_to_be_reviewed.txt b/src/coreclr/pal/tests/palsuite/paltestlist_to_be_reviewed.txt index f42b770082edc4..d4a5dd02c3b491 100644 --- a/src/coreclr/pal/tests/palsuite/paltestlist_to_be_reviewed.txt +++ b/src/coreclr/pal/tests/palsuite/paltestlist_to_be_reviewed.txt @@ -74,8 +74,6 @@ threading/CreateEventW/test3/paltest_createeventw_test3 threading/CreateMutexW_ReleaseMutex/test2/paltest_createmutexw_releasemutex_test2 threading/CreateSemaphoreW_ReleaseSemaphore/test3/paltest_createsemaphorew_releasesemaphore_test3 threading/CreateThread/test2/paltest_createthread_test2 -threading/CriticalSectionFunctions/test5/paltest_criticalsectionfunctions_test5 -threading/CriticalSectionFunctions/test6/paltest_criticalsectionfunctions_test6 threading/DuplicateHandle/test1/paltest_duplicatehandle_test1 threading/DuplicateHandle/test11/paltest_duplicatehandle_test11 threading/DuplicateHandle/test12/paltest_duplicatehandle_test12 diff --git a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.cpp b/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.cpp deleted file mode 100644 index 750e42d0672b46..00000000000000 --- a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test1/InitializeCriticalSection.cpp +++ /dev/null @@ -1,234 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** Source: criticalsectionfunctions/test1/initializecriticalsection.c -** -** Purpose: Test Semaphore operation using classic IPC problem: -** "Producer-Consumer Problem". -** -** Dependencies: CreateThread -** InitializeCriticalSection -** EnterCriticalSection -** LeaveCriticalSection -** DeleteCriticalSection -** WaitForSingleObject -** Sleep -** - -** -**=========================================================*/ - -#include - -#define PRODUCTION_TOTAL 26 - -#define _BUF_SIZE 10 - -DWORD dwThreadId_CriticalSectionFunctions_test1; /* consumer thread identifier */ - -HANDLE hThread_CriticalSectionFunctions_test1; /* handle to consumer thread */ - -CRITICAL_SECTION CriticalSectionM_CriticalSectionFunctions_test1; /* Critical Section Object (used as mutex) */ - -typedef struct Buffer -{ - short readIndex; - short writeIndex; - CHAR message[_BUF_SIZE]; - -} BufferStructure; - -CHAR producerItems_CriticalSectionFunctions_test1[PRODUCTION_TOTAL + 1]; - -CHAR consumerItems_CriticalSectionFunctions_test1[PRODUCTION_TOTAL + 1]; - -/* - * Read next message from the Buffer into provided pointer. - * Returns: 0 on failure, 1 on success. - */ -int -readBuf_CriticalSectionFunctions_test1(BufferStructure *Buffer, char *c) -{ - if( Buffer -> writeIndex == Buffer -> readIndex ) - { - return 0; - } - *c = Buffer -> message[Buffer -> readIndex++]; - Buffer -> readIndex %= _BUF_SIZE; - return 1; -} - -/* - * Write message generated by the producer to Buffer. - * Returns: 0 on failure, 1 on success. - */ -int -writeBuf_CriticalSectionFunctions_test1(BufferStructure *Buffer, CHAR c) -{ - if( ( ((Buffer -> writeIndex) + 1) % _BUF_SIZE) == - (Buffer -> readIndex) ) - { - return 0; - } - Buffer -> message[Buffer -> writeIndex++] = c; - Buffer -> writeIndex %= _BUF_SIZE; - return 1; -} - -/* - * Sleep 500 milleseconds. - */ -VOID -consumerSleep_CriticalSectionFunctions_test1(VOID) -{ - Sleep(500); -} - -/* - * Sleep between 10 milleseconds. - */ -VOID -producerSleep_CriticalSectionFunctions_test1(VOID) -{ - Sleep(10); -} - -/* - * Produce a message and write the message to Buffer. - */ -VOID -producer_CriticalSectionFunctions_test1(BufferStructure *Buffer) -{ - - int n = 0; - char c; - - while (n < PRODUCTION_TOTAL) - { - c = 'A' + n ; /* Produce Item */ - - EnterCriticalSection(&CriticalSectionM_CriticalSectionFunctions_test1); - - if (writeBuf_CriticalSectionFunctions_test1(Buffer, c)) - { - printf("Producer produces %c.\n", c); - producerItems_CriticalSectionFunctions_test1[n++] = c; - } - - LeaveCriticalSection(&CriticalSectionM_CriticalSectionFunctions_test1); - - producerSleep_CriticalSectionFunctions_test1(); - } - - return; -} - -/* - * Read and "Consume" the messages in Buffer. - */ -DWORD -PALAPI -consumer_CriticalSectionFunctions_test1( LPVOID lpParam ) -{ - int n = 0; - char c; - - consumerSleep_CriticalSectionFunctions_test1(); - - while (n < PRODUCTION_TOTAL) - { - - EnterCriticalSection(&CriticalSectionM_CriticalSectionFunctions_test1); - - if (readBuf_CriticalSectionFunctions_test1((BufferStructure*)lpParam, &c)) - { - printf("\tConsumer consumes %c.\n", c); - consumerItems_CriticalSectionFunctions_test1[n++] = c; - } - - LeaveCriticalSection(&CriticalSectionM_CriticalSectionFunctions_test1); - - consumerSleep_CriticalSectionFunctions_test1(); - } - - return 0; -} - -PALTEST(threading_CriticalSectionFunctions_test1_paltest_criticalsectionfunctions_test1, "threading/CriticalSectionFunctions/test1/paltest_criticalsectionfunctions_test1") -{ - - BufferStructure Buffer, *pBuffer; - - pBuffer = &Buffer; - - if(0 != (PAL_Initialize(argc, argv))) - { - return FAIL; - } - - /* - * Create mutual exclusion mechanisms - */ - - InitializeCriticalSection ( &CriticalSectionM_CriticalSectionFunctions_test1 ); - - /* - * Initialize Buffer - */ - pBuffer->writeIndex = pBuffer->readIndex = 0; - - - - /* - * Create Consumer - */ - hThread_CriticalSectionFunctions_test1 = CreateThread( - NULL, - 0, - consumer_CriticalSectionFunctions_test1, - &Buffer, - 0, - &dwThreadId_CriticalSectionFunctions_test1); - - if ( NULL == hThread_CriticalSectionFunctions_test1 ) - { - Fail ( "CreateThread() returned NULL. Failing test.\n" - "GetLastError returned %d\n", GetLastError()); - } - - /* - * Start producing - */ - producer_CriticalSectionFunctions_test1(pBuffer); - - /* - * Wait for consumer to complete - */ - WaitForSingleObject (hThread_CriticalSectionFunctions_test1, INFINITE); - - /* - * Compare items produced vs. items consumed - */ - if ( 0 != strncmp (producerItems_CriticalSectionFunctions_test1, consumerItems_CriticalSectionFunctions_test1, PRODUCTION_TOTAL) ) - { - Fail("The producerItems_CriticalSectionFunctions_test1 string %s\n and the consumerItems_CriticalSectionFunctions_test1 string " - "%s\ndo not match. This could be a problem with the strncmp()" - " function\n FailingTest\nGetLastError() returned %d\n", - producerItems_CriticalSectionFunctions_test1, consumerItems_CriticalSectionFunctions_test1, GetLastError()); - } - - /* - * Clean up Critical Section object - */ - DeleteCriticalSection(&CriticalSectionM_CriticalSectionFunctions_test1); - - Trace("producerItems_CriticalSectionFunctions_test1 and consumerItems_CriticalSectionFunctions_test1 arrays match. All %d\nitems " - "were produced and consumed in order.\nTest passed.\n", - PRODUCTION_TOTAL); - - PAL_Terminate(); - return (PASS); - -} diff --git a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.cpp b/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.cpp deleted file mode 100644 index 4bb75dfcf95f6f..00000000000000 --- a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test2/test2.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** Source: CriticalSectionFunctions/test2/test2.c -** -** Purpose: Test that we are able to nest critical section calls. -** The initial thread makes a call to EnterCriticalSection once, -** blocking on a CRITICAL_SECTION object and creates a new thread. -** The newly created thread blocks on the same CRITICAL_SECTION object. -** The first thread now makes a call to LeaveCriticalSection. -** Test to see that the new thread doesn't get unblocked. -** -** Dependencies: CreateThread -** InitializeCriticalSection -** EnterCriticalSection -** LeaveCriticalSection -** DeleteCriticalSection -** WaitForSingleObject -** - -** -**=========================================================*/ - -#include - -volatile BOOL t0_tflag = FAIL; /* thread 0 timeout flag */ -volatile BOOL t1_aflag = FAIL; /* thread 1 access flag */ -volatile BOOL t1_cflag = FAIL; /* thread 1 critical section flag */ -volatile BOOL bTestResult = FAIL; - -DWORD PALAPI Thread_CriticalSectionFunctions_test2(LPVOID lpParam) -{ - t1_aflag = PASS; - EnterCriticalSection(&CriticalSection); - t1_cflag = PASS; - LeaveCriticalSection(&CriticalSection); - return 0; -} - -PALTEST(threading_CriticalSectionFunctions_test2_paltest_criticalsectionfunctions_test2, "threading/CriticalSectionFunctions/test2/paltest_criticalsectionfunctions_test2") -{ - HANDLE hThread; - DWORD dwThreadId; - DWORD dwRet; - - if(0 != (PAL_Initialize(argc, argv))) - { - return (bTestResult); - } - - /* - * Create critical section object and enter it - */ - InitializeCriticalSection ( &CriticalSection ); - EnterCriticalSection(&CriticalSection); - - /* - * Create a suspended thread - */ - hThread = CreateThread(NULL, - 0, - &Thread_CriticalSectionFunctions_test2, - (LPVOID) NULL, - CREATE_SUSPENDED, - &dwThreadId); - - if (hThread == NULL) - { - Trace("PALSUITE ERROR: CreateThread call failed. GetLastError " - "returned %d.\n", GetLastError()); - LeaveCriticalSection(&CriticalSection); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - - EnterCriticalSection(&CriticalSection); - /* - * Set priority of the thread to greater than that of the currently - * running thread so it is guaranteed to run. - */ - dwRet = (DWORD) SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL); - - if (0 == dwRet) - { - Trace("PALSUITE ERROR: SetThreadPriority (%p, %d) call failed.\n" - "GetLastError returned %d.\n", hThread, - THREAD_PRIORITY_NORMAL, GetLastError()); - LeaveCriticalSection(&CriticalSection); - CloseHandle(hThread); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - - dwRet = ResumeThread(hThread); - - if (-1 == dwRet) - { - Trace("PALSUITE ERROR: ResumeThread(%p) call failed.\nGetLastError " - "returned %d.\n", hThread, GetLastError()); - LeaveCriticalSection(&CriticalSection); - CloseHandle(hThread); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - /* - * Sleep until we know the thread has been invoked. This sleep in - * combination with the higher priority of the other thread should - * guarantee both threads block on the critical section. - */ - while (t1_aflag == FAIL) - { - Sleep(1); - } - - LeaveCriticalSection(&CriticalSection); - - switch ((WaitForSingleObject( - hThread, - 10000))) /* Wait 10 seconds */ - { - case WAIT_OBJECT_0: - /* Object (thread) is signaled */ - LeaveCriticalSection(&CriticalSection); - CloseHandle(hThread); - DeleteCriticalSection(&CriticalSection); - Fail("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " - "returned\nWAIT_TIMEOUT ('%d'), instead it returned " - "WAIT_OBJECT_0 ('%d').\nA nested LeaveCriticalSection(%p) " - "call released both threads that were waiting on it!\n", - hThread, 10000, WAIT_TIMEOUT, WAIT_OBJECT_0, &CriticalSection); - break; - case WAIT_ABANDONED: - /* - * Object was mutex object whose owning - * thread has terminated. Shouldn't occur. - */ - Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " - "returned\nWAIT_TIMEOUT ('%d'), instead it returned " - "WAIT_ABANDONED ('%d').\nGetLastError returned '%d'\n", - hThread, 10000, WAIT_TIMEOUT, WAIT_ABANDONED, GetLastError()); - LeaveCriticalSection(&CriticalSection); - CloseHandle(hThread); - DeleteCriticalSection(&CriticalSection); - Fail(""); - break; - case WAIT_FAILED: /* WaitForSingleObject function failed */ - Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " - "returned\nWAIT_TIMEOUT ('%d'), instead it returned " - "WAIT_FAILED ('%d').\nGetLastError returned '%d'\n", - hThread, 10000, WAIT_TIMEOUT, WAIT_FAILED, GetLastError()); - LeaveCriticalSection(&CriticalSection); - CloseHandle(hThread); - DeleteCriticalSection(&CriticalSection); - Fail(""); - break; - case WAIT_TIMEOUT: - /* - * We expect this thread to timeout waiting for the - * critical section object to become available. - */ - t0_tflag = PASS; - break; - } - - LeaveCriticalSection(&CriticalSection); - - if (WAIT_OBJECT_0 != WaitForSingleObject (hThread, 10000)) - { - if (0 == CloseHandle(hThread)) - { - Trace("PALSUITE ERROR: CloseHandle(%p) call failed.\n" - "WaitForSingleObject(%p,%d) should have returned " - "WAIT_OBJECT_0 ('%d').\nBoth calls failed. " - "Deleted CRITICAL_SECTION object which likely means\n" - "thread %p is now in an undefined state. GetLastError " - "returned '%d'.\n", hThread, hThread, 10000, WAIT_OBJECT_0, - hThread, GetLastError()); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - else - { - Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " - "returned WAIT_OBJECT_0 ('%d').\n GetLastError returned " - "'%d'.\n", hThread, hThread, 10000, WAIT_OBJECT_0, - hThread, GetLastError()); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - } - - if (0 == CloseHandle(hThread)) - { - Trace("PALSUITE ERROR: CloseHandle(%p) call failed.\n" - "Deleted CRITICAL_SECTION object which likely means\n" - "thread %p is now in an undefined state. GetLastError " - "returned '%d'.\n", hThread, hThread, GetLastError()); - DeleteCriticalSection(&CriticalSection); - Fail(""); - - } - DeleteCriticalSection(&CriticalSection); - /* - * Ensure both thread 0 experienced a wait timeout and thread 1 - * accessed the critical section or fail the test, otherwise pass it. - */ - if ((t0_tflag == FAIL) || (t1_cflag == FAIL)) - { - Trace("PALSUITE ERROR: Thread 0 returned %d when %d was expected.\n" - "Thread 1 returned %d when %d was expected.\n", t0_tflag, - PASS, t1_cflag, PASS); - bTestResult=FAIL; - } - else - { - bTestResult=PASS; - } - - PAL_TerminateEx(bTestResult); - return (bTestResult); -} diff --git a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp b/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp deleted file mode 100644 index 14a737abd3a905..00000000000000 --- a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test4/test4.cpp +++ /dev/null @@ -1,240 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*============================================================ -** -** Source: criticalsectionfunctions/test4/test4.c -** -** Purpose: Test to see if threads blocked on a CRITICAL_SECTION object will -** be released in an orderly manner. This case looks at the following -** scenario. If one thread owns a CRITICAL_SECTION object and two threads -** block in EnterCriticalSection, trying to hold the already owned -** CRITICAL_SECTION object, when the first thread releases the CRITICAL_SECTION -** object, will one and only one of the waiters get unblocked? -** -** Dependencies: CreateThread -** InitializeCriticalSection -** EnterCriticalSection -** LeaveCriticalSection -** DeleteCriticalSection -** Sleep -** WaitForSingleObject -** - -** -**=========================================================*/ - -#include - -#define NUM_BLOCKING_THREADS 2 - -BOOL bTestResult_CriticalSectionFunctions_test4; -CRITICAL_SECTION CriticalSection_CriticalSectionFunctions_test4; -HANDLE hThread_CriticalSectionFunctions_test4[NUM_BLOCKING_THREADS]; -HANDLE hEvent_CriticalSectionFunctions_test4; -DWORD dwThreadId_CriticalSectionFunctions_test4[NUM_BLOCKING_THREADS]; -volatile int flags_CriticalSectionFunctions_test4[NUM_BLOCKING_THREADS] = {0,0}; - -DWORD PALAPI ThreadTest1_CriticalSectionFunctions_test4(LPVOID lpParam) -{ - - EnterCriticalSection ( &CriticalSection_CriticalSectionFunctions_test4 ); - - flags_CriticalSectionFunctions_test4[0] = 1; - - return 0; - -} - -DWORD PALAPI ThreadTest2_CriticalSectionFunctions_test4(LPVOID lpParam) -{ - - EnterCriticalSection ( &CriticalSection_CriticalSectionFunctions_test4 ); - - flags_CriticalSectionFunctions_test4[1] = 1; - - return 0; - -} - -PALTEST(threading_CriticalSectionFunctions_test4_paltest_criticalsectionfunctions_test4, "threading/CriticalSectionFunctions/test4/paltest_criticalsectionfunctions_test4") -{ - - DWORD dwRet; - DWORD dwRet1; - bTestResult_CriticalSectionFunctions_test4 = FAIL; - - if ((PAL_Initialize(argc,argv)) != 0) - { - return(bTestResult_CriticalSectionFunctions_test4); - } - - /* - * Create Critical Section Object - */ - InitializeCriticalSection ( &CriticalSection_CriticalSectionFunctions_test4 ); - - EnterCriticalSection ( &CriticalSection_CriticalSectionFunctions_test4 ); - - hThread_CriticalSectionFunctions_test4[0] = CreateThread(NULL, - 0, - &ThreadTest1_CriticalSectionFunctions_test4, - (LPVOID) 0, - CREATE_SUSPENDED, - &dwThreadId_CriticalSectionFunctions_test4[0]); - if (hThread_CriticalSectionFunctions_test4[0] == NULL) - { - Trace("PALSUITE ERROR: CreateThread(%p, %d, %p, %p, %d, %p) call " - "failed.\nGetLastError returned %d.\n", NULL, 0, &ThreadTest1_CriticalSectionFunctions_test4, - (LPVOID) 0, CREATE_SUSPENDED, &dwThreadId_CriticalSectionFunctions_test4[0], GetLastError()); - LeaveCriticalSection(&CriticalSection_CriticalSectionFunctions_test4); - DeleteCriticalSection ( &CriticalSection_CriticalSectionFunctions_test4 ); - Fail(""); - } - - hThread_CriticalSectionFunctions_test4[1] = CreateThread(NULL, - 0, - &ThreadTest2_CriticalSectionFunctions_test4, - (LPVOID) 0, - CREATE_SUSPENDED, - &dwThreadId_CriticalSectionFunctions_test4[1]); - if (hThread_CriticalSectionFunctions_test4[1] == NULL) - { - Trace("PALSUITE ERROR: CreateThread(%p, %d, %p, %p, %d, %p) call " - "failed.\nGetLastError returned %d.\n", NULL, 0, &ThreadTest2_CriticalSectionFunctions_test4, - (LPVOID) 0, CREATE_SUSPENDED, &dwThreadId_CriticalSectionFunctions_test4[1], GetLastError()); - LeaveCriticalSection(&CriticalSection_CriticalSectionFunctions_test4); - - dwRet = ResumeThread(hThread_CriticalSectionFunctions_test4[0]); - if (-1 == dwRet) - { - Trace("PALSUITE ERROR: ResumeThread(%p) call failed.\n" - "GetLastError returned '%d'.\n", hThread_CriticalSectionFunctions_test4[0], - GetLastError()); - } - - dwRet = WaitForSingleObject(hThread_CriticalSectionFunctions_test4[0], 10000); - if (WAIT_OBJECT_0 == dwRet) - { - Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call " - "failed. '%d' was returned instead of the expected '%d'.\n" - "GetLastError returned '%d'.\n", hThread_CriticalSectionFunctions_test4[0], 10000, dwRet, - WAIT_OBJECT_0, GetLastError()); - } - - if (0 == CloseHandle(hThread_CriticalSectionFunctions_test4[0])) - { - Trace("PALSUITE NOTIFICATION: CloseHandle(%p) call failed.\n" - "GetLastError returned %d. Not failing tests.\n", - hThread_CriticalSectionFunctions_test4[0], GetLastError()); - } - - DeleteCriticalSection(&CriticalSection_CriticalSectionFunctions_test4); - Fail(""); - } - - /* - * Set other thread priorities to be higher than ours & Sleep to ensure - * we give up the processor. - */ - dwRet = (DWORD) SetThreadPriority(hThread_CriticalSectionFunctions_test4[0], - THREAD_PRIORITY_ABOVE_NORMAL); - if (0 == dwRet) - { - Trace("PALSUITE ERROR: SetThreadPriority(%p, %d) call failed.\n" - "GetLastError returned %d", hThread_CriticalSectionFunctions_test4[0], - THREAD_PRIORITY_ABOVE_NORMAL, GetLastError()); - } - - dwRet = (DWORD) SetThreadPriority(hThread_CriticalSectionFunctions_test4[1], - THREAD_PRIORITY_ABOVE_NORMAL); - if (0 == dwRet) - { - Trace("PALSUITE ERROR: SetThreadPriority(%p, %d) call failed.\n" - "GetLastError returned %d", hThread_CriticalSectionFunctions_test4[1], - THREAD_PRIORITY_ABOVE_NORMAL, GetLastError()); - } - - dwRet = ResumeThread(hThread_CriticalSectionFunctions_test4[0]); - if (-1 == dwRet) - { - Trace("PALSUITE ERROR: ResumeThread(%p, %d) call failed.\n" - "GetLastError returned %d", hThread_CriticalSectionFunctions_test4[0], - GetLastError() ); - } - - dwRet = ResumeThread(hThread_CriticalSectionFunctions_test4[1]); - if (-1 == dwRet) - { - Trace("PALSUITE ERROR: ResumeThread(%p, %d) call failed.\n" - "GetLastError returned %d", hThread_CriticalSectionFunctions_test4[0], - GetLastError()); - } - - Sleep (0); - - LeaveCriticalSection (&CriticalSection_CriticalSectionFunctions_test4); - - dwRet = WaitForSingleObject(hThread_CriticalSectionFunctions_test4[0], 10000); - dwRet1 = WaitForSingleObject(hThread_CriticalSectionFunctions_test4[1], 10000); - - if ((WAIT_OBJECT_0 == dwRet) || - (WAIT_OBJECT_0 == dwRet1)) - { - if ((1 == flags_CriticalSectionFunctions_test4[0] && 0 == flags_CriticalSectionFunctions_test4[1]) || - (0 == flags_CriticalSectionFunctions_test4[0] && 1 == flags_CriticalSectionFunctions_test4[1])) - { - bTestResult_CriticalSectionFunctions_test4 = PASS; - } - else - { - bTestResult_CriticalSectionFunctions_test4 = FAIL; - Trace ("PALSUITE ERROR: flags[%d] = {%d,%d}. These values are" - "inconsistent.\nCriticalSection test failed.\n", - NUM_BLOCKING_THREADS, flags_CriticalSectionFunctions_test4[0], flags_CriticalSectionFunctions_test4[1]); - } - - /* Fail the test if both threads returned WAIT_OBJECT_0 */ - if ((WAIT_OBJECT_0 == dwRet) && (WAIT_OBJECT_0 == dwRet1)) - { - bTestResult_CriticalSectionFunctions_test4 = FAIL; - Trace ("PALSUITE ERROR: WaitForSingleObject(%p, %d) and " - "WaitForSingleObject(%p, %d)\nboth returned dwRet = '%d'\n" - "One should have returned WAIT_TIMEOUT ('%d').\n", - hThread_CriticalSectionFunctions_test4[0], 10000, hThread_CriticalSectionFunctions_test4[1], 10000, dwRet, WAIT_TIMEOUT); - } - } - else - { - bTestResult_CriticalSectionFunctions_test4 = FAIL; - Trace ("PALSUITE ERROR: WaitForSingleObject(%p, %d) and " - "WaitForSingleObject(%p, %d)\nReturned dwRet = '%d' and\n" - "dwRet1 = '%d' respectively.\n", hThread_CriticalSectionFunctions_test4[0], 10000, hThread_CriticalSectionFunctions_test4[1], - 10000, dwRet, dwRet1); - } - - if (WAIT_OBJECT_0 == dwRet) - { - if (0 == CloseHandle(hThread_CriticalSectionFunctions_test4[0])) - { - Trace("PALSUITE NOTIFICATION: CloseHandle(%p) call failed.\n" - "GetLastError returned %d. Not failing tests.\n", - hThread_CriticalSectionFunctions_test4[0], GetLastError()); - } - } - if (WAIT_OBJECT_0 == dwRet1) - { - if (0 == CloseHandle(hThread_CriticalSectionFunctions_test4[1])) - { - Trace("PALSUITE NOTIFICATION: CloseHandle(%p) call failed.\n" - "GetLastError returned %d. Not failing tests.\n", - hThread_CriticalSectionFunctions_test4[1], GetLastError()); - } - } - - /* Leaking the CS on purpose, since there is still a thread - waiting on it */ - - PAL_TerminateEx(bTestResult_CriticalSectionFunctions_test4); - return (bTestResult_CriticalSectionFunctions_test4); -} diff --git a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.cpp b/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.cpp deleted file mode 100644 index 4556c082f67e2f..00000000000000 --- a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test5/test5.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: CriticalSectionFunctions/test5/test5.c -** -** Purpose: Attempt to delete a critical section owned by another -** thread. -** -** -**===================================================================*/ -#include - -DWORD PALAPI Thread_CriticalSectionFunctions_test5(LPVOID lpParam) -{ - DWORD dwTRet; - - EnterCriticalSection(&CriticalSection); - - /* signal thread 0 */ - if (0 == SetEvent(hToken[0])) - { - Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during " - "clean up.\nGetLastError returned '%u'.\n", hToken[0], - GetLastError()); - LeaveCriticalSection(&CriticalSection); - Cleanup (&hToken[0], NUM_TOKENS); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - - /* wait to be signaled */ - dwTRet = WaitForSingleObject(hToken[1], 10000); - if (WAIT_OBJECT_0 != dwTRet) - - { - Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " - "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " - "('%d').\nGetLastError returned '%u'.\n", - hToken[1], 10000, WAIT_OBJECT_0, dwTRet, GetLastError()); - LeaveCriticalSection(&CriticalSection); - Cleanup (&hToken[0], NUM_TOKENS); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - - LeaveCriticalSection(&CriticalSection); - return 0; -} - -PALTEST(threading_CriticalSectionFunctions_test5_paltest_criticalsectionfunctions_test5, "threading/CriticalSectionFunctions/test5/paltest_criticalsectionfunctions_test5") -{ - DWORD dwThreadId; - DWORD dwMRet; - - if ((PAL_Initialize(argc,argv)) != 0) - { - return(FAIL); - } - - /* thread 0 event */ - hToken[0] = CreateEvent(NULL, TRUE, FALSE, NULL); - if (NULL == hToken[0]) - { - Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError " - "returned %u.\n", GetLastError()); - } - - /* thread 1 event */ - hToken[1] = CreateEvent(NULL, TRUE, FALSE, NULL); - if (NULL == hToken[1]) - { - Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError " - "returned %u.\n", GetLastError()); - Cleanup(&hToken[0], (NUM_TOKENS - 2)); - Fail(""); - } - - InitializeCriticalSection(&CriticalSection); - - hToken[2] = CreateThread(NULL, - 0, - &Thread_CriticalSectionFunctions_test5, - (LPVOID) NULL, - 0, - &dwThreadId); - if (hToken[2] == NULL) - { - Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError " - "returned %u.\n", GetLastError()); - Cleanup(&hToken[0], (NUM_TOKENS - 1)); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - - /* wait for thread 0 to be signaled */ - dwMRet = WaitForSingleObject(hToken[0], 10000); - if (WAIT_OBJECT_0 != dwMRet) - { - Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " - "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " - "('%d').\nGetLastError returned '%u'.\n", hToken[0], 10000, - WAIT_OBJECT_0, dwMRet, GetLastError()); - Cleanup(&hToken[0], NUM_TOKENS); - Fail(""); - } - - /* - * Attempt to do delete CriticalSection object owned by other thread - */ - DeleteCriticalSection(&CriticalSection); - - /* signal thread 1 */ - if (0 == SetEvent(hToken[1])) - { - Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n" - "GetLastError returned '%u'.\n", hToken[1], - GetLastError()); - Cleanup(&hToken[0], NUM_TOKENS); - Fail(""); - } - - dwMRet = WaitForSingleObject(hToken[2], 10000); - if (WAIT_OBJECT_0 != dwMRet) - { - Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call " - "returned an unexpected value '%d'.\nGetLastError returned " - "%u.\n", hToken[2], 10000, dwMRet, GetLastError()); - Cleanup(&hToken[0], NUM_TOKENS); - Fail(""); - } - - if (!Cleanup(&hToken[0], NUM_TOKENS)) - { - Fail(""); - } - - PAL_Terminate(); - - return (PASS); -} diff --git a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.cpp b/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.cpp deleted file mode 100644 index 672637159c3d82..00000000000000 --- a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test6/test6.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: CriticalSectionFunctions/test6/test6.c -** -** Purpose: Attempt to leave a critical section which is owned by -** another thread. -** -** -**===================================================================*/ -#include - - -DWORD PALAPI Thread_CriticalSectionFunctions_test6(LPVOID lpParam) -{ - DWORD dwTRet; - - EnterCriticalSection(&CriticalSection); - - /* signal thread 0 */ - if (0 == SetEvent(hToken[0])) - { - Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during " - "clean up.\nGetLastError returned '%u'.\n", hToken[0], - GetLastError()); - LeaveCriticalSection(&CriticalSection); - Cleanup (&hToken[0], NUM_TOKENS); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - - /* wait to be signaled */ - dwTRet = WaitForSingleObject(hToken[1], 10000); - if (WAIT_OBJECT_0 != dwTRet) - { - Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " - "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " - "('%d').\nGetLastError returned '%u'.\n", - hToken[1], 10000, WAIT_OBJECT_0, dwTRet, GetLastError()); - LeaveCriticalSection(&CriticalSection); - Cleanup (&hToken[0], NUM_TOKENS); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - - LeaveCriticalSection(&CriticalSection); - - return 0; -} - -PALTEST(threading_CriticalSectionFunctions_test6_paltest_criticalsectionfunctions_test6, "threading/CriticalSectionFunctions/test6/paltest_criticalsectionfunctions_test6") -{ - DWORD dwThreadId; - DWORD dwMRet; - - if ((PAL_Initialize(argc,argv)) != 0) - { - return(FAIL); - } - - /* thread 0 event */ - hToken[0] = CreateEvent(NULL, TRUE, FALSE, NULL); - - if (hToken[0] == NULL) - { - Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError " - "returned %u.\n", GetLastError()); - } - - /* thread 1 event */ - hToken[1] = CreateEvent(NULL, TRUE, FALSE, NULL); - - if (hToken[1] == NULL) - { - Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError " - "returned %u.\n", GetLastError()); - Cleanup(&hToken[0], (NUM_TOKENS - 2)); - Fail(""); - } - - InitializeCriticalSection(&CriticalSection); - - hToken[2] = CreateThread(NULL, - 0, - &Thread_CriticalSectionFunctions_test6, - (LPVOID) NULL, - 0, - &dwThreadId); - - if (hToken[2] == NULL) - { - Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError " - "returned %u.\n", GetLastError()); - Cleanup(&hToken[0], (NUM_TOKENS - 1)); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - - /* wait for thread 0 to be signaled */ - dwMRet = WaitForSingleObject(hToken[0], 10000); - if (WAIT_OBJECT_0 != dwMRet) - { - Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " - "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " - "('%d').\nGetLastError returned '%u'.\n", hToken[0], 10000, - WAIT_OBJECT_0, dwMRet, GetLastError()); - Cleanup(&hToken[0], NUM_TOKENS); - Fail(""); - } - - /* - * Attempt to leave critical section which is owned by the other thread. - */ - LeaveCriticalSection(&CriticalSection); - - /* signal thread 1 */ - if (0 == SetEvent(hToken[1])) - { - Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n" - "GetLastError returned '%u'.\n", hToken[1], - GetLastError()); - Cleanup(&hToken[0], NUM_TOKENS); - Fail(""); - } - - dwMRet = WaitForSingleObject(hToken[2], 10000); - if (WAIT_OBJECT_0 != dwMRet) - { - Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call " - "returned an unexpected value '%d'.\nGetLastError returned " - "%u.\n", hToken[2], 10000, dwMRet, GetLastError()); - Cleanup(&hToken[0], NUM_TOKENS); - Fail(""); - } - - if (!Cleanup(&hToken[0], NUM_TOKENS)) - { - Fail(""); - } - - PAL_Terminate(); - - return(PASS); -} diff --git a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.cpp b/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.cpp deleted file mode 100644 index e4ad81364c4aa4..00000000000000 --- a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test7/test7.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: CriticalSectionFunctions/test7/test7.c -** -** Purpose: Attempt to delete a critical section owned by the current -** thread. -** -** -**===================================================================*/ -#include - -DWORD PALAPI Thread_CriticalSectionFunctions_test7(LPVOID lpParam) -{ - DWORD dwTRet; - - EnterCriticalSection(&CriticalSection); - - /* signal thread 0 */ - if (0 == SetEvent(hToken[0])) - { - Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) during " - "clean up.\nGetLastError returned '%u'.\n", hToken[0], - GetLastError()); - LeaveCriticalSection(&CriticalSection); - Cleanup (&hToken[0], NUM_TOKENS); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - - /* wait to be signaled */ - dwTRet = WaitForSingleObject(hToken[1], 10000); - if (WAIT_OBJECT_0 != dwTRet) - { - Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " - "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " - "('%d').\nGetLastError returned '%u'.\n", - hToken[0], 10000, WAIT_OBJECT_0, dwTRet, GetLastError()); - LeaveCriticalSection(&CriticalSection); - Cleanup (&hToken[0], NUM_TOKENS); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - - DeleteCriticalSection(&CriticalSection); - - return 0; -} - -PALTEST(threading_CriticalSectionFunctions_test7_paltest_criticalsectionfunctions_test7, "threading/CriticalSectionFunctions/test7/paltest_criticalsectionfunctions_test7") -{ - DWORD dwThreadId; - DWORD dwMRet; - - if ((PAL_Initialize(argc,argv)) != 0) - { - return(FAIL); - } - - /* thread 0 event */ - hToken[0] = CreateEvent(NULL, TRUE, FALSE, NULL); - - if (hToken[0] == NULL) - { - Fail("PALSUITE ERROR: CreateEvent call #0 failed. GetLastError " - "returned %u.\n", GetLastError()); - } - - /* thread 1 event */ - hToken[1] = CreateEvent(NULL, TRUE, FALSE, NULL); - - if (hToken[1] == NULL) - { - Trace("PALSUITE ERROR: CreateEvent call #1 failed. GetLastError " - "returned %u.\n", GetLastError()); - Cleanup (&hToken[0], (NUM_TOKENS - 2)); - Fail(""); - } - - InitializeCriticalSection(&CriticalSection); - - hToken[2] = CreateThread(NULL, - 0, - &Thread_CriticalSectionFunctions_test7, - (LPVOID) NULL, - 0, - &dwThreadId); - - if (hToken[2] == NULL) - { - Trace("PALSUITE ERROR: CreateThread call #0 failed. GetLastError " - "returned %u.\n", GetLastError()); - Cleanup (&hToken[0], (NUM_TOKENS - 1)); - DeleteCriticalSection(&CriticalSection); - Fail(""); - } - - /* wait for thread 0 to be signaled */ - dwMRet = WaitForSingleObject(hToken[0], 10000); - if (WAIT_OBJECT_0 != dwMRet) - { - Trace("PALSUITE ERROR: WaitForSingleObject(%p,%d) should have " - "returned\nWAIT_OBJECT_0 ('%d'), instead it returned " - "('%d').\nGetLastError returned '%u'.\n", hToken[0], 10000, - WAIT_OBJECT_0, dwMRet, GetLastError()); - Cleanup (&hToken[0], NUM_TOKENS); - Fail(""); - } - - /* signal thread 1 */ - if (0 == SetEvent(hToken[1])) - { - Trace("PALSUITE ERROR: Unable to execute SetEvent(%p) call.\n" - "GetLastError returned '%u'.\n", hToken[1], - GetLastError()); - Cleanup (&hToken[0], NUM_TOKENS); - Fail(""); - } - - dwMRet = WaitForSingleObject(hToken[2], 10000); - if (WAIT_OBJECT_0 != dwMRet) - { - Trace("PALSUITE ERROR: WaitForSingleObject(%p, %d) call " - "returned an unexpected value '%d'.\nGetLastError returned " - "%u.\n", hToken[2], 10000, dwMRet, GetLastError()); - Cleanup (&hToken[0], NUM_TOKENS); - Fail(""); - } - - if (!Cleanup(&hToken[0], NUM_TOKENS)) - { - Fail(""); - } - - PAL_Terminate(); - - return (PASS); -} - - - diff --git a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp b/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp deleted file mode 100644 index 8081b69109a9a8..00000000000000 --- a/src/coreclr/pal/tests/palsuite/threading/CriticalSectionFunctions/test8/test8.cpp +++ /dev/null @@ -1,217 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*===================================================================== -** -** Source: CriticalSectionFunctions/test8/test8.c -** -** Pyrpose: Ensure critical section functionality is working by -** having multiple threads racing on a CS under different -** scenarios -** -** -**===================================================================*/ -#include -#include - -#define MAX_THREAD_COUNT 128 -#define DEFAULT_THREAD_COUNT 10 -#define DEFAULT_LOOP_COUNT 1000 - -#ifndef MIN -#define MIN(a,b) (((a)<(b)) ? (a) : (b)) -#endif - -int g_iThreadCount = DEFAULT_THREAD_COUNT; -int g_iLoopCount = DEFAULT_LOOP_COUNT; -volatile LONG g_lCriticalCount = 0; -HANDLE g_hEvStart = NULL; - -CRITICAL_SECTION g_cs; -DWORD PALAPI Thread_CriticalSectionFunctions_test8(LPVOID lpParam) -{ - int i, j, iLpCnt; - DWORD dwRet = 0; - DWORD dwTid = GetCurrentThreadId(); - LONG lRet; - BOOL bSleepInside; - BOOL bSleepOutside; - - Trace("[tid=%u] Thread starting\n", dwTid); - - dwRet = WaitForSingleObject(g_hEvStart, INFINITE); - if (WAIT_OBJECT_0 != dwRet) - { - Fail("WaitForSingleObject returned unexpected %u [GetLastError()=%u]\n", - dwRet, GetLastError()); - } - - for (j=0;j<8;j++) - { - bSleepInside = 2 & j; - bSleepOutside = 4 & j; - - iLpCnt = g_iLoopCount; - if (bSleepInside || bSleepOutside) - { - iLpCnt /= 10; - } - - for (i=0;i= iVal) - { - g_iThreadCount = iVal; - } - } - break; - default: - break; - } - } - } - - Trace ("Iterations:\t%d\n", g_iLoopCount); - Trace ("Threads:\t%d\n", g_iThreadCount); - - g_hEvStart = CreateEvent(NULL, TRUE, FALSE, NULL); - - if (g_hEvStart == NULL) - { - Fail("CreateEvent call failed. GetLastError " - "returned %u.\n", GetLastError()); - } - - InitializeCriticalSection(&g_cs); - - for (i=0;i iThreadCount) - { - Fail("Failed to create minimum number if threads, i.e. 2\n"); - } - - if (!SetEvent(g_hEvStart)) - { - Fail("SetEvent failed [GetLastError()=%u]\n", GetLastError()); - } - - for (i=0; i const int ChildThreadSleepTime = 2000; -const int InterruptTime = 1000; +const int InterruptTime = 1000; /* We need to keep in mind that BSD has a timer resolution of 10ms, so - we need to adjust our delta to keep that in mind. Besides we need some - tolerance to account for different scheduling strategies, heavy load + we need to adjust our delta to keep that in mind. Besides we need some + tolerance to account for different scheduling strategies, heavy load scenarios, etc. - + Real-world data also tells us we can expect a big difference between values when run on real iron vs run in a hypervisor. @@ -50,15 +50,15 @@ PALTEST(threading_SleepEx_test2_paltest_sleepex_test2, "threading/SleepEx/test2/ } /* - On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects - (such as conditions) involves some pthread internal initialization that + On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects + (such as conditions) involves some pthread internal initialization that can make the first wait slighty longer, potentially going above the acceptable delta for this test. Let's add a dummy wait to preinitialize internal structures */ Sleep(100); - - /* + + /* * Check that Queueing an APC in the middle of a sleep does interrupt * it, if it's in an alertable state. */ @@ -73,12 +73,12 @@ PALTEST(threading_SleepEx_test2_paltest_sleepex_test2, "threading/SleepEx/test2/ if (dwAvgDelta > AcceptableDelta) { Fail("Expected thread to sleep for %d ms (and get interrupted).\n" - "Average delta: %u ms, acceptable delta: %u\n", + "Average delta: %u ms, acceptable delta: %u\n", InterruptTime, dwAvgDelta, AcceptableDelta); } - /* - * Check that Queueing an APC in the middle of a sleep does NOT interrupt + /* + * Check that Queueing an APC in the middle of a sleep does NOT interrupt * it, if it is not in an alertable state. */ dwAvgDelta = 0; @@ -92,7 +92,7 @@ PALTEST(threading_SleepEx_test2_paltest_sleepex_test2, "threading/SleepEx/test2/ if (dwAvgDelta > AcceptableDelta) { Fail("Expected thread to sleep for %d ms (and not be interrupted).\n" - "Average delta: %u ms, acceptable delta: %u\n", + "Average delta: %u ms, acceptable delta: %u\n", ChildThreadSleepTime, dwAvgDelta, AcceptableDelta); } @@ -108,7 +108,7 @@ void RunTest_SleepEx_test2(BOOL AlertThread) s_preWaitTimestampRecorded = false; hThread = CreateThread( NULL, - 0, + 0, (LPTHREAD_START_ROUTINE)SleeperProc_SleepEx_test2, (LPVOID) AlertThread, 0, @@ -141,7 +141,7 @@ void RunTest_SleepEx_test2(BOOL AlertThread) ret = WaitForSingleObject(hThread, INFINITE); if (ret == WAIT_FAILED) { - Fail("Unable to wait on child thread!\nGetLastError returned %d.", + Fail("Unable to wait on child thread!\nGetLastError returned %d.", GetLastError()); } } @@ -166,7 +166,7 @@ DWORD PALAPI SleeperProc_SleepEx_test2(LPVOID lpParameter) s_preWaitTimestampRecorded = true; ret = SleepEx(ChildThreadSleepTime, Alertable); - + NewTimeStamp = minipal_hires_ticks(); if (Alertable && ret != WAIT_IO_COMPLETION) diff --git a/src/coreclr/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.cpp b/src/coreclr/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.cpp index 60672669d60278..06b0c0995943a8 100644 --- a/src/coreclr/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.cpp +++ b/src/coreclr/pal/tests/palsuite/threading/WaitForMultipleObjectsEx/test2/test2.cpp @@ -55,7 +55,7 @@ PALTEST(threading_WaitForMultipleObjectsEx_test2_paltest_waitformultipleobjectse RunTest_WFMO_test2(TRUE); // Make sure that the wait returns in time greater than interrupt and less than // wait timeout - if ( + if ( ((ThreadWaitDelta_WFMO_test2 >= ChildThreadWaitTime) && (ThreadWaitDelta_WFMO_test2 - ChildThreadWaitTime) > TOLERANCE) || (( ThreadWaitDelta_WFMO_test2 < InterruptTime) && (InterruptTime - ThreadWaitDelta_WFMO_test2) > TOLERANCE) ) diff --git a/src/coreclr/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.cpp b/src/coreclr/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.cpp index a231ea769a9674..a8a24b456f6024 100644 --- a/src/coreclr/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.cpp +++ b/src/coreclr/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExMutexTest/WFSOExMutexTest.cpp @@ -5,7 +5,7 @@ ** ** Source: WFSOExMutex.c ** -** Purpose: Tests a child thread in the middle of a +** Purpose: Tests a child thread in the middle of a ** WaitForSingleObjectEx call will be interrupted by QueueUserAPC ** if the alert flag was set. ** @@ -31,31 +31,31 @@ static volatile bool s_preWaitTimestampRecorded = false; PALTEST(threading_WaitForSingleObject_WFSOExMutexTest_paltest_waitforsingleobject_wfsoexmutextest, "threading/WaitForSingleObject/WFSOExMutexTest/paltest_waitforsingleobject_wfsoexmutextest") { int ret=0; - + if (0 != (PAL_Initialize(argc, argv))) { return FAIL; } /* - On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects - (such as conditions) involves some pthread internal initialization that + On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects + (such as conditions) involves some pthread internal initialization that can make the first wait slighty longer, potentially going above the acceptable delta for this test. Let's add a dummy wait to preinitialize internal structures */ Sleep(100); - + /* - The state of a mutex object is signaled when it is not owned by any thread. - The creating thread can use the bInitialOwner flag to request immediate ownership - of the mutex. Otherwise, a thread must use one of the wait functions to request - ownership. When the mutex's state is signaled, one waiting thread is granted - ownership, the mutex's state changes to nonsignaled, and the wait function returns. - Only one thread can own a mutex at any given time. The owning thread uses the + The state of a mutex object is signaled when it is not owned by any thread. + The creating thread can use the bInitialOwner flag to request immediate ownership + of the mutex. Otherwise, a thread must use one of the wait functions to request + ownership. When the mutex's state is signaled, one waiting thread is granted + ownership, the mutex's state changes to nonsignaled, and the wait function returns. + Only one thread can own a mutex at any given time. The owning thread uses the ReleaseMutex function to release its ownership. */ - + /* Create a mutex that is not in the signalled state */ hMutex_WFSOExMutexTest = CreateMutex(NULL, //No security attributes TRUE, //Iniitally owned @@ -66,7 +66,7 @@ PALTEST(threading_WaitForSingleObject_WFSOExMutexTest_paltest_waitforsingleobjec Fail("Failed to create mutex! GetLastError returned %d.\n", GetLastError()); } - /* + /* * Check that Queueing an APC in the middle of a wait does interrupt * it, if it's in an alertable state. */ @@ -75,25 +75,25 @@ PALTEST(threading_WaitForSingleObject_WFSOExMutexTest_paltest_waitforsingleobjec if ((ThreadWaitDelta_WFSOExMutexTest - InterruptTime) > AcceptableDelta) { Fail("Expected thread to wait for %d ms (and get interrupted).\n" - "Thread waited for %d ms! (Acceptable delta: %d)\n", + "Thread waited for %d ms! (Acceptable delta: %d)\n", InterruptTime, ThreadWaitDelta_WFSOExMutexTest, AcceptableDelta); } - /* - * Check that Queueing an APC in the middle of a wait does NOT interrupt + /* + * Check that Queueing an APC in the middle of a wait does NOT interrupt * it, if it is not in an alertable state. */ RunTest_WFSOExMutexTest(FALSE); if ((ThreadWaitDelta_WFSOExMutexTest - ChildThreadWaitTime) > AcceptableDelta) { Fail("Expected thread to wait for %d ms (and not be interrupted).\n" - "Thread waited for %d ms! (Acceptable delta: %d)\n", + "Thread waited for %d ms! (Acceptable delta: %d)\n", ChildThreadWaitTime, ThreadWaitDelta_WFSOExMutexTest, AcceptableDelta); } - + //Release Mutex ret = ReleaseMutex(hMutex_WFSOExMutexTest); if (0==ret) @@ -109,14 +109,14 @@ PALTEST(threading_WaitForSingleObject_WFSOExMutexTest_paltest_waitforsingleobjec Fail("Unable to close handle to Mutex!\n" "GetLastError returned %d\n", GetLastError()); } - + PAL_Terminate(); return PASS; } void RunTest_WFSOExMutexTest(BOOL AlertThread) { - + HANDLE hThread = 0; DWORD dwThreadId = 0; @@ -124,7 +124,7 @@ void RunTest_WFSOExMutexTest(BOOL AlertThread) s_preWaitTimestampRecorded = false; hThread = CreateThread( NULL, - 0, + 0, (LPTHREAD_START_ROUTINE)WaiterProc_WFSOExMutexTest, (LPVOID) AlertThread, 0, @@ -146,32 +146,32 @@ void RunTest_WFSOExMutexTest(BOOL AlertThread) Sleep(InterruptTime); ret = QueueUserAPC(APCFunc_WFSOExMutexTest, hThread, 0); - + if (ret == 0) { - Fail("QueueUserAPC failed! GetLastError returned %d\n", + Fail("QueueUserAPC failed! GetLastError returned %d\n", GetLastError()); } - + ret = WaitForSingleObject(hThread, INFINITE); - + if (ret == WAIT_FAILED) { - Fail("Unable to wait on child thread!\nGetLastError returned %d.\n", + Fail("Unable to wait on child thread!\nGetLastError returned %d.\n", GetLastError()); } - + if (0==CloseHandle(hThread)) { - Trace("Could not close Thread handle\n"); - Fail ( "GetLastError returned %d\n", GetLastError()); - } + Trace("Could not close Thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } } /* Function doesn't do anything, just needed to interrupt the wait*/ VOID PALAPI APCFunc_WFSOExMutexTest(ULONG_PTR dwParam) -{ +{ } /* Entry Point for child thread. */ @@ -187,10 +187,10 @@ DWORD PALAPI WaiterProc_WFSOExMutexTest(LPVOID lpParameter) OldTimeStamp = minipal_hires_ticks(); s_preWaitTimestampRecorded = true; - ret = WaitForSingleObjectEx( hMutex_WFSOExMutexTest, - ChildThreadWaitTime, + ret = WaitForSingleObjectEx( hMutex_WFSOExMutexTest, + ChildThreadWaitTime, Alertable); - + NewTimeStamp = minipal_hires_ticks(); if (Alertable && ret != WAIT_IO_COMPLETION) @@ -204,8 +204,8 @@ DWORD PALAPI WaiterProc_WFSOExMutexTest(LPVOID lpParameter) "Expected return of WAIT_TIMEOUT, got %d.\n", ret); } - ThreadWaitDelta_WFSOExMutexTest = (NewTimeStamp - OldTimeStamp) / (minipal_hires_tick_frequency() / 1000);; - + ThreadWaitDelta_WFSOExMutexTest = NewTimeStamp - OldTimeStamp; + return 0; } diff --git a/src/coreclr/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.cpp b/src/coreclr/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.cpp index f659c5fdb459cb..8bce543098da3b 100644 --- a/src/coreclr/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.cpp +++ b/src/coreclr/pal/tests/palsuite/threading/WaitForSingleObject/WFSOExThreadTest/WFSOExThreadTest.cpp @@ -5,7 +5,7 @@ ** ** Source: WFSOExThreadTest.c ** -** Purpose: Tests a child thread in the middle of a +** Purpose: Tests a child thread in the middle of a ** WaitForSingleObjectEx call will be interrupted by QueueUserAPC ** if the alert flag was set. ** @@ -17,7 +17,7 @@ /*Based on SleepEx/test2 */ const int ChildThreadWaitTime = 4000; -const int InterruptTime = 2000; +const int InterruptTime = 2000; const DWORD AcceptableDelta = 300; void RunTest_WFSOExThreadTest(BOOL AlertThread); @@ -36,15 +36,15 @@ PALTEST(threading_WaitForSingleObject_WFSOExThreadTest_paltest_waitforsingleobje } /* - On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects - (such as conditions) involves some pthread internal initialization that + On some platforms (e.g. FreeBSD 4.9) the first call to some synch objects + (such as conditions) involves some pthread internal initialization that can make the first wait slighty longer, potentially going above the acceptable delta for this test. Let's add a dummy wait to preinitialize internal structures */ Sleep(100); - /* + /* * Check that Queueing an APC in the middle of a wait does interrupt * it, if it's in an alertable state. */ @@ -53,20 +53,20 @@ PALTEST(threading_WaitForSingleObject_WFSOExThreadTest_paltest_waitforsingleobje if (abs(ThreadWaitDelta_WFSOExThreadTest - InterruptTime) > AcceptableDelta) { Fail("Expected thread to wait for %d ms (and get interrupted).\n" - "Thread waited for %d ms! (Acceptable delta: %d)\n", + "Thread waited for %d ms! (Acceptable delta: %d)\n", InterruptTime, ThreadWaitDelta_WFSOExThreadTest, AcceptableDelta); } - /* - * Check that Queueing an APC in the middle of a wait does NOT interrupt + /* + * Check that Queueing an APC in the middle of a wait does NOT interrupt * it, if it is not in an alertable state. */ RunTest_WFSOExThreadTest(FALSE); if (abs(ThreadWaitDelta_WFSOExThreadTest - ChildThreadWaitTime) > AcceptableDelta) { Fail("Expected thread to wait for %d ms (and not be interrupted).\n" - "Thread waited for %d ms! (Acceptable delta: %d)\n", + "Thread waited for %d ms! (Acceptable delta: %d)\n", ChildThreadWaitTime, ThreadWaitDelta_WFSOExThreadTest, AcceptableDelta); } @@ -81,10 +81,10 @@ void RunTest_WFSOExThreadTest(BOOL AlertThread) DWORD dwThreadId = 0; int ret; - //Create thread + //Create thread s_preWaitTimestampRecorded = false; hThread = CreateThread( NULL, - 0, + 0, (LPTHREAD_START_ROUTINE)WaiterProc_WFSOExThreadTest, (LPVOID) AlertThread, 0, @@ -108,28 +108,28 @@ void RunTest_WFSOExThreadTest(BOOL AlertThread) ret = QueueUserAPC(APCFunc_WFSOExThreadTest, hThread, 0); if (ret == 0) { - Fail("QueueUserAPC failed! GetLastError returned %d\n", + Fail("QueueUserAPC failed! GetLastError returned %d\n", GetLastError()); } - + ret = WaitForSingleObject(hThread, INFINITE); if (ret == WAIT_FAILED) { - Fail("Unable to wait on child thread!\nGetLastError returned %d.\n", + Fail("Unable to wait on child thread!\nGetLastError returned %d.\n", GetLastError()); } if (0==CloseHandle(hThread)) { - Trace("Could not close Thread handle\n"); - Fail ( "GetLastError returned %d\n", GetLastError()); - } + Trace("Could not close Thread handle\n"); + Fail ( "GetLastError returned %d\n", GetLastError()); + } } /* Function doesn't do anything, just needed to interrupt the wait*/ VOID PALAPI APCFunc_WFSOExThreadTest(ULONG_PTR dwParam) -{ +{ } /* Entry Point for child thread. */ @@ -143,13 +143,13 @@ DWORD PALAPI WaiterProc_WFSOExThreadTest(LPVOID lpParameter) DWORD dwThreadId = 0; /* -When a thread terminates, the thread object attains a signaled state, +When a thread terminates, the thread object attains a signaled state, satisfying any threads that were waiting on the object. */ /* Create a thread that does not return immediately to maintain a non signaled test*/ - hWaitThread = CreateThread( NULL, - 0, + hWaitThread = CreateThread( NULL, + 0, (LPTHREAD_START_ROUTINE)WorkerThread_WFSOExThreadTest, NULL, 0, @@ -166,10 +166,10 @@ satisfying any threads that were waiting on the object. OldTimeStamp = minipal_hires_ticks(); s_preWaitTimestampRecorded = true; - ret = WaitForSingleObjectEx( hWaitThread, - ChildThreadWaitTime, + ret = WaitForSingleObjectEx( hWaitThread, + ChildThreadWaitTime, Alertable); - + NewTimeStamp = minipal_hires_ticks(); @@ -199,7 +199,7 @@ satisfying any threads that were waiting on the object. void WorkerThread_WFSOExThreadTest(void) { - + //Make the worker thread sleep to test WFSOEx Functionality Sleep(2*ChildThreadWaitTime); diff --git a/src/coreclr/pal/tests/palsuite/wasm/index.html b/src/coreclr/pal/tests/palsuite/wasm/index.html index 28dd69524bb356..f1cd117d4bbd73 100644 --- a/src/coreclr/pal/tests/palsuite/wasm/index.html +++ b/src/coreclr/pal/tests/palsuite/wasm/index.html @@ -20,7 +20,6 @@

PAL Tests WASM

"miscellaneous/InterlockedDecrement/test2/paltest_interlockeddecrement_test2", // MT test "miscellaneous/InterlockedIncrement/test2/paltest_interlockedincrement_test2", // MT test "threading/", // we're single-threaded - // "threading/CriticalSectionFunctions/test8/paltest_criticalsectionfunctions_test8", // blocks main thread ]; const nextRunDelay = 50, reloadDelay = 50; diff --git a/src/coreclr/runtime/CachedInterfaceDispatch.cpp b/src/coreclr/runtime/CachedInterfaceDispatch.cpp index 323210dd7e587d..3f0c479f24df25 100644 --- a/src/coreclr/runtime/CachedInterfaceDispatch.cpp +++ b/src/coreclr/runtime/CachedInterfaceDispatch.cpp @@ -7,6 +7,8 @@ // // ============================================================================ #include "common.h" +#include + #ifdef FEATURE_CACHED_INTERFACE_DISPATCH #include "CachedInterfaceDispatchPal.h" #include "CachedInterfaceDispatch.h" diff --git a/src/coreclr/tools/superpmi/superpmi-shared/logging.cpp b/src/coreclr/tools/superpmi/superpmi-shared/logging.cpp index e72e9b130275e3..63b2c5ee4a1121 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/logging.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/logging.cpp @@ -20,7 +20,7 @@ bool Logger::s_initialized = false; UINT32 Logger::s_logLevel = LOGMASK_DEFAULT; HANDLE Logger::s_logFile = INVALID_HANDLE_VALUE; char* Logger::s_logFilePath = nullptr; -CRITICAL_SECTION Logger::s_critSec; +minipal_mutex Logger::s_critSec; // // Initializes the logging subsystem. This must be called before invoking any of the logging functionality. @@ -30,7 +30,7 @@ void Logger::Initialize() { if (!s_initialized) { - InitializeCriticalSection(&s_critSec); + minipal_mutex_init(&s_critSec); s_initialized = true; } } @@ -43,7 +43,7 @@ void Logger::Shutdown() { if (s_initialized) { - DeleteCriticalSection(&s_critSec); + minipal_mutex_destroy(&s_critSec); CloseLogFile(); s_initialized = false; } @@ -244,7 +244,7 @@ void Logger::LogVprintf( // maintaining chronological order is crucial, then we can implement a priority queueing system // for log messages. - EnterCriticalSection(&s_critSec); + minipal_mutex_enter(&s_critSec); if (level < LOGLEVEL_INFO) fprintf(dest, "%s: ", logLevelStr); @@ -305,7 +305,7 @@ void Logger::LogVprintf( CleanUp: #endif // !TARGET_UNIX - LeaveCriticalSection(&s_critSec); + minipal_mutex_leave(&s_critSec); delete[] fullMsg; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/logging.h b/src/coreclr/tools/superpmi/superpmi-shared/logging.h index 15d7d097fcb5b7..f7af0132630284 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/logging.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/logging.h @@ -7,6 +7,8 @@ #ifndef _Logging #define _Logging +#include + // // General purpose logging macros // @@ -65,7 +67,7 @@ class Logger static UINT32 s_logLevel; static HANDLE s_logFile; static char* s_logFilePath; - static CRITICAL_SECTION s_critSec; + static minipal_mutex s_critSec; public: static void Initialize(); diff --git a/src/coreclr/utilcode/hostimpl.cpp b/src/coreclr/utilcode/hostimpl.cpp index 4ba20554c824c8..e463af9f705a08 100644 --- a/src/coreclr/utilcode/hostimpl.cpp +++ b/src/coreclr/utilcode/hostimpl.cpp @@ -3,6 +3,8 @@ #include "stdafx.h" +#include + #include "mscoree.h" #include "clrinternal.h" #include "clrhost.h" @@ -12,28 +14,28 @@ thread_local size_t t_ThreadType; CRITSEC_COOKIE ClrCreateCriticalSection(CrstType crstType, CrstFlags flags) { - CRITICAL_SECTION *cs = (CRITICAL_SECTION*)malloc(sizeof(CRITICAL_SECTION)); - InitializeCriticalSection(cs); - return (CRITSEC_COOKIE)cs; + minipal_mutex* mt = (minipal_mutex*)malloc(sizeof(minipal_mutex)); + minipal_mutex_init(mt); + return (CRITSEC_COOKIE)mt; } void ClrDeleteCriticalSection(CRITSEC_COOKIE cookie) { _ASSERTE(cookie); - DeleteCriticalSection((CRITICAL_SECTION*)cookie); + minipal_mutex_destroy((minipal_mutex*)cookie); free(cookie); } void ClrEnterCriticalSection(CRITSEC_COOKIE cookie) { _ASSERTE(cookie); - EnterCriticalSection((CRITICAL_SECTION*)cookie); + minipal_mutex_enter((minipal_mutex*)cookie); } void ClrLeaveCriticalSection(CRITSEC_COOKIE cookie) { _ASSERTE(cookie); - LeaveCriticalSection((CRITICAL_SECTION*)cookie); + minipal_mutex_leave((minipal_mutex*)cookie); } DWORD ClrSleepEx(DWORD dwMilliseconds, BOOL bAlertable) diff --git a/src/coreclr/vm/crst.cpp b/src/coreclr/vm/crst.cpp index c313a710517e4d..37cb9904986113 100644 --- a/src/coreclr/vm/crst.cpp +++ b/src/coreclr/vm/crst.cpp @@ -21,19 +21,6 @@ #include #undef __IN_CRST_CPP -#if defined(DACCESS_COMPILE) && defined(TARGET_UNIX) && !defined(CROSS_COMPILE) - // Validate the DAC T_CRITICAL_SECTION matches the runtime CRITICAL section when we are not cross compiling. - // This is important when we are cross OS compiling the DAC - static_assert(PAL_CS_NATIVE_DATA_SIZE == DAC_CS_NATIVE_DATA_SIZE, T_CRITICAL_SECTION_VALIDATION_MESSAGE); - static_assert(sizeof(CRITICAL_SECTION) == sizeof(T_CRITICAL_SECTION), T_CRITICAL_SECTION_VALIDATION_MESSAGE); - - static_assert(offsetof(CRITICAL_SECTION, DebugInfo) == offsetof(T_CRITICAL_SECTION, DebugInfo), T_CRITICAL_SECTION_VALIDATION_MESSAGE); - static_assert(offsetof(CRITICAL_SECTION, LockCount) == offsetof(T_CRITICAL_SECTION, LockCount), T_CRITICAL_SECTION_VALIDATION_MESSAGE); - static_assert(offsetof(CRITICAL_SECTION, RecursionCount) == offsetof(T_CRITICAL_SECTION, RecursionCount), T_CRITICAL_SECTION_VALIDATION_MESSAGE); - static_assert(offsetof(CRITICAL_SECTION, OwningThread) == offsetof(T_CRITICAL_SECTION, OwningThread), T_CRITICAL_SECTION_VALIDATION_MESSAGE); - static_assert(offsetof(CRITICAL_SECTION, SpinCount) == offsetof(T_CRITICAL_SECTION, SpinCount), T_CRITICAL_SECTION_VALIDATION_MESSAGE); -#endif // defined(DACCESS_COMPILE) && defined(TARGET_UNIX) && !defined(CROSS_COMPILE) - #ifndef DACCESS_COMPILE Volatile g_ShutdownCrstUsageCount = 0; @@ -49,13 +36,8 @@ VOID CrstBase::InitWorker(INDEBUG_COMMA(CrstType crstType) CrstFlags flags) _ASSERTE((flags & CRST_INITIALIZED) == 0); - { - SetOSCritSec (); - } - - { - InitializeCriticalSection(&m_criticalsection); - } + bool suc = minipal_mutex_init(&m_lock._mtx); + _ASSERTE(suc); SetFlags(flags); SetCrstInitialized(); @@ -88,9 +70,7 @@ void CrstBase::Destroy() // deadlock detection is finished. GCPreemp __gcHolder((m_dwFlags & CRST_HOST_BREAKABLE) == CRST_HOST_BREAKABLE); - { - DeleteCriticalSection(&m_criticalsection); - } + minipal_mutex_destroy(&m_lock._mtx); LOG((LF_SYNC, INFO3, "CrstBase::Destroy %p\n", this)); #ifdef _DEBUG @@ -280,9 +260,6 @@ void CrstBase::Enter(INDEBUG(NoLevelCheckFlag noLevelCheckFlag/* = CRST_LEVEL_CH _ASSERTE(IsCrstInitialized()); - // Is Critical Section entered? - // We could have perhaps used m_criticalsection.LockCount, but - // while spinning, we want to fire the ETW event only once BOOL fIsCriticalSectionEnteredAfterFailingOnce = FALSE; Thread * pThread; @@ -319,7 +296,7 @@ void CrstBase::Enter(INDEBUG(NoLevelCheckFlag noLevelCheckFlag/* = CRST_LEVEL_CH } } - EnterCriticalSection(&m_criticalsection); + minipal_mutex_enter(&m_lock._mtx); #ifdef _DEBUG PostEnter(); @@ -350,7 +327,7 @@ void CrstBase::Leave() Thread * pThread = GetThreadNULLOk(); #endif - LeaveCriticalSection(&m_criticalsection); + minipal_mutex_leave(&m_lock._mtx); // Check for both rare case using one if-check if (m_dwFlags & (CRST_TAKEN_DURING_SHUTDOWN | CRST_DEBUGGER_THREAD)) @@ -608,7 +585,6 @@ void CrstBase::DebugInit(CrstType crstType, CrstFlags flags) CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD | CRST_HOST_BREAKABLE | - CRST_OS_CRIT_SEC | CRST_INITIALIZED | CRST_TAKEN_DURING_SHUTDOWN | CRST_GC_NOTRIGGER_WHEN_TAKEN | @@ -667,7 +643,7 @@ void CrstBase::DebugDestroy() "this=0x%p, m_prev=0x%p. m_next=0x%p", m_tag, this, this->m_prev, this->m_next)); } - FillMemory(&m_criticalsection, sizeof(m_criticalsection), 0xcc); + FillMemory(&m_lock, sizeof(m_lock), 0xcc); m_holderthreadid.Clear(); m_entercount = 0xcccccccc; diff --git a/src/coreclr/vm/crst.h b/src/coreclr/vm/crst.h index 65769569c4bea3..8f66534fa291f4 100644 --- a/src/coreclr/vm/crst.h +++ b/src/coreclr/vm/crst.h @@ -87,6 +87,7 @@ #include "util.hpp" #include "debugmacros.h" #include "log.h" +#include #define ShutDown_Start 0x00000001 #define ShutDown_Finalize1 0x00000002 @@ -103,28 +104,28 @@ extern Volatile g_ShutdownCrstUsageCount; // The CRST. class CrstBase { -// The following classes and methods violate the requirement that Crst usage be -// exception-safe, or they satisfy that requirement using techniques other than -// Holder objects: -friend class Thread; -friend class ThreadStore; -friend class ThreadSuspend; -template -friend class ListLockBase; -template -friend class ListLockEntryBase; -friend struct SavedExceptionInfo; -friend void ClrEnterCriticalSection(CRITSEC_COOKIE cookie); -friend void ClrLeaveCriticalSection(CRITSEC_COOKIE cookie); -friend class CodeVersionManager; - -friend class Debugger; -friend class Crst; + // The following classes and methods violate the requirement that Crst usage be + // exception-safe, or they satisfy that requirement using techniques other than + // Holder objects: + friend class Thread; + friend class ThreadStore; + friend class ThreadSuspend; + template + friend class ListLockBase; + template + friend class ListLockEntryBase; + friend struct SavedExceptionInfo; + friend void ClrEnterCriticalSection(CRITSEC_COOKIE cookie); + friend void ClrLeaveCriticalSection(CRITSEC_COOKIE cookie); + friend class CodeVersionManager; + + friend class Debugger; + friend class Crst; #ifdef FEATURE_DBGIPC_TRANSPORT_VM // The debugger transport code uses a holder for its Crst, but it needs to share the holder implementation // with its right side code as well (which can't see the Crst implementation and actually uses a - // CRITICAL_SECTION as the base lock). So make DbgTransportSession a friend here so we can use Enter() and + // minipal_mutex as the base lock). So make DbgTransportSession a friend here so we can use Enter() and // Leave() in order to build a shared holder class. friend class DbgTransportLock; #endif // FEATURE_DBGIPC_TRANSPORT_VM @@ -282,16 +283,14 @@ friend class Crst; void DebugDestroy(); #endif - T_CRITICAL_SECTION m_criticalsection; + tgt_minipal_mutex m_lock; typedef enum { // Mask to indicate reserved flags - CRST_RESERVED_FLAGS_MASK = 0xC0000000, + CRST_RESERVED_FLAGS_MASK = 0x80000000, // private flag to indicate initialized Crsts - CRST_INITIALIZED = 0x80000000, - // private flag to indicate Crst is OS Critical Section - CRST_OS_CRIT_SEC = 0x40000000, + CRST_INITIALIZED = 0x80000000 // rest of the flags are CrstFlags } CrstReservedFlags; DWORD m_dwFlags; // Re-entrancy and same level @@ -314,19 +313,6 @@ friend class Crst; #endif //_DEBUG private: - - void SetOSCritSec () - { - m_dwFlags |= CRST_OS_CRIT_SEC; - } - void ResetOSCritSec () - { - m_dwFlags &= ~CRST_OS_CRIT_SEC; - } - BOOL IsOSCritSec () - { - return m_dwFlags & CRST_OS_CRIT_SEC; - } void SetCrstInitialized() { m_dwFlags |= CRST_INITIALIZED; diff --git a/src/coreclr/vm/threads.cpp b/src/coreclr/vm/threads.cpp index b3ad5b35b47960..b86922e7fec1c5 100644 --- a/src/coreclr/vm/threads.cpp +++ b/src/coreclr/vm/threads.cpp @@ -4979,15 +4979,6 @@ void ThreadStore::AddThread(Thread *newThread) _ASSERTE(!newThread->IsDead()); } -// this function is just desgined to avoid deadlocks during abnormal process termination, and should not be used for any other purpose -BOOL ThreadStore::CanAcquireLock() -{ - WRAPPER_NO_CONTRACT; - { - return (s_pThreadStore->m_Crst.m_criticalsection.LockCount == -1 || (size_t)s_pThreadStore->m_Crst.m_criticalsection.OwningThread == (size_t)GetCurrentThreadId()); - } -} - // Whenever one of the components of OtherThreadsComplete() has changed in the // correct direction, see whether we can now shutdown the EE because only background // threads are running. diff --git a/src/coreclr/vm/threads.h b/src/coreclr/vm/threads.h index aebee5e6a0739c..531a5c6ae683bd 100644 --- a/src/coreclr/vm/threads.h +++ b/src/coreclr/vm/threads.h @@ -4068,8 +4068,6 @@ class ThreadStore // RemoveThread finds the thread in the ThreadStore and discards it. static BOOL RemoveThread(Thread *target); - static BOOL CanAcquireLock(); - // Transfer a thread from the unstarted to the started list. static void TransferStartedThread(Thread *target); diff --git a/src/native/minipal/CMakeLists.txt b/src/native/minipal/CMakeLists.txt index f27ad0d5fea50e..78011d4779694a 100644 --- a/src/native/minipal/CMakeLists.txt +++ b/src/native/minipal/CMakeLists.txt @@ -2,6 +2,7 @@ include(configure.cmake) set(SOURCES cpufeatures.c + mutex.c guid.c random.c debugger.c diff --git a/src/native/minipal/mutex.c b/src/native/minipal/mutex.c new file mode 100644 index 00000000000000..8d34ca95f5a9ae --- /dev/null +++ b/src/native/minipal/mutex.c @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include +#include +#include "mutex.h" + +bool minipal_mutex_init(minipal_mutex* mtx) +{ + assert(mtx != NULL); +#ifdef HOST_WINDOWS + InitializeCriticalSection(&mtx->_impl); + return true; +#else + pthread_mutexattr_t mutexAttributes; + int st = pthread_mutexattr_init(&mutexAttributes); + if (st != 0) + return false; + + st = pthread_mutexattr_settype(&mutexAttributes, PTHREAD_MUTEX_RECURSIVE); + if (st == 0) + st = pthread_mutex_init(&mtx->_impl, &mutexAttributes); + + pthread_mutexattr_destroy(&mutexAttributes); + + return (st == 0); +#endif // HOST_WINDOWS +} + +void minipal_mutex_destroy(minipal_mutex* mtx) +{ + assert(mtx != NULL); +#ifdef HOST_WINDOWS + DeleteCriticalSection(&mtx->_impl); +#else + int st = pthread_mutex_destroy(&mtx->_impl); + assert(st == 0); + (void)st; +#endif // HOST_WINDOWS + +#ifdef _DEBUG + memset(mtx, 0, sizeof(*mtx)); +#endif // _DEBUG +} + +void minipal_mutex_enter(minipal_mutex* mtx) +{ + assert(mtx != NULL); +#ifdef HOST_WINDOWS + EnterCriticalSection(&mtx->_impl); +#else + int st = pthread_mutex_lock(&mtx->_impl); + assert(st == 0); + (void)st; +#endif // HOST_WINDOWS +} + +void minipal_mutex_leave(minipal_mutex* mtx) +{ + assert(mtx != NULL); +#ifdef HOST_WINDOWS + LeaveCriticalSection(&mtx->_impl); +#else + int st = pthread_mutex_unlock(&mtx->_impl); + assert(st == 0); + (void)st; +#endif // HOST_WINDOWS +} diff --git a/src/native/minipal/mutex.h b/src/native/minipal/mutex.h new file mode 100644 index 00000000000000..df94bac6f1bd33 --- /dev/null +++ b/src/native/minipal/mutex.h @@ -0,0 +1,72 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifndef HAVE_MINIPAL_MUTEX_H +#define HAVE_MINIPAL_MUTEX_H + +#include + +#ifdef HOST_WINDOWS +#include +typedef CRITICAL_SECTION MINIPAL_MUTEX_IMPL; +#else // !HOST_WINDOWS +#include +typedef pthread_mutex_t MINIPAL_MUTEX_IMPL; +#endif // HOST_WINDOWS + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +typedef struct _minipal_mutex +{ + MINIPAL_MUTEX_IMPL _impl; +} minipal_mutex; + +// Initialize the mutex. +bool minipal_mutex_init(minipal_mutex* mt); + +// Destroy the mutex. +void minipal_mutex_destroy(minipal_mutex* mt); + +// Enter the mutex. Blocks until the mutex can be entered. +// Recursive enters are allowed. +void minipal_mutex_enter(minipal_mutex* mt); + +// Leave the mutex. +void minipal_mutex_leave(minipal_mutex* mt); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#ifdef __cplusplus +namespace minipal +{ + class MutexHolder final + { + minipal_mutex& _mtx; + + public: + explicit MutexHolder(minipal_mutex& mtx) + : _mtx{ mtx } + { + minipal_mutex_enter(&_mtx); + } + + ~MutexHolder() noexcept + { + minipal_mutex_leave(&_mtx); + } + + MutexHolder(MutexHolder const&) = delete; + MutexHolder& operator=(MutexHolder const&) = delete; + + MutexHolder(MutexHolder&&) = delete; + MutexHolder& operator=(MutexHolder&&) = delete; + }; +} +#endif // __cplusplus + +#endif // HAVE_MINIPAL_MUTEX_H