aboutsummaryrefslogtreecommitdiffstats
path: root/erts/lib_src/pthread/ethread.c
diff options
context:
space:
mode:
Diffstat (limited to 'erts/lib_src/pthread/ethread.c')
-rw-r--r--erts/lib_src/pthread/ethread.c223
1 files changed, 211 insertions, 12 deletions
diff --git a/erts/lib_src/pthread/ethread.c b/erts/lib_src/pthread/ethread.c
index fb7d135418..29bffa7e12 100644
--- a/erts/lib_src/pthread/ethread.c
+++ b/erts/lib_src/pthread/ethread.c
@@ -1,18 +1,19 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 2010-2011. All Rights Reserved.
+ * Copyright Ericsson AB 2010-2016. All Rights Reserved.
*
- * The contents of this file are subject to the Erlang Public License,
- * Version 1.1, (the "License"); you may not use this file except in
- * compliance with the License. You should have received a copy of the
- * Erlang Public License along with this software. If not, it can be
- * retrieved online at http://www.erlang.org/.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
*
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*
* %CopyrightEnd%
*/
@@ -42,6 +43,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
+#include <string.h>
#include <limits.h>
@@ -49,6 +51,8 @@
#define ETHREAD_IMPL__
#include "ethread.h"
+#undef ETHR_INCLUDE_MONOTONIC_CLOCK__
+#define ETHR_INCLUDE_MONOTONIC_CLOCK__
#include "ethr_internal.h"
#ifndef ETHR_HAVE_ETHREAD_DEFINES
@@ -77,6 +81,8 @@ typedef struct {
void *(*thr_func)(void *);
void *arg;
void *prep_func_res;
+ char *name;
+ char name_buff[16];
} ethr_thr_wrap_data__;
static void *thr_wrapper(void *vtwd)
@@ -98,6 +104,8 @@ static void *thr_wrapper(void *vtwd)
tsep = twd->tse; /* We aren't allowed to follow twd after
result has been set! */
+ if (twd->name)
+ ethr_setname(twd->name);
ethr_atomic32_set(&twd->result, result);
@@ -232,6 +240,10 @@ ethr_x86_cpuid__(int *eax, int *ebx, int *ecx, int *edx)
#endif /* ETHR_X86_RUNTIME_CONF__ */
+#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME
+static void init_get_monotonic_time(void);
+#endif
+
/*
* --------------------------------------------------------------------------
* Exported functions
@@ -254,6 +266,10 @@ ethr_init(ethr_init_data *id)
goto error;
#endif
+#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME
+ init_get_monotonic_time();
+#endif
+
res = ethr_init_common__(id);
if (res != 0)
goto error;
@@ -315,6 +331,12 @@ ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg,
twd.thr_func = func;
twd.arg = arg;
+ if (opts && opts->name) {
+ snprintf(twd.name_buff, 16, "%s", opts->name);
+ twd.name = twd.name_buff;
+ } else
+ twd.name = NULL;
+
res = pthread_attr_init(&attr);
if (res != 0)
return res;
@@ -445,6 +467,30 @@ ethr_self(void)
}
int
+ethr_getname(ethr_tid tid, char *buf, size_t len)
+{
+#if defined(ETHR_HAVE_PTHREAD_GETNAME_NP_3)
+ return pthread_getname_np((pthread_t) tid, buf, len);
+#elif defined(ETHR_HAVE_PTHREAD_GETNAME_NP_2)
+ return pthread_getname_np((pthread_t) tid, buf);
+#else
+ return ENOSYS;
+#endif
+}
+
+void
+ethr_setname(char *name)
+{
+#if defined(ETHR_HAVE_PTHREAD_SETNAME_NP_2)
+ pthread_setname_np(ethr_self(), name);
+#elif defined(ETHR_HAVE_PTHREAD_SET_NAME_NP_2)
+ pthread_set_name_np(ethr_self(), name);
+#elif defined(ETHR_HAVE_PTHREAD_SETNAME_NP_1)
+ pthread_setname_np(name);
+#endif
+}
+
+int
ethr_equal_tids(ethr_tid tid1, ethr_tid tid2)
{
return pthread_equal((pthread_t) tid1, (pthread_t) tid2);
@@ -472,7 +518,7 @@ ethr_leave_ts_event(ethr_ts_event *tsep)
*/
int
-ethr_tsd_key_create(ethr_tsd_key *keyp)
+ethr_tsd_key_create(ethr_tsd_key *keyp, char *keyname)
{
#if ETHR_XCHK
if (ethr_not_inited__) {
@@ -541,7 +587,11 @@ int ethr_sigmask(int how, const sigset_t *set, sigset_t *oset)
return EINVAL;
}
#endif
- return pthread_sigmask(how, set, oset);
+#if defined(__ANDROID__)
+ return sigprocmask(how, set, oset);
+#else
+ return pthread_sigmask(how, set, oset);
+#endif
}
int ethr_sigwait(const sigset_t *set, int *sig)
@@ -561,8 +611,157 @@ int ethr_sigwait(const sigset_t *set, int *sig)
return 0;
}
+int ethr_kill(const ethr_tid tid, const int sig)
+{
+#if ETHR_XCHK
+ if (ethr_not_inited__) {
+ ETHR_ASSERT(0);
+ return EACCES;
+ }
+#endif
+ return pthread_kill((const pthread_t)tid, sig);
+}
+
#endif /* #if ETHR_HAVE_ETHR_SIG_FUNCS */
+#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME
+
+static int broken_get_monotonic_time;
+
+#if defined(ETHR_HAVE_CLOCK_GETTIME_MONOTONIC)
+# ifndef ETHR_MONOTONIC_CLOCK_ID
+# error ETHR_MONOTONIC_CLOCK_ID should have been defined
+# endif
+
+ethr_sint64_t
+ethr_get_monotonic_time(void)
+{
+ ethr_sint64_t time;
+ struct timespec ts;
+
+ if (broken_get_monotonic_time)
+ return (ethr_sint64_t) 0;
+
+ if (0 != clock_gettime(ETHR_MONOTONIC_CLOCK_ID, &ts))
+ ETHR_FATAL_ERROR__(errno);
+
+ time = (ethr_sint64_t) ts.tv_sec;
+ time *= (ethr_sint64_t) 1000*1000*1000;
+ time += (ethr_sint64_t) ts.tv_nsec;
+ return time;
+}
+
+#elif defined(ETHR_HAVE_MACH_CLOCK_GET_TIME)
+# ifndef ETHR_MONOTONIC_CLOCK_ID
+# error ETHR_MONOTONIC_CLOCK_ID should have been defined
+# endif
+
+ethr_sint64_t
+ethr_get_monotonic_time(void)
+{
+ ethr_sint64_t time;
+ kern_return_t res;
+ clock_serv_t clk_srv;
+ mach_timespec_t time_spec;
+
+ if (broken_get_monotonic_time)
+ return (ethr_sint64_t) 0;
+
+ errno = EFAULT;
+ host_get_clock_service(mach_host_self(),
+ ETHR_MONOTONIC_CLOCK_ID,
+ &clk_srv);
+ res = clock_get_time(clk_srv, &time_spec);
+ if (res != KERN_SUCCESS)
+ ETHR_FATAL_ERROR__(errno);
+ mach_port_deallocate(mach_task_self(), clk_srv);
+
+ time = (ethr_sint64_t) time_spec.tv_sec;
+ time *= (ethr_sint64_t) 1000*1000*1000;
+ time += (ethr_sint64_t) time_spec.tv_nsec;
+ return time;
+}
+
+#elif defined(ETHR_HAVE_GETHRTIME)
+
+ethr_sint64_t
+ethr_get_monotonic_time(void)
+{
+ if (broken_get_monotonic_time)
+ return (ethr_sint64_t) 0;
+ return (ethr_sint64_t) gethrtime();
+}
+
+#else
+#error missing monotonic clock
+#endif
+
+int
+ethr_get_monotonic_time_is_broken(void)
+{
+ return broken_get_monotonic_time;
+}
+
+#include <string.h>
+#include <ctype.h>
+#include <sys/utsname.h>
+
+static void
+init_get_monotonic_time(void)
+{
+ struct utsname uts;
+ int vsn[3];
+ int i;
+ char *c;
+
+ broken_get_monotonic_time = 0;
+
+ (void) uname(&uts);
+
+ for (c = uts.sysname; *c; c++) {
+ if (isupper((int) *c))
+ *c = tolower((int) *c);
+ }
+
+ c = uts.release;
+ for (i = 0; i < sizeof(vsn)/sizeof(int); i++) {
+ if (!isdigit((int) *c))
+ vsn[i] = 0;
+ else {
+ char *c2 = c;
+ do {
+ c2++;
+ } while (isdigit((int) *c2));
+ *c2 = '\0';
+ vsn[i] = atoi(c);
+ c = c2;
+ c++;
+ }
+ }
+
+ if (strcmp("linux", uts.sysname) == 0) {
+ if (vsn[0] < 2
+ || (vsn[0] == 2 && vsn[1] < 6)
+ || (vsn[0] == 2 && vsn[1] == 6 && vsn[2] < 33)) {
+ broken_get_monotonic_time = 1;
+ }
+ }
+ else if (strcmp("sunos", uts.sysname) == 0) {
+ if ((vsn[0] < 5
+ || (vsn[0] == 5 && vsn[1] < 8))
+#if defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_CONF)
+ && sysconf(_SC_NPROCESSORS_CONF) > 1
+#endif
+ ) {
+ broken_get_monotonic_time = 1;
+ }
+ }
+
+}
+
+
+#endif /* ETHR_HAVE_ETHR_GET_MONOTONIC_TIME */
+
ETHR_IMPL_NORETURN__
ethr_abort__(void)
{