diff options
Diffstat (limited to 'erts/lib_src')
-rw-r--r-- | erts/lib_src/Makefile | 23 | ||||
-rw-r--r-- | erts/lib_src/Makefile.in | 29 | ||||
-rw-r--r-- | erts/lib_src/common/erl_memory_trace_parser.c | 23 | ||||
-rw-r--r-- | erts/lib_src/common/erl_misc_utils.c | 40 | ||||
-rw-r--r-- | erts/lib_src/common/erl_printf.c | 107 | ||||
-rw-r--r-- | erts/lib_src/common/erl_printf_format.c | 48 | ||||
-rw-r--r-- | erts/lib_src/common/ethr_atomics.c | 21 | ||||
-rw-r--r-- | erts/lib_src/common/ethr_aux.c | 78 | ||||
-rw-r--r-- | erts/lib_src/common/ethr_cbf.c | 21 | ||||
-rw-r--r-- | erts/lib_src/common/ethr_mutex.c | 29 | ||||
-rw-r--r-- | erts/lib_src/ose/ethr_event.c | 219 | ||||
-rw-r--r-- | erts/lib_src/ose/ethread.c | 832 | ||||
-rw-r--r-- | erts/lib_src/pthread/ethr_event.c | 527 | ||||
-rw-r--r-- | erts/lib_src/pthread/ethr_x86_sse2_asm.c | 21 | ||||
-rw-r--r-- | erts/lib_src/pthread/ethread.c | 215 | ||||
-rwxr-xr-x | erts/lib_src/utils/make_atomics_api | 40 | ||||
-rw-r--r-- | erts/lib_src/win/ethr_event.c | 80 | ||||
-rw-r--r-- | erts/lib_src/win/ethread.c | 34 |
18 files changed, 1047 insertions, 1340 deletions
diff --git a/erts/lib_src/Makefile b/erts/lib_src/Makefile index f94e47a856..882a050ffd 100644 --- a/erts/lib_src/Makefile +++ b/erts/lib_src/Makefile @@ -1,18 +1,19 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2004-2009. All Rights Reserved. +# Copyright Ericsson AB 2004-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/. -# -# 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. +# 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 +# +# 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% # diff --git a/erts/lib_src/Makefile.in b/erts/lib_src/Makefile.in index cf1aef518a..601f3917a8 100644 --- a/erts/lib_src/Makefile.in +++ b/erts/lib_src/Makefile.in @@ -1,18 +1,19 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2004-2013. All Rights Reserved. +# Copyright Ericsson AB 2004-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% # @@ -92,6 +93,11 @@ CFLAGS += -DERTS_FRMPTR OMIT_OMIT_FP=yes PRE_LD= else +ifeq ($(TYPE),icount) +TYPE_SUFFIX = .icount +CFLAGS += -DERTS_OPCODE_COUNTER_SUPPORT +PRE_LD= +else override TYPE=opt OMIT_FP=true TYPE_SUFFIX= @@ -105,6 +111,7 @@ endif endif endif endif +endif OPSYS=@OPSYS@ sol2CFLAGS= @@ -458,13 +465,13 @@ RELSYSDIR = $(RELEASE_PATH)/erts-$(VSN) RELEASE_INCLUDES= \ $(ERTS_INCL)/erl_memory_trace_parser.h \ $(ERTS_INCL)/$(TARGET)/erl_int_sizes_config.h \ - $(ERTS_INCL)/$(TARGET)/erl_native_features_config.h \ $(ERTS_INCL)/erl_fixed_size_int_types.h RELEASE_LIBS=$(ERTS_LIBS) INTERNAL_RELEASE_INCLUDES= \ $(ERTS_INCL_INT)/README \ $(ERTS_INCL_INT)/ethread.h \ + $(ERTS_INCL_INT)/ethread_inline.h \ $(ERTS_INCL_INT)/ethr_mutex.h \ $(ERTS_INCL_INT)/ethr_optimized_fallbacks.h \ $(ERTS_INCL_INT)/ethr_atomics.h \ diff --git a/erts/lib_src/common/erl_memory_trace_parser.c b/erts/lib_src/common/erl_memory_trace_parser.c index 625c140cf9..0232708ad1 100644 --- a/erts/lib_src/common/erl_memory_trace_parser.c +++ b/erts/lib_src/common/erl_memory_trace_parser.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2004-2011. All Rights Reserved. + * Copyright Ericsson AB 2004-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/. - * - * 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. + * 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 + * + * 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% */ diff --git a/erts/lib_src/common/erl_misc_utils.c b/erts/lib_src/common/erl_misc_utils.c index 5a271c5268..8186463b9c 100644 --- a/erts/lib_src/common/erl_misc_utils.c +++ b/erts/lib_src/common/erl_misc_utils.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2006-2013. All Rights Reserved. + * Copyright Ericsson AB 2006-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% */ @@ -25,6 +26,7 @@ # include <windows.h> #endif +#include "ethread_inline.h" #include "erl_misc_utils.h" #if defined(__WIN32__) @@ -158,8 +160,6 @@ erts_milli_sleep(long ms) if (ms > 0) { #ifdef __WIN32__ Sleep((DWORD) ms); -#elif defined(__OSE__) - delay(ms); #else struct timeval tv; tv.tv_sec = ms / 1000; @@ -191,7 +191,7 @@ struct erts_cpu_info_t_ { #if defined(__WIN32__) -static __forceinline int +static ETHR_FORCE_INLINE int get_proc_affinity(erts_cpu_info_t *cpuinfo, cpu_set_t *cpuset) { DWORD_PTR pamask; @@ -206,7 +206,7 @@ get_proc_affinity(erts_cpu_info_t *cpuinfo, cpu_set_t *cpuset) } } -static __forceinline int +static ETHR_FORCE_INLINE int set_thr_affinity(cpu_set_t *set) { if (*set == (cpu_set_t) 0) @@ -318,10 +318,6 @@ erts_cpu_info_update(erts_cpu_info_t *cpuinfo) online = 0; #endif } -#elif defined(__OSE__) - online = ose_num_cpus(); - configured = ose_num_cpus(); - available = ose_num_cpus(); #endif if (online > configured) @@ -1157,7 +1153,7 @@ read_topology(erts_cpu_info_t *cpuinfo) #define ERTS_MU_RELATION_CACHE 2 /* RelationCache */ #define ERTS_MU_RELATION_PROCESSOR_PACKAGE 3 /* RelationProcessorPackage */ -static __forceinline int +static ETHR_FORCE_INLINE int rel_cmp_val(int r) { switch (r) { @@ -1514,7 +1510,7 @@ const char* parse_topology_spec_group(erts_cpu_info_t *cpuinfo, const char* xml, if (is_thread_group) { thread++; } else { - *core_p = (*core_p)++; + *core_p = (*core_p) + 1; } index_procs++; } @@ -1534,9 +1530,9 @@ const char* parse_topology_spec_group(erts_cpu_info_t *cpuinfo, const char* xml, if (parentCacheLevel == 0) { *core_p = 0; - *processor_p = (*processor_p)++; + *processor_p = (*processor_p) + 1; } else { - *core_p = (*core_p)++; + *core_p = (*core_p) + 1; } if (error) diff --git a/erts/lib_src/common/erl_printf.c b/erts/lib_src/common/erl_printf.c index 2c177ee5ac..7781fc2196 100644 --- a/erts/lib_src/common/erl_printf.c +++ b/erts/lib_src/common/erl_printf.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2005-2012. All Rights Reserved. + * Copyright Ericsson AB 2005-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/. - * - * 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. + * 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 + * + * 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% */ @@ -87,6 +88,41 @@ void (*erts_printf_unblock_fpe)(int) = NULL; # define FWRITE fwrite #endif +/* We use write for stdout and stderr as they could be + set to non-blocking by shell drivers, and non-blocking + FILE * functions work unpredictably as best */ +static int +printf_putc(int c, FILE *stream) { + if ((FILE*)stream == stdout || (FILE*)stream == stderr) { + int fd = stream == stdout ? fileno(stdout) : fileno(stderr); + /* cast to a char here, because write expects bytes. */ + unsigned char buf[1] = { c }; + int res; + do { + res = write(fd, buf, 1); + } while (res == -1 && (errno == EAGAIN || errno == EINTR)); + if (res == -1) return EOF; + return res; + } + + return PUTC(c, stream); +} + +static size_t +printf_fwrite(const void *ptr, size_t size, size_t nitems, + FILE *stream) { + if ((FILE*)stream == stdout || (FILE*)stream == stderr) { + int fd = stream == stdout ? fileno(stdout) : fileno(stderr); + int res; + do { + res = write(fd, ptr, size*nitems); + } while (res == -1 && (errno == EAGAIN || errno == EINTR)); + if (res == -1) return 0; + return res; + } + return FWRITE(ptr, size, nitems, stream); +} + static int get_error_result(void) { @@ -103,10 +139,10 @@ write_f_add_cr(void *vfp, char* buf, size_t len) size_t i; ASSERT(vfp); for (i = 0; i < len; i++) { - if (buf[i] == '\n' && PUTC('\r', (FILE *) vfp) == EOF) - return get_error_result(); - if (PUTC(buf[i], (FILE *) vfp) == EOF) - return get_error_result(); + if (buf[i] == '\n' && printf_putc('\r', (FILE *) vfp) == EOF) + return get_error_result(); + if (printf_putc(buf[i], (FILE *) vfp) == EOF) + return get_error_result(); } return len; } @@ -119,18 +155,18 @@ write_f(void *vfp, char* buf, size_t len) if (len <= 64) { /* Try to optimize writes of small bufs. */ int i; for (i = 0; i < len; i++) - if (PUTC(buf[i], (FILE *) vfp) == EOF) + if (printf_putc(buf[i], (FILE *) vfp) == EOF) return get_error_result(); } else #endif - if (FWRITE((void *) buf, sizeof(char), len, (FILE *) vfp) != len) + if (printf_fwrite((void *) buf, sizeof(char), len, (FILE *) vfp) != len) return get_error_result(); return len; } -static int -write_fd(void *vfdp, char* buf, size_t len) +int +erts_write_fd(void *vfdp, char* buf, size_t len) { ssize_t size; size_t res = len; @@ -190,8 +226,8 @@ write_sn(void *vwsnap, char* buf, size_t len) return rv; } -static int -write_ds(void *vdsbufp, char* buf, size_t len) +int +erts_write_ds(void *vdsbufp, char* buf, size_t len) { erts_dsprintf_buf_t *dsbufp = (erts_dsprintf_buf_t *) vdsbufp; size_t need_len = len + 1; /* Also trailing '\0' */ @@ -265,7 +301,7 @@ erts_fdprintf(int fd, const char *format, ...) va_list arglist; va_start(arglist, format); errno = 0; - res = erts_printf_format(write_fd,(void *)&fd,(char *)format,arglist); + res = erts_printf_format(erts_write_fd,(void *)&fd,(char *)format,arglist); va_end(arglist); return res; } @@ -319,7 +355,7 @@ erts_dsprintf(erts_dsprintf_buf_t *dsbufp, const char *format, ...) return -EINVAL; va_start(arglist, format); errno = 0; - res = erts_printf_format(write_ds, (void *)dsbufp, (char *)format, arglist); + res = erts_printf_format(erts_write_ds, (void *)dsbufp, (char *)format, arglist); if (dsbufp->str) { if (res < 0) dsbufp->str[0] = '\0'; @@ -330,6 +366,20 @@ erts_dsprintf(erts_dsprintf_buf_t *dsbufp, const char *format, ...) return res; } +/* + * Callback printf + */ +int erts_cbprintf(fmtfn_t cb_fn, void* cb_arg, const char* format, ...) +{ + int res; + va_list arglist; + va_start(arglist, format); + errno = 0; + res = erts_printf_format(cb_fn, cb_arg, (char *)format, arglist); + va_end(arglist); + return res; +} + int erts_vprintf(const char *format, va_list arglist) { @@ -375,7 +425,7 @@ erts_vfdprintf(int fd, const char *format, va_list arglist) { int res; errno = 0; - res = erts_printf_format(write_fd,(void *)&fd,(char *)format,arglist); + res = erts_printf_format(erts_write_fd,(void *)&fd,(char *)format,arglist); return res; } @@ -420,7 +470,7 @@ erts_vdsprintf(erts_dsprintf_buf_t *dsbufp, const char *format, va_list arglist) if (!dsbufp) return -EINVAL; errno = 0; - res = erts_printf_format(write_ds, (void *)dsbufp, (char *)format, arglist); + res = erts_printf_format(erts_write_ds, (void *)dsbufp, (char *)format, arglist); if (dsbufp->str) { if (res < 0) dsbufp->str[0] = '\0'; @@ -429,3 +479,10 @@ erts_vdsprintf(erts_dsprintf_buf_t *dsbufp, const char *format, va_list arglist) } return res; } + +int +erts_vcbprintf(fmtfn_t cb_fn, void* cb_arg, const char *format, va_list arglist) +{ + errno = 0; + return erts_printf_format(cb_fn, cb_arg, (char *)format, arglist); +} diff --git a/erts/lib_src/common/erl_printf_format.c b/erts/lib_src/common/erl_printf_format.c index d6ae76f14c..3daa066fd3 100644 --- a/erts/lib_src/common/erl_printf_format.c +++ b/erts/lib_src/common/erl_printf_format.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2005-2013. All Rights Reserved. + * Copyright Ericsson AB 2005-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/. - * - * 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. + * 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 + * + * 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% */ @@ -77,15 +78,7 @@ #endif #ifndef ERTS_SIZEOF_ETERM -# ifdef HALFWORD_HEAP_EMULATOR -# if SIZEOF_VOID_P == 8 -# define ERTS_SIZEOF_ETERM 4 -# else -# error "HALFWORD_HEAP_EMULATOR only allowed on 64-bit architecture" -# endif -# else -# define ERTS_SIZEOF_ETERM SIZEOF_VOID_P -# endif +#define ERTS_SIZEOF_ETERM SIZEOF_VOID_P #endif #if defined(__GNUC__) @@ -101,7 +94,7 @@ #endif #define FMTC_d 0x0000 -#define FMTC_R 0x0001 +/*empty 0x0001 was RELATIVE */ #define FMTC_o 0x0002 #define FMTC_u 0x0003 #define FMTC_x 0x0004 @@ -165,7 +158,7 @@ static char heX[] = "0123456789ABCDEF"; #define SIGN(X) ((X) > 0 ? 1 : ((X) < 0 ? -1 : 0)) #define USIGN(X) ((X) == 0 ? 0 : 1) -int (*erts_printf_eterm_func)(fmtfn_t, void*, ErlPfEterm, long, ErlPfEterm*) = NULL; +int (*erts_printf_eterm_func)(fmtfn_t, void*, ErlPfEterm, long) = NULL; static int noop_fn(void *vfp, char* buf, size_t len) @@ -644,7 +637,6 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap) case 'p': ptr++; fmt |= FMTC_p; break; case 'n': ptr++; fmt |= FMTC_n; break; case 'T': ptr++; fmt |= FMTC_T; break; - case 'R': ptr++; fmt |= FMTC_R; break; case '%': FMT(fn,arg,ptr,1,count); ptr++; @@ -819,11 +811,9 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap) default: *va_arg(ap,int*) = count; break; } break; - case FMTC_T: /* Eterm */ - case FMTC_R: { /* Eterm, Eterm* base (base ignored if !HALFWORD_HEAP) */ + case FMTC_T: { /* Eterm */ long prec; ErlPfEterm eterm; - ErlPfEterm* eterm_base; if (!erts_printf_eterm_func) return -EINVAL; @@ -834,16 +824,14 @@ int erts_printf_format(fmtfn_t fn, void* arg, char* fmt, va_list ap) else prec = (long) precision; eterm = va_arg(ap, ErlPfEterm); - eterm_base = ((fmt & FMTC_MASK) == FMTC_R) ? - va_arg(ap, ErlPfEterm*) : NULL; if (width > 0 && !(fmt & FMTF_adj)) { - res = (*erts_printf_eterm_func)(noop_fn, NULL, eterm, prec, eterm_base); + res = (*erts_printf_eterm_func)(noop_fn, NULL, eterm, prec); if (res < 0) return res; if (width > res) BLANKS(fn, arg, width - res, count); } - res = (*erts_printf_eterm_func)(fn, arg, eterm, prec, eterm_base); + res = (*erts_printf_eterm_func)(fn, arg, eterm, prec); if (res < 0) return res; count += res; diff --git a/erts/lib_src/common/ethr_atomics.c b/erts/lib_src/common/ethr_atomics.c index c52166a7ec..1594d78f5e 100644 --- a/erts/lib_src/common/ethr_atomics.c +++ b/erts/lib_src/common/ethr_atomics.c @@ -10,18 +10,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2011-2012. All Rights Reserved. + * Copyright Ericsson AB 2011-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% */ diff --git a/erts/lib_src/common/ethr_aux.c b/erts/lib_src/common/ethr_aux.c index ceecdcef64..420efd725f 100644 --- a/erts/lib_src/common/ethr_aux.c +++ b/erts/lib_src/common/ethr_aux.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2010-2012. 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% */ @@ -40,8 +41,8 @@ #include <unistd.h> #endif -#define ERTS_TS_EV_ALLOC_DEFAULT_POOL_SIZE 4000 -#define ERTS_TS_EV_ALLOC_POOL_SIZE 25 +#define ERTS_TS_EV_ALLOC_DEFAULT_POOL_SIZE 2048 +#define ERTS_TS_EV_ALLOC_POOL_SIZE 32 erts_cpu_info_t *ethr_cpu_info__; @@ -138,6 +139,38 @@ x86_init(void) #endif /* bit 26 of edx is set if we have sse2 */ ethr_runtime__.conf.have_sse2 = (edx & (1 << 26)); + + /* check if we have extended feature set */ + eax = 0x80000000; + ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx); + + if (eax < 0x80000001) + return; + + if (eax >= 0x80000007) { + /* Advanced Power Management Information */ + eax = 0x80000007; + ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx); + + /* I got the values below from: + http://lxr.free-electrons.com/source/arch/x86/include/asm/cpufeature.h + They can be gotten from the intel/amd manual as well. + */ + + ethr_runtime__.conf.have_constant_tsc = (edx & (1 << 8)); + ethr_runtime__.conf.have_tsc_reliable = (edx & (1 << 23)); + ethr_runtime__.conf.have_nonstop_tsc = (edx & (1 << 24)); + ethr_runtime__.conf.have_nonstop_tsc_s3 = (edx & (1 << 30)); + + } + + /* Extended Processor Info and Feature Bits */ + eax = 0x80000001; + ethr_x86_cpuid__(&eax, &ebx, &ecx, &edx); + + /* bit 27 of edx is set if we have rdtscp */ + ethr_runtime__.conf.have_rdtscp = (edx & (1 << 27)); + } #endif /* ETHR_X86_RUNTIME_CONF__ */ @@ -148,6 +181,8 @@ ethr_init_common__(ethr_init_data *id) { int res; + ethr_init_event__(); + #if defined(ETHR_X86_RUNTIME_CONF__) x86_init(); #endif @@ -204,18 +239,7 @@ ethr_init_common__(ethr_init_data *id) ethr_min_stack_size__ = ETHR_B2KW(ethr_min_stack_size__); -#ifdef __OSE__ - /* For supervisor processes, OSE adds a number of bytes to the requested stack. With this - * addition, the resulting size must not exceed the largest available stack size. The number - * of bytes that will be added is configured in the monolith and can therefore not be - * specified here. We simply assume that it is less than 0x1000. The available stack sizes - * are configured in the .lmconf file and the largest one is usually 65536 bytes. - * Consequently, the requested stack size is limited to 0xF000. - */ - ethr_max_stack_size__ = 0xF000; -#else ethr_max_stack_size__ = 32*1024*1024; -#endif #if SIZEOF_VOID_P == 8 ethr_max_stack_size__ *= 2; #endif @@ -360,10 +384,10 @@ static ethr_ts_event *ts_event_pool(int size, ethr_ts_event **endpp) int i; ethr_aligned_ts_event *atsev; atsev = ethr_mem__.std.alloc(sizeof(ethr_aligned_ts_event) * size - + ETHR_CACHE_LINE_SIZE); + + ETHR_CACHE_LINE_SIZE - 1); if (!atsev) return NULL; - if ((((ethr_uint_t) atsev) & ETHR_CACHE_LINE_MASK) == 0) + if ((((ethr_uint_t) atsev) & ETHR_CACHE_LINE_MASK) != 0) atsev = ((ethr_aligned_ts_event *) ((((ethr_uint_t) atsev) & ~ETHR_CACHE_LINE_MASK) + ETHR_CACHE_LINE_SIZE)); @@ -661,10 +685,6 @@ ETHR_IMPL_NORETURN__ ethr_fatal_error__(const char *file, int ethr_assert_failed(const char *file, int line, const char *func, char *a) { fprintf(stderr, "%s:%d: %s(): Assertion failed: %s\n", file, line, func, a); -#ifdef __OSE__ - ramlog_printf("%d: %s:%d: %s(): Assertion failed: %s\n", - current_process(),file, line, func, a); -#endif ethr_abort__(); return 0; } diff --git a/erts/lib_src/common/ethr_cbf.c b/erts/lib_src/common/ethr_cbf.c index 04feceec89..037559be22 100644 --- a/erts/lib_src/common/ethr_cbf.c +++ b/erts/lib_src/common/ethr_cbf.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2010. 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% */ diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c index 72b44033ad..5e7e7b2f32 100644 --- a/erts/lib_src/common/ethr_mutex.c +++ b/erts/lib_src/common/ethr_mutex.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2010-2013. 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% */ @@ -1249,7 +1250,7 @@ ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx) return 0; } -#elif (defined(ETHR_PTHREADS) || defined(ETHR_OSE_THREADS)) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS) +#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS) /* -- pthread mutex and condition variables -------------------------------- */ int @@ -1433,7 +1434,7 @@ void LeaveCriticalSection(CRITICAL_SECTION *cs) #define ETHR_CND_WAIT__ ((ethr_sint32_t) 0x11dead11) #define ETHR_CND_WAKEUP__ ((ethr_sint32_t) 0x11beef11) -static __forceinline void +static ETHR_FORCE_INLINE void cond_wakeup(ethr_ts_event *tse) { ETHR_ASSERT(ethr_atomic32_read(&tse->uaflgs) == ETHR_CND_WAIT__); @@ -1574,7 +1575,7 @@ ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx) return 0; } -static __forceinline void +static ETHR_FORCE_INLINE void posix_compliant_mtx_enqueue(ethr_mutex *mtx, ethr_ts_event *tse_start, ethr_ts_event *tse_end) @@ -1614,7 +1615,7 @@ posix_compliant_mtx_enqueue(ethr_mutex *mtx, } } -static __forceinline void +static ETHR_FORCE_INLINE void enqueue_cond_wakeups(ethr_ts_event *queue, int posix_compliant) { if (queue) { diff --git a/erts/lib_src/ose/ethr_event.c b/erts/lib_src/ose/ethr_event.c deleted file mode 100644 index 87294c98ea..0000000000 --- a/erts/lib_src/ose/ethr_event.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2009-2010. 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/. - * - * 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. - * - * %CopyrightEnd% - */ - -/* - * Author: Rickard Green - */ - -#define ETHR_INLINE_FUNC_NAME_(X) X ## __ -#define ETHR_EVENT_IMPL__ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "ethread.h" - -#ifdef USE_PTHREAD_API - -int -ethr_event_init(ethr_event *e) -{ - int res; - ethr_atomic32_init(&e->state, ETHR_EVENT_OFF__); - res = pthread_mutex_init(&e->mtx, NULL); - if (res != 0) - return res; - res = pthread_cond_init(&e->cnd, NULL); - if (res != 0) { - pthread_mutex_destroy(&e->mtx); - return res; - } - return 0; -} - -int -ethr_event_destroy(ethr_event *e) -{ - int res; - res = pthread_mutex_destroy(&e->mtx); - if (res != 0) - return res; - res = pthread_cond_destroy(&e->cnd); - if (res != 0) - return res; - return 0; -} - -static ETHR_INLINE int -wait__(ethr_event *e, int spincount) -{ - int sc = spincount; - ethr_sint32_t val; - int res, ulres; - int until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS; - - if (spincount < 0) - ETHR_FATAL_ERROR__(EINVAL); - - while (1) { - val = ethr_atomic32_read(&e->state); - if (val == ETHR_EVENT_ON__) - return 0; - if (sc == 0) - break; - sc--; - ETHR_SPIN_BODY; - if (--until_yield == 0) { - until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS; - res = ETHR_YIELD(); - if (res != 0) - ETHR_FATAL_ERROR__(res); - } - } - - if (val != ETHR_EVENT_OFF_WAITER__) { - val = ethr_atomic32_cmpxchg(&e->state, - ETHR_EVENT_OFF_WAITER__, - ETHR_EVENT_OFF__); - if (val == ETHR_EVENT_ON__) - return 0; - ETHR_ASSERT(val == ETHR_EVENT_OFF__); - } - - ETHR_ASSERT(val == ETHR_EVENT_OFF_WAITER__ - || val == ETHR_EVENT_OFF__); - - res = pthread_mutex_lock(&e->mtx); - if (res != 0) - ETHR_FATAL_ERROR__(res); - - while (1) { - - val = ethr_atomic32_read(&e->state); - if (val == ETHR_EVENT_ON__) - break; - - res = pthread_cond_wait(&e->cnd, &e->mtx); - if (res == EINTR) - break; - if (res != 0) - ETHR_FATAL_ERROR__(res); - } - - ulres = pthread_mutex_unlock(&e->mtx); - if (ulres != 0) - ETHR_FATAL_ERROR__(ulres); - - return res; /* 0 || EINTR */ -} - -#else -/* --- OSE implementation of events ---------------------------- */ - -#ifdef DEBUG -union SIGNAL { - SIGSELECT signo; -}; -#endif - -int -ethr_event_init(ethr_event *e) -{ - ethr_atomic32_init(&e->state, ETHR_EVENT_OFF__); - e->proc = current_process(); - return 0; -} - -int -ethr_event_destroy(ethr_event *e) -{ - return 0; -} - -static ETHR_INLINE int -wait__(ethr_event *e, int spincount) -{ - int sc = spincount; - int res; - int until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS; - - if (spincount < 0) - ETHR_FATAL_ERROR__(EINVAL); - - ETHR_ASSERT(e->proc == current_process()); - ETHR_ASSERT(get_fsem(current_process()) == 0); - - while (1) { - ethr_sint32_t val; - while (1) { - val = ethr_atomic32_read(&e->state); - if (val == ETHR_EVENT_ON__) - return 0; - if (sc == 0) - break; - sc--; - ETHR_SPIN_BODY; - if (--until_yield == 0) { - until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS; - res = ETHR_YIELD(); - if (res != 0) - ETHR_FATAL_ERROR__(res); - } - } - if (val != ETHR_EVENT_OFF_WAITER__) { - val = ethr_atomic32_cmpxchg(&e->state, - ETHR_EVENT_OFF_WAITER__, - ETHR_EVENT_OFF__); - if (val == ETHR_EVENT_ON__) - return 0; - ETHR_ASSERT(val == ETHR_EVENT_OFF__); - } - - wait_fsem(1); - - ETHR_ASSERT(get_fsem(current_process()) == 0); - } -} - -#endif - -void -ethr_event_reset(ethr_event *e) -{ - ethr_event_reset__(e); -} - -void -ethr_event_set(ethr_event *e) -{ - ethr_event_set__(e); -} - -int -ethr_event_wait(ethr_event *e) -{ - return wait__(e, 0); -} - -int -ethr_event_swait(ethr_event *e, int spincount) -{ - return wait__(e, spincount); -} diff --git a/erts/lib_src/ose/ethread.c b/erts/lib_src/ose/ethread.c deleted file mode 100644 index 53628382b1..0000000000 --- a/erts/lib_src/ose/ethread.c +++ /dev/null @@ -1,832 +0,0 @@ -/* - * %CopyrightBegin% - * - * Copyright Ericsson AB 2010-2011. 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/. - * - * 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. - * - * %CopyrightEnd% - */ - -/* - * Description: OSE implementation of the ethread library - * Author: Lukas Larsson - */ - - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "stdio.h" -#ifdef ETHR_TIME_WITH_SYS_TIME -# include "time.h" -# include "sys/time.h" -#else -# ifdef ETHR_HAVE_SYS_TIME_H -# include "sys/time.h" -# else -# include "time.h" -# endif -#endif -#include "sys/types.h" -#include "unistd.h" - -#include "limits.h" - -#define ETHR_INLINE_FUNC_NAME_(X) X ## __ -#define ETHREAD_IMPL__ - -#include "ethread.h" -#include "ethr_internal.h" - -#include "erl_printf.h" -#include "efs.h" -#include "ose.h" - -#include "ose_spi.h" - -#include "string.h" -#include "ctype.h" -#include "stdlib.h" - -#ifndef ETHR_HAVE_ETHREAD_DEFINES -#error Missing configure defines -#endif - -#define ETHR_INVALID_TID_ID -1 - -#define DEFAULT_PRIO_NAME "ERTS_ETHR_DEFAULT_PRIO" - -/* Set the define to 1 to get some logging */ -#if 0 -#include "ramlog.h" -#define LOG(output) ramlog_printf output -#else -#define LOG(output) -#endif - -static ethr_tid main_thr_tid; -static const char* own_tid_key = "ethread_own_tid"; -ethr_tsd_key ethr_ts_event_key__; - -#define ETHREADWRAPDATASIG 1 - -/* Init data sent to thr_wrapper() */ -typedef struct { - SIGSELECT sig_no; - ethr_ts_event *tse; - ethr_tid *tid; - ethr_sint32_t result; - void *(*thr_func)(void *); - void *arg; - void *prep_func_res; - const char *name; -} ethr_thr_wrap_data__; - -union SIGNAL { - SIGSELECT sig_no; - ethr_thr_wrap_data__ data; -}; - -#define ETHR_GET_OWN_TID__ ((ethr_tid *) get_envp(current_process(),\ - own_tid_key)) - -/* - * -------------------------------------------------------------------------- - * Static functions - * -------------------------------------------------------------------------- - */ - -/* Will retrive the instrinsic name by removing the 'prefix' and the - * suffix from 'name'. - * The 'prefix' is given as an inparameter. If NULL or an empty string no - * prefix will be removed. - * If 'strip_suffix' is 1 suffixes in the form of '_123' will be removed. - * Will return a pointer to a newly allocated buffer containing the intrinsic - * name in uppercase characters. - * The caller must remember to free this buffer when no lnger needed. - */ -static char * -ethr_intrinsic_name(const char *name, const char *prefix, int strip_suffix) -{ - const char *start = name; - const char *end = name + strlen(name); - char *intrinsic_name = NULL; - int i; - - if (name == NULL) { - LOG(("ERTS - ethr_intrinsic_namNo input name.\n")); - return NULL; - } - - /* take care of the prefix */ - if ((prefix != NULL) && (*prefix != '\0')) { - const char *found = strstr(name, prefix); - - if (found == name) { - /* found the prefix at the beginning */ - start += strlen(prefix); - } - } - - /* take care of the suffix */ - if (strip_suffix) { - const char *suffix_start = strrchr(start, '_'); - - if (suffix_start != NULL) { - const char *ch; - int only_numbers = 1; - - for (ch = suffix_start + 1; *ch != '\0'; ch++) { - if (strchr("0123456789", *ch) == NULL) { - only_numbers = 0; - break; - } - } - - if (only_numbers) { - end = suffix_start; - } - } - } - - intrinsic_name = malloc(end - start + 1); - for (i = 0; (start + i) < end; i++) { - intrinsic_name[i] = toupper(start[i]); - } - intrinsic_name[i] = '\0'; - - return intrinsic_name; -} - -static char * -ethr_get_amended_env(const char *name, const char *prefix, const char *suffix) -{ - unsigned len; - char *env_name = NULL; - char *env_value = NULL; - - if (name == NULL) { - return NULL; - } - - len = strlen(name); - - if (prefix != NULL) { - len += strlen(prefix); - } - - if (suffix != NULL) { - len += strlen(suffix); - } - - env_name = malloc(len + 1); - sprintf(env_name, "%s%s%s", (prefix != NULL) ? prefix : "", - name, - (suffix != NULL) ? suffix : ""); - env_value = get_env(get_bid(current_process()), env_name); - - if (env_value == NULL) { - LOG(("ERTS - ethr_get_amended_env(): %s environment variable not present\n", env_name)); - } else { - LOG(("ERTS - ethr_get_amended_env(): Found %s environment variable: %s.\n", env_name, env_value)); - } - free(env_name); - - return env_value; -} - -/* Reads the environment variable derived from 'name' and interprets it as as an - * OSE priority. If successfull it will update 'out_prio'. - * Returns: 0 if successfull - * -1 orherwise. - */ -static int -ethr_get_prio(const char *name, OSPRIORITY *out_prio) -{ - int rc = -1; - char *intrinsic_name = NULL; - char *prio_env = NULL; - long prio; - char *endptr = NULL; - - LOG(("ERTS - ethr_get_prio(): name: %s.\n", name)); - - intrinsic_name = ethr_intrinsic_name(name, NULL, 1); - LOG(("ERTS - ethr_get_prio(): Intrinsic name: %s.\n", intrinsic_name)); - - prio_env = ethr_get_amended_env(intrinsic_name, "ERTS_", "_PRIO"); - if (prio_env == NULL) { - goto fini; - } - - prio = efs_str_to_long(prio_env, (const char **)&endptr); - if (endptr != NULL) { - LOG(("ERTS - ethr_get_prio(): Environment varible for '%s' includes " - "non-numerical characters: '%s'.\n", intrinsic_name, prio_env)); - goto fini; - } - - if ((prio < 0) || (prio > 32)) { - LOG(("ERTS - ethr_get_prio(): prio for '%s' (%d) is out of bounds (0-32).\n", - intrinsic_name, prio)); - goto fini; - } - - /* Success */ - *out_prio = (OSPRIORITY)prio; - rc = 0; - -fini: - if (intrinsic_name != NULL) { - free(intrinsic_name); - } - if (prio_env != NULL) { - free_buf((union SIGNAL **) &prio_env); - } - - return rc; -} - -static PROCESS blockId(void) { - static PROCESS bid = (PROCESS)0; - - /* For now we only use the same block. */ - /* if (bid == 0) { - bid = create_block("Erlang-VM", 0, 0, 0, 0); - } - return bid; */ - return 0; -} - -static void thr_exit_cleanup(ethr_tid *tid, void *res) -{ - - ETHR_ASSERT(tid == ETHR_GET_OWN_TID__); - - tid->res = res; - - ethr_run_exit_handlers__(); - ethr_ts_event_destructor__((void *) ethr_get_tse__()); -} - -//static OS_PROCESS(thr_wrapper); -static OS_PROCESS(thr_wrapper) -{ - ethr_tid my_tid; - ethr_sint32_t result; - void *res; - void *(*thr_func)(void *); - void *arg; - ethr_ts_event *tsep = NULL; - -#ifdef DEBUG - { - PROCESS pid = current_process(); - - const char *execMode; - - PROCESS bid = get_bid(pid); - - /* In the call below, 16 is a secret number provided by frbr that makes - * the function return current domain. */ - OSADDRESS domain = get_pid_info(current_process(), 16); - -#ifdef HAVE_OSE_SPI_H - execMode = get_pid_info(pid, OSE_PI_SUPERVISOR) - ? "Supervisor" - : "User"; -#else - execMode = "unknown"; -#endif - - fprintf(stderr,"[0x%x] New process. Bid:0x%x, domain:%d, exec mode:%s\n", - current_process(), bid, domain, execMode); - } -#endif - - { - SIGSELECT sigsel[] = {1,ETHREADWRAPDATASIG}; - union SIGNAL *init_msg = receive(sigsel); - - thr_func = init_msg->data.thr_func; - arg = init_msg->data.arg; - - result = (ethr_sint32_t) ethr_make_ts_event__(&tsep); - - if (result == 0) { - tsep->iflgs |= ETHR_TS_EV_ETHREAD; - my_tid = *init_msg->data.tid; - set_envp(current_process(), own_tid_key, (OSADDRESS)&my_tid); - if (ethr_thr_child_func__) - ethr_thr_child_func__(init_msg->data.prep_func_res); - } - - init_msg->data.result = result; - - send(&init_msg,sender(&init_msg)); - } - - /* pthread mutex api says we have to do this */ - signal_fsem(current_process()); - ETHR_ASSERT(get_fsem(current_process()) == 0); - - res = result == 0 ? (*thr_func)(arg) : NULL; - - ethr_thr_exit(&res); -} - -/* internal exports */ - -int ethr_set_tse__(ethr_ts_event *tsep) -{ - return ethr_tsd_set(ethr_ts_event_key__,(void *) tsep); -} - -ethr_ts_event *ethr_get_tse__(void) -{ - return (ethr_ts_event *) ethr_tsd_get(ethr_ts_event_key__); -} - -#if defined(ETHR_PPC_RUNTIME_CONF__) - -static int -ppc_init__(void) -{ - int pid; - - - ethr_runtime__.conf.have_lwsync = 0; - - return 0; -} - -#endif - -#if defined(ETHR_X86_RUNTIME_CONF__) - -void -ethr_x86_cpuid__(int *eax, int *ebx, int *ecx, int *edx) -{ -#if ETHR_SIZEOF_PTR == 4 - int have_cpuid; - /* - * If it is possible to toggle eflags bit 21, - * we have the cpuid instruction. - */ - __asm__ ("pushf\n\t" - "popl %%eax\n\t" - "movl %%eax, %%ecx\n\t" - "xorl $0x200000, %%eax\n\t" - "pushl %%eax\n\t" - "popf\n\t" - "pushf\n\t" - "popl %%eax\n\t" - "movl $0x0, %0\n\t" - "xorl %%ecx, %%eax\n\t" - "jz no_cpuid\n\t" - "movl $0x1, %0\n\t" - "no_cpuid:\n\t" - : "=r"(have_cpuid) - : - : "%eax", "%ecx", "cc"); - if (!have_cpuid) { - *eax = *ebx = *ecx = *edx = 0; - return; - } -#endif -#if ETHR_SIZEOF_PTR == 4 && defined(__PIC__) && __PIC__ - /* - * When position independet code is used in 32-bit mode, the B register - * is used for storage of global offset table address, and we may not - * use it as input or output in an asm. We need to save and restore the - * B register explicitly (for some reason gcc doesn't provide this - * service to us). - */ - __asm__ ("pushl %%ebx\n\t" - "cpuid\n\t" - "movl %%ebx, %1\n\t" - "popl %%ebx\n\t" - : "=a"(*eax), "=r"(*ebx), "=c"(*ecx), "=d"(*edx) - : "0"(*eax) - : "cc"); -#else - __asm__ ("cpuid\n\t" - : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) - : "0"(*eax) - : "cc"); -#endif -} - -#endif /* ETHR_X86_RUNTIME_CONF__ */ - -/* - * -------------------------------------------------------------------------- - * Exported functions - * -------------------------------------------------------------------------- - */ - -int -ethr_init(ethr_init_data *id) -{ - int res; - - if (!ethr_not_inited__) - return EINVAL; - - -#if defined(ETHR_PPC_RUNTIME_CONF__) - res = ppc_init__(); - if (res != 0) - goto error; -#endif - - res = ethr_init_common__(id); - if (res != 0) - goto error; - - main_thr_tid.id = current_process(); - main_thr_tid.tsd_key_index = 0; - - set_envp(current_process(),own_tid_key,(OSADDRESS)&main_thr_tid); - signal_fsem(current_process()); - - - ETHR_ASSERT(&main_thr_tid == ETHR_GET_OWN_TID__); - - ethr_not_inited__ = 0; - - ethr_tsd_key_create(ðr_ts_event_key__,"ethread_tse"); - - return 0; - error: - ethr_not_inited__ = 1; - return res; - -} - -int -ethr_late_init(ethr_late_init_data *id) -{ - int res = ethr_late_init_common__(id); - if (res != 0) - return res; - ethr_not_completely_inited__ = 0; - return res; -} - -int -ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg, - ethr_thr_opts *opts) -{ - int res; - int use_stack_size = (opts && opts->suggested_stack_size >= 0 - ? opts->suggested_stack_size - : 0x200 /* Use system default */); - OSPRIORITY use_prio; - char *use_name; - char default_thr_name[20]; - static int no_of_thr = 0; - cpuid_t use_core; - - union SIGNAL *init_msg; - SIGSELECT sigsel[] = {1,ETHREADWRAPDATASIG}; - void *prep_func_res; - - - if (opts != NULL) { - LOG(("ERTS - ethr_thr_create(): opts supplied: name: %s, coreNo: %u.\n", - opts->name, opts->coreNo)); - use_name = opts->name; - use_core = opts->coreNo; - if (0 != ethr_get_prio(use_name, &use_prio)) { - if (0 != ethr_get_prio("DEFAULT", &use_prio)) { - use_prio = get_pri(current_process()); - LOG(("ERTS - ethr_thr_create(): Using current process' prio: %d.\n", use_prio)); - } else { - LOG(("ERTS - ethr_thr_create(): Using default prio: %d.\n", use_prio)); - } - } else { - LOG(("ERTS - ethr_thr_create(): Using configured prio: %d.\n", use_prio)); - } - } else { - LOG(("ERTS - ethr_thr_create(): opts not supplied. Using defaults.\n")); - no_of_thr++; - sprintf(default_thr_name, "ethread_%d", no_of_thr); - use_name = default_thr_name; - use_core = ose_cpu_id(); - - if (0 != ethr_get_prio("DEFAULT", &use_prio)) { - use_prio = get_pri(current_process()); - LOG(("ERTS - ethr_thr_create(): Using current process' prio: %d.\n", use_prio)); - } - } - -#ifdef ETHR_MODIFIED_DEFAULT_STACK_SIZE - if (use_stack_size < 0) - use_stack_size = ETHR_MODIFIED_DEFAULT_STACK_SIZE; -#endif - -#if ETHR_XCHK - if (ethr_not_completely_inited__) { - ETHR_ASSERT(0); - return EACCES; - } - if (!tid || !func) { - ETHR_ASSERT(0); - return EINVAL; - } -#endif - - if (use_stack_size >= 0) { - size_t suggested_stack_size = (size_t) use_stack_size; - size_t stack_size; -#ifdef ETHR_DEBUG - suggested_stack_size /= 2; /* Make sure we got margin */ -#endif -#ifdef ETHR_STACK_GUARD_SIZE - /* The guard is at least on some platforms included in the stack size - passed when creating threads */ - suggested_stack_size += ETHR_B2KW(ETHR_STACK_GUARD_SIZE); -#endif - - if (suggested_stack_size < ethr_min_stack_size__) - stack_size = ETHR_KW2B(ethr_min_stack_size__); - else if (suggested_stack_size > ethr_max_stack_size__) - stack_size = ETHR_KW2B(ethr_max_stack_size__); - else - stack_size = ETHR_PAGE_ALIGN(ETHR_KW2B(suggested_stack_size)); - use_stack_size = stack_size; - } - - init_msg = alloc(sizeof(ethr_thr_wrap_data__), ETHREADWRAPDATASIG); - - /* Call prepare func if it exist */ - if (ethr_thr_prepare_func__) - init_msg->data.prep_func_res = ethr_thr_prepare_func__(); - else - init_msg->data.prep_func_res = NULL; - - LOG(("ERTS - ethr_thr_create(): Process [0x%x] is creating '%s', coreNo = %u, prio:%u\n", - current_process(), use_name, use_core, use_prio)); - - tid->id = create_process(OS_PRI_PROC, use_name, thr_wrapper, - use_stack_size, use_prio, 0, - get_bid(current_process()), NULL, 0, 0); - if (ose_bind_process(tid->id, use_core)) { - LOG(("ERTS - ethr_thr_create(): Bound pid 0x%x (%s) to core no %u.\n", - tid->id, use_name, use_core)); - } else { - LOG(("ERTS - ethr_thr_create(): Failed binding pid 0x%x (%s) to core no %u.\n", - tid->id, use_name, use_core)); - } - - /*FIXME!!! Normally this shouldn't be used in shared mode. Still there is - * a problem with stdin fd in fd_ processes which should be further - * investigated */ - efs_clone(tid->id); - - tid->tsd_key_index = 0; - tid->res = NULL; - - init_msg->data.tse = ethr_get_ts_event(); - init_msg->data.thr_func = func; - init_msg->data.arg = arg; - init_msg->data.tid = tid; - init_msg->data.name = opts->name; - - send(&init_msg, tid->id); - - start(tid->id); - init_msg = receive(sigsel); - - res = init_msg->data.result; - prep_func_res = init_msg->data.prep_func_res; - - free_buf(&init_msg); - /* Cleanup... */ - - if (ethr_thr_parent_func__) - ethr_thr_parent_func__(prep_func_res); - - LOG(("ERTS - ethr_thr_create(): Exiting.\n")); - return res; -} - -int -ethr_thr_join(ethr_tid tid, void **res) -{ - SIGSELECT sigsel[] = {1,OS_ATTACH_SIG}; -#if ETHR_XCHK - if (ethr_not_inited__) { - ETHR_ASSERT(0); - return EACCES; - } -#endif - - if (tid.id == ETHR_INVALID_TID_ID) - return EINVAL; - - attach(NULL,tid.id); - receive(sigsel); - - if (res) - *res = tid.res; - - return 0; -} - -int -ethr_thr_detach(ethr_tid tid) -{ -#if ETHR_XCHK - if (ethr_not_inited__) { - ETHR_ASSERT(0); - return EACCES; - } -#endif - return 0; -} - -void -ethr_thr_exit(void *res) -{ - ethr_tid *tid; -#if ETHR_XCHK - if (ethr_not_inited__) { - ETHR_ASSERT(0); - return; - } -#endif - tid = ETHR_GET_OWN_TID__; - if (!tid) { - ETHR_ASSERT(0); - kill_proc(current_process()); - } - thr_exit_cleanup(tid, res); - /* Harakiri possible? */ - kill_proc(current_process()); -} - -ethr_tid -ethr_self(void) -{ - ethr_tid *tid; -#if ETHR_XCHK - if (ethr_not_inited__) { - ethr_tid dummy_tid = {ETHR_INVALID_TID_ID, 0, NULL}; - ETHR_ASSERT(0); - return dummy_tid; - } -#endif - tid = ETHR_GET_OWN_TID__; - if (!tid) { - ethr_tid dummy_tid = {ETHR_INVALID_TID_ID, 0, NULL}; - return dummy_tid; - } - return *tid; -} - -int -ethr_equal_tids(ethr_tid tid1, ethr_tid tid2) -{ - return tid1.id == tid2.id && tid1.id != ETHR_INVALID_TID_ID; -} - - -/* - * Thread specific events - */ - -ethr_ts_event * -ethr_get_ts_event(void) -{ - return ethr_get_ts_event__(); -} - -void -ethr_leave_ts_event(ethr_ts_event *tsep) -{ - ethr_leave_ts_event__(tsep); -} - -/* - * Thread specific data - */ - -int -ethr_tsd_key_create(ethr_tsd_key *keyp, char *keyname) -{ - -#if ETHR_XCHK - if (ethr_not_inited__) { - ETHR_ASSERT(0); - return EACCES; - } - if (!keyp) { - ETHR_ASSERT(0); - return EINVAL; - } -#endif - - ose_create_ppdata(keyname,keyp); - - return 0; -} - -int -ethr_tsd_key_delete(ethr_tsd_key key) -{ -#if ETHR_XCHK - if (ethr_not_inited__) { - ETHR_ASSERT(0); - return EACCES; - } -#endif - /* Not possible to delete ppdata */ - - return 0; -} - -int -ethr_tsd_set(ethr_tsd_key key, void *value) -{ - void **ppdp; -#if ETHR_XCHK - if (ethr_not_inited__) { - ETHR_ASSERT(0); - return EACCES; - } -#endif - ppdp = (void **)ose_get_ppdata(key); - *ppdp = value; - return 0; -} - -void * -ethr_tsd_get(ethr_tsd_key key) -{ -#if ETHR_XCHK - if (ethr_not_inited__) { - ETHR_ASSERT(0); - return NULL; - } -#endif - return *(void**)ose_get_ppdata(key); -} - -/* - * Signal functions - */ - -#if ETHR_HAVE_ETHR_SIG_FUNCS - -int ethr_sigmask(int how, const sigset_t *set, sigset_t *oset) -{ -#if ETHR_XCHK - if (ethr_not_inited__) { - ETHR_ASSERT(0); - return EACCES; - } - if (!set && !oset) { - ETHR_ASSERT(0); - return EINVAL; - } -#endif - return pthread_sigmask(how, set, oset); -} - -int ethr_sigwait(const sigset_t *set, int *sig) -{ -#if ETHR_XCHK - if (ethr_not_inited__) { - ETHR_ASSERT(0); - return EACCES; - } - if (!set || !sig) { - ETHR_ASSERT(0); - return EINVAL; - } -#endif - if (sigwait(set, sig) < 0) - return errno; - return 0; -} - -#endif /* #if ETHR_HAVE_ETHR_SIG_FUNCS */ - -ETHR_IMPL_NORETURN__ -ethr_abort__(void) -{ - abort(); -} diff --git a/erts/lib_src/pthread/ethr_event.c b/erts/lib_src/pthread/ethr_event.c index 9434d60d0a..464875570a 100644 --- a/erts/lib_src/pthread/ethr_event.c +++ b/erts/lib_src/pthread/ethr_event.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009-2010. All Rights Reserved. + * Copyright Ericsson AB 2009-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% */ @@ -28,7 +29,17 @@ #include "config.h" #endif +#if defined(__APPLE__) && defined(__MACH__) && !defined(__DARWIN__) +# define __DARWIN__ 1 +#endif +#ifdef __DARWIN__ +# define _DARWIN_UNLIMITED_SELECT +#endif + #include "ethread.h" +#undef ETHR_INCLUDE_MONOTONIC_CLOCK__ +#define ETHR_INCLUDE_MONOTONIC_CLOCK__ +#include "ethr_internal.h" #if defined(ETHR_LINUX_FUTEX_IMPL__) /* --- Linux futex implementation of ethread events ------------------------- */ @@ -38,6 +49,12 @@ #define ETHR_YIELD_AFTER_BUSY_LOOPS 50 +void +ethr_init_event__(void) +{ + +} + int ethr_event_init(ethr_event *e) { @@ -46,27 +63,55 @@ ethr_event_init(ethr_event *e) } int +ethr_event_prepare_timed(ethr_event *e) +{ + return 0; +} + +int ethr_event_destroy(ethr_event *e) { return 0; } static ETHR_INLINE int -wait__(ethr_event *e, int spincount) +wait__(ethr_event *e, int spincount, ethr_sint64_t timeout) { unsigned sc = spincount; int res; ethr_sint32_t val; int until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS; + ethr_sint64_t time = 0; /* SHUT UP annoying faulty warning... */ + struct timespec ts, *tsp; +#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME + ethr_sint64_t start = 0; /* SHUT UP annoying faulty warning... */ +#endif if (spincount < 0) ETHR_FATAL_ERROR__(EINVAL); + if (timeout < 0) { + tsp = NULL; + } + else { +#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME + start = ethr_get_monotonic_time(); +#endif + tsp = &ts; + time = timeout; + if (spincount == 0) { + val = ethr_atomic32_read(&e->futex); + if (val == ETHR_EVENT_ON__) + goto return_event_on; + goto set_timeout; + } + } + while (1) { while (1) { val = ethr_atomic32_read(&e->futex); if (val == ETHR_EVENT_ON__) - return 0; + goto return_event_on; if (sc == 0) break; sc--; @@ -79,44 +124,202 @@ wait__(ethr_event *e, int spincount) } } + if (timeout >= 0) { +#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME + time = timeout - (ethr_get_monotonic_time() - start); +#endif + set_timeout: + if (time <= 0) { + val = ethr_atomic32_read(&e->futex); + if (val == ETHR_EVENT_ON__) + goto return_event_on; + return ETIMEDOUT; + } + ts.tv_sec = time / (1000*1000*1000); + ts.tv_nsec = time % (1000*1000*1000); + } + if (val != ETHR_EVENT_OFF_WAITER__) { val = ethr_atomic32_cmpxchg(&e->futex, ETHR_EVENT_OFF_WAITER__, ETHR_EVENT_OFF__); if (val == ETHR_EVENT_ON__) - return 0; + goto return_event_on; ETHR_ASSERT(val == ETHR_EVENT_OFF__); } res = ETHR_FUTEX__(&e->futex, ETHR_FUTEX_WAIT__, - ETHR_EVENT_OFF_WAITER__); - if (res == EINTR) + ETHR_EVENT_OFF_WAITER__, + tsp); + switch (res) { + case EINTR: + case ETIMEDOUT: + return res; + case 0: + case EWOULDBLOCK: break; - if (res != 0 && res != EWOULDBLOCK) + default: ETHR_FATAL_ERROR__(res); + } } - return res; +return_event_on: + + ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore); + + return 0; + } #elif defined(ETHR_PTHREADS) -/* --- Posix mutex/cond implementation of events ---------------------------- */ +/* --- Posix mutex/cond pipe/select implementation of events ---------------- */ + +#include <fcntl.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> +#include <sys/select.h> +#include <errno.h> +#include <string.h> + +#include "erl_misc_utils.h" + +#ifdef __DARWIN__ + +struct ethr_event_fdsets___ { + fd_set *rsetp; + fd_set *esetp; + size_t mem_size; + fd_mask mem[1]; +}; + +#endif + +static void +setup_nonblocking_pipe(ethr_event *e) +{ + int flgs; + int res; + + res = pipe(e->fd); + if (res != 0) + ETHR_FATAL_ERROR__(errno); + + ETHR_ASSERT(e->fd[0] >= 0 && e->fd[1] >= 0); + + flgs = fcntl(e->fd[0], F_GETFL, 0); + fcntl(e->fd[0], F_SETFL, flgs | O_NONBLOCK); + flgs = fcntl(e->fd[1], F_GETFL, 0); + fcntl(e->fd[1], F_SETFL, flgs | O_NONBLOCK); + + +#ifndef __DARWIN__ + if (e->fd[0] >= FD_SETSIZE) + ETHR_FATAL_ERROR__(ENOTSUP); +#else + { + int nmasks; + ethr_event_fdsets__ *fdsets; + size_t mem_size; + + nmasks = (e->fd[0]+NFDBITS)/NFDBITS; + mem_size = 2*nmasks*sizeof(fd_mask); + if (mem_size < 2*sizeof(fd_set)) { + mem_size = 2*sizeof(fd_set); + nmasks = mem_size/(2*sizeof(fd_mask)); + } + + fdsets = malloc(sizeof(ethr_event_fdsets__) + + mem_size + - sizeof(fd_mask)); + if (!fdsets) + ETHR_FATAL_ERROR__(ENOMEM); + fdsets->rsetp = (fd_set *) (char *) &fdsets->mem[0]; + fdsets->esetp = (fd_set *) (char *) &fdsets->mem[nmasks]; + fdsets->mem_size = mem_size; + e->fdsets = fdsets; + } +#endif + + ETHR_MEMBAR(ETHR_StoreStore); +} + +#define ETHR_EVENT_INVALID_FD__ -1 +#define ETHR_EVENT_COND_TIMEDWAIT__ -2 + +#ifdef ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC +static pthread_condattr_t monotonic_clock_cond_attr; +#endif +static pthread_condattr_t *monotonic_clock_cond_attr_p; + +#ifndef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME +# undef ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC +#endif +#ifndef ETHR_MONOTONIC_CLOCK_ID +# undef ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC +#endif + +void +ethr_init_event__(void) +{ + monotonic_clock_cond_attr_p = NULL; +#ifdef ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC + if (!ethr_get_monotonic_time_is_broken() + && pthread_condattr_init(&monotonic_clock_cond_attr) == 0) { + if (pthread_condattr_setclock(&monotonic_clock_cond_attr, + ETHR_MONOTONIC_CLOCK_ID) == 0) + monotonic_clock_cond_attr_p = &monotonic_clock_cond_attr; + else + pthread_condattr_destroy(&monotonic_clock_cond_attr); + } +#endif +} int ethr_event_init(ethr_event *e) { int res; + ethr_atomic32_init(&e->state, ETHR_EVENT_OFF__); + res = pthread_mutex_init(&e->mtx, NULL); if (res != 0) return res; - res = pthread_cond_init(&e->cnd, NULL); + + res = pthread_cond_init(&e->cnd, monotonic_clock_cond_attr_p); if (res != 0) { pthread_mutex_destroy(&e->mtx); return res; } + +#ifdef ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC + /* + * If ethr_get_monotonic_time() is broken we + * fall back on the pipe/select solution... + */ + if (monotonic_clock_cond_attr_p) { + e->fd[0] = e->fd[1] = ETHR_EVENT_COND_TIMEDWAIT__; + return 0; + } +#endif + + e->fd[0] = e->fd[1] = ETHR_EVENT_INVALID_FD__; + +#ifdef __DARWIN__ + e->fdsets = NULL; +#endif + + return 0; +} + +int +ethr_event_prepare_timed(ethr_event *e) +{ + if (e->fd[0] == ETHR_EVENT_INVALID_FD__) + setup_nonblocking_pipe(e); + return 0; } @@ -124,22 +327,67 @@ int ethr_event_destroy(ethr_event *e) { int res; + if (e->fd[0] >= 0) { + close(e->fd[0]); + close(e->fd[1]); + } +#ifdef __DARWIN__ + if (e->fdsets) + free(e->fdsets); +#endif res = pthread_mutex_destroy(&e->mtx); if (res != 0) return res; - res = pthread_cond_destroy(&e->cnd); - if (res != 0) - return res; - return 0; + return pthread_cond_destroy(&e->cnd); } static ETHR_INLINE int -wait__(ethr_event *e, int spincount) +wait__(ethr_event *e, int spincount, ethr_sint64_t timeout) { int sc = spincount; ethr_sint32_t val; int res, ulres; int until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS; + ethr_sint64_t time = 0; +#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME + ethr_sint64_t timeout_time = 0; /* SHUT UP annoying faulty warning... */ +#endif + + val = ethr_atomic32_read(&e->state); + if (val == ETHR_EVENT_ON__) + goto return_event_on; + + if (timeout < 0) { + if (spincount == 0) + goto set_event_off_waiter; + } + if (timeout == 0) + return ETIMEDOUT; + else { +#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME + timeout_time = ethr_get_monotonic_time(); + timeout_time += timeout; +#endif + switch (e->fd[0]) { + case ETHR_EVENT_INVALID_FD__: + time = timeout; + setup_nonblocking_pipe(e); + break; +#ifdef ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC + case ETHR_EVENT_COND_TIMEDWAIT__: + time = -1; + if (spincount == 0) + goto set_event_off_waiter; + break; +#endif + default: + time = timeout; + /* Already initialized pipe... */ + if (spincount == 0) + goto set_select_timeout; + break; + } + } if (spincount < 0) ETHR_FATAL_ERROR__(EINVAL); @@ -147,7 +395,8 @@ wait__(ethr_event *e, int spincount) while (1) { val = ethr_atomic32_read(&e->state); if (val == ETHR_EVENT_ON__) - return 0; + goto return_event_on; + if (sc == 0) break; sc--; @@ -160,40 +409,204 @@ wait__(ethr_event *e, int spincount) } } - if (val != ETHR_EVENT_OFF_WAITER__) { - val = ethr_atomic32_cmpxchg(&e->state, - ETHR_EVENT_OFF_WAITER__, - ETHR_EVENT_OFF__); - if (val == ETHR_EVENT_ON__) - return 0; - ETHR_ASSERT(val == ETHR_EVENT_OFF__); + if (timeout < 0 +#ifdef ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC + || e->fd[0] == ETHR_EVENT_COND_TIMEDWAIT__ +#endif + ) { +#ifdef ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC + struct timespec cond_timeout; +#endif + + set_event_off_waiter: + + if (val != ETHR_EVENT_OFF_WAITER__) { + ethr_sint32_t act; + act = ethr_atomic32_cmpxchg(&e->state, + ETHR_EVENT_OFF_WAITER__, + val); + if (act == ETHR_EVENT_ON__) + goto return_event_on; + ETHR_ASSERT(act == val); + } + + res = pthread_mutex_lock(&e->mtx); + if (res != 0) + ETHR_FATAL_ERROR__(res); + + while (1) { + + val = ethr_atomic32_read(&e->state); + if (val == ETHR_EVENT_ON__) { + ETHR_ASSERT(res == 0); + ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore); + break; + } + +#ifdef ETHR_HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC + if (timeout > 0) { + if (time != timeout_time) { + time = timeout_time; + +#if ERTS_USE_PREMATURE_TIMEOUT + { + ethr_sint64_t rtmo; + + rtmo = timeout_time - ethr_get_monotonic_time(); + if (rtmo <= 0) { + res = ETIMEDOUT; + break; + } + time = timeout_time; + time -= ERTS_PREMATURE_TIMEOUT(rtmo, 1000*1000*1000); + } +#endif + + cond_timeout.tv_sec = time / (1000*1000*1000); + cond_timeout.tv_nsec = time % (1000*1000*1000); + } + res = pthread_cond_timedwait(&e->cnd, &e->mtx, &cond_timeout); + if (res == EINTR + || (res == ETIMEDOUT +#if ERTS_USE_PREMATURE_TIMEOUT + && time == timeout_time +#endif + )) { + break; + } + } + else +#endif + { + res = pthread_cond_wait(&e->cnd, &e->mtx); + if (res == EINTR) + break; + } + if (res != 0) + ETHR_FATAL_ERROR__(res); + } + + ulres = pthread_mutex_unlock(&e->mtx); + if (ulres != 0) + ETHR_FATAL_ERROR__(ulres); + } + else { + int fd; + int sres; + ssize_t rres; +#ifndef __DARWIN__ + fd_set rset, eset; +#endif + fd_set *rsetp, *esetp; + struct timeval select_timeout; - ETHR_ASSERT(val == ETHR_EVENT_OFF_WAITER__ - || val == ETHR_EVENT_OFF__); +#ifdef ETHR_HAVE_ETHR_GET_MONOTONIC_TIME +#if ERTS_USE_PREMATURE_TIMEOUT + restart_select: +#endif - res = pthread_mutex_lock(&e->mtx); - if (res != 0) - ETHR_FATAL_ERROR__(res); + time = timeout_time - ethr_get_monotonic_time(); + if (time <= 0) + return ETIMEDOUT; +#endif - while (1) { + set_select_timeout: + + ETHR_ASSERT(time > 0); + + /* + * timeout in nano-second, but we can only wait + * for micro-seconds... + */ + time = ((time - 1) / 1000) + 1; + +#if defined(ETHR_HAVE_ETHR_GET_MONOTONIC_TIME) \ + && ERTS_USE_PREMATURE_TIMEOUT + time -= ERTS_PREMATURE_TIMEOUT(time, 1000*1000); +#endif + + select_timeout.tv_sec = time / (1000*1000); + select_timeout.tv_usec = time % (1000*1000); + + ETHR_ASSERT(val != ETHR_EVENT_ON__); + + fd = e->fd[0]; + + /* Cleanup pipe... */ + do { + char buf[64]; + rres = read(fd, buf, sizeof(buf)); + } while (rres > 0 || (rres < 0 && errno == EINTR)); + if (rres < 0 && errno != EAGAIN && errno != EWOULDBLOCK) + ETHR_FATAL_ERROR__(errno); + + /* + * Need to verify that state is still off + * after cleaning the pipe... + */ + if (val == ETHR_EVENT_OFF_WAITER_SELECT__) { + val = ethr_atomic32_read(&e->state); + if (val == ETHR_EVENT_ON__) + goto return_event_on; + } + else { + ethr_sint32_t act; + act = ethr_atomic32_cmpxchg(&e->state, + ETHR_EVENT_OFF_WAITER_SELECT__, + val); + if (act == ETHR_EVENT_ON__) + goto return_event_on; + ETHR_ASSERT(act == val); + } + + +#ifdef __DARWIN__ + rsetp = e->fdsets->rsetp; + esetp = e->fdsets->esetp; + memset((void *) &e->fdsets->mem[0], 0, e->fdsets->mem_size); +#else + FD_ZERO(&rset); + FD_ZERO(&eset); + rsetp = &rset; + esetp = &eset; +#endif + + FD_SET(fd, rsetp); + FD_SET(fd, esetp); + + sres = select(fd + 1, rsetp, NULL, esetp, &select_timeout); + if (sres == 0) + res = ETIMEDOUT; + else { + res = EINTR; + if (sres < 0 && errno != EINTR) + ETHR_FATAL_ERROR__(errno); + /* else: + * Event is *probably* set, but it can be a + * lingering writer. That is, it is important + * that we verify that it actually is set. If + * it isn't, return EINTR (spurious wakeup). + */ + } val = ethr_atomic32_read(&e->state); if (val == ETHR_EVENT_ON__) - break; - - res = pthread_cond_wait(&e->cnd, &e->mtx); - if (res == EINTR) - break; - if (res != 0) - ETHR_FATAL_ERROR__(res); + goto return_event_on; +#if defined(ETHR_HAVE_ETHR_GET_MONOTONIC_TIME) \ + && ERTS_USE_PREMATURE_TIMEOUT + if (res == ETIMEDOUT) + goto restart_select; /* Verify timeout */ +#endif } - ulres = pthread_mutex_unlock(&e->mtx); - if (ulres != 0) - ETHR_FATAL_ERROR__(ulres); + return res; + +return_event_on: - return res; /* 0 || EINTR */ + ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore); + + return 0; } #else @@ -215,11 +628,23 @@ ethr_event_set(ethr_event *e) int ethr_event_wait(ethr_event *e) { - return wait__(e, 0); + return wait__(e, 0, -1); } int ethr_event_swait(ethr_event *e, int spincount) { - return wait__(e, spincount); + return wait__(e, spincount, -1); +} + +int +ethr_event_twait(ethr_event *e, ethr_sint64_t timeout) +{ + return wait__(e, 0, timeout); +} + +int +ethr_event_stwait(ethr_event *e, int spincount, ethr_sint64_t timeout) +{ + return wait__(e, spincount, timeout); } diff --git a/erts/lib_src/pthread/ethr_x86_sse2_asm.c b/erts/lib_src/pthread/ethr_x86_sse2_asm.c index 6cbe73cf16..bdcf3ac1c3 100644 --- a/erts/lib_src/pthread/ethr_x86_sse2_asm.c +++ b/erts/lib_src/pthread/ethr_x86_sse2_asm.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2011. All Rights Reserved. + * Copyright Ericsson AB 2011-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% */ diff --git a/erts/lib_src/pthread/ethread.c b/erts/lib_src/pthread/ethread.c index 79784c5b84..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); @@ -565,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) { diff --git a/erts/lib_src/utils/make_atomics_api b/erts/lib_src/utils/make_atomics_api index 74736c5a2d..f960b97c87 100755 --- a/erts/lib_src/utils/make_atomics_api +++ b/erts/lib_src/utils/make_atomics_api @@ -4,18 +4,19 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2012. All Rights Reserved. +%% Copyright Ericsson AB 2011-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% %% @@ -1419,16 +1420,17 @@ comments() -> * * Copyright Ericsson AB ", Years, ". 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 + * + * http://www.apache.org/licenses/LICENSE-2.0 * - * 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. + * 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% */ diff --git a/erts/lib_src/win/ethr_event.c b/erts/lib_src/win/ethr_event.c index bc2f635c26..383f7c876e 100644 --- a/erts/lib_src/win/ethr_event.c +++ b/erts/lib_src/win/ethr_event.c @@ -1,18 +1,19 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2009-2011. All Rights Reserved. + * Copyright Ericsson AB 2009-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% */ @@ -25,9 +26,16 @@ #define ETHR_EVENT_IMPL__ #include "ethread.h" +#include "ethr_internal.h" /* --- Windows implementation of thread events ------------------------------ */ +void +ethr_init_event__(void) +{ + +} + int ethr_event_init(ethr_event *e) { @@ -39,6 +47,12 @@ ethr_event_init(ethr_event *e) } int +ethr_event_prepare_timed(ethr_event *e) +{ + return 0; +} + +int ethr_event_destroy(ethr_event *e) { BOOL res = CloseHandle(e->handle); @@ -58,11 +72,29 @@ ethr_event_reset(ethr_event *e) } static ETHR_INLINE int -wait(ethr_event *e, int spincount) +wait(ethr_event *e, int spincount, ethr_sint64_t timeout) { - DWORD code; + DWORD code, tmo; int sc, res, until_yield = ETHR_YIELD_AFTER_BUSY_LOOPS; + if (timeout < 0) + tmo = INFINITE; + else if (timeout == 0) { + ethr_sint32_t state = ethr_atomic32_read(&e->state); + if (state == ETHR_EVENT_ON__) { + ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore); + return 0; + } + return ETIMEDOUT; + } + else { + /* + * Timeout in nano-seconds, but we can only + * wait for milli-seconds... + */ + tmo = (DWORD) (timeout - 1) / (1000*1000) + 1; + } + if (spincount < 0) ETHR_FATAL_ERROR__(EINVAL); @@ -72,8 +104,10 @@ wait(ethr_event *e, int spincount) ethr_sint32_t state; while (1) { state = ethr_atomic32_read(&e->state); - if (state == ETHR_EVENT_ON__) + if (state == ETHR_EVENT_ON__) { + ETHR_MEMBAR(ETHR_LoadLoad|ETHR_LoadStore); return 0; + } if (sc == 0) break; sc--; @@ -95,7 +129,9 @@ wait(ethr_event *e, int spincount) ETHR_ASSERT(state == ETHR_EVENT_OFF__); } - code = WaitForSingleObject(e->handle, INFINITE); + code = WaitForSingleObject(e->handle, tmo); + if (code == WAIT_TIMEOUT) + return ETIMEDOUT; if (code != WAIT_OBJECT_0) ETHR_FATAL_ERROR__(ethr_win_get_errno__()); } @@ -105,11 +141,23 @@ wait(ethr_event *e, int spincount) int ethr_event_wait(ethr_event *e) { - return wait(e, 0); + return wait(e, 0, -1); } int ethr_event_swait(ethr_event *e, int spincount) { - return wait(e, spincount); + return wait(e, spincount, -1); +} + +int +ethr_event_twait(ethr_event *e, ethr_sint64_t timeout) +{ + return wait(e, 0, timeout); +} + +int +ethr_event_stwait(ethr_event *e, int spincount, ethr_sint64_t timeout) +{ + return wait(e, spincount, timeout); } diff --git a/erts/lib_src/win/ethread.c b/erts/lib_src/win/ethread.c index 14d0b6deff..e0f19f7ba1 100644 --- a/erts/lib_src/win/ethread.c +++ b/erts/lib_src/win/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% */ @@ -508,6 +509,19 @@ ethr_self(void) return *tid; } +/* getname and setname are not available on windows */ +int +ethr_getname(ethr_tid tid, char *buf, size_t len) +{ + return ENOSYS; +} + +void +ethr_setname(char *name) +{ + return; +} + int ethr_equal_tids(ethr_tid tid1, ethr_tid tid2) { |