diff options
author | Robert Mustacchi <rm@joyent.com> | 2016-03-28 19:43:25 -0700 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2016-05-19 07:45:52 -0700 |
commit | fc2512cfb727d49529d8ed99164db871f4829b73 (patch) | |
tree | 89ea56b5a9833e92795bf45c723c6de65b7490f2 /usr/src/lib/libc | |
parent | ea4a67f462de0a39a9adea8197bcdef849de5371 (diff) | |
download | illumos-joyent-fc2512cfb727d49529d8ed99164db871f4829b73.tar.gz |
6951 Initial c11 support
6952 gets should not be visible in C11
6953 add support for c11 threads api
6954 Symbols test should support validating pre-processor symbols
Reviewed by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
Reviewed by: Dan McDonald <danmcd@omniti.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Approved by: Garrett D'Amore <garrett@damore.org>
Diffstat (limited to 'usr/src/lib/libc')
-rw-r--r-- | usr/src/lib/libc/amd64/Makefile | 4 | ||||
-rw-r--r-- | usr/src/lib/libc/i386/Makefile.com | 4 | ||||
-rw-r--r-- | usr/src/lib/libc/inc/thr_uberdata.h | 26 | ||||
-rw-r--r-- | usr/src/lib/libc/port/gen/atexit.c | 53 | ||||
-rw-r--r-- | usr/src/lib/libc/port/gen/memalign.c | 15 | ||||
-rw-r--r-- | usr/src/lib/libc/port/gen/timespec_get.c | 33 | ||||
-rw-r--r-- | usr/src/lib/libc/port/mapfile-vers | 35 | ||||
-rw-r--r-- | usr/src/lib/libc/port/threads/c11_thr.c | 293 | ||||
-rw-r--r-- | usr/src/lib/libc/port/threads/thr.c | 7 | ||||
-rw-r--r-- | usr/src/lib/libc/sparc/Makefile.com | 4 | ||||
-rw-r--r-- | usr/src/lib/libc/sparcv9/Makefile.com | 2 |
11 files changed, 466 insertions, 10 deletions
diff --git a/usr/src/lib/libc/amd64/Makefile b/usr/src/lib/libc/amd64/Makefile index 9da581df4e..0a55bf964f 100644 --- a/usr/src/lib/libc/amd64/Makefile +++ b/usr/src/lib/libc/amd64/Makefile @@ -20,7 +20,7 @@ # # # Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. -# Copyright (c) 2015, Joyent, Inc. All rights reserved. +# Copyright 2016 Joyent, Inc. # # Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. # Copyright 2013 Garrett D'Amore <garrett@damore.org> @@ -565,6 +565,7 @@ PORTGEN= \ tfind.o \ time_data.o \ time_gdata.o \ + timespec_get.o \ tls_data.o \ truncate.o \ tsdalloc.o \ @@ -810,6 +811,7 @@ TPOOLOBJS= \ THREADSOBJS= \ alloc.o \ assfail.o \ + c11_thr.o \ cancel.o \ door_calls.o \ tmem.o \ diff --git a/usr/src/lib/libc/i386/Makefile.com b/usr/src/lib/libc/i386/Makefile.com index 62e6fe5d5e..21adf0d5a1 100644 --- a/usr/src/lib/libc/i386/Makefile.com +++ b/usr/src/lib/libc/i386/Makefile.com @@ -20,7 +20,7 @@ # # # Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. -# Copyright (c) 2015, Joyent, Inc. All rights reserved. +# Copyright 2016 Joyent, Inc. # Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. # Copyright 2013 Garrett D'Amore <garrett@damore.org> # @@ -595,6 +595,7 @@ PORTGEN= \ tfind.o \ time_data.o \ time_gdata.o \ + timespec_get.o \ tls_data.o \ truncate.o \ tsdalloc.o \ @@ -855,6 +856,7 @@ THREADSOBJS= \ alloc.o \ assfail.o \ cancel.o \ + c11_thr.o \ door_calls.o \ tmem.o \ pthr_attr.o \ diff --git a/usr/src/lib/libc/inc/thr_uberdata.h b/usr/src/lib/libc/inc/thr_uberdata.h index 4815d11486..0cf92cf499 100644 --- a/usr/src/lib/libc/inc/thr_uberdata.h +++ b/usr/src/lib/libc/inc/thr_uberdata.h @@ -23,7 +23,7 @@ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright (c) 2015, Joyent, Inc. + * Copyright 2016 Joyent, Inc. */ #ifndef _THR_UBERDATA_H @@ -893,6 +893,28 @@ typedef struct { } atexit_root32_t; #endif /* _SYSCALL32 */ +/* + * at_quick_exit() and quick_exit() data structures. The ISO/IEC C11 odd + * siblings of atexit() + */ +typedef void (*_quick_exithdlr_func_t)(void); + +typedef struct _qexthdlr { + struct _qexthdlr *next; /* next in handler list */ + _quick_exithdlr_func_t hdlr; /* handler itself */ +} _qexthdlr_t; + +typedef struct { + mutex_t exitfns_lock; + _qexthdlr_t *head; +} quickexit_root_t; + +#ifdef _SYSCALL32 +typedef struct { + mutex_t exitfns_lock; + caddr32_t head; +} quickexit_root32_t; +#endif /* _SYSCALL32 */ /* * This is data that is global to all link maps (uberdata, aka super-global). @@ -910,6 +932,7 @@ typedef struct uberdata { siguaction_t siguaction[NSIG]; bucket_t bucket[NBUCKETS]; atexit_root_t atexit_root; + quickexit_root_t quickexit_root; tsd_metadata_t tsd_metadata; tls_metadata_t tls_metadata; /* @@ -1126,6 +1149,7 @@ typedef struct uberdata32 { siguaction32_t siguaction[NSIG]; bucket32_t bucket[NBUCKETS]; atexit_root32_t atexit_root; + quickexit_root32_t quickexit_root; tsd_metadata32_t tsd_metadata; tls_metadata32_t tls_metadata; char primary_map; diff --git a/usr/src/lib/libc/port/gen/atexit.c b/usr/src/lib/libc/port/gen/atexit.c index 32e54fae11..e2882afdd4 100644 --- a/usr/src/lib/libc/port/gen/atexit.c +++ b/usr/src/lib/libc/port/gen/atexit.c @@ -22,6 +22,8 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2016 Joyent, Inc. */ /* Copyright (c) 1988 AT&T */ @@ -80,11 +82,13 @@ void atexit_locks() { (void) mutex_lock(&__uberdata.atexit_root.exitfns_lock); + (void) mutex_lock(&__uberdata.quickexit_root.exitfns_lock); } void atexit_unlocks() { + (void) mutex_unlock(&__uberdata.quickexit_root.exitfns_lock); (void) mutex_unlock(&__uberdata.atexit_root.exitfns_lock); } @@ -382,3 +386,52 @@ in_range(void *addr, Lc_addr_range_t ranges[], uint_t count) return (0); } + +int +at_quick_exit(void (*func)(void)) +{ + ulwp_t *self; + quickexit_root_t *arp; + _qexthdlr_t *p; + + if ((p = lmalloc(sizeof (_qexthdlr_t))) == NULL) + return (-1); + + if ((self = __curthread()) == NULL) { + arp = &__uberdata.quickexit_root; + } else { + arp = &self->ul_uberdata->quickexit_root; + (void) mutex_lock(&arp->exitfns_lock); + } + p->hdlr = func; + p->next = arp->head; + arp->head = p; + + if (self != NULL) + (void) mutex_unlock(&arp->exitfns_lock); + return (0); + +} + +void +quick_exit(int status) +{ + quickexit_root_t *qrp = &curthread->ul_uberdata->quickexit_root; + _qexthdlr_t *p; + int cancel_state; + + (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state); + (void) mutex_lock(&qrp->exitfns_lock); + + p = qrp->head; + while (p != NULL) { + qrp->head = p->next; + p->hdlr(); + lfree(p, sizeof (_qexthdlr_t)); + p = qrp->head; + } + + (void) mutex_unlock(&qrp->exitfns_lock); + (void) pthread_setcancelstate(cancel_state, NULL); + _Exit(status); +} diff --git a/usr/src/lib/libc/port/gen/memalign.c b/usr/src/lib/libc/port/gen/memalign.c index a54a10868f..a6320a7a0b 100644 --- a/usr/src/lib/libc/port/gen/memalign.c +++ b/usr/src/lib/libc/port/gen/memalign.c @@ -22,13 +22,12 @@ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2016 Joyent, Inc. */ /* Copyright (c) 1988 AT&T */ /* All Rights Reserved */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include "lint.h" #include "mallint.h" #include "mtlib.h" @@ -183,3 +182,15 @@ memalign(size_t align, size_t nbytes) (void) mutex_unlock(&libc_malloc_lock); return (DATA(aligned_blk)); } + +/* + * This is the ISO/IEC C11 version of memalign. We have kept it as a separate + * function, but it is basically the same thing. Note that this is implemented + * this way to make life easier to libraries which already interpose on + * memalign. + */ +void * +aligned_alloc(size_t align, size_t size) +{ + return (memalign(align, size)); +} diff --git a/usr/src/lib/libc/port/gen/timespec_get.c b/usr/src/lib/libc/port/gen/timespec_get.c new file mode 100644 index 0000000000..e16f6acf28 --- /dev/null +++ b/usr/src/lib/libc/port/gen/timespec_get.c @@ -0,0 +1,33 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright (c) 2015 Joyent, Inc. + */ + +/* + * C11 timespec_get(3C). Note the standard does not want us mucking about with + * errno, but at least we don't have to preserve it. + */ + +#include <time.h> + +int +timespec_get(struct timespec *ts, int base) +{ + if (base != TIME_UTC) + return (0); + + if (clock_gettime(CLOCK_REALTIME, ts) != 0) + return (0); + + return (TIME_UTC); +} diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers index 2e51bc8f54..fa9931c23b 100644 --- a/usr/src/lib/libc/port/mapfile-vers +++ b/usr/src/lib/libc/port/mapfile-vers @@ -25,7 +25,7 @@ # Use is subject to license terms. # # Copyright (c) 2012 by Delphix. All rights reserved. -# Copyright (c) 2015, Joyent, Inc. All rights reserved. +# Copyright 2016 Joyent, Inc. # Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. # Copyright (c) 2013 Gary Mills # Copyright 2014 Garrett D'Amore <garrett@damore.org> @@ -93,6 +93,39 @@ $if _x86 && _ELF64 $add amd64 $endif +SYMBOL_VERSION ILLUMOS_0.20 { # C11 + protected: + aligned_alloc; + at_quick_exit; + 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; + quick_exit; + thrd_create; + thrd_current; + thrd_detach; + thrd_equal; + thrd_exit; + thrd_join; + thrd_sleep; + thrd_yield; + timespec_get; + tss_create; + tss_delete; + tss_get; + tss_set; +} ILLUMOS_0.19; + SYMBOL_VERSION ILLUMOS_0.19 { # flock protected: flock; diff --git a/usr/src/lib/libc/port/threads/c11_thr.c b/usr/src/lib/libc/port/threads/c11_thr.c new file mode 100644 index 0000000000..6a8c6d157e --- /dev/null +++ b/usr/src/lib/libc/port/threads/c11_thr.c @@ -0,0 +1,293 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2016 Joyent, Inc. + */ + +#include <pthread.h> +#include <thread.h> +#include <synch.h> +#include <threads.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> + +/* + * ISO/IEC C11 thread support. + * + * In illumos, the underlying implementation of lock related routines is the + * same between pthreads and traditional SunOS routines. The same is true with + * the C11 routines. Their types are actually just typedef's to other things. + * Thus in the implementation here, we treat this as a wrapper around existing + * thread related routines and don't sweet the extra indirection. + * + * Note that in many places the C standard doesn't allow for errors to be + * returned. In those cases, if we have an instance of programmer error + * (something resulting in EINVAL), we opt to abort the program as we don't have + * much other recourse available. + */ + +void +call_once(once_flag *flag, void (*func)(void)) +{ + if (pthread_once(flag, func) != 0) + abort(); +} + +int +cnd_broadcast(cnd_t *cnd) +{ + int ret; + + ret = pthread_cond_broadcast(cnd); + if (ret == 0) + return (thrd_success); + else + return (thrd_error); +} + +void +cnd_destroy(cnd_t *cnd) +{ + if (pthread_cond_destroy(cnd) != 0) + abort(); +} + +int +cnd_init(cnd_t *cnd) +{ + int ret; + + ret = pthread_cond_init(cnd, NULL); + if (ret == 0) + return (thrd_success); + return (thrd_error); +} + +int +cnd_signal(cnd_t *cnd) +{ + int ret; + + ret = pthread_cond_signal(cnd); + if (ret == 0) + return (thrd_success); + else + return (thrd_error); +} + +/* ARGSUSED */ +int +cnd_timedwait(cnd_t *_RESTRICT_KYWD cnd, mtx_t *_RESTRICT_KYWD mtx, + const struct timespec *_RESTRICT_KYWD ts) +{ + int ret; + + ret = pthread_cond_timedwait(cnd, mtx, ts); + if (ret == 0) + return (thrd_success); + if (ret == ETIMEDOUT) + return (thrd_timedout); + return (thrd_error); +} + +/* ARGSUSED */ +int +cnd_wait(cnd_t *cnd, mtx_t *mtx) +{ + int ret; + + ret = pthread_cond_wait(cnd, mtx); + if (ret == 0) + return (thrd_success); + return (thrd_error); +} + +void +mtx_destroy(mtx_t *mtx) +{ + if (pthread_mutex_destroy(mtx) != 0) + abort(); +} + +int +mtx_init(mtx_t *mtx, int type) +{ + int mtype; + + switch (type) { + case mtx_plain: + case mtx_timed: + mtype = USYNC_THREAD; + break; + case mtx_plain | mtx_recursive: + case mtx_timed | mtx_recursive: + mtype = USYNC_THREAD | LOCK_RECURSIVE; + break; + default: + return (thrd_error); + } + + /* + * Here, we buck the trend and use the traditional SunOS routine. It's + * much simpler than fighting with pthread attributes. + */ + if (mutex_init((mutex_t *)mtx, mtype, NULL) == 0) + return (thrd_success); + return (thrd_error); +} + +int +mtx_lock(mtx_t *mtx) +{ + if (pthread_mutex_lock(mtx) == 0) + return (thrd_success); + return (thrd_error); +} + +int +mtx_timedlock(mtx_t *_RESTRICT_KYWD mtx, + const struct timespec *_RESTRICT_KYWD abstime) +{ + int ret; + + ret = pthread_mutex_timedlock(mtx, abstime); + if (ret == ETIMEDOUT) + return (thrd_timedout); + else if (ret != 0) + return (thrd_error); + return (thrd_success); +} + +int +mtx_trylock(mtx_t *mtx) +{ + int ret; + + ret = pthread_mutex_trylock(mtx); + if (ret == 0) + return (thrd_success); + else if (ret == EBUSY) + return (thrd_busy); + else + return (thrd_error); +} + +int +mtx_unlock(mtx_t *mtx) +{ + if (pthread_mutex_unlock(mtx) == 0) + return (thrd_success); + return (thrd_error); +} + +int +thrd_create(thrd_t *thr, thrd_start_t func, void *arg) +{ + int ret; + + ret = pthread_create(thr, NULL, (void *(*)(void *))func, arg); + if (ret == 0) + return (thrd_success); + else if (ret == -1 && errno == EAGAIN) + return (thrd_nomem); + else + return (thrd_error); +} + +thrd_t +thrd_current(void) +{ + return (pthread_self()); +} + +int +thrd_detach(thrd_t thr) +{ + if (pthread_detach(thr) == 0) + return (thrd_success); + return (thrd_error); +} + +int +thrd_equal(thrd_t t1, thrd_t t2) +{ + return (!pthread_equal(t1, t2)); +} + +_NORETURN_KYWD void +thrd_exit(int res) +{ + pthread_exit((void *)(uintptr_t)res); +} + +int +thrd_join(thrd_t thrd, int *res) +{ + void *es; + + if (pthread_join(thrd, &es) != 0) + return (thrd_error); + if (res != NULL) + *res = (uintptr_t)es; + return (thrd_success); +} + +/* + * thrd_sleep has somewhat odd standardized return values. It doesn't use the + * same returns values as the thrd_* family of functions at all. + */ +int +thrd_sleep(const struct timespec *rqtp, struct timespec *rmtp) +{ + int ret; + if ((ret = nanosleep(rqtp, rmtp)) == 0) + return (0); + if (ret == -1 && errno == EINTR) + return (-1); + return (-2); +} + +void +thrd_yield(void) +{ + thr_yield(); +} + +int +tss_create(tss_t *key, tss_dtor_t dtor) +{ + if (pthread_key_create(key, dtor) == 0) + return (thrd_success); + return (thrd_error); +} + +void +tss_delete(tss_t key) +{ + if (pthread_key_delete(key) != 0) + abort(); +} + +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_success); + return (thrd_error); +} diff --git a/usr/src/lib/libc/port/threads/thr.c b/usr/src/lib/libc/port/threads/thr.c index b5d848449d..88ce377f21 100644 --- a/usr/src/lib/libc/port/threads/thr.c +++ b/usr/src/lib/libc/port/threads/thr.c @@ -23,7 +23,7 @@ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. */ /* - * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright 2016 Joyent, Inc. */ #include "lint.h" @@ -105,6 +105,7 @@ uberdata_t __uberdata = { { DEFAULTMUTEX, NULL, 0 }, { DEFAULTMUTEX, NULL, 0 }}, { RECURSIVEMUTEX, NULL, NULL }, /* atexit_root */ + { RECURSIVEMUTEX, NULL }, /* quickexit_root */ { DEFAULTMUTEX, 0, 0, NULL }, /* tsd_metadata */ { DEFAULTMUTEX, {0, 0}, {0, 0} }, /* tls_metadata */ 0, /* primary_map */ @@ -556,7 +557,7 @@ find_lwp(thread_t tid) int _thrp_create(void *stk, size_t stksize, void *(*func)(void *), void *arg, - long flags, thread_t *new_thread, size_t guardsize) + long flags, thread_t *new_thread, size_t guardsize) { ulwp_t *self = curthread; uberdata_t *udp = self->ul_uberdata; @@ -719,7 +720,7 @@ _thrp_create(void *stk, size_t stksize, void *(*func)(void *), void *arg, int thr_create(void *stk, size_t stksize, void *(*func)(void *), void *arg, - long flags, thread_t *new_thread) + long flags, thread_t *new_thread) { return (_thrp_create(stk, stksize, func, arg, flags, new_thread, 0)); } diff --git a/usr/src/lib/libc/sparc/Makefile.com b/usr/src/lib/libc/sparc/Makefile.com index 6a0f6b6fe4..5302bb8ebd 100644 --- a/usr/src/lib/libc/sparc/Makefile.com +++ b/usr/src/lib/libc/sparc/Makefile.com @@ -20,7 +20,7 @@ # # # Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. -# Copyright (c) 2015, Joyent, Inc. All rights reserved. +# Copyright 2016 Joyent, Inc. # Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved. # Copyright 2013 Garrett D'Amore <garrett@damore.org> # @@ -629,6 +629,7 @@ PORTGEN= \ tfind.o \ time_data.o \ time_gdata.o \ + timespec_get.o \ tls_data.o \ truncate.o \ tsdalloc.o \ @@ -889,6 +890,7 @@ THREADSOBJS= \ alloc.o \ assfail.o \ cancel.o \ + c11_thr.o \ door_calls.o \ tmem.o \ pthr_attr.o \ diff --git a/usr/src/lib/libc/sparcv9/Makefile.com b/usr/src/lib/libc/sparcv9/Makefile.com index 71d5b604b3..d323044aff 100644 --- a/usr/src/lib/libc/sparcv9/Makefile.com +++ b/usr/src/lib/libc/sparcv9/Makefile.com @@ -589,6 +589,7 @@ PORTGEN= \ tfind.o \ time_data.o \ time_gdata.o \ + timespec_get.o \ tls_data.o \ truncate.o \ tsdalloc.o \ @@ -834,6 +835,7 @@ TPOOLOBJS= \ THREADSOBJS= \ alloc.o \ assfail.o \ + c11_thr.o \ cancel.o \ door_calls.o \ tmem.o \ |