summaryrefslogtreecommitdiff
path: root/rts/posix
diff options
context:
space:
mode:
Diffstat (limited to 'rts/posix')
-rw-r--r--rts/posix/GetTime.c6
-rw-r--r--rts/posix/OSThreads.c14
-rw-r--r--rts/posix/Signals.c48
-rw-r--r--rts/posix/itimer/Pthread.c19
4 files changed, 55 insertions, 32 deletions
diff --git a/rts/posix/GetTime.c b/rts/posix/GetTime.c
index 0128e3bc8b..7d53f95401 100644
--- a/rts/posix/GetTime.c
+++ b/rts/posix/GetTime.c
@@ -85,7 +85,9 @@ Time getCurrentThreadCPUTime(void)
defined(CLOCK_PROCESS_CPUTIME_ID) && \
defined(HAVE_SYSCONF)
static bool have_checked_usability = false;
- if (!have_checked_usability) {
+ // The RELAXED operation is fine here as it's okay if we do the check below
+ // more than once.
+ if (!RELAXED_LOAD(&have_checked_usability)) {
// The Linux clock_getres(2) manpage claims that some early versions of
// Linux will return values which are uninterpretable in the presence
// of migration across CPUs. They claim that clock_getcpuclockid(0)
@@ -95,7 +97,7 @@ Time getCurrentThreadCPUTime(void)
sysErrorBelch("getCurrentThreadCPUTime: no supported");
stg_exit(EXIT_FAILURE);
}
- have_checked_usability = true;
+ RELAXED_STORE(&have_checked_usability, true);
}
return getClockTime(CLOCK_THREAD_CPUTIME_ID);
#else
diff --git a/rts/posix/OSThreads.c b/rts/posix/OSThreads.c
index 42d72c2e0d..6347e8ce7a 100644
--- a/rts/posix/OSThreads.c
+++ b/rts/posix/OSThreads.c
@@ -240,13 +240,14 @@ forkOS_createThread ( HsStablePtr entry )
void freeThreadingResources (void) { /* nothing */ }
+static uint32_t nproc_cache = 0;
+
// Get the number of logical CPU cores available to us. Note that this is
// different from the number of physical cores (see #14781).
uint32_t
getNumberOfProcessors (void)
{
- static uint32_t nproc = 0;
-
+ uint32_t nproc = RELAXED_LOAD(&nproc_cache);
if (nproc == 0) {
#if defined(HAVE_SCHED_GETAFFINITY)
cpu_set_t mask;
@@ -287,6 +288,7 @@ getNumberOfProcessors (void)
#else
nproc = 1;
#endif
+ RELAXED_STORE(&nproc_cache, nproc);
}
return nproc;
@@ -396,6 +398,14 @@ interruptOSThread (OSThreadId id)
pthread_kill(id, SIGPIPE);
}
+void
+joinOSThread (OSThreadId id)
+{
+ if (pthread_join(id, NULL) != 0) {
+ sysErrorBelch("joinOSThread: error %d", errno);
+ }
+}
+
KernelThreadId kernelThreadId (void)
{
#if defined(linux_HOST_OS)
diff --git a/rts/posix/Signals.c b/rts/posix/Signals.c
index 2e534042f3..5ad688bc2f 100644
--- a/rts/posix/Signals.c
+++ b/rts/posix/Signals.c
@@ -128,7 +128,7 @@ more_handlers(int sig)
}
// Here's the pipe into which we will send our signals
-static volatile int io_manager_wakeup_fd = -1;
+static int io_manager_wakeup_fd = -1;
static int timer_manager_control_wr_fd = -1;
#define IO_MANAGER_WAKEUP 0xff
@@ -136,7 +136,7 @@ static int timer_manager_control_wr_fd = -1;
#define IO_MANAGER_SYNC 0xfd
void setTimerManagerControlFd(int fd) {
- timer_manager_control_wr_fd = fd;
+ RELAXED_STORE(&timer_manager_control_wr_fd, fd);
}
void
@@ -144,7 +144,7 @@ setIOManagerWakeupFd (int fd)
{
// only called when THREADED_RTS, but unconditionally
// compiled here because GHC.Event.Control depends on it.
- io_manager_wakeup_fd = fd;
+ SEQ_CST_STORE(&io_manager_wakeup_fd, fd);
}
/* -----------------------------------------------------------------------------
@@ -154,14 +154,15 @@ void
ioManagerWakeup (void)
{
int r;
+ const int wakeup_fd = SEQ_CST_LOAD(&io_manager_wakeup_fd);
// Wake up the IO Manager thread by sending a byte down its pipe
- if (io_manager_wakeup_fd >= 0) {
+ if (wakeup_fd >= 0) {
#if defined(HAVE_EVENTFD)
StgWord64 n = (StgWord64)IO_MANAGER_WAKEUP;
- r = write(io_manager_wakeup_fd, (char *) &n, 8);
+ r = write(wakeup_fd, (char *) &n, 8);
#else
StgWord8 byte = (StgWord8)IO_MANAGER_WAKEUP;
- r = write(io_manager_wakeup_fd, &byte, 1);
+ r = write(wakeup_fd, &byte, 1);
#endif
/* N.B. If the TimerManager is shutting down as we run this
* then there is a possibility that our first read of
@@ -174,7 +175,7 @@ ioManagerWakeup (void)
* Since this is not an error condition, we do not print the error
* message in this case.
*/
- if (r == -1 && io_manager_wakeup_fd >= 0) {
+ if (r == -1 && SEQ_CST_LOAD(&io_manager_wakeup_fd) >= 0) {
sysErrorBelch("ioManagerWakeup: write");
}
}
@@ -186,21 +187,27 @@ ioManagerDie (void)
{
StgWord8 byte = (StgWord8)IO_MANAGER_DIE;
uint32_t i;
- int fd;
int r;
- if (0 <= timer_manager_control_wr_fd) {
- r = write(timer_manager_control_wr_fd, &byte, 1);
- if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
- timer_manager_control_wr_fd = -1;
- }
-
- for (i=0; i < n_capabilities; i++) {
- fd = capabilities[i]->io_manager_control_wr_fd;
+ {
+ // Shut down timer manager
+ const int fd = RELAXED_LOAD(&timer_manager_control_wr_fd);
if (0 <= fd) {
r = write(fd, &byte, 1);
if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
- capabilities[i]->io_manager_control_wr_fd = -1;
+ RELAXED_STORE(&timer_manager_control_wr_fd, -1);
+ }
+ }
+
+ {
+ // Shut down IO managers
+ for (i=0; i < n_capabilities; i++) {
+ const int fd = RELAXED_LOAD(&capabilities[i]->io_manager_control_wr_fd);
+ if (0 <= fd) {
+ r = write(fd, &byte, 1);
+ if (r == -1) { sysErrorBelch("ioManagerDie: write"); }
+ RELAXED_STORE(&capabilities[i]->io_manager_control_wr_fd, -1);
+ }
}
}
}
@@ -216,7 +223,7 @@ ioManagerStart (void)
{
// Make sure the IO manager thread is running
Capability *cap;
- if (timer_manager_control_wr_fd < 0 || io_manager_wakeup_fd < 0) {
+ if (SEQ_CST_LOAD(&timer_manager_control_wr_fd) < 0 || SEQ_CST_LOAD(&io_manager_wakeup_fd) < 0) {
cap = rts_lock();
ioManagerStartCap(&cap);
rts_unlock(cap);
@@ -258,9 +265,10 @@ generic_handler(int sig USED_IF_THREADS,
memcpy(buf+1, info, sizeof(siginfo_t));
}
- if (0 <= timer_manager_control_wr_fd)
+ int timer_control_fd = RELAXED_LOAD(&timer_manager_control_wr_fd);
+ if (0 <= timer_control_fd)
{
- r = write(timer_manager_control_wr_fd, buf, sizeof(siginfo_t)+1);
+ r = write(timer_control_fd, buf, sizeof(siginfo_t)+1);
if (r == -1 && errno == EAGAIN) {
errorBelch("lost signal due to full pipe: %d\n", sig);
}
diff --git a/rts/posix/itimer/Pthread.c b/rts/posix/itimer/Pthread.c
index dd36137b72..82379b9172 100644
--- a/rts/posix/itimer/Pthread.c
+++ b/rts/posix/itimer/Pthread.c
@@ -85,11 +85,11 @@ static Time itimer_interval = DEFAULT_TICK_INTERVAL;
// Should we be firing ticks?
// Writers to this must hold the mutex below.
-static volatile bool stopped = false;
+static bool stopped = false;
// should the ticker thread exit?
// This can be set without holding the mutex.
-static volatile bool exited = true;
+static bool exited = true;
// Signaled when we want to (re)start the timer
static Condition start_cond;
@@ -120,7 +120,9 @@ static void *itimer_thread_func(void *_handle_tick)
}
#endif
- while (!exited) {
+ // Relaxed is sufficient: If we don't see that exited was set in one iteration we will
+ // see it next time.
+ while (!RELAXED_LOAD(&exited)) {
if (USE_TIMERFD_FOR_ITIMER) {
ssize_t r = read(timerfd, &nticks, sizeof(nticks));
if ((r == 0) && (errno == 0)) {
@@ -142,7 +144,8 @@ static void *itimer_thread_func(void *_handle_tick)
}
// first try a cheap test
- if (stopped) {
+ TSAN_ANNOTATE_BENIGN_RACE(&stopped, "itimer_thread_func");
+ if (RELAXED_LOAD(&stopped)) {
OS_ACQUIRE_LOCK(&mutex);
// should we really stop?
if (stopped) {
@@ -186,7 +189,7 @@ void
startTicker(void)
{
OS_ACQUIRE_LOCK(&mutex);
- stopped = 0;
+ RELAXED_STORE(&stopped, false);
signalCondition(&start_cond);
OS_RELEASE_LOCK(&mutex);
}
@@ -196,7 +199,7 @@ void
stopTicker(void)
{
OS_ACQUIRE_LOCK(&mutex);
- stopped = 1;
+ RELAXED_STORE(&stopped, true);
OS_RELEASE_LOCK(&mutex);
}
@@ -204,8 +207,8 @@ stopTicker(void)
void
exitTicker (bool wait)
{
- ASSERT(!exited);
- exited = true;
+ ASSERT(!SEQ_CST_LOAD(&exited));
+ SEQ_CST_STORE(&exited, true);
// ensure that ticker wakes up if stopped
startTicker();