summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2016-03-28 19:43:25 -0700
committerRobert Mustacchi <rm@joyent.com>2016-05-19 07:45:52 -0700
commitfc2512cfb727d49529d8ed99164db871f4829b73 (patch)
tree89ea56b5a9833e92795bf45c723c6de65b7490f2 /usr/src/lib/libc
parentea4a67f462de0a39a9adea8197bcdef849de5371 (diff)
downloadillumos-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/Makefile4
-rw-r--r--usr/src/lib/libc/i386/Makefile.com4
-rw-r--r--usr/src/lib/libc/inc/thr_uberdata.h26
-rw-r--r--usr/src/lib/libc/port/gen/atexit.c53
-rw-r--r--usr/src/lib/libc/port/gen/memalign.c15
-rw-r--r--usr/src/lib/libc/port/gen/timespec_get.c33
-rw-r--r--usr/src/lib/libc/port/mapfile-vers35
-rw-r--r--usr/src/lib/libc/port/threads/c11_thr.c293
-rw-r--r--usr/src/lib/libc/port/threads/thr.c7
-rw-r--r--usr/src/lib/libc/sparc/Makefile.com4
-rw-r--r--usr/src/lib/libc/sparcv9/Makefile.com2
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 \