20 #ifndef KSHAREDDATACACHE_P_H 21 #define KSHAREDDATACACHE_P_H 23 #include <config-util.h> 25 #include <QtCore/QSharedPointer> 26 #include <QtCore/QBasicAtomicInt> 43 #if defined(_POSIX_TIMEOUTS) && ((_POSIX_TIMEOUTS == 0) || (_POSIX_TIMEOUTS >= 200112L)) 44 #define KSDC_TIMEOUTS_SUPPORTED 1 47 #if defined(__GNUC__) && !defined(KSDC_TIMEOUTS_SUPPORTED) 48 #warning "No support for POSIX timeouts -- application hangs are possible if the cache is corrupt" 51 #if defined(_POSIX_THREAD_PROCESS_SHARED) && ((_POSIX_THREAD_PROCESS_SHARED == 0) || (_POSIX_THREAD_PROCESS_SHARED >= 200112L)) && !defined(__APPLE__) 53 #define KSDC_THREAD_PROCESS_SHARED_SUPPORTED 1 56 #if defined(_POSIX_SEMAPHORES) && ((_POSIX_SEMAPHORES == 0) || (_POSIX_SEMAPHORES >= 200112L)) 57 #include <semaphore.h> 58 #define KSDC_SEMAPHORES_SUPPORTED 1 61 #if defined(__GNUC__) && !defined(KSDC_SEMAPHORES_SUPPORTED) && !defined(KSDC_THREAD_PROCESS_SHARED_SUPPORTED) 62 #warning "No system support claimed for process-shared synchronization, KSharedDataCache will be mostly useless." 65 #if defined(_POSIX_MAPPED_FILES) && ((_POSIX_MAPPED_FILES == 0) || (_POSIX_MAPPED_FILES >= 200112L)) 66 #define KSDC_MAPPED_FILES_SUPPORTED 1 69 #if defined(_POSIX_SYNCHRONIZED_IO) && ((_POSIX_SYNCHRONIZED_IO == 0) || (_POSIX_SYNCHRONIZED_IO >= 200112L)) 70 #define KSDC_SYNCHRONIZED_IO_SUPPORTED 1 74 #if defined(KSDC_MAPPED_FILES_SUPPORTED) && defined(KSDC_SYNCHRONIZED_IO_SUPPORTED) 75 #define KSDC_MSYNC_SUPPORTED 80 #if defined(_POSIX_ADVISORY_INFO) && ((_POSIX_ADVISORY_INFO == 0) || (_POSIX_ADVISORY_INFO >= 200112L)) 81 #define KSDC_POSIX_FALLOCATE_SUPPORTED 1 88 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) 89 #define MAP_ANONYMOUS MAP_ANON 107 processSharingSupported =
false;
130 : m_spinlock(spinlock)
138 processSharingSupported =
true;
146 for (
unsigned i = 50; i > 0; --i) {
147 if (m_spinlock.testAndSetAcquire(0, 1)) {
161 m_spinlock.testAndSetRelease(1, 0);
166 __attribute__((always_inline, gnu_inline, artificial))
168 static inline void loopSpinPause()
172 #ifdef _POSIX_PRIORITY_SCHEDULING 176 struct timespec wait_time = { 0 , 100 };
177 ::nanosleep(&wait_time, static_cast<struct timespec*>(0));
181 QBasicAtomicInt &m_spinlock;
184 #ifdef KSDC_THREAD_PROCESS_SHARED_SUPPORTED 188 pthreadLock(pthread_mutex_t &mutex)
193 virtual bool initialize(
bool &processSharingSupported)
196 pthread_mutexattr_t mutexAttr;
197 processSharingSupported =
false;
201 if (::sysconf(_SC_THREAD_PROCESS_SHARED) >= 200112L && pthread_mutexattr_init(&mutexAttr) == 0) {
202 if (pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED) == 0 &&
203 pthread_mutex_init(&m_mutex, &mutexAttr) == 0)
205 processSharingSupported =
true;
207 pthread_mutexattr_destroy(&mutexAttr);
211 if (!processSharingSupported && pthread_mutex_init(&m_mutex, NULL) != 0) {
220 return pthread_mutex_lock(&m_mutex) == 0;
225 pthread_mutex_unlock(&m_mutex);
229 pthread_mutex_t &m_mutex;
233 #if defined(KSDC_THREAD_PROCESS_SHARED_SUPPORTED) && defined(KSDC_TIMEOUTS_SUPPORTED) 234 class pthreadTimedLock :
public pthreadLock
237 pthreadTimedLock(pthread_mutex_t &mutex)
244 struct timespec timeout;
249 timeout.tv_sec = 10 + ::time(NULL);
252 return pthread_mutex_timedlock(&m_mutex, &timeout) == 0;
257 #ifdef KSDC_SEMAPHORES_SUPPORTED 258 class semaphoreLock :
public KSDCLock 261 semaphoreLock(sem_t &semaphore)
262 : m_semaphore(semaphore)
266 virtual bool initialize(
bool &processSharingSupported)
268 processSharingSupported =
false;
269 if (::sysconf(_SC_SEMAPHORES) < 200112L) {
274 if (sem_init(&m_semaphore, 1, 1) == 0) {
275 processSharingSupported =
true;
278 else if (sem_init(&m_semaphore, 0, 1) != 0) {
287 return sem_wait(&m_semaphore) == 0;
292 sem_post(&m_semaphore);
300 #if defined(KSDC_SEMAPHORES_SUPPORTED) && defined(KSDC_TIMEOUTS_SUPPORTED) 301 class semaphoreTimedLock :
public semaphoreLock
304 semaphoreTimedLock(sem_t &semaphore)
305 : semaphoreLock(semaphore)
311 struct timespec timeout;
316 timeout.tv_sec = 10 + ::time(NULL);
319 return sem_timedwait(&m_semaphore, &timeout) == 0;
341 #if defined(KSDC_THREAD_PROCESS_SHARED_SUPPORTED) 342 pthread_mutex_t mutex;
344 #if defined(KSDC_SEMAPHORES_SUPPORTED) 369 bool timeoutsSupported =
false;
370 bool pthreadsProcessShared =
false;
371 bool semaphoresProcessShared =
false;
373 #ifdef KSDC_TIMEOUTS_SUPPORTED 374 timeoutsSupported = ::sysconf(_SC_TIMEOUTS) >= 200112L;
379 #ifdef KSDC_THREAD_PROCESS_SHARED_SUPPORTED 381 pthread_mutex_t tempMutex;
382 QSharedPointer<KSDCLock> tempLock(0);
383 if (timeoutsSupported) {
384 #ifdef KSDC_TIMEOUTS_SUPPORTED 385 tempLock = QSharedPointer<KSDCLock>(
new pthreadTimedLock(tempMutex));
389 tempLock = QSharedPointer<KSDCLock>(
new pthreadLock(tempMutex));
392 tempLock->initialize(pthreadsProcessShared);
397 if(timeoutsSupported && pthreadsProcessShared) {
401 #ifdef KSDC_SEMAPHORES_SUPPORTED 404 QSharedPointer<KSDCLock> tempLock(0);
405 if (timeoutsSupported) {
406 tempLock = QSharedPointer<KSDCLock>(
new semaphoreTimedLock(tempSemaphore));
409 tempLock = QSharedPointer<KSDCLock>(
new semaphoreLock(tempSemaphore));
412 tempLock->initialize(semaphoresProcessShared);
416 if(timeoutsSupported && semaphoresProcessShared) {
419 else if(pthreadsProcessShared) {
422 else if(semaphoresProcessShared) {
433 #ifdef KSDC_THREAD_PROCESS_SHARED_SUPPORTED 435 #ifdef KSDC_TIMEOUTS_SUPPORTED 436 if (::sysconf(_SC_TIMEOUTS) >= 200112L) {
437 return new pthreadTimedLock(lock.mutex);
440 return new pthreadLock(lock.mutex);
445 #ifdef KSDC_SEMAPHORES_SUPPORTED 447 #ifdef KSDC_TIMEOUTS_SUPPORTED 448 if (::sysconf(_SC_SEMAPHORES) >= 200112L) {
449 return new semaphoreTimedLock(lock.semaphore);
452 return new semaphoreLock(lock.semaphore);
469 #ifdef KSDC_POSIX_FALLOCATE_SUPPORTED 471 while ((result = ::posix_fallocate(fd, 0, fileSize)) == EINTR) {
478 <<
"bytes for mapped cache, " 479 "abandoning the cache for crash-safety.";
487 #warning "This system does not seem to support posix_fallocate, which is needed to ensure KSharedDataCache's underlying files are fully committed to disk to avoid crashes with low disk space." 490 " -- ensure this partition has room for at least" 491 << fileSize <<
"bytes.";
static SharedLockId findBestSharedLock()
This is a method to determine the best lock type to use for a shared cache, based on local support...
virtual bool initialize(bool &processSharingSupported)
static bool ensureFileAllocated(int fd, size_t fileSize)
static QDebug kError(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
This is a very basic lock that should work on any system where GCC atomic intrinsics are supported...
simpleSpinLock(QBasicAtomicInt &spinlock)
virtual bool initialize(bool &processSharingSupported)
static KSDCLock * createLockFromId(SharedLockId id, SharedLock &lock)
This class defines an interface used by KSharedDataCache::Private to offload proper locking and unloc...