20 #ifndef KSHAREDDATACACHE_P_H
21 #define KSHAREDDATACACHE_P_H
23 #include <config-util.h>
25 #include <QtCore/QSharedPointer>
26 #include <QtCore/QBasicAtomicInt>
47 #if defined(_POSIX_TIMEOUTS) && ((_POSIX_TIMEOUTS == 0) || (_POSIX_TIMEOUTS >= 200112L))
48 #define KSDC_TIMEOUTS_SUPPORTED 1
51 #if defined(__GNUC__) && !defined(KSDC_TIMEOUTS_SUPPORTED)
52 #warning "No support for POSIX timeouts -- application hangs are possible if the cache is corrupt"
55 #if defined(_POSIX_THREAD_PROCESS_SHARED) && ((_POSIX_THREAD_PROCESS_SHARED == 0) || (_POSIX_THREAD_PROCESS_SHARED >= 200112L))
57 #define KSDC_THREAD_PROCESS_SHARED_SUPPORTED 1
60 #if defined(_POSIX_SEMAPHORES) && ((_POSIX_SEMAPHORES == 0) || (_POSIX_SEMAPHORES >= 200112L))
61 #include <semaphore.h>
62 #define KSDC_SEMAPHORES_SUPPORTED 1
65 #if defined(__GNUC__) && !defined(KSDC_SEMAPHORES_SUPPORTED) && !defined(KSDC_THREAD_PROCESS_SHARED_SUPPORTED)
66 #warning "No system support claimed for process-shared synchronization, KSharedDataCache will be mostly useless."
69 #if defined(_POSIX_MAPPED_FILES) && ((_POSIX_MAPPED_FILES == 0) || (_POSIX_MAPPED_FILES >= 200112L))
70 #define KSDC_MAPPED_FILES_SUPPORTED 1
73 #if defined(_POSIX_SYNCHRONIZED_IO) && ((_POSIX_SYNCHRONIZED_IO == 0) || (_POSIX_SYNCHRONIZED_IO >= 200112L))
74 #define KSDC_SYNCHRONIZED_IO_SUPPORTED 1
78 #if defined(KSDC_MAPPED_FILES_SUPPORTED) && defined(KSDC_SYNCHRONIZED_IO_SUPPORTED)
79 #define KSDC_MSYNC_SUPPORTED
84 #if (defined(_POSIX_ADVISORY_INFO) && ((_POSIX_ADVISORY_INFO == 0) || (_POSIX_ADVISORY_INFO >= 200112L))) || defined(__APPLE__)
85 #define KSDC_POSIX_FALLOCATE_SUPPORTED 1
92 #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
93 #define MAP_ANONYMOUS MAP_ANON
111 processSharingSupported =
false;
134 : m_spinlock(spinlock)
142 processSharingSupported =
true;
150 for (
unsigned i = 50; i > 0; --i) {
151 if (m_spinlock.testAndSetAcquire(0, 1)) {
165 m_spinlock.testAndSetRelease(1, 0);
170 __attribute__((always_inline, gnu_inline, artificial))
172 static inline void loopSpinPause()
176 #ifdef _POSIX_PRIORITY_SCHEDULING
180 struct timespec wait_time = { 0 , 100 };
181 ::nanosleep(&wait_time, static_cast<struct timespec*>(0));
185 QBasicAtomicInt &m_spinlock;
188 #ifdef KSDC_THREAD_PROCESS_SHARED_SUPPORTED
192 pthreadLock(pthread_mutex_t &mutex)
197 virtual bool initialize(
bool &processSharingSupported)
200 pthread_mutexattr_t mutexAttr;
201 processSharingSupported =
false;
205 if (::sysconf(_SC_THREAD_PROCESS_SHARED) >= 200112L && pthread_mutexattr_init(&mutexAttr) == 0) {
206 if (pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED) == 0 &&
207 pthread_mutex_init(&m_mutex, &mutexAttr) == 0)
209 processSharingSupported =
true;
211 pthread_mutexattr_destroy(&mutexAttr);
215 if (!processSharingSupported && pthread_mutex_init(&m_mutex, NULL) != 0) {
224 return pthread_mutex_lock(&m_mutex) == 0;
229 pthread_mutex_unlock(&m_mutex);
233 pthread_mutex_t &m_mutex;
237 #if defined(KSDC_THREAD_PROCESS_SHARED_SUPPORTED) && defined(KSDC_TIMEOUTS_SUPPORTED)
238 class pthreadTimedLock :
public pthreadLock
241 pthreadTimedLock(pthread_mutex_t &mutex)
253 timeout.tv_sec = 10 + ::time(NULL);
256 return pthread_mutex_timedlock(&m_mutex, &
timeout) == 0;
261 #ifdef KSDC_SEMAPHORES_SUPPORTED
262 class semaphoreLock :
public KSDCLock
265 semaphoreLock(sem_t &semaphore)
266 : m_semaphore(semaphore)
270 virtual bool initialize(
bool &processSharingSupported)
272 processSharingSupported =
false;
273 if (::sysconf(_SC_SEMAPHORES) < 200112L) {
278 if (sem_init(&m_semaphore, 1, 1) == 0) {
279 processSharingSupported =
true;
282 else if (sem_init(&m_semaphore, 0, 1) != 0) {
291 return sem_wait(&m_semaphore) == 0;
296 sem_post(&m_semaphore);
304 #if defined(KSDC_SEMAPHORES_SUPPORTED) && defined(KSDC_TIMEOUTS_SUPPORTED)
305 class semaphoreTimedLock :
public semaphoreLock
308 semaphoreTimedLock(sem_t &semaphore)
309 : semaphoreLock(semaphore)
320 timeout.tv_sec = 10 + ::time(NULL);
323 return sem_timedwait(&m_semaphore, &
timeout) == 0;
345 #if defined(KSDC_THREAD_PROCESS_SHARED_SUPPORTED)
346 pthread_mutex_t mutex;
348 #if defined(KSDC_SEMAPHORES_SUPPORTED)
373 bool timeoutsSupported =
false;
374 bool pthreadsProcessShared =
false;
375 bool semaphoresProcessShared =
false;
377 #ifdef KSDC_TIMEOUTS_SUPPORTED
378 timeoutsSupported = ::sysconf(_SC_TIMEOUTS) >= 200112L;
383 #ifdef KSDC_THREAD_PROCESS_SHARED_SUPPORTED
385 pthread_mutex_t tempMutex;
387 if (timeoutsSupported) {
388 #ifdef KSDC_TIMEOUTS_SUPPORTED
396 tempLock->initialize(pthreadsProcessShared);
401 if(timeoutsSupported && pthreadsProcessShared) {
405 #ifdef KSDC_SEMAPHORES_SUPPORTED
409 if (timeoutsSupported) {
416 tempLock->initialize(semaphoresProcessShared);
420 if(timeoutsSupported && semaphoresProcessShared) {
423 else if(pthreadsProcessShared) {
426 else if(semaphoresProcessShared) {
437 #ifdef KSDC_THREAD_PROCESS_SHARED_SUPPORTED
439 #ifdef KSDC_TIMEOUTS_SUPPORTED
440 if (::sysconf(_SC_TIMEOUTS) >= 200112L) {
441 return new pthreadTimedLock(lock.mutex);
444 return new pthreadLock(lock.mutex);
449 #ifdef KSDC_SEMAPHORES_SUPPORTED
451 #ifdef KSDC_TIMEOUTS_SUPPORTED
452 if (::sysconf(_SC_SEMAPHORES) >= 200112L) {
453 return new semaphoreTimedLock(lock.semaphore);
456 return new semaphoreLock(lock.semaphore);
473 #ifdef KSDC_POSIX_FALLOCATE_SUPPORTED
482 <<
"bytes for mapped cache, "
483 "abandoning the cache for crash-safety.";
491 #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."
494 " -- ensure this partition has room for at least"
495 << 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)
static int posix_fallocate(int fd, off_t offset, off_t len)
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...