Serene Runtime 1.0.0
C runtime for the Serene programming language
Loading...
Searching...
No Matches
thread_posix.c File Reference

POSIX implementation of the thread-level operations in serene/rt/fiber/thread.h, realised with pthreads. More...

#include "serene/rt/fiber/thread.h"
#include "serene/utils.h"
#include <errno.h>
Include dependency graph for thread_posix.c:

Go to the source code of this file.

Macros

#define THREAD_LOG(FMT, ...)
 

Functions

static srn_thread_status_t status_from_errno (int rc)
 Map a pthreads return code onto the neutral status.
 
static void * posix_trampoline (void *arg)
 pthreads run a thread through a void *(*)(void *) routine, while the modeled operation runs a void (*)(void *).
 
srn_thread_status_t srn_thread_spawn (srn_thread_t *t, void(*fn)(void *), void *arg)
 Run fn(arg) on a new OS thread.
 
srn_thread_status_t srn_thread_join (srn_thread_t *t)
 Block until the thread started for t returns.
 
srn_thread_status_t srn_mutex_init (srn_mutex_t *m)
 
srn_thread_status_t srn_mutex_lock (srn_mutex_t *m)
 
srn_thread_status_t srn_mutex_unlock (srn_mutex_t *m)
 
srn_thread_status_t srn_mutex_destroy (srn_mutex_t *m)
 Release a mutex's resources.
 
srn_thread_status_t srn_cond_init (srn_cond_t *c)
 
srn_thread_status_t srn_cond_wait (srn_cond_t *c, srn_mutex_t *m)
 Release m, sleep until notified, then re-acquire m before returning.
 
srn_thread_status_t srn_cond_notify_one (srn_cond_t *c)
 Wake one waiter.
 
srn_thread_status_t srn_cond_notify_all (srn_cond_t *c)
 Wake every waiter.
 
srn_thread_status_t srn_cond_destroy (srn_cond_t *c)
 Release a condition's resources.
 

Detailed Description

POSIX implementation of the thread-level operations in serene/rt/fiber/thread.h, realised with pthreads.

The pthreads mutex and condition functions return their error code as the return value and leave the global errno untouched. Every such code is mapped to an srn_thread_status_t so no pthread code escapes the public API. The raw code is also logged through THREAD_LOG, which is a debug-only diagnostic and not part of the interface.

Definition in file thread_posix.c.

Macro Definition Documentation

◆ THREAD_LOG

#define THREAD_LOG ( FMT,
... )
Value:
DBG("THREAD", FMT __VA_OPT__(, ) __VA_ARGS__)
#define DBG(...)
Definition utils.h:177

Definition at line 33 of file thread_posix.c.

Function Documentation

◆ posix_trampoline()

static void * posix_trampoline ( void * arg)
static

pthreads run a thread through a void *(*)(void *) routine, while the modeled operation runs a void (*)(void *).

This trampoline bridges the two: it reads the function and argument the spawn recorded on the thread, runs them, and returns the null pthreads expects.

Definition at line 57 of file thread_posix.c.

57 {
58 srn_thread_t *t = arg;
59 t->fn(t->arg);
60 return nullptr;
61}
void * arg
Definition thread.h:47
void(* fn)(void *)
The function the thread runs and its argument, recorded by srn_thread_spawn and read once by the back...
Definition thread.h:46
Here is the caller graph for this function:

◆ srn_cond_destroy()

srn_thread_status_t srn_cond_destroy ( srn_cond_t * c)

Release a condition's resources.

It must have no waiters, and must not be used again without a fresh srn_cond_init.

Definition at line 160 of file thread_posix.c.

160 {
161 PANIC_IF_NULL(c);
162 int rc = pthread_cond_destroy(&c->handle);
163 if (rc != 0) {
164 THREAD_LOG("pthread_cond_destroy failed (errno %d)", rc);
165 }
166 return status_from_errno(rc);
167}
pthread_cond_t handle
Definition thread.h:55
#define THREAD_LOG(FMT,...)
static srn_thread_status_t status_from_errno(int rc)
Map a pthreads return code onto the neutral status.
#define PANIC_IF_NULL(ptr)
Definition utils.h:64
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_cond_init()

srn_thread_status_t srn_cond_init ( srn_cond_t * c)

Definition at line 123 of file thread_posix.c.

123 {
124 PANIC_IF_NULL(c);
125 int rc = pthread_cond_init(&c->handle, nullptr);
126 if (rc != 0) {
127 THREAD_LOG("pthread_cond_init failed (errno %d)", rc);
128 }
129 return status_from_errno(rc);
130}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_cond_notify_all()

srn_thread_status_t srn_cond_notify_all ( srn_cond_t * c)

Wake every waiter.

Definition at line 151 of file thread_posix.c.

151 {
152 PANIC_IF_NULL(c);
153 int rc = pthread_cond_broadcast(&c->handle);
154 if (rc != 0) {
155 THREAD_LOG("pthread_cond_broadcast failed (errno %d)", rc);
156 }
157 return status_from_errno(rc);
158}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_cond_notify_one()

srn_thread_status_t srn_cond_notify_one ( srn_cond_t * c)

Wake one waiter.

Definition at line 142 of file thread_posix.c.

142 {
143 PANIC_IF_NULL(c);
144 int rc = pthread_cond_signal(&c->handle);
145 if (rc != 0) {
146 THREAD_LOG("pthread_cond_signal failed (errno %d)", rc);
147 }
148 return status_from_errno(rc);
149}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_cond_wait()

