From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/5986 Path: news.gmane.org!not-for-mail From: Jens Gustedt Newsgroups: gmane.linux.lib.musl.general Subject: [PATCH 1/8] interface additions for the C thread implementation Date: Sat, 30 Aug 2014 20:46:23 +0200 Message-ID: References: Reply-To: musl@lists.openwall.com NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Transfer-Encoding: 7bit X-Trace: ger.gmane.org 1409424415 5814 80.91.229.3 (30 Aug 2014 18:46:55 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Sat, 30 Aug 2014 18:46:55 +0000 (UTC) To: musl@lists.openwall.com Original-X-From: musl-return-5993-gllmg-musl=m.gmane.org@lists.openwall.com Sat Aug 30 20:46:49 2014 Return-path: Envelope-to: gllmg-musl@plane.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by plane.gmane.org with smtp (Exim 4.69) (envelope-from ) id 1XNnfl-0000GV-4h for gllmg-musl@plane.gmane.org; Sat, 30 Aug 2014 20:46:49 +0200 Original-Received: (qmail 3626 invoked by uid 550); 30 Aug 2014 18:46:45 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Original-Received: (qmail 3521 invoked from network); 30 Aug 2014 18:46:44 -0000 X-IronPort-AV: E=Sophos;i="5.04,432,1406584800"; d="scan'208";a="92267752" In-Reply-To: Resent-From: Jens Gustedt Resent-To: musl@lists.openwall.com X-Mailer: Evolution 3.4.4-3 Xref: news.gmane.org gmane.linux.lib.musl.general:5986 Archived-At: This adds all the constant, type and function interfaces. It makes pthread_mutex_t, mtx_t, pthread_cond_t and cnd_t different types. This only works because - under hood the corresponding pairs of types use exactly the same definition for the type - the types are a struct types without tag name - no comparison or assignment is allowed for any of these types. For the POSIX types this interdiction is written in the standard. For the C thread types, this is an extension that this implementation imposes, but which might be integrated in a later version of the C standard. - initialization is default initialization of an array of int. For the POSIX types, initialization expressions are provided. For C thread types the only initialization foreseen by the standard are the init functions. - any calls to standard functions use pointers, and because pointer representations for struct types are the same. For the C++ API/ABI, these also are different types, now, with type names (that are used for name mangling, e.g) as listed above. Somebody better versed in C++ could perhaps contribute code that overloads the comparison and assignment operators such that a compilation that tries to compare or copy these types fails. --- arch/arm/bits/alltypes.h.in | 10 +++- arch/i386/bits/alltypes.h.in | 10 +++- arch/microblaze/bits/alltypes.h.in | 10 +++- arch/mips/bits/alltypes.h.in | 10 +++- arch/or1k/bits/alltypes.h.in | 10 +++- arch/powerpc/bits/alltypes.h.in | 10 +++- arch/sh/bits/alltypes.h.in | 10 +++- arch/x32/bits/alltypes.h.in | 10 +++- arch/x86_64/bits/alltypes.h.in | 10 +++- include/alltypes.h.in | 10 ++++ include/threads.h | 110 ++++++++++++++++++++++++++++++++++++ include/time.h | 11 ++++ 12 files changed, 212 insertions(+), 9 deletions(-) create mode 100644 include/threads.h diff --git a/arch/arm/bits/alltypes.h.in b/arch/arm/bits/alltypes.h.in index 183c4c4..1dcb920 100644 --- a/arch/arm/bits/alltypes.h.in +++ b/arch/arm/bits/alltypes.h.in @@ -18,8 +18,16 @@ TYPEDEF struct { long long __ll; long double __ld; } max_align_t; TYPEDEF long time_t; TYPEDEF long suseconds_t; -TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; +/* The pairs of equivalent definitions for pthread and C thread types + * should always be kept in sync. + * + * Also this only works because the underlying struct has no struct + * tag. Don't introduce one. */ TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; +TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } mtx_t; TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; +TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } cnd_t; + +TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; diff --git a/arch/i386/bits/alltypes.h.in b/arch/i386/bits/alltypes.h.in index 8ba8f6f..6fe9d05 100644 --- a/arch/i386/bits/alltypes.h.in +++ b/arch/i386/bits/alltypes.h.in @@ -32,8 +32,16 @@ TYPEDEF struct { _Alignas(8) long long __ll; long double __ld; } max_align_t; TYPEDEF long time_t; TYPEDEF long suseconds_t; -TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; +/* The pairs of equivalent definitions for pthread and C thread types + * should always be kept in sync. + * + * Also this only works because the underlying struct has no struct + * tag. Don't introduce one. */ TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; +TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } mtx_t; TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; +TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } cnd_t; + +TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; diff --git a/arch/microblaze/bits/alltypes.h.in b/arch/microblaze/bits/alltypes.h.in index a03e1b8..ad4d898 100644 --- a/arch/microblaze/bits/alltypes.h.in +++ b/arch/microblaze/bits/alltypes.h.in @@ -18,8 +18,16 @@ TYPEDEF struct { long long __ll; long double __ld; } max_align_t; TYPEDEF long time_t; TYPEDEF long suseconds_t; -TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; +/* The pairs of equivalent definitions for pthread and C thread types + * should always be kept in sync. + * + * Also this only works because the underlying struct has no struct + * tag. Don't introduce one. */ TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; +TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } mtx_t; TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; +TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } cnd_t; + +TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; diff --git a/arch/mips/bits/alltypes.h.in b/arch/mips/bits/alltypes.h.in index a03e1b8..ad4d898 100644 --- a/arch/mips/bits/alltypes.h.in +++ b/arch/mips/bits/alltypes.h.in @@ -18,8 +18,16 @@ TYPEDEF struct { long long __ll; long double __ld; } max_align_t; TYPEDEF long time_t; TYPEDEF long suseconds_t; -TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; +/* The pairs of equivalent definitions for pthread and C thread types + * should always be kept in sync. + * + * Also this only works because the underlying struct has no struct + * tag. Don't introduce one. */ TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; +TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } mtx_t; TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; +TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } cnd_t; + +TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; diff --git a/arch/or1k/bits/alltypes.h.in b/arch/or1k/bits/alltypes.h.in index 183c4c4..1dcb920 100644 --- a/arch/or1k/bits/alltypes.h.in +++ b/arch/or1k/bits/alltypes.h.in @@ -18,8 +18,16 @@ TYPEDEF struct { long long __ll; long double __ld; } max_align_t; TYPEDEF long time_t; TYPEDEF long suseconds_t; -TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; +/* The pairs of equivalent definitions for pthread and C thread types + * should always be kept in sync. + * + * Also this only works because the underlying struct has no struct + * tag. Don't introduce one. */ TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; +TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } mtx_t; TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; +TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } cnd_t; + +TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; diff --git a/arch/powerpc/bits/alltypes.h.in b/arch/powerpc/bits/alltypes.h.in index ee7f137..63f88ca 100644 --- a/arch/powerpc/bits/alltypes.h.in +++ b/arch/powerpc/bits/alltypes.h.in @@ -18,8 +18,16 @@ TYPEDEF struct { long long __ll; long double __ld; } max_align_t; TYPEDEF long time_t; TYPEDEF long suseconds_t; -TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; +/* The pairs of equivalent definitions for pthread and C thread types + * should always be kept in sync. + * + * Also this only works because the underlying struct has no struct + * tag. Don't introduce one. */ TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; +TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } mtx_t; TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; +TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } cnd_t; + +TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; diff --git a/arch/sh/bits/alltypes.h.in b/arch/sh/bits/alltypes.h.in index ee7f137..63f88ca 100644 --- a/arch/sh/bits/alltypes.h.in +++ b/arch/sh/bits/alltypes.h.in @@ -18,8 +18,16 @@ TYPEDEF struct { long long __ll; long double __ld; } max_align_t; TYPEDEF long time_t; TYPEDEF long suseconds_t; -TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; +/* The pairs of equivalent definitions for pthread and C thread types + * should always be kept in sync. + * + * Also this only works because the underlying struct has no struct + * tag. Don't introduce one. */ TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } pthread_mutex_t; +TYPEDEF struct { union { int __i[6]; volatile void *volatile __p[6]; } __u; } mtx_t; TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } pthread_cond_t; +TYPEDEF struct { union { int __i[12]; void *__p[12]; } __u; } cnd_t; + +TYPEDEF struct { union { int __i[9]; unsigned __s[9]; } __u; } pthread_attr_t; TYPEDEF struct { union { int __i[8]; void *__p[8]; } __u; } pthread_rwlock_t; TYPEDEF struct { union { int __i[5]; void *__p[5]; } __u; } pthread_barrier_t; diff --git a/arch/x32/bits/alltypes.h.in b/arch/x32/bits/alltypes.h.in index 8e396c9..3e8f086 100644 --- a/arch/x32/bits/alltypes.h.in +++ b/arch/x32/bits/alltypes.h.in @@ -23,8 +23,16 @@ TYPEDEF struct { long long __ll; long double __ld; } max_align_t; TYPEDEF long long time_t; TYPEDEF long long suseconds_t; -TYPEDEF struct { union { int __i[14]; unsigned long __s[7]; } __u; } pthread_attr_t; +/* The pairs of equivalent definitions for pthread and C thread types + * should always be kept in sync. + * + * Also this only works because the underlying struct has no struct + * tag. Don't introduce one. */ TYPEDEF struct { union { int __i[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t; +TYPEDEF struct { union { int __i[10]; volatile void *volatile __p[5]; } __u; } mtx_t; TYPEDEF struct { union { int __i[12]; void *__p[6]; } __u; } pthread_cond_t; +TYPEDEF struct { union { int __i[12]; void *__p[6]; } __u; } cnd_t; + +TYPEDEF struct { union { int __i[14]; unsigned long __s[7]; } __u; } pthread_attr_t; TYPEDEF struct { union { int __i[14]; void *__p[7]; } __u; } pthread_rwlock_t; TYPEDEF struct { union { int __i[8]; void *__p[4]; } __u; } pthread_barrier_t; diff --git a/arch/x86_64/bits/alltypes.h.in b/arch/x86_64/bits/alltypes.h.in index 7b4f3e7..c0169c7 100644 --- a/arch/x86_64/bits/alltypes.h.in +++ b/arch/x86_64/bits/alltypes.h.in @@ -23,8 +23,16 @@ TYPEDEF struct { long long __ll; long double __ld; } max_align_t; TYPEDEF long time_t; TYPEDEF long suseconds_t; -TYPEDEF struct { union { int __i[14]; unsigned long __s[7]; } __u; } pthread_attr_t; +/* The pairs of equivalent definitions for pthread and C thread types + * should always be kept in sync. + * + * Also this only works because the underlying struct has no struct + * tag. Don't introduce one. */ TYPEDEF struct { union { int __i[10]; volatile void *volatile __p[5]; } __u; } pthread_mutex_t; +TYPEDEF struct { union { int __i[10]; volatile void *volatile __p[5]; } __u; } mtx_t; TYPEDEF struct { union { int __i[12]; void *__p[6]; } __u; } pthread_cond_t; +TYPEDEF struct { union { int __i[12]; void *__p[6]; } __u; } cnd_t; + +TYPEDEF struct { union { int __i[14]; unsigned long __s[7]; } __u; } pthread_attr_t; TYPEDEF struct { union { int __i[14]; void *__p[7]; } __u; } pthread_rwlock_t; TYPEDEF struct { union { int __i[8]; void *__p[4]; } __u; } pthread_barrier_t; diff --git a/include/alltypes.h.in b/include/alltypes.h.in index c4ca5d5..94364e8 100644 --- a/include/alltypes.h.in +++ b/include/alltypes.h.in @@ -43,13 +43,23 @@ TYPEDEF unsigned gid_t; TYPEDEF int key_t; TYPEDEF unsigned useconds_t; +/* The pairs of equivalent definitions for pthread and C thread types + * should always be kept in sync. */ #ifdef __cplusplus TYPEDEF unsigned long pthread_t; +TYPEDEF unsigned long thrd_t; #else TYPEDEF struct __pthread * pthread_t; +TYPEDEF struct __pthread * thrd_t; #endif TYPEDEF int pthread_once_t; +TYPEDEF int once_flag; TYPEDEF unsigned pthread_key_t; +TYPEDEF unsigned tss_t; + +TYPEDEF pthread_cond_t cnd_t; +TYPEDEF pthread_mutex_t mtx_t; + TYPEDEF int pthread_spinlock_t; TYPEDEF struct { unsigned __attr; } pthread_mutexattr_t; TYPEDEF struct { unsigned __attr; } pthread_condattr_t; diff --git a/include/threads.h b/include/threads.h new file mode 100644 index 0000000..0e99443 --- /dev/null +++ b/include/threads.h @@ -0,0 +1,110 @@ +#ifndef _THREADS_H +#define _THREADS_H + +/* This one is explicitly allowed to be included. */ +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +/* These may or may not be implemented to be the same as some POSIX + * types. Don't rely on any assumption about that, in particular if + * you happen to use both interfaces in the same code. */ + +#define __NEED_cnd_t +#define __NEED_mtx_t +#define __NEED_once_flag +#define __NEED_thrd_t +#define __NEED_tss_t + +#include + +typedef int (*thrd_start_t)(void*); +typedef void (*tss_dtor_t)(void*); + +/* This should be a keyword for C++11 */ +#ifndef __cplusplus +# define thread_local _Thread_local +#endif + + /* The following list of 10 integer constants makes up for the binary + compatibility of this C thread implementation. You must never + link code against versions of the C library that do not agree + upon these ABI parameters. + + Additionally this implementation assumes that the 5 types have + the same size across C libraries and that these types can be + initialized by the default initializer. + + The values for the 10 parameters are those that we proposed to + glibc, in the hope that they will agree. + */ + +#define TSS_DTOR_ITERATIONS 4 + +enum { + thrd_success = 0, + thrd_busy = 1, + thrd_error = 2, + thrd_nomem = 3, + thrd_timedout = 4, +}; + +enum { + mtx_plain = 0, + mtx_recursive = 1, + // all mutexes are timed, here. so this is a no-op + mtx_timed = 2, +}; + +#define ONCE_FLAG_INIT { 0 } + +#ifdef __cplusplus +extern "C" { +#endif + +int thrd_create(thrd_t *, thrd_start_t, void *); +_Noreturn void thrd_exit(int); + +int thrd_detach(thrd_t); +int thrd_join(thrd_t, int *); + +int thrd_sleep(const struct timespec *, struct timespec *); +void thrd_yield(void); + +thrd_t thrd_current(void); +int thrd_equal(thrd_t, thrd_t); +#define thrd_equal(A, B) ((A) == (B)) + +void call_once(once_flag *, void (*)(void)); + +int mtx_init(mtx_t *, int); +void mtx_destroy(mtx_t *); + +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 cnd_init(cnd_t *); +void cnd_destroy(cnd_t *); + +int cnd_broadcast(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 *); + +int tss_create(tss_t *, tss_dtor_t); +void tss_delete(tss_t key); + +int tss_set(tss_t, void *); +void *tss_get(tss_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/time.h b/include/time.h index dc88070..9ea9c73 100644 --- a/include/time.h +++ b/include/time.h @@ -129,6 +129,17 @@ int stime(const time_t *); time_t timegm(struct tm *); #endif + /* Implementation specific choice: The epoch that the TIME_UTC clock + is based upon is the Unix Epoch, that is a struct timespec + represents the number of seconds that have elapsed since 00:00:00 + Coordinated Universal Time (UTC), Thursday, 1 January + 1970. Because of differences in leap seconds this is not + completely equivalent to UTC. */ + /* Beware that the TIME_UTC constant itself per the standard must be + greater than 0. */ +#define TIME_UTC 1 +int timespec_get(struct timespec *, int); + #ifdef __cplusplus } #endif -- 1.7.10.4