xref: /netbsd-src/lib/libpthread/thrd.c (revision 36ec32beff138f56e5b9d363d9cab30b5f2b03dd)
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