srn_thread_status_t srn_cond_wait ( srn_cond_t * c,
srn_mutex_t * m )

Release m, sleep until notified, then re-acquire m before returning.

A wait can wake spuriously, so the caller must re-check its predicate in a loop.

Definition at line 132 of file thread_posix.c.

132 {
133 PANIC_IF_NULL(c);
134 PANIC_IF_NULL(m);
135 int rc = pthread_cond_wait(&c->handle, &m->handle);
136 if (rc != 0) {
137 THREAD_LOG("pthread_cond_wait failed (errno %d)", rc);
138 }
139 return status_from_errno(rc);
140}
pthread_mutex_t handle
Definition thread.h:51
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_mutex_destroy()

srn_thread_status_t srn_mutex_destroy ( srn_mutex_t * m)

Release a mutex's resources.

The mutex must be unlocked and have no waiters, and must not be used again without a fresh srn_mutex_init.

Definition at line 114 of file thread_posix.c.

114 {
115 PANIC_IF_NULL(m);
116 int rc = pthread_mutex_destroy(&m->handle);
117 if (rc != 0) {
118 THREAD_LOG("pthread_mutex_destroy failed (errno %d)", rc);
119 }
120 return status_from_errno(rc);
121}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_mutex_init()

srn_thread_status_t srn_mutex_init ( srn_mutex_t * m)

Definition at line 87 of file thread_posix.c.

87 {
89 int rc = pthread_mutex_init(&m->handle, nullptr);
90 if (rc != 0) {
91 THREAD_LOG("pthread_mutex_init failed (errno %d)", rc);
92 }
93 return status_from_errno(rc);
94}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_mutex_lock()

srn_thread_status_t srn_mutex_lock ( srn_mutex_t * m)

Definition at line 96 of file thread_posix.c.

96 {
98 int rc = pthread_mutex_lock(&m->handle);
99 if (rc != 0) {
100 THREAD_LOG("pthread_mutex_lock failed (errno %d)", rc);
101 }
102 return status_from_errno(rc);
103}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_mutex_unlock()

srn_thread_status_t srn_mutex_unlock ( srn_mutex_t * m)

Definition at line 105 of file thread_posix.c.

105 {
106 PANIC_IF_NULL(m);
107 int rc = pthread_mutex_unlock(&m->handle);
108 if (rc != 0) {
109 THREAD_LOG("pthread_mutex_unlock failed (errno %d)", rc);
110 }
111 return status_from_errno(rc);
112}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_thread_join()

srn_thread_status_t srn_thread_join ( srn_thread_t * t)

Block until the thread started for t returns.

Definition at line 77 of file thread_posix.c.

77 {
79 // The thread's return value is discarded. The trampoline always returns null.
80 int rc = pthread_join(t->handle, nullptr);
81 if (rc != 0) {
82 THREAD_LOG("pthread_join failed (errno %d)", rc);
83 }
84 return status_from_errno(rc);
85}
pthread_t handle
Definition thread.h:41
Here is the call graph for this function:
Here is the caller graph for this function:

◆ srn_thread_spawn()

srn_thread_status_t srn_thread_spawn ( srn_thread_t * t,
void(* fn )(void *),
void * arg )

Run fn(arg) on a new OS thread.

Returns SRN_THREAD_OK, or a status describing why the thread could not be created. The caller owns t and must keep it alive until srn_thread_join returns.

Definition at line 63 of file thread_posix.c.

63 {
65 PANIC_IF_NULL(fn);
66
67 t->fn = fn;
68 t->arg = arg;
69
70 int rc = pthread_create(&t->handle, nullptr, posix_trampoline, t);
71 if (rc != 0) {
72 THREAD_LOG("pthread_create failed (errno %d)", rc);
73 }
74 return status_from_errno(rc);
75}
static void * posix_trampoline(void *arg)
pthreads run a thread through a void *(*)(void *) routine, while the modeled operation runs a void (*...
Here is the call graph for this function:
Here is the caller graph for this function:

◆ status_from_errno()

static srn_thread_status_t status_from_errno ( int rc)
static

Map a pthreads return code onto the neutral status.

Anything without a dedicated code (EDEADLK, EINVAL, ESRCH, and so on) becomes SRN_THREAD_ERROR. The precise code is recovered from the THREAD_LOG line at the call site.

Definition at line 38 of file thread_posix.c.

38 {
39 switch (rc) {
40 case 0:
41 return SRN_THREAD_OK;
42 case EAGAIN:
43 return SRN_THREAD_AGAIN;
44 case ENOMEM:
45 return SRN_THREAD_NOMEM;
46 case EPERM:
47 return SRN_THREAD_PERM;
48 default:
49 return SRN_THREAD_ERROR;
50 }
51}
@ SRN_THREAD_AGAIN
The system lacked the resources to start the thread, such as a per-process thread limit.
Definition thread.h:65
@ SRN_THREAD_OK
Definition thread.h:62
@ SRN_THREAD_ERROR
A failure the backend could not map to the above.
Definition thread.h:71
@ SRN_THREAD_PERM
The caller lacks permission for the requested operation.
Definition thread.h:69
@ SRN_THREAD_NOMEM
Out of memory.
Definition thread.h:67
Here is the caller graph for this function: