Add libstdthreads.

This library implements the C11 threads interface on top of the pthreads
library.  As discussed on the lists, the preferred way to implement
this, is as a separate library.

It is unlikely that these functions will be used a lot in the future. It
would have been easier if the C11 working group standardized (a subset
of) pthreads and clock_nanosleep(). Having it as a separate library
allows the embedded people to omit it from their system.

Discussed on:	arch@, threads@
This commit is contained in:
ed 2011-12-26 21:51:53 +00:00
parent 2667624c1c
commit 6f5f2f5fd7
12 changed files with 896 additions and 0 deletions

View File

@ -814,6 +814,7 @@
.ds doc-str-Lb-librt \*[Px] \*[doc-str-Lb]Real-time Library (librt, \-lrt) .ds doc-str-Lb-librt \*[Px] \*[doc-str-Lb]Real-time Library (librt, \-lrt)
.ds doc-str-Lb-libsdp Bluetooth Service Discovery Protocol User Library (libsdp, \-lsdp) .ds doc-str-Lb-libsdp Bluetooth Service Discovery Protocol User Library (libsdp, \-lsdp)
.ds doc-str-Lb-libssp Buffer Overflow Protection Library (libssp, \-lssp) .ds doc-str-Lb-libssp Buffer Overflow Protection Library (libssp, \-lssp)
.ds doc-str-Lb-libstdthreads C11 Threads Library (libstdthreads, \-lstdthreads)
.ds doc-str-Lb-libSystem System Library (libSystem, \-lSystem) .ds doc-str-Lb-libSystem System Library (libSystem, \-lSystem)
.ds doc-str-Lb-libtermcap Termcap Access Library (libtermcap, \-ltermcap) .ds doc-str-Lb-libtermcap Termcap Access Library (libtermcap, \-ltermcap)
.ds doc-str-Lb-libterminfo Terminal Information Library (libterminfo, \-lterminfo) .ds doc-str-Lb-libterminfo Terminal Information Library (libterminfo, \-lterminfo)

View File

@ -1797,6 +1797,8 @@ and their results are:
.Lb libsdp .Lb libsdp
.It Li libssp .It Li libssp
.Lb libssp .Lb libssp
.It Li libstdthreads
.Lb libstdthreads
.It Li libSystem .It Li libSystem
.Lb libSystem .Lb libSystem
.It Li libtermcap .It Li libtermcap

View File

@ -101,6 +101,7 @@ SUBDIR= ${SUBDIR_ORDERED} \
${_libsmdb} \ ${_libsmdb} \
${_libsmutil} \ ${_libsmutil} \
libstand \ libstand \
libstdthreads \
${_libtelnet} \ ${_libtelnet} \
${_libthr} \ ${_libthr} \
libthread_db \ libthread_db \

View File

@ -0,0 +1,41 @@
# $FreeBSD$
LIB= stdthreads
SHLIB_MAJOR= 0
INCS= threads.h
SRCS= threads.h call_once.c cnd.c mtx.c thrd.c tss.c
MAN= thrd_create.3
MLINKS= thrd_create.3 call_once.3 \
thrd_create.3 cnd_broadcast.3 \
thrd_create.3 cnd_destroy.3 \
thrd_create.3 cnd_init.3 \
thrd_create.3 cnd_signal.3 \
thrd_create.3 cnd_timedwait.3 \
thrd_create.3 cnd_wait.3 \
thrd_create.3 mtx_destroy.3 \
thrd_create.3 mtx_init.3 \
thrd_create.3 mtx_lock.3 \
thrd_create.3 mtx_timedlock.3 \
thrd_create.3 mtx_trylock.3 \
thrd_create.3 mtx_unlock.3 \
thrd_create.3 thrd_current.3 \
thrd_create.3 thrd_detach.3 \
thrd_create.3 thrd_equal.3 \
thrd_create.3 thrd_exit.3 \
thrd_create.3 thrd_join.3 \
thrd_create.3 thrd_sleep.3 \
thrd_create.3 thrd_yield.3 \
thrd_create.3 tss_create.3 \
thrd_create.3 tss_delete.3 \
thrd_create.3 tss_get.3 \
thrd_create.3 tss_set.3
DPADD= ${LIBPTHREAD}
LDADD= -lpthread
VERSION_DEF= ${.CURDIR}/../libc/Versions.def
SYMBOL_MAPS= ${.CURDIR}/Symbol.map
.include <bsd.lib.mk>

View File

@ -0,0 +1,31 @@
/*
* $FreeBSD$
*/
FBSD_1.3 {
call_once;
cnd_broadcast;
cnd_destroy;
cnd_init;
cnd_signal;
cnd_timedwait;
cnd_wait;
mtx_destroy;
mtx_init;
mtx_lock;
mtx_timedlock;
mtx_trylock;
mtx_unlock;
thrd_create;
thrd_current;
thrd_detach;
thrd_equal;
thrd_exit;
thrd_join;
thrd_sleep;
thrd_yield;
tss_create;
tss_delete;
tss_get;
tss_set;
};

View File

@ -0,0 +1,44 @@
/*-
* Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <pthread.h>
#include "threads.h"
void
call_once(once_flag *flag, void (*func)(void))
{
(void)pthread_once((pthread_once_t *)flag, func);
}
_Static_assert(sizeof(once_flag) == sizeof(pthread_once_t),
"once_flag must be of the same size as pthread_once_t");

98
lib/libstdthreads/cnd.c Normal file
View File

@ -0,0 +1,98 @@
/*-
* Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <errno.h>
#include <pthread.h>
#include "threads.h"
int
cnd_broadcast(cnd_t *cond)
{
if (pthread_cond_broadcast(cond) != 0)
return (thrd_error);
return (thrd_success);
}
void
cnd_destroy(cnd_t *cond)
{
(void)pthread_cond_destroy(cond);
}
int
cnd_init(cnd_t *cond)
{
switch (pthread_cond_init(cond, NULL)) {
case 0:
return (thrd_success);
case ENOMEM:
return (thrd_nomem);
default:
return (thrd_error);
}
}
int
cnd_signal(cnd_t *cond)
{
if (pthread_cond_signal(cond) != 0)
return (thrd_error);
return (thrd_success);
}
int
cnd_timedwait(cnd_t *restrict cond, mtx_t *restrict mtx,
const struct timespec *restrict ts)
{
switch (pthread_cond_timedwait(cond, mtx, ts)) {
case 0:
return (thrd_success);
case ETIMEDOUT:
return (thrd_timedout);
default:
return (thrd_error);
}
}
int
cnd_wait(cnd_t *cond, mtx_t *mtx)
{
if (pthread_cond_wait(cond, mtx) != 0)
return (thrd_error);
return (thrd_success);
}

116
lib/libstdthreads/mtx.c Normal file
View File

@ -0,0 +1,116 @@
/*-
* Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <errno.h>
#include <pthread.h>
#include "threads.h"
void
mtx_destroy(mtx_t *mtx)
{
(void)pthread_mutex_destroy(mtx);
}
int
mtx_init(mtx_t *mtx, int type)
{
pthread_mutexattr_t attr;
int mt;
switch (type) {
case mtx_plain:
case mtx_timed:
mt = PTHREAD_MUTEX_NORMAL;
break;
case mtx_plain | mtx_recursive:
case mtx_timed | mtx_recursive:
mt = PTHREAD_MUTEX_RECURSIVE;
break;
default:
return (thrd_error);
}
if (pthread_mutexattr_init(&attr) != 0)
return (thrd_error);
if (pthread_mutexattr_settype(&attr, mt) != 0)
return (thrd_error);
if (pthread_mutex_init(mtx, &attr) != 0)
return (thrd_error);
return (thrd_success);
}
int
mtx_lock(mtx_t *mtx)
{
if (pthread_mutex_lock(mtx) != 0)
return (thrd_error);
return (thrd_success);
}
int
mtx_timedlock(mtx_t *restrict mtx, const struct timespec *restrict ts)
{
switch (pthread_mutex_timedlock(mtx, ts)) {
case 0:
return (thrd_success);
case ETIMEDOUT:
return (thrd_timedout);
default:
return (thrd_error);
}
}
int
mtx_trylock(mtx_t *mtx)
{
switch (pthread_mutex_lock(mtx)) {
case 0:
return (thrd_success);
case EBUSY:
return (thrd_busy);
default:
return (thrd_error);
}
}
int
mtx_unlock(mtx_t *mtx)
{
if (pthread_mutex_unlock(mtx) != 0)
return (thrd_error);
return (thrd_success);
}

127
lib/libstdthreads/thrd.c Normal file
View File

@ -0,0 +1,127 @@
/*-
* Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <pthread.h>
#include <stdint.h>
#include <stdlib.h>
#include "threads.h"
struct thrd_param {
thrd_start_t func;
void *arg;
};
static void *
thrd_entry(void *arg)
{
struct thrd_param tp;
tp = *(struct thrd_param *)arg;
free(arg);
return ((void *)(intptr_t)tp.func(tp.arg));
}
int
thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
{
struct thrd_param *tp;
/*
* Work around return type inconsistency. Wrap execution using
* a function conforming to pthread_create()'s start_routine.
*/
tp = malloc(sizeof(*tp));
if (tp == NULL)
return (thrd_nomem);
tp->func = func;
tp->arg = arg;
if (pthread_create(thr, NULL, thrd_entry, tp) != 0) {
free(tp);
return (thrd_error);
}
return (thrd_success);
}
thrd_t
thrd_current(void)
{
return (pthread_self());
}
int
thrd_detach(thrd_t thr)
{
if (pthread_detach(thr) != 0)
return (thrd_error);
return (thrd_success);
}
int
thrd_equal(thrd_t thr0, thrd_t thr1)
{
return (pthread_equal(thr0, thr1));
}
_Noreturn void
thrd_exit(int res)
{
pthread_exit((void *)(intptr_t)res);
}
int
thrd_join(thrd_t thr, int *res)
{
void *value_ptr;
if (pthread_join(thr, &value_ptr) != 0)
return (thrd_error);
*res = (intptr_t)value_ptr;
return (thrd_success);
}
int
thrd_sleep(const struct timespec *duration, struct timespec *remaining)
{
return (nanosleep(duration, remaining));
}
void
thrd_yield(void)
{
pthread_yield();
}

View File

@ -0,0 +1,260 @@
.\" Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd December 26, 2011
.Dt THRD_CREATE 3
.Os
.Sh NAME
.Nm call_once ,
.Nm cnd_broadcast ,
.Nm cnd_destroy ,
.Nm cnd_init ,
.Nm cnd_signal ,
.Nm cnd_timedwait ,
.Nm cnd_wait ,
.Nm mtx_destroy ,
.Nm mtx_init ,
.Nm mtx_lock ,
.Nm mtx_timedlock ,
.Nm mtx_trylock ,
.Nm mtx_unlock ,
.Nm thrd_create ,
.Nm thrd_current ,
.Nm thrd_detach ,
.Nm thrd_equal ,
.Nm thrd_exit ,
.Nm thrd_join ,
.Nm thrd_sleep ,
.Nm thrd_yield ,
.Nm tss_create ,
.Nm tss_delete ,
.Nm tss_get ,
.Nm tss_set
.Nd C11 threads interface
.Sh LIBRARY
.Lb libstdthreads
.Sh SYNOPSIS
.In threads.h
.Ft void
.Fn call_once "once_flag *flag" "void (*func)(void)"
.Ft int
.Fn cnd_broadcast "cnd_t *cond"
.Ft void
.Fn cnd_destroy "cnd_t *cond"
.Ft int
.Fn cnd_init "cnd_t *cond"
.Ft int
.Fn cnd_signal "cnd_t *cond"
.Ft int
.Fn cnd_timedwait "cnd_t * restrict cond" "mtx_t * restrict mtx" "const struct timespec * restrict ts"
.Ft int
.Fn cnd_wait "cnd_t *cond" "mtx_t *mtx"
.Ft void
.Fn mtx_destroy "mtx_t *mtx"
.Ft int
.Fn mtx_init "mtx_t *mtx" "int type"
.Ft int
.Fn mtx_lock "mtx_t *mtx"
.Ft int
.Fn mtx_timedlock "mtx_t * restrict mtx" "const struct timespec * restrict ts"
.Ft int
.Fn mtx_trylock "mtx_t *mtx"
.Ft int
.Fn mtx_unlock "mtx_t *mtx"
.Ft int
.Fn thrd_create "thrd_t *thr" "int (*func)(void *)" "void *arg"
.Ft thrd_t
.Fn thrd_current "void"
.Ft int
.Fn thrd_detach "thrd_t thr"
.Ft int
.Fn thrd_equal "thrd_t thr0" "thrd_t thr1"
.Ft _Noreturn void
.Fn thrd_exit "int res"
.Ft int
.Fn thrd_join "thrd_t thr" "int *res"
.Ft int
.Fn thrd_sleep "const struct timespec *duration" "struct timespec *remaining"
.Ft void
.Fn thrd_yield "void"
.Ft int
.Fn tss_create "tss_t *key" "void (*dtor)(void *)"
.Ft void
.Fn tss_delete "tss_t key"
.Ft void *
.Fn tss_get "tss_t key"
.Ft int
.Fn tss_set "tss_t key" "void *val"
.Sh DESCRIPTION
As of
.St -isoC-11 ,
the C standard includes an API for writing multithreaded applications.
Since POSIX.1 already includes a threading API that is used by virtually
any multithreaded application, the interface provided by the C standard
can be considered superfluous.
.Pp
In this implementation, the threading interface is therefore implemented
as a light-weight layer on top of existing interfaces.
The functions to which these routines are mapped, are listed in the
following table.
Please refer to the documentation of the POSIX equivalent functions for
more information.
.Bl -column ".Fn mtx_timedlock" ".Xr pthread_mutex_timedlock 3" -offset indent
.It Em Function Ta Em POSIX equivalent
.It Fn call_once Ta Xr pthread_once 3
.It Fn cnd_broadcast Ta Xr pthread_cond_broadcast 3
.It Fn cnd_destroy Ta Xr pthread_cond_destroy 3
.It Fn cnd_init Ta Xr pthread_cond_init 3
.It Fn cnd_signal Ta Xr pthread_cond_signal 3
.It Fn cnd_timedwait Ta Xr pthread_cond_timedwait 3
.It Fn cnd_wait Ta Xr pthread_cond_wait 3
.It Fn mtx_destroy Ta Xr pthread_mutex_destroy 3
.It Fn mtx_init Ta Xr pthread_mutex_init 3
.It Fn mtx_lock Ta Xr pthread_mutex_lock 3
.It Fn mtx_timedlock Ta Xr pthread_mutex_timedlock 3
.It Fn mtx_trylock Ta Xr pthread_mutex_trylock 3
.It Fn mtx_unlock Ta Xr pthread_mutex_unlock 3
.It Fn thrd_create Ta Xr pthread_create 3
.It Fn thrd_current Ta Xr pthread_self 3
.It Fn thrd_detach Ta Xr pthread_detach 3
.It Fn thrd_equal Ta Xr pthread_equal 3
.It Fn thrd_exit Ta Xr pthread_exit 3
.It Fn thrd_join Ta Xr pthread_join 3
.It Fn thrd_sleep Ta Xr nanosleep 2
.It Fn thrd_yield Ta Xr pthread_yield 3
.It Fn tss_create Ta Xr pthread_key_create 3
.It Fn tss_delete Ta Xr pthread_key_delete 3
.It Fn tss_get Ta Xr pthread_getspecific 3
.It Fn tss_set Ta Xr pthread_setspecific 3
.El
.Sh DIFFERENCES WITH POSIX EQUIVALENTS
The
.Fn thrd_exit
function returns an integer value to the thread calling
.Fn thrd_join ,
whereas the
.Fn pthread_exit
function uses a pointer.
.Pp
The mutex created by
.Fn mtx_init
can be of
.Fa type
.Dv mtx_plain
or
.Dv mtx_timed
to distinguish between a mutex that supports
.Fn mtx_timedlock .
This type can be
.Em or'd
with
.Dv mtx_recursive
to create a mutex that allows recursive acquisition.
These properties are normally set using
.Fn pthread_mutex_init Ns 's
.Fa attr
parameter.
.Sh RETURN VALUES
If successful, the
.Fn cnd_broadcast ,
.Fn cnd_init ,
.Fn cnd_signal ,
.Fn cnd_timedwait ,
.Fn cnd_wait ,
.Fn mtx_init ,
.Fn mtx_lock ,
.Fn mtx_timedlock ,
.Fn mtx_trylock ,
.Fn mtx_unlock ,
.Fn thrd_create ,
.Fn thrd_detach ,
.Fn thrd_equal ,
.Fn thrd_join ,
.Fn thrd_sleep ,
.Fn tss_create
and
.Fn tss_set
functions return
.Dv thrd_success .
Otherwise an error code will be returned to indicate the error.
.Pp
The
.Fn thrd_current
function returns the thread ID of the calling thread.
.Pp
The
.Fn tss_get
function returns the thread-specific data value associated with the
given
.Fa key .
If no thread-specific data value is associated with
.Fa key ,
then the value NULL is returned.
.Sh ERRORS
The
.Fn cnd_init
and
.Fn thrd_create
functions will fail if:
.Bl -tag -width thrd_timedout
.It Dv thrd_nomem
The system has insufficient memory.
.El
.Pp
The
.Fn cnd_timedwait
and
.Fn mtx_timedlock
functions will fail if:
.Bl -tag -width thrd_timedout
.It Dv thrd_timedout
The system time has reached or exceeded the time specified in
.Fa ts
before the operation could be completed.
.El
.Pp
The
.Fn mtx_trylock
function will fail if:
.Bl -tag -width thrd_timedout
.It Dv thrd_busy
The mutex is already locked.
.El
.Pp
In all other cases, these functions may fail by returning general error
code
.Dv thrd_error .
.Sh SEE ALSO
.Xr nanosleep 2 ,
.Xr pthread 3
.Sh STANDARDS
These functions are expected to conform to
.St -isoC-11 .
.Sh HISTORY
These functions appeared in
.Fx 10.0 .
.Sh AUTHORS
.An Ed Schouten Aq ed@FreeBSD.org

