1228904Sed/*-
2228904Sed * Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
3228904Sed * All rights reserved.
4228904Sed *
5228904Sed * Redistribution and use in source and binary forms, with or without
6228904Sed * modification, are permitted provided that the following conditions
7228904Sed * are met:
8228904Sed * 1. Redistributions of source code must retain the above copyright
9228904Sed *    notice, this list of conditions and the following disclaimer.
10228904Sed * 2. Redistributions in binary form must reproduce the above copyright
11228904Sed *    notice, this list of conditions and the following disclaimer in the
12228904Sed *    documentation and/or other materials provided with the distribution.
13228904Sed *
14228904Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15228904Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16228904Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17228904Sed * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18228904Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19228904Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20228904Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21228904Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22228904Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23228904Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24228904Sed * SUCH DAMAGE.
25228904Sed *
26228904Sed * $FreeBSD$
27228904Sed */
28228904Sed
29228904Sed#include <sys/cdefs.h>
30228904Sed__FBSDID("$FreeBSD$");
31228904Sed
32228904Sed#include <pthread.h>
33228904Sed#include <stdint.h>
34228904Sed#include <stdlib.h>
35228904Sed
36228904Sed#include "threads.h"
37228904Sed
38228904Sedstruct thrd_param {
39228904Sed	thrd_start_t	 func;
40228904Sed	void		*arg;
41228904Sed};
42228904Sed
43228904Sedstatic void *
44228904Sedthrd_entry(void *arg)
45228904Sed{
46228904Sed	struct thrd_param tp;
47228904Sed
48228904Sed	tp = *(struct thrd_param *)arg;
49228904Sed	free(arg);
50228904Sed	return ((void *)(intptr_t)tp.func(tp.arg));
51228904Sed}
52228904Sed
53228904Sedint
54228904Sedthrd_create(thrd_t *thr, thrd_start_t func, void *arg)
55228904Sed{
56228904Sed	struct thrd_param *tp;
57228904Sed
58228904Sed	/*
59228904Sed	 * Work around return type inconsistency.  Wrap execution using
60228904Sed	 * a function conforming to pthread_create()'s start_routine.
61228904Sed	 */
62228904Sed	tp = malloc(sizeof(*tp));
63228904Sed	if (tp == NULL)
64228904Sed		return (thrd_nomem);
65228904Sed	tp->func = func;
66228904Sed	tp->arg = arg;
67228904Sed	if (pthread_create(thr, NULL, thrd_entry, tp) != 0) {
68228904Sed		free(tp);
69228904Sed		return (thrd_error);
70228904Sed	}
71228904Sed	return (thrd_success);
72228904Sed}
73228904Sed
74228904Sedthrd_t
75228904Sedthrd_current(void)
76228904Sed{
77228904Sed
78228904Sed	return (pthread_self());
79228904Sed}
80228904Sed
81228904Sedint
82228904Sedthrd_detach(thrd_t thr)
83228904Sed{
84228904Sed
85228904Sed	if (pthread_detach(thr) != 0)
86228904Sed		return (thrd_error);
87228904Sed	return (thrd_success);
88228904Sed}
89228904Sed
90228904Sedint
91228904Sedthrd_equal(thrd_t thr0, thrd_t thr1)
92228904Sed{
93228904Sed
94228904Sed	return (pthread_equal(thr0, thr1));
95228904Sed}
96228904Sed
97228904Sed_Noreturn void
98228904Sedthrd_exit(int res)
99228904Sed{
100228904Sed
101228904Sed	pthread_exit((void *)(intptr_t)res);
102228904Sed}
103228904Sed
104228904Sedint
105228904Sedthrd_join(thrd_t thr, int *res)
106228904Sed{
107228904Sed	void *value_ptr;
108228904Sed
109228904Sed	if (pthread_join(thr, &value_ptr) != 0)
110228904Sed		return (thrd_error);
111228904Sed	*res = (intptr_t)value_ptr;
112228904Sed	return (thrd_success);
113228904Sed}
114228904Sed
115228904Sedint
116228904Sedthrd_sleep(const struct timespec *duration, struct timespec *remaining)
117228904Sed{
118228904Sed
119228904Sed	return (nanosleep(duration, remaining));
120228904Sed}
121228904Sed
122228904Sedvoid
123228904Sedthrd_yield(void)
124228904Sed{
125228904Sed
126228904Sed	pthread_yield();
127228904Sed}
128