File indexing completed on 2024-05-19 03:56:18
0001 /* 0002 * This file is part of the KDE project. 0003 * 0004 * SPDX-FileCopyrightText: 2010 Michael Pyne <mpyne@kde.org> 0005 * SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "ksdclock_p.h" 0009 0010 #include "kcoreaddons_debug.h" 0011 0012 #include <memory> 0013 0014 /** 0015 * This is a method to determine the best lock type to use for a 0016 * shared cache, based on local support. An identifier to the appropriate 0017 * SharedLockId is returned, which can be passed to createLockFromId(). 0018 */ 0019 SharedLockId findBestSharedLock() 0020 { 0021 // We would prefer a process-shared capability that also supports 0022 // timeouts. Failing that, process-shared is preferred over timeout 0023 // support. Failing that we'll go thread-local 0024 bool timeoutsSupported = false; 0025 bool pthreadsProcessShared = false; 0026 bool semaphoresProcessShared = false; 0027 0028 #ifdef KSDC_TIMEOUTS_SUPPORTED 0029 timeoutsSupported = ::sysconf(_SC_TIMEOUTS) >= 200112L; 0030 #endif 0031 0032 // Now that we've queried timeouts, try actually creating real locks and 0033 // seeing if there's issues with that. 0034 #ifdef KSDC_THREAD_PROCESS_SHARED_SUPPORTED 0035 { 0036 pthread_mutex_t tempMutex; 0037 std::unique_ptr<KSDCLock> tempLock; 0038 if (timeoutsSupported) { 0039 #ifdef KSDC_TIMEOUTS_SUPPORTED 0040 tempLock = std::make_unique<pthreadTimedLock>(tempMutex); 0041 #endif 0042 } else { 0043 tempLock = std::make_unique<pthreadLock>(tempMutex); 0044 } 0045 0046 tempLock->initialize(pthreadsProcessShared); 0047 } 0048 #endif // KSDC_THREAD_PROCESS_SHARED_SUPPORTED 0049 0050 // Our first choice is pthread_mutex_t for compatibility. 0051 if (timeoutsSupported && pthreadsProcessShared) { 0052 return LOCKTYPE_MUTEX; 0053 } 0054 0055 #ifdef KSDC_SEMAPHORES_SUPPORTED 0056 { 0057 sem_t tempSemaphore; 0058 std::unique_ptr<KSDCLock> tempLock; 0059 if (timeoutsSupported) { 0060 tempLock = std::make_unique<semaphoreTimedLock>(tempSemaphore); 0061 } else { 0062 tempLock = std::make_unique<semaphoreLock>(tempSemaphore); 0063 } 0064 0065 tempLock->initialize(semaphoresProcessShared); 0066 } 0067 #endif // KSDC_SEMAPHORES_SUPPORTED 0068 0069 if (timeoutsSupported && semaphoresProcessShared) { 0070 return LOCKTYPE_SEMAPHORE; 0071 } else if (pthreadsProcessShared) { 0072 return LOCKTYPE_MUTEX; 0073 } else if (semaphoresProcessShared) { 0074 return LOCKTYPE_SEMAPHORE; 0075 } 0076 0077 // Fallback to a dumb-simple but possibly-CPU-wasteful solution. 0078 return LOCKTYPE_SPINLOCK; 0079 } 0080 0081 KSDCLock *createLockFromId(SharedLockId id, SharedLock &lock) 0082 { 0083 switch (id) { 0084 #ifdef KSDC_THREAD_PROCESS_SHARED_SUPPORTED 0085 case LOCKTYPE_MUTEX: 0086 #ifdef KSDC_TIMEOUTS_SUPPORTED 0087 if (::sysconf(_SC_TIMEOUTS) >= 200112L) { 0088 return new pthreadTimedLock(lock.mutex); 0089 } 0090 #endif 0091 return new pthreadLock(lock.mutex); 0092 0093 break; 0094 #endif // KSDC_THREAD_PROCESS_SHARED_SUPPORTED 0095 0096 #ifdef KSDC_SEMAPHORES_SUPPORTED 0097 case LOCKTYPE_SEMAPHORE: 0098 #ifdef KSDC_TIMEOUTS_SUPPORTED 0099 if (::sysconf(_SC_SEMAPHORES) >= 200112L) { 0100 return new semaphoreTimedLock(lock.semaphore); 0101 } 0102 #endif 0103 return new semaphoreLock(lock.semaphore); 0104 0105 break; 0106 #endif // KSDC_SEMAPHORES_SUPPORTED 0107 0108 case LOCKTYPE_SPINLOCK: 0109 return new simpleSpinLock(lock.spinlock); 0110 break; 0111 0112 default: 0113 qCCritical(KCOREADDONS_DEBUG) << "Creating shell of a lock!"; 0114 return new KSDCLock; 0115 } 0116 }