106
lib/libstdthreads/threads.h Normal file
View File

@ -0,0 +1,106 @@
/*-
* Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _THREADS_H_
#define _THREADS_H_
#include <time.h>
/*
* The C11 threads interface.
*
* This interface is implemented as a light-weight wrapper around
* <pthread.h>. To prevent namespace pollution, the once_flag object,
* its corresponding ONCE_FLAG_INIT and TSS_DTOR_ITERATIONS have been
* copied from this header file. They must be kept in sync.
*/
typedef struct pthread_cond *cnd_t;
typedef struct pthread_mutex *mtx_t;
typedef struct pthread *thrd_t;
typedef int tss_t;
typedef struct {
int __state;
mtx_t __mutex;
} once_flag;
typedef void (*tss_dtor_t)(void *);
typedef int (*thrd_start_t)(void *);
enum {
mtx_plain = 0x1,
mtx_recursive = 0x2,
mtx_timed = 0x4
};
enum {
thrd_busy = 1,
thrd_error = 2,
thrd_nomem = 3,
thrd_success = 4,
thrd_timedout = 5
};
#if !defined(__cplusplus) || __cplusplus < 201103L
#define thread_local _Thread_local
#endif
#define ONCE_FLAG_INIT { 0, NULL }
#define TSS_DTOR_ITERATIONS 4
__BEGIN_DECLS
void call_once(once_flag *, void (*)(void));
int cnd_broadcast(cnd_t *);
void cnd_destroy(cnd_t *);
int cnd_init(cnd_t *);
int cnd_signal(cnd_t *);
int cnd_timedwait(cnd_t *__restrict, mtx_t *__restrict,
const struct timespec *__restrict);
int cnd_wait(cnd_t *, mtx_t *);
void mtx_destroy(mtx_t *);
int mtx_init(mtx_t *, int);
int mtx_lock(mtx_t *);
int mtx_timedlock(mtx_t *__restrict, const struct timespec *__restrict);
int mtx_trylock(mtx_t *);
int mtx_unlock(mtx_t *);
int thrd_create(thrd_t *, thrd_start_t, void *);
thrd_t thrd_current(void);
int thrd_detach(thrd_t);
int thrd_equal(thrd_t, thrd_t);
_Noreturn void
thrd_exit(int);
int thrd_join(thrd_t, int *);
int thrd_sleep(const struct timespec *, struct timespec *);
void thrd_yield(void);
int tss_create(tss_t *, tss_dtor_t);
void tss_delete(tss_t);
void * tss_get(tss_t);
int tss_set(tss_t, void *);
__END_DECLS
#endif /* !_THREADS_H_ */

69
lib/libstdthreads/tss.c Normal file
View File

@ -0,0 +1,69 @@
/*-
* Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <pthread.h>
#include "threads.h"
int
tss_create(tss_t *key, tss_dtor_t dtor)
{
if (pthread_key_create(key, dtor) != 0)
return (thrd_error);
return (thrd_success);
}
void
tss_delete(tss_t key)
{
(void)pthread_key_delete(key);
}
void *
tss_get(tss_t key)
{
return (pthread_getspecific(key));
}
int
tss_set(tss_t key, void *val)
{
if (pthread_setspecific(key, val) != 0)
return (thrd_error);
return (thrd_success);
}
_Static_assert(TSS_DTOR_ITERATIONS == PTHREAD_DESTRUCTOR_ITERATIONS,
"TSS_DTOR_ITERATIONS must be identical to PTHREAD_DESTRUCTOR_ITERATIONS");