1*36ec32beSkamil /* $NetBSD: thrd.c,v 1.4 2019/09/10 22:34:19 kamil Exp $ */
2a9ca1710Skamil
3a9ca1710Skamil /*-
4a9ca1710Skamil * Copyright (c) 2016 The NetBSD Foundation, Inc.
5a9ca1710Skamil * All rights reserved.
6a9ca1710Skamil *
7a9ca1710Skamil * This code is derived from software contributed to The NetBSD Foundation
8a9ca1710Skamil * by Kamil Rytarowski.
9a9ca1710Skamil *
10a9ca1710Skamil * Redistribution and use in source and binary forms, with or without
11a9ca1710Skamil * modification, are permitted provided that the following conditions
12a9ca1710Skamil * are met:
13a9ca1710Skamil * 1. Redistributions of source code must retain the above copyright
14a9ca1710Skamil * notice, this list of conditions and the following disclaimer.
15a9ca1710Skamil * 2. Redistributions in binary form must reproduce the above copyright
16a9ca1710Skamil * notice, this list of conditions and the following disclaimer in the
17a9ca1710Skamil * documentation and/or other materials provided with the distribution.
18a9ca1710Skamil *
19a9ca1710Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20a9ca1710Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21a9ca1710Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22a9ca1710Skamil * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23a9ca1710Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24a9ca1710Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25a9ca1710Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26a9ca1710Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27a9ca1710Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28a9ca1710Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29a9ca1710Skamil * POSSIBILITY OF SUCH DAMAGE.
30a9ca1710Skamil */
31a9ca1710Skamil
32a9ca1710Skamil #include <sys/cdefs.h>
33*36ec32beSkamil __RCSID("$NetBSD: thrd.c,v 1.4 2019/09/10 22:34:19 kamil Exp $");
34a9ca1710Skamil
35a9ca1710Skamil #include <assert.h>
36a9ca1710Skamil #include <errno.h>
37a9ca1710Skamil #include <pthread.h>
38a9ca1710Skamil #include <sched.h>
3945dae603Skamil #include <stdlib.h>
40a9ca1710Skamil #include <time.h>
41a9ca1710Skamil #include <threads.h>
42a9ca1710Skamil
4345dae603Skamil struct __thrd_tramp_data {
4445dae603Skamil thrd_start_t func;
4545dae603Skamil void *arg;
4645dae603Skamil };
4745dae603Skamil
4845dae603Skamil static void *
__thrd_create_tramp(void * arg)4945dae603Skamil __thrd_create_tramp(void *arg)
5045dae603Skamil {
5145dae603Skamil struct __thrd_tramp_data *cookie;
5245dae603Skamil int ret;
5345dae603Skamil
5445dae603Skamil _DIAGASSERT(arg != NULL);
5545dae603Skamil
5645dae603Skamil cookie = (struct __thrd_tramp_data *)arg;
5745dae603Skamil
5845dae603Skamil ret = (cookie->func)(cookie->arg);
5945dae603Skamil
6045dae603Skamil free(cookie);
6145dae603Skamil
6245dae603Skamil return (void *)(intptr_t)ret;
6345dae603Skamil }
6445dae603Skamil
65a9ca1710Skamil int
thrd_create(thrd_t * thr,thrd_start_t func,void * arg)66a9ca1710Skamil thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
67a9ca1710Skamil {
6845dae603Skamil struct __thrd_tramp_data *cookie;
6945dae603Skamil int error;
70a9ca1710Skamil
71a9ca1710Skamil _DIAGASSERT(thr != NULL);
72a9ca1710Skamil _DIAGASSERT(func != NULL);
73a9ca1710Skamil
7445dae603Skamil cookie = malloc(sizeof(*cookie));
7545dae603Skamil if (cookie == NULL)
7645dae603Skamil return thrd_nomem;
7745dae603Skamil
7845dae603Skamil cookie->func = func;
7945dae603Skamil cookie->arg = arg;
8045dae603Skamil
8145dae603Skamil switch(pthread_create(thr, NULL, __thrd_create_tramp, cookie)) {
82a9ca1710Skamil case 0:
83a9ca1710Skamil return thrd_success;
8445dae603Skamil case ENOMEM:
8545dae603Skamil error = thrd_nomem;
8645dae603Skamil break;
87a9ca1710Skamil default:
8845dae603Skamil error = thrd_error;
89a9ca1710Skamil }
9045dae603Skamil
9145dae603Skamil free(cookie);
9245dae603Skamil
9345dae603Skamil return error;
94a9ca1710Skamil }
95a9ca1710Skamil
96a9ca1710Skamil thrd_t
thrd_current(void)97a9ca1710Skamil thrd_current(void)
98a9ca1710Skamil {
99a9ca1710Skamil
100a9ca1710Skamil return pthread_self();
101a9ca1710Skamil }
102a9ca1710Skamil
103a9ca1710Skamil int
thrd_detach(thrd_t thr)104a9ca1710Skamil thrd_detach(thrd_t thr)
105a9ca1710Skamil {
106a9ca1710Skamil
107a9ca1710Skamil _DIAGASSERT(thr != NULL);
108a9ca1710Skamil
109a9ca1710Skamil if (pthread_detach(thr) == 0)
110a9ca1710Skamil return thrd_success;
111a9ca1710Skamil
112a9ca1710Skamil return thrd_error;
113a9ca1710Skamil }
114a9ca1710Skamil
115a9ca1710Skamil int
thrd_equal(thrd_t t1,thrd_t t2)116a9ca1710Skamil thrd_equal(thrd_t t1, thrd_t t2)
117a9ca1710Skamil {
118a9ca1710Skamil
119a9ca1710Skamil _DIAGASSERT(t1 != NULL);
120a9ca1710Skamil _DIAGASSERT(t2 != NULL);
121a9ca1710Skamil
122a9ca1710Skamil return pthread_equal(t1, t2);
123a9ca1710Skamil }
124a9ca1710Skamil
125*36ec32beSkamil __dead void
thrd_exit(int res)126a9ca1710Skamil thrd_exit(int res)
127a9ca1710Skamil {
128a9ca1710Skamil
129a9ca1710Skamil pthread_exit((void *)(intptr_t)res);
130a9ca1710Skamil }
131a9ca1710Skamil
132a9ca1710Skamil int
thrd_join(thrd_t thrd,int * res)133a9ca1710Skamil thrd_join(thrd_t thrd, int *res)
134a9ca1710Skamil {
135a9ca1710Skamil void *ptr;
136a9ca1710Skamil
137a9ca1710Skamil _DIAGASSERT(thrd != NULL);
138a9ca1710Skamil
139a9ca1710Skamil if (pthread_join(thrd, &ptr) == 0) {
140a9ca1710Skamil if (res)
141a9ca1710Skamil *res = (int)(intptr_t)ptr;
142a9ca1710Skamil
143a9ca1710Skamil return thrd_success;
144a9ca1710Skamil }
145a9ca1710Skamil
146a9ca1710Skamil return thrd_error;
147a9ca1710Skamil }
148a9ca1710Skamil
149a9ca1710Skamil int
thrd_sleep(const struct timespec * duration,struct timespec * remaining)150a9ca1710Skamil thrd_sleep(const struct timespec *duration, struct timespec *remaining)
151a9ca1710Skamil {
152a9ca1710Skamil
153a9ca1710Skamil _DIAGASSERT(duration != NULL);
154a9ca1710Skamil
155a9ca1710Skamil /* Use clock_nanosleep(3) to skip handling errno */
156a9ca1710Skamil
157a9ca1710Skamil switch (clock_nanosleep(CLOCK_MONOTONIC, TIMER_RELTIME, duration,
158a9ca1710Skamil remaining)) {
159a9ca1710Skamil case 0:
160a9ca1710Skamil return 0;
161a9ca1710Skamil case EINTR:
162a9ca1710Skamil return -1;
163a9ca1710Skamil default:
164a9ca1710Skamil /* Negative value different than -1 */
165a9ca1710Skamil return -2;
166a9ca1710Skamil }
167a9ca1710Skamil }
168a9ca1710Skamil
169a9ca1710Skamil void
thrd_yield(void)170a9ca1710Skamil thrd_yield(void)
171a9ca1710Skamil {
172a9ca1710Skamil
173a9ca1710Skamil sched_yield();
174a9ca1710Skamil }
175