diff --git a/eng/native/tryrun.browser.cmake b/eng/native/tryrun.browser.cmake index 87425dc4d7eee7..71b3f48baad1d1 100644 --- a/eng/native/tryrun.browser.cmake +++ b/eng/native/tryrun.browser.cmake @@ -101,9 +101,6 @@ set(COMPILER_SUPPORTS_F_ALIGNED_NEW 1 CACHE INTERNAL "") set(COMPILER_SUPPORTS_W_IMPLICIT_FALLTHROUGH 1 CACHE INTERNAL "") set(COMPILER_SUPPORTS_W_PRE_C11_COMPAT 1 CACHE INTERNAL "") set(COMPILER_SUPPORTS_W_RESERVED_IDENTIFIER 1 CACHE INTERNAL "") -set(HAS_POSIX_SEMAPHORES_COMPILED TRUE CACHE INTERNAL "") -set_cache_value(HAS_POSIX_SEMAPHORES_EXITCODE 0) -set(HAS_POSIX_SEMAPHORES 1 CACHE INTERNAL "") set(HAS_PTHREAD_MUTEXES 1 CACHE INTERNAL "") set(HAS_SYSV_SEMAPHORES "" CACHE INTERNAL "") set(HAVE___GREGSET_T "" CACHE INTERNAL "") @@ -381,13 +378,7 @@ set(HAVE_YIELD_SYSCALL "" CACHE INTERNAL "") set(ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS_COMPILED TRUE CACHE INTERNAL "") set_cache_value(ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS_EXITCODE 1) set(ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS "" CACHE INTERNAL "") -set(PTHREAD_CREATE_MODIFIES_ERRNO_COMPILED TRUE CACHE INTERNAL "") -set_cache_value(PTHREAD_CREATE_MODIFIES_ERRNO_EXITCODE 1) -set(PTHREAD_CREATE_MODIFIES_ERRNO "" CACHE INTERNAL "") set(PTHREAD_RWLOCK_T 32 CACHE INTERNAL "") set(REALPATH_SUPPORTS_NONEXISTENT_FILES_COMPILED TRUE CACHE INTERNAL "") set_cache_value(REALPATH_SUPPORTS_NONEXISTENT_FILES_EXITCODE 1) set(REALPATH_SUPPORTS_NONEXISTENT_FILES "" CACHE INTERNAL "") -set(SEM_INIT_MODIFIES_ERRNO_COMPILED TRUE CACHE INTERNAL "") -set_cache_value(SEM_INIT_MODIFIES_ERRNO_EXITCODE 1) -set(SEM_INIT_MODIFIES_ERRNO "" CACHE INTERNAL "") diff --git a/eng/native/tryrun.cmake b/eng/native/tryrun.cmake index 4f84aa93668096..32ce86cc0fae94 100644 --- a/eng/native/tryrun.cmake +++ b/eng/native/tryrun.cmake @@ -51,7 +51,6 @@ endif() if(DARWIN AND NOT DEFINED ANDROID_BUILD) if(TARGET_ARCH_NAME MATCHES "^(arm64|x64)$") - set_cache_value(HAS_POSIX_SEMAPHORES_EXITCODE 1) set_cache_value(HAVE_BROKEN_FIFO_KEVENT_EXITCODE 1) set_cache_value(HAVE_BROKEN_FIFO_SELECT_EXITCODE 1) set_cache_value(HAVE_CLOCK_MONOTONIC_COARSE_EXITCODE 1) @@ -69,15 +68,12 @@ if(DARWIN AND NOT DEFINED ANDROID_BUILD) set_cache_value(HAVE_WORKING_GETTIMEOFDAY_EXITCODE 0) set_cache_value(MMAP_ANON_IGNORES_PROTECTION_EXITCODE 1) set_cache_value(ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS_EXITCODE 1) - set_cache_value(PTHREAD_CREATE_MODIFIES_ERRNO_EXITCODE 1) set_cache_value(REALPATH_SUPPORTS_NONEXISTENT_FILES_EXITCODE 1) - set_cache_value(SEM_INIT_MODIFIES_ERRNO_EXITCODE 1) set_cache_value(HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP_EXITCODE 1) else() message(FATAL_ERROR "Arch is ${TARGET_ARCH_NAME}. Only arm64 or x64 is supported for OSX cross build!") endif() else() - set_cache_value(HAS_POSIX_SEMAPHORES_EXITCODE 0) set_cache_value(HAVE_CLOCK_MONOTONIC_COARSE_EXITCODE 0) set_cache_value(HAVE_CLOCK_MONOTONIC_EXITCODE 0) set_cache_value(HAVE_CLOCK_REALTIME_EXITCODE 0) @@ -91,10 +87,7 @@ else() set_cache_value(HAVE_WORKING_CLOCK_GETTIME_EXITCODE 0) set_cache_value(HAVE_WORKING_GETTIMEOFDAY_EXITCODE 0) set_cache_value(ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS_EXITCODE 1) - set_cache_value(PTHREAD_CREATE_MODIFIES_ERRNO_EXITCODE 1) set_cache_value(REALPATH_SUPPORTS_NONEXISTENT_FILES_EXITCODE 1) - set_cache_value(SEM_INIT_MODIFIES_ERRNO_EXITCODE 1) - if(ALPINE_LINUX) set_cache_value(HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP_EXITCODE 1) else() diff --git a/eng/native/tryrun_ios_tvos.cmake b/eng/native/tryrun_ios_tvos.cmake index 8dfecf22e12e69..7b98f6dcd055ef 100644 --- a/eng/native/tryrun_ios_tvos.cmake +++ b/eng/native/tryrun_ios_tvos.cmake @@ -10,7 +10,6 @@ set_cache_value(HAVE_CLOCK_MONOTONIC_EXITCODE 0) # TODO: these are taken from macOS, check these whether they're correct for iOS # some of them are probably not used by what we use from NativeAOT so could be reduced -set_cache_value(HAS_POSIX_SEMAPHORES_EXITCODE 1) set_cache_value(HAVE_BROKEN_FIFO_KEVENT_EXITCODE 1) set_cache_value(HAVE_BROKEN_FIFO_SELECT_EXITCODE 1) set_cache_value(HAVE_CLOCK_REALTIME_EXITCODE 0) @@ -25,7 +24,5 @@ set_cache_value(HAVE_WORKING_CLOCK_GETTIME_EXITCODE 0) set_cache_value(HAVE_WORKING_GETTIMEOFDAY_EXITCODE 0) set_cache_value(MMAP_ANON_IGNORES_PROTECTION_EXITCODE 1) set_cache_value(ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS_EXITCODE 1) -set_cache_value(PTHREAD_CREATE_MODIFIES_ERRNO_EXITCODE 1) set_cache_value(REALPATH_SUPPORTS_NONEXISTENT_FILES_EXITCODE 1) -set_cache_value(SEM_INIT_MODIFIES_ERRNO_EXITCODE 1) set_cache_value(HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP_EXITCODE 1) diff --git a/src/coreclr/pal/src/config.h.in b/src/coreclr/pal/src/config.h.in index 3338faf883ce30..49795de0a3dc41 100644 --- a/src/coreclr/pal/src/config.h.in +++ b/src/coreclr/pal/src/config.h.in @@ -90,17 +90,13 @@ #cmakedefine01 HAVE_PTHREAD_CONDATTR_SETCLOCK #cmakedefine01 MMAP_ANON_IGNORES_PROTECTION #cmakedefine01 ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS -#cmakedefine01 PTHREAD_CREATE_MODIFIES_ERRNO -#cmakedefine01 SEM_INIT_MODIFIES_ERRNO #cmakedefine01 HAVE_PROCFS_CTL #cmakedefine01 HAVE_PROCFS_STAT -#cmakedefine01 HAS_POSIX_SEMAPHORES #define PAL_THREAD_PRIORITY_MIN 0 #define PAL_THREAD_PRIORITY_MAX 0 #cmakedefine01 HAVE__NSGETENVIRON -#cmakedefine01 DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX #cmakedefine PAL_PTRACE(cmd, pid, addr, data) @PAL_PTRACE@ #cmakedefine01 SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING #cmakedefine01 ERROR_FUNC_FOR_GLOB_HAS_FIXED_PARAMS diff --git a/src/coreclr/pal/src/configure.cmake b/src/coreclr/pal/src/configure.cmake index c5814814ff446e..3bae23f79ac427 100644 --- a/src/coreclr/pal/src/configure.cmake +++ b/src/coreclr/pal/src/configure.cmake @@ -497,52 +497,6 @@ int main(void) exit(ret != 1); }" ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS) -set(CMAKE_REQUIRED_LIBRARIES pthread) -check_cxx_source_runs(" -#include -#include -#include - -void *start_routine(void *param) { return NULL; } - -int main() { - int result; - pthread_t tid; - - errno = 0; - result = pthread_create(&tid, NULL, start_routine, NULL); - if (result != 0) { - exit(1); - } - if (errno != 0) { - exit(0); - } - exit(1); -}" PTHREAD_CREATE_MODIFIES_ERRNO) -set(CMAKE_REQUIRED_LIBRARIES) -set(CMAKE_REQUIRED_LIBRARIES pthread) -check_cxx_source_runs(" -#include -#include -#include - -int main() { - int result; - sem_t sema; - - errno = 50; - result = sem_init(&sema, 0, 0); - if (result != 0) - { - exit(1); - } - if (errno != 50) - { - exit(0); - } - exit(1); -}" SEM_INIT_MODIFIES_ERRNO) -set(CMAKE_REQUIRED_LIBRARIES) check_cxx_source_runs(" #include #include @@ -566,7 +520,7 @@ int main(void) { } exit(0); }" HAVE_PROCFS_CTL) -set(CMAKE_REQUIRED_LIBRARIES) + check_cxx_source_runs(" #include #include @@ -592,21 +546,6 @@ int main(void) { }" HAVE_PROCFS_STAT) set(CMAKE_REQUIRED_LIBRARIES) -set(CMAKE_REQUIRED_LIBRARIES ${PTHREAD_LIBRARY}) -check_cxx_source_runs(" -#include -#include -#include - -int main() { - sem_t sema; - if (sem_init(&sema, 0, 0) == -1){ - exit(1); - } - exit(0); -}" HAS_POSIX_SEMAPHORES) -set(CMAKE_REQUIRED_LIBRARIES) - set(SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING 1) set(ERROR_FUNC_FOR_GLOB_HAS_FIXED_PARAMS 1) @@ -667,12 +606,10 @@ int main(int argc, char **argv) if(CLR_CMAKE_TARGET_APPLE) set(HAVE__NSGETENVIRON 1) - set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 1) set(PAL_PTRACE "ptrace((cmd), (pid), (caddr_t)(addr), (data))") set(HAVE_SCHED_OTHER_ASSIGNABLE 1) elseif(CLR_CMAKE_TARGET_FREEBSD) - set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 0) set(PAL_PTRACE "ptrace((cmd), (pid), (caddr_t)(addr), (data))") if (CLR_CMAKE_HOST_ARCH_AMD64) set(BSD_REGS_STYLE "((reg).r_##rr)") @@ -683,21 +620,17 @@ elseif(CLR_CMAKE_TARGET_FREEBSD) endif() set(HAVE_SCHED_OTHER_ASSIGNABLE 1) elseif(CLR_CMAKE_TARGET_NETBSD) - set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 0) set(PAL_PTRACE "ptrace((cmd), (pid), (void*)(addr), (data))") set(BSD_REGS_STYLE "((reg).regs[_REG_##RR])") set(HAVE_SCHED_OTHER_ASSIGNABLE 0) elseif(CLR_CMAKE_TARGET_SUNOS) - set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 0) set(PAL_PTRACE "ptrace((cmd), (pid), (caddr_t)(addr), (data))") set(SET_SCHEDPARAM_NEEDS_PRIVS 1) elseif(CLR_CMAKE_TARGET_HAIKU) # Haiku does not have ptrace. - set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 0) set(HAVE_SCHED_OTHER_ASSIGNABLE 1) elseif(CLR_CMAKE_TARGET_BROWSER) - set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 0) set(HAVE_SCHED_OTHER_ASSIGNABLE 0) else() # Anything else is Linux # LTTNG is not available on Android, so don't error out @@ -705,7 +638,6 @@ else() # Anything else is Linux unset(HAVE_LTTNG_TRACEPOINT_H CACHE) message(FATAL_ERROR "Cannot find liblttng-ust-dev. Try installing liblttng-ust-dev (or the appropriate packages for your platform)") endif() - set(DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX 0) set(PAL_PTRACE "ptrace((cmd), (pid), (void*)(addr), (data))") set(HAVE_SCHED_OTHER_ASSIGNABLE 1) endif(CLR_CMAKE_TARGET_APPLE) diff --git a/src/coreclr/pal/src/include/pal/process.h b/src/coreclr/pal/src/include/pal/process.h index fde6cce8d88956..fa2d24df05c418 100644 --- a/src/coreclr/pal/src/include/pal/process.h +++ b/src/coreclr/pal/src/include/pal/process.h @@ -95,38 +95,6 @@ Return --*/ VOID PROCCleanupInitialProcess(VOID); -#if USE_SYSV_SEMAPHORES -/*++ -Function: - PROCCleanupThreadSemIds(VOID); - -Abstract - Cleanup SysV semaphore ids for all threads. - -(no parameters, no return value) ---*/ -VOID PROCCleanupThreadSemIds(VOID); -#endif - -/*++ -Function: - PROCProcessLock - -Abstract - Enter the critical section associated to the current process ---*/ -VOID PROCProcessLock(VOID); - - -/*++ -Function: - PROCProcessUnlock - -Abstract - Leave the critical section associated to the current process ---*/ -VOID PROCProcessUnlock(VOID); - /*++ Function PROCAbortInitialize() diff --git a/src/coreclr/pal/src/include/pal/procobj.hpp b/src/coreclr/pal/src/include/pal/procobj.hpp index 12245042648418..80f9aa327a1058 100644 --- a/src/coreclr/pal/src/include/pal/procobj.hpp +++ b/src/coreclr/pal/src/include/pal/procobj.hpp @@ -88,11 +88,6 @@ namespace CorUnix LPPROCESS_INFORMATION lpProcessInformation ); - PAL_ERROR - InitializeProcessData( - void - ); - PAL_ERROR InitializeProcessCommandLine( LPWSTR lpwstrCmdLine, diff --git a/src/coreclr/pal/src/include/pal/threadsusp.hpp b/src/coreclr/pal/src/include/pal/threadsusp.hpp index eba859afe678e3..e02d2a2f13b1ce 100644 --- a/src/coreclr/pal/src/include/pal/threadsusp.hpp +++ b/src/coreclr/pal/src/include/pal/threadsusp.hpp @@ -28,57 +28,11 @@ Module Name: #if !HAVE_MACH_EXCEPTIONS #include #endif // !HAVE_MACH_EXCEPTIONS -#include -#include - -// We have a variety of options for synchronizing thread suspensions and resumptions between the requestor and -// target threads. Analyze the various capabilities given to us by configure and define one of three macros -// here for simplicity: -// USE_POSIX_SEMAPHORES -// USE_SYSV_SEMAPHORES -// USE_PTHREAD_CONDVARS -#if HAS_POSIX_SEMAPHORES - -// Favor posix semaphores. -#define USE_POSIX_SEMAPHORES 1 - -#if HAVE_SYS_SEMAPHORE_H -#include -#elif HAVE_SEMAPHORE_H -#include -#endif // HAVE_SYS_SEMAPHORE_H - -#elif HAS_PTHREAD_MUTEXES && (HAVE_MACH_EXCEPTIONS || defined(TARGET_TVOS)) - -// Can only use the pthread solution if we're not using signals since pthread mutexes are not signal safe. - -// On tvOS, HAVE_MACH_EXCEPTIONS is 0 because thread_set_exception_ports is not available in the SDK. -// However, System V IPC (semget) is also not available due to sandbox restrictions so we use pthread instead. -#define USE_PTHREAD_CONDVARS 1 - -#include - -#elif HAS_SYSV_SEMAPHORES - -// SYSV semaphores are our last choice since they're shared across processes so it's possible to leak them -// on abnormal process termination. -#define USE_SYSV_SEMAPHORES 1 - -#include -#include - -#else -#error "Don't know how to synchronize thread suspends and resumes on this platform" -#endif // HAS_POSIX_SEMAPHORES #include namespace CorUnix { -#ifdef _DEBUG -#define MAX_TRACKED_CRITSECS 8 -#endif - PAL_ERROR InternalResumeThread( CPalThread *pthrResumer, @@ -89,72 +43,18 @@ namespace CorUnix class CThreadSuspensionInfo : public CThreadInfoInitializer { private: - BOOL m_fPending; // TRUE if a suspension is pending on a thread (because the thread is in an unsafe region) BOOL m_fSelfsusp; // TRUE if thread is self suspending and while thread is self suspended - BOOL m_fSuspendedForShutdown; // TRUE once the thread is suspended during PAL cleanup int m_nBlockingPipe; // blocking pipe used for a process that was created suspended -#ifdef _DEBUG - Volatile m_lNumThreadsSuspendedByThisThread; // number of threads that this thread has suspended; used for suspension diagnostics -#endif -#if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX - int m_nSpinlock; // thread's suspension spinlock, which is used to synchronize suspension and resumption attempts -#else // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX pthread_mutex_t m_ptmSuspmutex; // thread's suspension mutex, which is used to synchronize suspension and resumption attempts BOOL m_fSuspmutexInitialized; -#endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX -#if USE_POSIX_SEMAPHORES - sem_t m_semSusp; // suspension semaphore - sem_t m_semResume; // resumption semaphore - BOOL m_fSemaphoresInitialized; -#elif USE_SYSV_SEMAPHORES - // necessary id's and sembuf structures for SysV semaphores - int m_nSemsuspid; // id for the suspend semaphore - int m_nSemrespid; // id for the resume semaphore - struct sembuf m_sbSemwait; // struct representing a wait operation - struct sembuf m_sbSempost; // struct representing a post operation -#elif USE_PTHREAD_CONDVARS - pthread_cond_t m_condSusp; // suspension condition variable - pthread_mutex_t m_mutexSusp; // mutex associated with the condition above - BOOL m_fSuspended; // set to true once the suspend has been acknowledged - - pthread_cond_t m_condResume; // resumption condition variable - pthread_mutex_t m_mutexResume; // mutex associated with the condition above - BOOL m_fResumed; // set to true once the resume has been acknowledged - - BOOL m_fSemaphoresInitialized; -#endif // USE_POSIX_SEMAPHORES /* Most of the variables above are either accessed by a thread holding the appropriate suspension mutex(es) or are only accessed by their own threads (and thus don't require synchronization). - m_fPending, m_fSuspendedForShutdown, - m_fSuspendSignalSent, and m_fResumeSignalSent - may be set by a different thread than the owner and thus - require synchronization. - m_fSelfsusp is set to TRUE only by its own thread but may be later - accessed by other threads. - - m_lNumThreadsSuspendedByThisThread is accessed by its owning - thread and therefore does not require synchronization. */ - -#ifdef _DEBUG - VOID - IncrNumThreadsSuspendedByThisThread( - ) - { - InterlockedIncrement(&m_lNumThreadsSuspendedByThisThread); - }; - - VOID - DecrNumThreadsSuspendedByThisThread( - ) - { - InterlockedDecrement(&m_lNumThreadsSuspendedByThisThread); - }; -#endif + accessed by other threads. */ VOID AcquireSuspensionLocks( @@ -168,49 +68,6 @@ namespace CorUnix CPalThread *pthrTarget ); -#if USE_POSIX_SEMAPHORES - sem_t* - GetSuspendSemaphore( - void - ) - { - return &m_semSusp; - }; - - sem_t* - GetResumeSemaphore( - void - ) - { - return &m_semResume; - }; -#elif USE_SYSV_SEMAPHORES - int - GetSuspendSemaphoreId( - void - ) - { - return m_nSemsuspid; - }; - - sembuf* - GetSemaphorePostBuffer( - void - ) - { - return &m_sbSempost; - }; -#endif // USE_POSIX_SEMAPHORES - -#if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX - LONG* - GetSuspensionSpinlock( - void - ) - { - return &m_nSpinlock; - } -#else // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX pthread_mutex_t* GetSuspensionMutex( void @@ -218,23 +75,6 @@ namespace CorUnix { return &m_ptmSuspmutex; } -#endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX - - void - SetSuspPending( - BOOL fPending - ) - { - m_fPending = fPending; - }; - - BOOL - GetSuspPending( - void - ) - { - return m_fPending; - }; void SetSelfSusp( @@ -252,18 +92,6 @@ namespace CorUnix return m_fSelfsusp; }; - void - PostOnSuspendSemaphore(); - - void - WaitOnSuspendSemaphore(); - - void - PostOnResumeSemaphore(); - - void - WaitOnResumeSemaphore(); - static BOOL TryAcquireSuspensionLock( @@ -281,57 +109,15 @@ namespace CorUnix virtual PAL_ERROR InitializePreCreate(); CThreadSuspensionInfo() - : m_fPending(FALSE) - , m_fSelfsusp(FALSE) - , m_fSuspendedForShutdown(FALSE) + : m_fSelfsusp(FALSE) , m_nBlockingPipe(-1) -#ifdef _DEBUG - , m_lNumThreadsSuspendedByThisThread(0) -#endif // _DEBUG -#if !DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX , m_fSuspmutexInitialized(FALSE) -#endif -#if USE_POSIX_SEMAPHORES || USE_PTHREAD_CONDVARS - , m_fSemaphoresInitialized(FALSE) -#endif { InitializeSuspensionLock(); }; virtual ~CThreadSuspensionInfo(); -#ifdef _DEBUG - LONG - GetNumThreadsSuspendedByThisThread( - void - ) - { - return m_lNumThreadsSuspendedByThisThread; - }; -#endif // _DEBUG - -#if USE_SYSV_SEMAPHORES - void - DestroySemaphoreIds( - void - ); -#endif - void - SetSuspendedForShutdown( - BOOL fSuspendedForShutdown - ) - { - m_fSuspendedForShutdown = fSuspendedForShutdown; - }; - - BOOL - GetSuspendedForShutdown( - void - ) - { - return m_fSuspendedForShutdown; - }; - void AcquireSuspensionLock( CPalThread *pthrCurrent @@ -368,9 +154,5 @@ namespace CorUnix extern const BYTE WAKEUPCODE; // use for pipe reads during self suspend. #endif // __cplusplus -#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION -extern LONG g_ssSuspensionLock; -#endif - #endif // _PAL_THREADSUSP_HPP diff --git a/src/coreclr/pal/src/init/pal.cpp b/src/coreclr/pal/src/init/pal.cpp index a1d5006a220050..b14b31c96007f1 100644 --- a/src/coreclr/pal/src/init/pal.cpp +++ b/src/coreclr/pal/src/init/pal.cpp @@ -119,10 +119,6 @@ static LPWSTR INIT_FormatCommandLine (int argc, const char * const *argv); static LPWSTR INIT_GetCurrentEXEPath(); static BOOL INIT_SharedFilesPath(void); -#ifdef _DEBUG -extern void PROCDumpThreadList(void); -#endif - /*++ Function: PAL_Initialize @@ -392,17 +388,6 @@ Initialize( // we use large numbers of threads or have many open files. } - // - // Initialize global process data - // - - palError = InitializeProcessData(); - if (NO_ERROR != palError) - { - ERROR("Unable to initialize process data\n"); - goto CLEANUP1; - } - #if HAVE_MACH_EXCEPTIONS // Mach exception port needs to be set up before the thread // data or threads are set up. @@ -425,8 +410,6 @@ Initialize( goto CLEANUP1a; } - PROCAddThread(pThread, pThread); - // // It's now safe to access our thread data // @@ -817,10 +800,6 @@ PALCommonCleanup() // Let the synchronization manager know we're about to shutdown // CPalSynchMgrController::PrepareForShutdown(); - -#ifdef _DEBUG - PROCDumpThreadList(); -#endif } } diff --git a/src/coreclr/pal/src/init/sxs.cpp b/src/coreclr/pal/src/init/sxs.cpp index 8c55aa99c223dc..7ff673156a4dce 100644 --- a/src/coreclr/pal/src/init/sxs.cpp +++ b/src/coreclr/pal/src/init/sxs.cpp @@ -89,8 +89,6 @@ AllocatePalThread(CPalThread **ppThread) // possibly release it. (void)g_pObjectManager->RevokeHandle(pThread, hThread); - PROCAddThread(pThread, pThread); - // Unmask the activation signal so that GC can suspend this thread UnmaskActivationSignal(); diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index 42897270a9456f..5cd4a18b074175 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -139,18 +139,6 @@ CAllowedObjectTypes aotProcess(otiProcess); // IPalObject* CorUnix::g_pobjProcess; -// -// Critical section that protects process data (e.g., the -// list of active threads)/ -// -minipal_mutex g_csProcess; - -// -// List and count of active threads -// -CPalThread* CorUnix::pGThreadList; -DWORD g_dwThreadCount; - // // The command line and app name for the process // @@ -2934,31 +2922,6 @@ PROCGetProcessIDFromHandle( return dwProcessId; } -PAL_ERROR -CorUnix::InitializeProcessData( - void - ) -{ - PAL_ERROR palError = NO_ERROR; - bool fLockInitialized = FALSE; - - pGThreadList = NULL; - g_dwThreadCount = 0; - - minipal_mutex_init(&g_csProcess); - fLockInitialized = TRUE; - - if (NO_ERROR != palError) - { - if (fLockInitialized) - { - minipal_mutex_destroy(&g_csProcess); - } - } - - return palError; -} - /*++ Function InitializeProcessCommandLine @@ -3167,224 +3130,18 @@ Return VOID PROCCleanupInitialProcess(VOID) { - CPalThread *pThread = InternalGetCurrentThread(); - - minipal_mutex_enter(&g_csProcess); - /* Free the application directory */ free(g_lpwstrAppDir); /* Free the stored command line */ free(g_lpwstrCmdLine); - minipal_mutex_leave(&g_csProcess); - // // Object manager shutdown will handle freeing the underlying // thread and process data // - -} - -/*++ -Function: - PROCAddThread - -Abstract - Add a thread to the thread list of the current process - -Parameter - pThread: Thread object - ---*/ -VOID -CorUnix::PROCAddThread( - CPalThread *pCurrentThread, - CPalThread *pTargetThread - ) -{ - /* protect the access of the thread list with critical section for - mutithreading access */ - minipal_mutex_enter(&g_csProcess); - - pTargetThread->SetNext(pGThreadList); - pGThreadList = pTargetThread; - g_dwThreadCount += 1; - - TRACE("Thread 0x%p (id %#x) added to the process thread list\n", - pTargetThread, pTargetThread->GetThreadId()); - - minipal_mutex_leave(&g_csProcess); -} - - -/*++ -Function: - PROCRemoveThread - -Abstract - Remove a thread form the thread list of the current process - -Parameter - CPalThread *pThread : thread object to remove - -(no return value) ---*/ -VOID -CorUnix::PROCRemoveThread( - CPalThread *pCurrentThread, - CPalThread *pTargetThread - ) -{ - CPalThread *curThread, *prevThread; - - /* protect the access of the thread list with critical section for - mutithreading access */ - minipal_mutex_enter(&g_csProcess); - - curThread = pGThreadList; - - /* if thread list is empty */ - if (curThread == NULL) - { - ASSERT("Thread list is empty.\n"); - goto EXIT; - } - - /* do we remove the first thread? */ - if (curThread == pTargetThread) - { - pGThreadList = curThread->GetNext(); - TRACE("Thread 0x%p (id %#x) removed from the process thread list\n", - pTargetThread, pTargetThread->GetThreadId()); - goto EXIT; - } - - prevThread = curThread; - curThread = curThread->GetNext(); - /* find the thread to remove */ - while (curThread != NULL) - { - if (curThread == pTargetThread) - { - /* found, fix the chain list */ - prevThread->SetNext(curThread->GetNext()); - g_dwThreadCount -= 1; - TRACE("Thread %p removed from the process thread list\n", pTargetThread); - goto EXIT; - } - - prevThread = curThread; - curThread = curThread->GetNext(); - } - - WARN("Thread %p not removed (it wasn't found in the list)\n", pTargetThread); - -EXIT: - minipal_mutex_leave(&g_csProcess); } - -/*++ -Function: - PROCGetNumberOfThreads - -Abstract - Return the number of threads in the thread list. - -Parameter - void - -Return - the number of threads. ---*/ -INT -CorUnix::PROCGetNumberOfThreads( - VOID) -{ - return g_dwThreadCount; -} - - -/*++ -Function: - PROCProcessLock - -Abstract - Enter the critical section associated to the current process - -Parameter - void - -Return - void ---*/ -VOID -PROCProcessLock( - VOID) -{ - CPalThread * pThread = - (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : NULL); - - minipal_mutex_enter(&g_csProcess); -} - - -/*++ -Function: - PROCProcessUnlock - -Abstract - Leave the critical section associated to the current process - -Parameter - void - -Return - void ---*/ -VOID -PROCProcessUnlock( - VOID) -{ - CPalThread * pThread = - (PALIsThreadDataInitialized() ? InternalGetCurrentThread() : NULL); - - minipal_mutex_leave(&g_csProcess); -} - -#if USE_SYSV_SEMAPHORES -/*++ -Function: - PROCCleanupThreadSemIds - -Abstract - Cleanup SysV semaphore ids for all threads - -(no parameters, no return value) ---*/ -VOID -PROCCleanupThreadSemIds(void) -{ - // - // When using SysV semaphores, the semaphore ids used by PAL threads must be removed - // so they can be used again. - // - - PROCProcessLock(); - - CPalThread *pTargetThread = pGThreadList; - while (NULL != pTargetThread) - { - pTargetThread->suspensionInfo.DestroySemaphoreIds(); - pTargetThread = pTargetThread->GetNext(); - } - - PROCProcessUnlock(); - -} -#endif // USE_SYSV_SEMAPHORES - /*++ Function: TerminateCurrentProcessNoExit @@ -3654,31 +3411,6 @@ bool GetApplicationContainerFolder(PathCharString& buffer, const char *applicati } #endif // __APPLE__ -#ifdef _DEBUG -void PROCDumpThreadList() -{ - CPalThread *pThread; - - PROCProcessLock(); - - TRACE ("Threads:{\n"); - - pThread = pGThreadList; - while (NULL != pThread) - { - TRACE (" {pThr=0x%p tid=%#x lwpid=%#x state=%d finsusp=%d}\n", - pThread, (int)pThread->GetThreadId(), (int)pThread->GetLwpId(), - (int)pThread->synchronizationInfo.GetThreadState(), - (int)pThread->suspensionInfo.GetSuspendedForShutdown()); - - pThread = pThread->GetNext(); - } - TRACE ("Threads:}\n"); - - PROCProcessUnlock(); -} -#endif - /* Internal function definitions **********************************************/ /*++ diff --git a/src/coreclr/pal/src/thread/procprivate.hpp b/src/coreclr/pal/src/thread/procprivate.hpp index 4f3af27243e3b6..f59f1d33158fb8 100644 --- a/src/coreclr/pal/src/thread/procprivate.hpp +++ b/src/coreclr/pal/src/thread/procprivate.hpp @@ -27,36 +27,6 @@ Revision History: namespace CorUnix { - /*++ - Function: - PROCAddThread - - Abstract - Add a thread to the thread list of the current process - --*/ - void PROCAddThread(CPalThread *pCurrentThread, CPalThread *pTargetThread); - - extern CPalThread *pGThreadList; - - /*++ - Function: - PROCRemoveThread - - Abstract - Remove a thread form the thread list of the current process - --*/ - void PROCRemoveThread(CPalThread *pCurrentThread, CPalThread *pTargetThread); - - /*++ - Function: - PROCGetNumberOfThreads - - Abstract - Return the number of threads in the thread list. - --*/ - INT PROCGetNumberOfThreads(void); - - /*++ Function: TerminateCurrentProcessNoExit diff --git a/src/coreclr/pal/src/thread/thread.cpp b/src/coreclr/pal/src/thread/thread.cpp index 632baafa4308ec..9f3bd6e66297c3 100644 --- a/src/coreclr/pal/src/thread/thread.cpp +++ b/src/coreclr/pal/src/thread/thread.cpp @@ -438,15 +438,10 @@ CorUnix::InternalCreateThread( CPalThread *pNewThread = NULL; CObjectAttributes oa; bool fAttributesInitialized = FALSE; - bool fThreadDataAddedToProcessList = FALSE; HANDLE hNewThread = NULL; pthread_t pthread; pthread_attr_t pthreadAttr; -#if PTHREAD_CREATE_MODIFIES_ERRNO - int storedErrno; -#endif // PTHREAD_CREATE_MODIFIES_ERRNO - BOOL fHoldingProcessLock = FALSE; int iError = 0; size_t alignedStackSize; @@ -586,38 +581,12 @@ CorUnix::InternalCreateThread( // Add the thread to the process list // - // - // We use the process lock to ensure that we're not interrupted - // during the creation process. After adding the CPalThread reference - // to the process list, we want to make sure the actual thread has been - // started. Otherwise, there's a window where the thread can be found - // in the process list but doesn't yet exist in the system. - // - - PROCProcessLock(); - fHoldingProcessLock = TRUE; - - PROCAddThread(pThread, pNewThread); - fThreadDataAddedToProcessList = TRUE; - // // Spawn the new pthread // -#if PTHREAD_CREATE_MODIFIES_ERRNO - storedErrno = errno; -#endif // PTHREAD_CREATE_MODIFIES_ERRNO - iError = pthread_create(&pthread, &pthreadAttr, CPalThread::ThreadEntry, pNewThread); -#if PTHREAD_CREATE_MODIFIES_ERRNO - if (iError == 0) - { - // Restore errno if pthread_create succeeded. - errno = storedErrno; - } -#endif // PTHREAD_CREATE_MODIFIES_ERRNO - if (0 != iError) { ERROR("pthread_create failed, error is %d (%s)\n", iError, strerror(iError)); @@ -649,14 +618,6 @@ CorUnix::InternalCreateThread( goto EXIT; } - // - // If we're here, then we've locked the process list and both pthread_create - // and WaitForStartStatus succeeded. Thus, we can now unlock the process list. - // Since palError == NO_ERROR, we won't call this again in the exit block. - // - PROCProcessUnlock(); - fHoldingProcessLock = FALSE; - EXIT: if (fAttributesInitialized) @@ -667,31 +628,6 @@ CorUnix::InternalCreateThread( } } - if (NO_ERROR != palError) - { - // - // We either were not able to create the new thread, or a failure - // occurred in the new thread's entry routine. Free up the associated - // resources here - // - - if (fThreadDataAddedToProcessList) - { - PROCRemoveThread(pThread, pNewThread); - } - // - // Once we remove the thread from the process list, we can call - // PROCProcessUnlock. - // - if (fHoldingProcessLock) - { - PROCProcessUnlock(); - } - fHoldingProcessLock = FALSE; - } - - _ASSERT_MSG(!fHoldingProcessLock, "Exiting InternalCreateThread while still holding the process critical section.\n"); - return palError; } @@ -789,12 +725,6 @@ CorUnix::InternalEndCurrentThread( pThread->GetThreadObject()->ReleaseReference(pThread); - /* Remove thread for the thread list of the process - (don't do if this is the last thread -> gets handled by - TerminateProcess->PROCCleanupProcess->PROCTerminateOtherThreads) */ - - PROCRemoveThread(pThread, pThread); - // Ensure that EH is disabled on the current thread SEHDisable(pThread); diff --git a/src/coreclr/pal/src/thread/threadsusp.cpp b/src/coreclr/pal/src/thread/threadsusp.cpp index ec0dc9c5b92594..8136d24c4ab741 100644 --- a/src/coreclr/pal/src/thread/threadsusp.cpp +++ b/src/coreclr/pal/src/thread/threadsusp.cpp @@ -44,62 +44,6 @@ SET_DEFAULT_DEBUG_CHANNEL(THREAD); in suspended state in order to resume it. */ CONST BYTE WAKEUPCODE=0x2A; -// #define USE_GLOBAL_LOCK_FOR_SUSPENSION // Uncomment this define to use the global suspension lock. -/* The global suspension lock can be used in place of each thread having its own -suspension mutex or spinlock. The downside is that it restricts us to only -performing one suspension or resumption in the PAL at a time. */ -#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION - -namespace -{ - LONG g_ssSuspensionLock = 0; -} -#endif - -#define SYNCSPINLOCK_F_ASYMMETRIC 1 - -#define SPINLOCKInit(lock) (*(lock) = 0) - -namespace -{ - /* Basic spinlock implementation */ - void SPINLOCKAcquire (LONG * lock, unsigned int flags) - { - size_t loop_seed = 1, loop_count = 0; - - if (flags & SYNCSPINLOCK_F_ASYMMETRIC) - { - loop_seed = ((size_t)pthread_self() % 10) + 1; - } - while (InterlockedCompareExchange(lock, 1, 0)) - { - if (!(flags & SYNCSPINLOCK_F_ASYMMETRIC) || (++loop_count % loop_seed)) - { -#if PAL_IGNORE_NORMAL_THREAD_PRIORITY - struct timespec tsSleepTime; - tsSleepTime.tv_sec = 0; - tsSleepTime.tv_nsec = 1; - nanosleep(&tsSleepTime, NULL); -#else - sched_yield(); -#endif - } - } - - } - - void SPINLOCKRelease (LONG * lock) - { - VolatileStore(lock, 0); - } - - DWORD SPINLOCKTryAcquire (LONG * lock) - { - return InterlockedCompareExchange(lock, 1, 0); - // only returns 0 or 1. - } -} - /*++ Function: InternalSuspendNewThreadFromData @@ -382,7 +326,7 @@ CThreadSuspensionInfo::InternalResumeThreadFromData( TryAcquireSuspensionLock TryAcquireSuspensionLock is a utility function that tries to acquire a thread's -suspension mutex or spinlock. If it succeeds, the function returns TRUE. +suspension mutex. If it succeeds, the function returns TRUE. Otherwise, it returns FALSE. This function is used in AcquireSuspensionLocks. Note that the global lock cannot be acquired in this function since it makes no sense to do so. A thread holding the global lock is the only thread that @@ -394,17 +338,8 @@ CThreadSuspensionInfo::TryAcquireSuspensionLock( CPalThread* pthrTarget ) { - int iPthreadRet = 0; -#if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX -{ - iPthreadRet = SPINLOCKTryAcquire(pthrTarget->suspensionInfo.GetSuspensionSpinlock()); -} -#else // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX -{ - iPthreadRet = pthread_mutex_trylock(pthrTarget->suspensionInfo.GetSuspensionMutex()); + int iPthreadRet = pthread_mutex_trylock(pthrTarget->suspensionInfo.GetSuspensionMutex()); _ASSERT_MSG(iPthreadRet == 0 || iPthreadRet == EBUSY, "pthread_mutex_trylock returned %d\n", iPthreadRet); -} -#endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX // If iPthreadRet is 0, lock acquisition was successful. Otherwise, it failed. return (iPthreadRet == 0); @@ -414,8 +349,7 @@ CThreadSuspensionInfo::TryAcquireSuspensionLock( Function: AcquireSuspensionLock -AcquireSuspensionLock acquires a thread's suspension mutex or spinlock. -If USE_GLOBAL_LOCK_FOR_SUSPENSION is defined, it will acquire the global lock. +AcquireSuspensionLock acquires a thread's suspension mutex. A thread in this function blocks until it acquires its lock, unlike in TryAcquireSuspensionLock. --*/ @@ -424,59 +358,25 @@ CThreadSuspensionInfo::AcquireSuspensionLock( CPalThread* pthrCurrent ) { -#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION -{ - SPINLOCKAcquire(&g_ssSuspensionLock, 0); -} -#else // USE_GLOBAL_LOCK_FOR_SUSPENSION -{ - #if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX - { - SPINLOCKAcquire(&pthrCurrent->suspensionInfo.m_nSpinlock, 0); - } - #else // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX - { - INDEBUG(int iPthreadError = ) - pthread_mutex_lock(&pthrCurrent->suspensionInfo.m_ptmSuspmutex); - _ASSERT_MSG(iPthreadError == 0, "pthread_mutex_lock returned %d\n", iPthreadError); - } - #endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX -} -#endif // USE_GLOBAL_LOCK_FOR_SUSPENSION + INDEBUG(int iPthreadError = ) + pthread_mutex_lock(&pthrCurrent->suspensionInfo.m_ptmSuspmutex); + _ASSERT_MSG(iPthreadError == 0, "pthread_mutex_lock returned %d\n", iPthreadError); } /*++ Function: ReleaseSuspensionLock -ReleaseSuspensionLock is a function that releases a thread's suspension mutex -or spinlock. If USE_GLOBAL_LOCK_FOR_SUSPENSION is defined, -it will release the global lock. +ReleaseSuspensionLock is a function that releases a thread's suspension mutex. --*/ void CThreadSuspensionInfo::ReleaseSuspensionLock( CPalThread* pthrCurrent ) { -#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION -{ - SPINLOCKRelease(&g_ssSuspensionLock); -} -#else // USE_GLOBAL_LOCK_FOR_SUSPENSION -{ - #if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX - { - SPINLOCKRelease(&pthrCurrent->suspensionInfo.m_nSpinlock); - } - #else // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX - { - INDEBUG(int iPthreadError = ) - pthread_mutex_unlock(&pthrCurrent->suspensionInfo.m_ptmSuspmutex); - _ASSERT_MSG(iPthreadError == 0, "pthread_mutex_unlock returned %d\n", iPthreadError); - } - #endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX -} -#endif // USE_GLOBAL_LOCK_FOR_SUSPENSION + INDEBUG(int iPthreadError = ) + pthread_mutex_unlock(&pthrCurrent->suspensionInfo.m_ptmSuspmutex); + _ASSERT_MSG(iPthreadError == 0, "pthread_mutex_unlock returned %d\n", iPthreadError); } /*++ @@ -509,9 +409,6 @@ mutex first. This prevents you from being suspended while holding the target's mutex. Then, attempt to acquire the target's mutex. If the mutex cannot be acquired, release your own and try again. This all or nothing approach is the safest and avoids nasty race conditions. - -If USE_GLOBAL_LOCK_FOR_SUSPENSION is defined, the calling thread -will acquire the global lock when possible. --*/ VOID CThreadSuspensionInfo::AcquireSuspensionLocks( @@ -521,9 +418,6 @@ CThreadSuspensionInfo::AcquireSuspensionLocks( { BOOL fReacquire = FALSE; -#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION - AcquireSuspensionLock(pthrSuspender); -#else // USE_GLOBAL_LOCK_FOR_SUSPENSION do { fReacquire = FALSE; @@ -536,7 +430,6 @@ CThreadSuspensionInfo::AcquireSuspensionLocks( sched_yield(); } } while (fReacquire); -#endif // USE_GLOBAL_LOCK_FOR_SUSPENSION // Whenever the native implementation for the wait subsystem's thread // blocking requires a lock as protection (as pthread conditions do with @@ -572,7 +465,6 @@ ReleaseSuspensionLocks releases both thread's suspension mutexes. Note that the locks are released in the opposite order they're acquired. This prevents a suspending or resuming thread from being suspended while holding the target's lock. -If USE_GLOBAL_LOCK_FOR_SUSPENSION is defined, it simply releases the global lock. --*/ VOID CThreadSuspensionInfo::ReleaseSuspensionLocks( @@ -583,248 +475,20 @@ CThreadSuspensionInfo::ReleaseSuspensionLocks( // See comment in AcquireSuspensionLocks pthrTarget->ReleaseNativeWaitLock(); -#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION - ReleaseSuspensionLock(pthrSuspender); -#else // USE_GLOBAL_LOCK_FOR_SUSPENSION ReleaseSuspensionLock(pthrTarget); ReleaseSuspensionLock(pthrSuspender); -#endif // USE_GLOBAL_LOCK_FOR_SUSPENSION -} - -/*++ -Function: - PostOnSuspendSemaphore - -PostOnSuspendSemaphore is a utility function for a thread -to post on its POSIX or SysV suspension semaphore. ---*/ -void -CThreadSuspensionInfo::PostOnSuspendSemaphore() -{ -#if USE_POSIX_SEMAPHORES - if (sem_post(&m_semSusp) == -1) - { - ASSERT("sem_post returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); - } -#elif USE_SYSV_SEMAPHORES - if (semop(m_nSemsuspid, &m_sbSempost, 1) == -1) - { - ASSERT("semop - post returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); - } -#elif USE_PTHREAD_CONDVARS - int status; - - // The suspending thread may not have entered the wait yet, in which case the cond var - // signal below will be a no-op. To prevent the race condition we set m_fSuspended to - // TRUE first (which the suspender will take as an indication that no wait is required). - // But the setting of the flag and the signal must appear atomic to the suspender (as - // reading the flag and potentially waiting must appear to us) to avoid the race - // condition where the suspender reads the flag as FALSE, we set it and signal and the - // suspender then waits. - - // Acquire the suspend mutex. Once we enter the critical section the suspender has - // either gotten there before us (and is waiting for our signal) or is yet to even - // check the flag (so we can set it here to stop them attempting a wait). - status = pthread_mutex_lock(&m_mutexSusp); - if (status != 0) - { - ASSERT("pthread_mutex_lock returned %d (%s)\n", status, strerror(status)); - } - - m_fSuspended = TRUE; - - status = pthread_cond_signal(&m_condSusp); - if (status != 0) - { - ASSERT("pthread_cond_signal returned %d (%s)\n", status, strerror(status)); - } - - status = pthread_mutex_unlock(&m_mutexSusp); - if (status != 0) - { - ASSERT("pthread_mutex_unlock returned %d (%s)\n", status, strerror(status)); - } -#endif // USE_POSIX_SEMAPHORES -} - -/*++ -Function: - WaitOnSuspendSemaphore - -WaitOnSuspendSemaphore is a utility function for a thread -to wait on its POSIX or SysV suspension semaphore. ---*/ -void -CThreadSuspensionInfo::WaitOnSuspendSemaphore() -{ -#if USE_POSIX_SEMAPHORES - while (sem_wait(&m_semSusp) == -1) - { - ASSERT("sem_wait returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); - } -#elif USE_SYSV_SEMAPHORES - while (semop(m_nSemsuspid, &m_sbSemwait, 1) == -1) - { - ASSERT("semop wait returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); - } -#elif USE_PTHREAD_CONDVARS - int status; - - // By the time we wait the target thread may have already signalled its suspension (in - // which case m_fSuspended will be TRUE and we shouldn't wait on the cond var). But we - // must check the flag and potentially wait atomically to avoid the race where we read - // the flag and the target thread sets it and signals before we have a chance to wait. - - status = pthread_mutex_lock(&m_mutexSusp); - if (status != 0) - { - ASSERT("pthread_mutex_lock returned %d (%s)\n", status, strerror(status)); - } - - // If the target has already acknowledged the suspend we shouldn't wait. - while (!m_fSuspended) - { - // We got here before the target could signal. Wait on them (which atomically releases - // the mutex during the wait). - status = pthread_cond_wait(&m_condSusp, &m_mutexSusp); - if (status != 0) - { - ASSERT("pthread_cond_wait returned %d (%s)\n", status, strerror(status)); - } - } - - status = pthread_mutex_unlock(&m_mutexSusp); - if (status != 0) - { - ASSERT("pthread_mutex_unlock returned %d (%s)\n", status, strerror(status)); - } -#endif // USE_POSIX_SEMAPHORES -} - -/*++ -Function: - PostOnResumeSemaphore - -PostOnResumeSemaphore is a utility function for a thread -to post on its POSIX or SysV resume semaphore. ---*/ -void -CThreadSuspensionInfo::PostOnResumeSemaphore() -{ -#if USE_POSIX_SEMAPHORES - if (sem_post(&m_semResume) == -1) - { - ASSERT("sem_post returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); - } -#elif USE_SYSV_SEMAPHORES - if (semop(m_nSemrespid, &m_sbSempost, 1) == -1) - { - ASSERT("semop - post returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); - } -#elif USE_PTHREAD_CONDVARS - int status; - - // The resuming thread may not have entered the wait yet, in which case the cond var - // signal below will be a no-op. To prevent the race condition we set m_fResumed to - // TRUE first (which the resumer will take as an indication that no wait is required). - // But the setting of the flag and the signal must appear atomic to the resumer (as - // reading the flag and potentially waiting must appear to us) to avoid the race - // condition where the resumer reads the flag as FALSE, we set it and signal and the - // resumer then waits. - - // Acquire the resume mutex. Once we enter the critical section the resumer has - // either gotten there before us (and is waiting for our signal) or is yet to even - // check the flag (so we can set it here to stop them attempting a wait). - status = pthread_mutex_lock(&m_mutexResume); - if (status != 0) - { - ASSERT("pthread_mutex_lock returned %d (%s)\n", status, strerror(status)); - } - - m_fResumed = TRUE; - - status = pthread_cond_signal(&m_condResume); - if (status != 0) - { - ASSERT("pthread_cond_signal returned %d (%s)\n", status, strerror(status)); - } - - status = pthread_mutex_unlock(&m_mutexResume); - if (status != 0) - { - ASSERT("pthread_mutex_unlock returned %d (%s)\n", status, strerror(status)); - } -#endif // USE_POSIX_SEMAPHORES -} - -/*++ -Function: - WaitOnResumeSemaphore - -WaitOnResumeSemaphore is a utility function for a thread -to wait on its POSIX or SysV resume semaphore. ---*/ -void -CThreadSuspensionInfo::WaitOnResumeSemaphore() -{ -#if USE_POSIX_SEMAPHORES - while (sem_wait(&m_semResume) == -1) - { - ASSERT("sem_wait returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); - } -#elif USE_SYSV_SEMAPHORES - while (semop(m_nSemrespid, &m_sbSemwait, 1) == -1) - { - ASSERT("semop wait returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); - } -#elif USE_PTHREAD_CONDVARS - int status; - - // By the time we wait the target thread may have already signalled its resumption (in - // which case m_fResumed will be TRUE and we shouldn't wait on the cond var). But we - // must check the flag and potentially wait atomically to avoid the race where we read - // the flag and the target thread sets it and signals before we have a chance to wait. - - status = pthread_mutex_lock(&m_mutexResume); - if (status != 0) - { - ASSERT("pthread_mutex_lock returned %d (%s)\n", status, strerror(status)); - } - - // If the target has already acknowledged the resume we shouldn't wait. - while (!m_fResumed) - { - // We got here before the target could signal. Wait on them (which atomically releases - // the mutex during the wait). - status = pthread_cond_wait(&m_condResume, &m_mutexResume); - if (status != 0) - { - ASSERT("pthread_cond_wait returned %d (%s)\n", status, strerror(status)); - } - } - - status = pthread_mutex_unlock(&m_mutexResume); - if (status != 0) - { - ASSERT("pthread_mutex_unlock returned %d (%s)\n", status, strerror(status)); - } -#endif // USE_POSIX_SEMAPHORES } /*++ Function: InitializeSuspensionLock -InitializeSuspensionLock initializes a thread's suspension spinlock -or suspension mutex. It is called from the CThreadSuspensionInfo -constructor. +InitializeSuspensionLock initializes a thread's suspension mutex. +It is called from the CThreadSuspensionInfo constructor. --*/ VOID CThreadSuspensionInfo::InitializeSuspensionLock() { -#if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX - SPINLOCKInit(&m_nSpinlock); -#else int iError = pthread_mutex_init(&m_ptmSuspmutex, NULL); if (0 != iError ) { @@ -832,261 +496,26 @@ CThreadSuspensionInfo::InitializeSuspensionLock() return; } m_fSuspmutexInitialized = TRUE; -#endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX } /*++ Function: InitializePreCreate -InitializePreCreate initializes the semaphores and signal masks used -for thread suspension. At the end, it sets the calling thread's -signal mask to the default signal mask. +InitializePreCreate is called from the CThreadSuspensionInfo constructor. --*/ PAL_ERROR CThreadSuspensionInfo::InitializePreCreate() { - PAL_ERROR palError = ERROR_INTERNAL_ERROR; - int iError = 0; -#if SEM_INIT_MODIFIES_ERRNO - int nStoredErrno; -#endif // SEM_INIT_MODIFIES_ERRNO - -#if USE_POSIX_SEMAPHORES - -#if SEM_INIT_MODIFIES_ERRNO - nStoredErrno = errno; -#endif // SEM_INIT_MODIFIES_ERRNO - - // initialize suspension semaphore - iError = sem_init(&m_semSusp, 0, 0); - -#if SEM_INIT_MODIFIES_ERRNO - if (iError == 0) - { - // Restore errno if sem_init succeeded. - errno = nStoredErrno; - } -#endif // SEM_INIT_MODIFIES_ERRNO - - if (0 != iError ) - { - ASSERT("sem_init(&suspsem) returned %d\n", iError); - goto InitializePreCreateExit; - } - -#if SEM_INIT_MODIFIES_ERRNO - nStoredErrno = errno; -#endif // SEM_INIT_MODIFIES_ERRNO - - // initialize resume semaphore - iError = sem_init(&m_semResume, 0, 0); - -#if SEM_INIT_MODIFIES_ERRNO - if (iError == 0) - { - // Restore errno if sem_init succeeded. - errno = nStoredErrno; - } -#endif // SEM_INIT_MODIFIES_ERRNO - - if (0 != iError ) - { - ASSERT("sem_init(&suspsem) returned %d\n", iError); - sem_destroy(&m_semSusp); - goto InitializePreCreateExit; - } - - m_fSemaphoresInitialized = TRUE; - -#elif USE_SYSV_SEMAPHORES - // preparing to initialize the SysV semaphores. - union semun semunData; - m_nSemsuspid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666); - if (m_nSemsuspid == -1) - { - ASSERT("semget for suspension sem id returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); - goto InitializePreCreateExit; - } - - m_nSemrespid = semget(IPC_PRIVATE, 1, IPC_CREAT | 0666); - if (m_nSemrespid == -1) - { - ASSERT("semget for resumption sem id returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); - goto InitializePreCreateExit; - } - - if (m_nSemsuspid == m_nSemrespid) - { - ASSERT("Suspension and Resumption Semaphores have the same id\n"); - goto InitializePreCreateExit; - } - - semunData.val = 0; - iError = semctl(m_nSemsuspid, 0, SETVAL, semunData); - if (iError == -1) - { - ASSERT("semctl for suspension sem id returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); - goto InitializePreCreateExit; - } - - semunData.val = 0; - iError = semctl(m_nSemrespid, 0, SETVAL, semunData); - if (iError == -1) - { - ASSERT("semctl for resumption sem id returned -1 and set errno to %d (%s)\n", errno, strerror(errno)); - goto InitializePreCreateExit; - } - - // initialize suspend semaphore - m_sbSemwait.sem_num = 0; - m_sbSemwait.sem_op = -1; - m_sbSemwait.sem_flg = 0; - - // initialize resume semaphore - m_sbSempost.sem_num = 0; - m_sbSempost.sem_op = 1; - m_sbSempost.sem_flg = 0; -#elif USE_PTHREAD_CONDVARS - iError = pthread_cond_init(&m_condSusp, NULL); - if (iError != 0) - { - ASSERT("pthread_cond_init for suspension returned %d (%s)\n", iError, strerror(iError)); - goto InitializePreCreateExit; - } - - iError = pthread_mutex_init(&m_mutexSusp, NULL); - if (iError != 0) - { - ASSERT("pthread_mutex_init for suspension returned %d (%s)\n", iError, strerror(iError)); - goto InitializePreCreateExit; - } - - iError = pthread_cond_init(&m_condResume, NULL); - if (iError != 0) - { - ASSERT("pthread_cond_init for resume returned %d (%s)\n", iError, strerror(iError)); - goto InitializePreCreateExit; - } - - iError = pthread_mutex_init(&m_mutexResume, NULL); - if (iError != 0) - { - ASSERT("pthread_mutex_init for resume returned %d (%s)\n", iError, strerror(iError)); - goto InitializePreCreateExit; - } - - m_fSemaphoresInitialized = TRUE; -#endif // USE_POSIX_SEMAPHORES - - // Initialization was successful. - palError = NO_ERROR; - -InitializePreCreateExit: - - if (NO_ERROR == palError && 0 != iError) - { - switch (iError) - { - case ENOMEM: - case EAGAIN: - { - palError = ERROR_OUTOFMEMORY; - break; - } - default: - { - ASSERT("A pthrSuspender init call returned %d (%s)\n", iError, strerror(iError)); - palError = ERROR_INTERNAL_ERROR; - } - } - } - - return palError; + return NO_ERROR; } CThreadSuspensionInfo::~CThreadSuspensionInfo() { -#if !DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX if (m_fSuspmutexInitialized) { INDEBUG(int iError = ) pthread_mutex_destroy(&m_ptmSuspmutex); _ASSERT_MSG(0 == iError, "pthread_mutex_destroy returned %d (%s)\n", iError, strerror(iError)); } -#endif - -#if USE_POSIX_SEMAPHORES - if (m_fSemaphoresInitialized) - { - int iError; - - iError = sem_destroy(&m_semSusp); - _ASSERT_MSG(0 == iError, "sem_destroy failed and set errno to %d (%s)\n", errno, strerror(errno)); - - iError = sem_destroy(&m_semResume); - _ASSERT_MSG(0 == iError, "sem_destroy failed and set errno to %d (%s)\n", errno, strerror(errno)); - } -#elif USE_SYSV_SEMAPHORES - DestroySemaphoreIds(); -#elif USE_PTHREAD_CONDVARS - if (m_fSemaphoresInitialized) - { - int iError; - - iError = pthread_cond_destroy(&m_condSusp); - _ASSERT_MSG(0 == iError, "pthread_cond_destroy failed with %d (%s)\n", iError, strerror(iError)); - - iError = pthread_mutex_destroy(&m_mutexSusp); - _ASSERT_MSG(0 == iError, "pthread_mutex_destroy failed with %d (%s)\n", iError, strerror(iError)); - - iError = pthread_cond_destroy(&m_condResume); - _ASSERT_MSG(0 == iError, "pthread_cond_destroy failed with %d (%s)\n", iError, strerror(iError)); - - iError = pthread_mutex_destroy(&m_mutexResume); - _ASSERT_MSG(0 == iError, "pthread_mutex_destroy failed with %d (%s)\n", iError, strerror(iError)); - } -#endif // USE_POSIX_SEMAPHORES -} - -#if USE_SYSV_SEMAPHORES -/*++ -Function: - DestroySemaphoreIds - -DestroySemaphoreIds is called from the CThreadSuspensionInfo destructor and -from PROCCleanupThreadSemIds. If a thread exits before shutdown or is suspended -during shutdown, its destructor will be invoked and the semaphore ids destroyed. -In assert or exceptions situations that are suspension unsafe, -PROCCleanupThreadSemIds is called, which uses DestroySemaphoreIds. ---*/ -void -CThreadSuspensionInfo::DestroySemaphoreIds() -{ - union semun semunData; - if (m_nSemsuspid != 0) - { - semunData.val = 0; - if (0 != semctl(m_nSemsuspid, 0, IPC_RMID, semunData)) - { - ERROR("semctl(Semsuspid) failed and set errno to %d (%s)\n", errno, strerror(errno)); - } - else - { - m_nSemsuspid = 0; - } - } - if (this->m_nSemrespid) - { - semunData.val = 0; - if (0 != semctl(m_nSemrespid, 0, IPC_RMID, semunData)) - { - ERROR("semctl(Semrespid) failed and set errno to %d (%s)\n", errno, strerror(errno)); - } - else - { - m_nSemrespid = 0; - } - } } -#endif // USE_SYSV_SEMAPHORES