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

srn_thread_t, srn_mutex_t, and srn_cond_t model the thread-level operations the runtime needs, with semantics defined here rather than borrowed from one OS API. More...

#include <pthread.h>
Include dependency graph for thread.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  srn_thread_t
 
struct  srn_mutex_t
 
struct  srn_cond_t
 

Typedefs

typedef struct srn_thread_t srn_thread_t
 
typedef struct srn_mutex_t srn_mutex_t
 
typedef struct srn_cond_t srn_cond_t
 
typedef enum srn_thread_status_t srn_thread_status_t
 Result of a thread operation.
 

Enumerations

enum  srn_thread_status_t {
  SRN_THREAD_OK = 0 , SRN_THREAD_AGAIN , SRN_THREAD_NOMEM , SRN_THREAD_PERM ,
  SRN_THREAD_ERROR
}
 Result of a thread operation. More...
 

Functions

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

srn_thread_t, srn_mutex_t, and srn_cond_t model the thread-level operations the runtime needs, with semantics defined here rather than borrowed from one OS API.

The status enum and the operation signatures below are platform-neutral. Only the type realizations differ per platform, so each backend defines the three types over its own primitives inside the matching branch. pthreads back them on POSIX. A Windows backend realises the same operations on the Win32 API directly, so neither platform emulates the other. The types are thin wrappers so they embed inline in another struct rather than needing a separate allocation.

Bear in mind that, we only expose what we need. THIS IS NOT A GENERICE THREAD INTERFACE.

Definition in file thread.h.

Typedef Documentation

◆ srn_cond_t

typedef struct srn_cond_t srn_cond_t

◆ srn_mutex_t

typedef struct srn_mutex_t srn_mutex_t

◆ srn_thread_status_t

Result of a thread operation.

Each backend maps its own error space onto these, so a caller never sees a pthread or Win32 code.

◆ srn_thread_t

typedef struct srn_thread_t srn_thread_t

Enumeration Type Documentation

◆ srn_thread_status_t

Result of a thread operation.

Each backend maps its own error space onto these, so a caller never sees a pthread or Win32 code.

Enumerator
SRN_THREAD_OK 
SRN_THREAD_AGAIN 

The system lacked the resources to start the thread, such as a per-process thread limit.

Retrying after others exit may succeed.

SRN_THREAD_NOMEM 

Out of memory.

SRN_THREAD_PERM 

The caller lacks permission for the requested operation.

SRN_THREAD_ERROR 

A failure the backend could not map to the above.

Definition at line 61 of file thread.h.

61 {
62 SRN_THREAD_OK = 0,
63 /// The system lacked the resources to start the thread, such as a per-process
64 /// thread limit. Retrying after others exit may succeed.
66 /// Out of memory.
68 /// The caller lacks permission for the requested operation.
70 /// A failure the backend could not map to the above.
srn_thread_status_t
Result of a thread operation.
Definition thread.h:61
@ 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

Function Documentation

◆ 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}
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
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: