Files
swift-mirror/stdlib/public/runtime/MutexPThread.cpp
Saleem Abdulrasool d9ba70a595 runtime: tweak the compilation
Always include all the sources as we cannot include object libraries to be
subsumed.  This allows us to conditionally build the swift runtime for foreign
hosts simultaneously (e.g. cross compile for Linux and Windows simultaneously).
2016-06-22 21:38:15 -07:00

147 lines
5.1 KiB
C++

//===--- MutexPThread.cpp - Supports Mutex.h using PThreads ---------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// Mutex, ConditionVariable, Read/Write lock, and Scoped lock implementations
// using PThreads.
//
//===----------------------------------------------------------------------===//
#if !defined(_WIN32)
#include "swift/Runtime/Mutex.h"
#include "swift/Runtime/Debug.h"
#include <errno.h>
#include <stdlib.h>
using namespace swift;
#define reportError(PThreadFunction) \
do { \
int errorcode = PThreadFunction; \
if (errorcode != 0) { \
fatalError(/* flags = */ 0, "'%s' failed with error '%s'(%d)\n", \
#PThreadFunction, errorName(errorcode), errorcode); \
} \
} while (false)
#define returnTrueOrReportError(PThreadFunction, returnFalseOnEBUSY) \
do { \
int errorcode = PThreadFunction; \
if (errorcode == 0) \
return true; \
if (returnFalseOnEBUSY && errorcode == EBUSY) \
return false; \
fatalError(/* flags = */ 0, "'%s' failed with error '%s'(%d)\n", \
#PThreadFunction, errorName(errorcode), errorcode); \
} while (false)
static const char *errorName(int errorcode) {
switch (errorcode) {
case EINVAL:
return "EINVAL";
case EPERM:
return "EPERM";
case EDEADLK:
return "EDEADLK";
case ENOMEM:
return "ENOMEM";
case EAGAIN:
return "EAGAIN";
case EBUSY:
return "EBUSY";
default:
return "<unknown>";
}
}
void ConditionPlatformHelper::init(pthread_cond_t &condition) {
reportError(pthread_cond_init(&condition, nullptr));
}
void ConditionPlatformHelper::destroy(pthread_cond_t &condition) {
reportError(pthread_cond_destroy(&condition));
}
void ConditionPlatformHelper::notifyOne(pthread_cond_t &condition) {
reportError(pthread_cond_signal(&condition));
}
void ConditionPlatformHelper::notifyAll(pthread_cond_t &condition) {
reportError(pthread_cond_broadcast(&condition));
}
void ConditionPlatformHelper::wait(pthread_cond_t &condition,
pthread_mutex_t &mutex) {
reportError(pthread_cond_wait(&condition, &mutex));
}
void MutexPlatformHelper::init(pthread_mutex_t &mutex, bool checked) {
pthread_mutexattr_t attr;
int kind = (checked ? PTHREAD_MUTEX_ERRORCHECK : PTHREAD_MUTEX_NORMAL);
reportError(pthread_mutexattr_init(&attr));
reportError(pthread_mutexattr_settype(&attr, kind));
reportError(pthread_mutex_init(&mutex, &attr));
reportError(pthread_mutexattr_destroy(&attr));
}
void MutexPlatformHelper::destroy(pthread_mutex_t &mutex) {
reportError(pthread_mutex_destroy(&mutex));
}
void MutexPlatformHelper::lock(pthread_mutex_t &mutex) {
reportError(pthread_mutex_lock(&mutex));
}
void MutexPlatformHelper::unlock(pthread_mutex_t &mutex) {
reportError(pthread_mutex_unlock(&mutex));
}
bool MutexPlatformHelper::try_lock(pthread_mutex_t &mutex) {
returnTrueOrReportError(pthread_mutex_trylock(&mutex),
/* returnFalseOnEBUSY = */ true);
}
void ReadWriteLockPlatformHelper::init(pthread_rwlock_t &rwlock) {
reportError(pthread_rwlock_init(&rwlock, nullptr));
}
void ReadWriteLockPlatformHelper::destroy(pthread_rwlock_t &rwlock) {
reportError(pthread_rwlock_destroy(&rwlock));
}
void ReadWriteLockPlatformHelper::readLock(pthread_rwlock_t &rwlock) {
reportError(pthread_rwlock_rdlock(&rwlock));
}
bool ReadWriteLockPlatformHelper::try_readLock(pthread_rwlock_t &rwlock) {
returnTrueOrReportError(pthread_rwlock_tryrdlock(&rwlock),
/* returnFalseOnEBUSY = */ true);
}
void ReadWriteLockPlatformHelper::writeLock(pthread_rwlock_t &rwlock) {
reportError(pthread_rwlock_wrlock(&rwlock));
}
bool ReadWriteLockPlatformHelper::try_writeLock(pthread_rwlock_t &rwlock) {
returnTrueOrReportError(pthread_rwlock_trywrlock(&rwlock),
/* returnFalseOnEBUSY = */ true);
}
void ReadWriteLockPlatformHelper::readUnlock(pthread_rwlock_t &rwlock) {
reportError(pthread_rwlock_unlock(&rwlock));
}
void ReadWriteLockPlatformHelper::writeUnlock(pthread_rwlock_t &rwlock) {
reportError(pthread_rwlock_unlock(&rwlock));
}
#endif