2
* librd - Rapid Development C library
4
* Copyright (c) 2012-2013, Magnus Edenhill
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions are met:
10
* 1. Redistributions of source code must retain the above copyright notice,
11
* this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright notice,
13
* this list of conditions and the following disclaimer in the documentation
14
* and/or other materials provided with the distribution.
16
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
* POSSIBILITY OF SUCH DAMAGE.
36
#include <sys/prctl.h>
40
rd_thread_t *rd_mainthread;
41
__thread rd_thread_t *rd_currthread;
44
void rd_thread_init (void) {
45
pthread_t thr = pthread_self();
46
rd_mainthread = rd_thread_create0("main", &thr);
47
rd_currthread = rd_mainthread;
50
int rd_thread_poll (int timeout_ms) {
53
int nowait = timeout_ms == 0;
55
while ((rfqe = rd_fifoq_pop0(&rd_currthread->rdt_eventq,
56
nowait, timeout_ms))) {
57
rd_thread_event_t *rte = rfqe->rfqe_ptr;
59
rd_thread_event_call(rte);
61
rd_fifoq_elm_release(&rd_currthread->rdt_eventq, rfqe);
70
static void rd_thread_destroy (rd_thread_t *rdt) {
71
assert(rdt->rdt_state != RD_THREAD_S_RUNNING);
74
rd_fifoq_destroy(&rdt->rdt_eventq);
78
void rd_thread_cleanup (void) {
82
void rd_thread_dispatch (void) {
84
while (rd_currthread->rdt_state == RD_THREAD_S_RUNNING) {
85
/* FIXME: Proper conding for all thread inputs. */
93
static void *rd_thread_start_routine (void *arg) {
94
rd_thread_t *rdt = arg;
97
/* By default with block the user-defined signals. */
98
rd_thread_sigmask(SIG_BLOCK, SIGUSR1, SIGUSR2, RD_SIG_END);
102
ret = rdt->rdt_start(rdt->rdt_start_arg);
105
rd_thread_destroy(rdt);
111
rd_thread_t *rd_thread_create0 (const char *name, pthread_t *pthread) {
114
rdt = calloc(1, sizeof(*rdt));
117
rdt->rdt_name = strdup(name);
119
rdt->rdt_state = RD_THREAD_S_RUNNING;
121
rd_fifoq_init(&rdt->rdt_eventq);
124
rdt->rdt_thread = *pthread;
130
int rd_thread_create (rd_thread_t **rdt,
132
const pthread_attr_t *attr,
133
void *(*start_routine)(void*),
137
rdt0 = rd_thread_create0(name, NULL);
139
rdt0->rdt_start = start_routine;
140
rdt0->rdt_start_arg = arg;
145
/* FIXME: We should block all signals until pthread_create returns. */
146
if (pthread_create(&rdt0->rdt_thread, attr,
147
rd_thread_start_routine, rdt0)) {
148
int errno_save = errno;
149
rd_thread_destroy(rdt0);
157
prctl(PR_SET_NAME, (char *)rdt0->rdt_name, 0, 0, 0);
164
int rd_threads_create (const char *nameprefix, int threadcount,
165
const pthread_attr_t *attr,
166
void *(*start_routine)(void*),
169
char *name = alloca(strlen(nameprefix) + 4);
172
if (threadcount >= 1000) {
177
for (i = 0 ; i < threadcount ; i++) {
178
sprintf(name, "%s%i", nameprefix, i);
179
if (!rd_thread_create(NULL, name, attr, start_routine, arg))
183
if (failed == threadcount)
186
return threadcount - failed;
190
int rd_thread_sigmask (int how, ...) {
198
while ((sig = va_arg(ap, int)) != RD_SIG_END) {
199
if (sig == RD_SIG_ALL)
202
sigaddset(&set, sig);
206
return pthread_sigmask(how, &set, NULL);