From 200fbe924466720bd2a8c5eb05b05d67b0a2414c Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 14 Mar 2013 15:42:19 +0100 Subject: Added support for ENEA OSE This port has support for both non-smp and smp. It contains a new way to do io checking in which erts_poll_wait receives the payload of the polled entity. This has implications for all linked-in drivers. --- erts/lib_src/common/erl_misc_utils.c | 6 + erts/lib_src/common/ethr_aux.c | 15 + erts/lib_src/ose/ethr_event.c | 213 ++++++++++++ erts/lib_src/ose/ethread.c | 654 +++++++++++++++++++++++++++++++++++ 4 files changed, 888 insertions(+) create mode 100644 erts/lib_src/ose/ethr_event.c create mode 100644 erts/lib_src/ose/ethread.c (limited to 'erts/lib_src') diff --git a/erts/lib_src/common/erl_misc_utils.c b/erts/lib_src/common/erl_misc_utils.c index b32681f40e..5a271c5268 100644 --- a/erts/lib_src/common/erl_misc_utils.c +++ b/erts/lib_src/common/erl_misc_utils.c @@ -158,6 +158,8 @@ 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; @@ -316,6 +318,10 @@ 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) diff --git a/erts/lib_src/common/ethr_aux.c b/erts/lib_src/common/ethr_aux.c index f4ff08d368..ceecdcef64 100644 --- a/erts/lib_src/common/ethr_aux.c +++ b/erts/lib_src/common/ethr_aux.c @@ -204,7 +204,18 @@ 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 @@ -650,6 +661,10 @@ 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/ose/ethr_event.c b/erts/lib_src/ose/ethr_event.c new file mode 100644 index 0000000000..1cb3c223ab --- /dev/null +++ b/erts/lib_src/ose/ethr_event.c @@ -0,0 +1,213 @@ +/* + * %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 ---------------------------- */ + +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 new file mode 100644 index 0000000000..7d5101d115 --- /dev/null +++ b/erts/lib_src/ose/ethread.c @@ -0,0 +1,654 @@ +/* + * %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 +#ifdef ETHR_TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef ETHR_HAVE_SYS_TIME_H +# include +# else +# include +# endif +#endif +#include +#include + +#include + +#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_spi.h" + +#include "string.h" + +#ifndef ETHR_HAVE_ETHREAD_DEFINES +#error Missing configure defines +#endif + +#define ETHR_INVALID_TID_ID -1 + +static ethr_tid main_thr_tid; +static const char* own_tid_key = "ethread_own_tid"; +char* ethr_ts_event_key__ = "ethread_tse"; + +#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 + * -------------------------------------------------------------------------- + */ + +static PROCESS blockId(void) { + static PROCESS bid = (PROCESS)0; + + if (bid == 0) { + bid = create_block("Erlang-VM", 0, 0, 0, 0); + } + + return bid; +} + +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__()); +} + +/* For debug purpose. The process name will be stored in a per-process pointer + * for quick access. + */ +static OSPPDKEY nameKey = 0; + +//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; + + { + PROCESS pid = current_process(); + + const char *execMode = get_pid_info(pid, OSE_PI_SUPERVISOR) + ? "Supervisor" + : "User"; + 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); + + fprintf(stderr,"[0x%x] New process. Bid:0x%x, domain:%d, exec mode:%s\n", + current_process(), bid, domain, execMode); + } + + { + SIGSELECT sigsel[] = {1,ETHREADWRAPDATASIG}; + union SIGNAL *init_msg = receive(sigsel); + + { + char **name = (char**)ose_get_ppdata(nameKey); + + *name = (char*)alloc(strlen(init_msg->data.name)+1, 0); + strcpy(*name, init_msg->data.name); + } + + 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 */ + /*erts_fprintf(stderr, "(%s / %d) curr_pid 0x%x / signal_fsem to 0x%x (fsem val %d)\n", + __FUNCTION__, __LINE__, current_process(), current_process(), get_fsem(current_process()));*/ + signal_fsem(current_process()); + ETHR_ASSERT(get_fsem(current_process()) == 0); + + res = result == 0 ? (*thr_func)(arg) : NULL; + + thr_exit_cleanup(&my_tid, res); +} + +/* internal exports */ + +int ethr_set_tse__(ethr_ts_event *tsep) +{ + return set_envp(current_process(),ethr_ts_event_key__, (OSADDRESS) tsep); +} + +ethr_ts_event *ethr_get_tse__(void) +{ + return (ethr_ts_event *) get_envp(current_process(),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); + /*erts_fprintf(stderr, "(%s / %d) curr_pid 0x%x / signal_fsem to 0x%x (fsem_val %d)\n", + __FUNCTION__, __LINE__, current_process(), current_process(), get_fsem(current_process()));*/ + signal_fsem(current_process()); + + ETHR_ASSERT(&main_thr_tid == ETHR_GET_OWN_TID__); + + ose_create_ppdata("ProcName", &nameKey); + + ethr_not_inited__ = 0; + + 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 */); + union SIGNAL *init_msg; + SIGSELECT sigsel[] = {1,ETHREADWRAPDATASIG}; + void *prep_func_res; + +#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; + + /*erts_fprintf(stderr, "creating process %s / stack %d\n", opts->name, use_stack_size);*/ + +#if 0 + ramlog_printf("[0x%x] process '%s', coreNo = %u\n", + current_process(), opts->name, opts->coreNo); +#endif + tid->id = create_process(/*OS_PRI_PROC*/OS_BG_PROC, opts->name, thr_wrapper, + use_stack_size, /*opts->prio+5*/31, 0, + blockId(), NULL, 0, 0); + + if (ose_bind_process(tid->id, opts->coreNo)) { + printf("[0x%x] Binding pid 0x%x (%s) to core no %u.\n", + current_process(), tid->id, opts->name, opts->coreNo); + } + + /*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); + + 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) +{ + ethr_tid *tid = ETHR_GET_OWN_TID__; + ethr_tsd_key key; + +#if ETHR_XCHK + if (ethr_not_inited__) { + ETHR_ASSERT(0); + return EACCES; + } + if (!keyp) { + ETHR_ASSERT(0); + return EINVAL; + } +#endif + if (tid->tsd_key_index > 999) + return EAGAIN; + + /* ethread_tsd_key_YYYYYYYY_XXX\0 */ + key = malloc(sizeof(ethr_tsd_key)+sizeof(char)*(strlen("ethread_tsd_key_0xYYYYYYYY_XXX")+1)); + /* What do we do it tds_key_index happens to wrap? Slot search? */ + sprintf(key->key,"ethread_tsd_key_0x%x_%d",tid->id,tid->tsd_key_index++); + key->id = current_process(); + + *keyp = key; + + return 0; +} + +int +ethr_tsd_key_delete(ethr_tsd_key key) +{ +#if ETHR_XCHK + if (ethr_not_inited__) { + ETHR_ASSERT(0); + return EACCES; + } +#endif + free(key); + return 0; +} + +int +ethr_tsd_set(ethr_tsd_key key, void *value) +{ +#if ETHR_XCHK + if (ethr_not_inited__) { + ETHR_ASSERT(0); + return EACCES; + } +#endif + return set_envp(current_process(), key->key, (OSADDRESS)value)?0:1; +} + +void * +ethr_tsd_get(ethr_tsd_key key) +{ +#if ETHR_XCHK + if (ethr_not_inited__) { + ETHR_ASSERT(0); + return NULL; + } +#endif + return (void*)get_envp(current_process(),key->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(); +} + +const char *procName(void); +const char * +procName(void) { + char **procName_p = (char**)ose_get_ppdata(nameKey); + if (procName_p) { + return *procName_p; + } + + return NULL; +} -- cgit v1.2.3 From e6c7086e6befb3eb9e8ad4fb7de62f1ee810508c Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 25 Sep 2013 11:53:59 +0200 Subject: ose: Debug wait__ does receive_fsem instead of wait_fsem This is done in order to catch rogue signals --- erts/lib_src/ose/ethr_event.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'erts/lib_src') diff --git a/erts/lib_src/ose/ethr_event.c b/erts/lib_src/ose/ethr_event.c index 1cb3c223ab..5905fe22a9 100644 --- a/erts/lib_src/ose/ethr_event.c +++ b/erts/lib_src/ose/ethr_event.c @@ -127,6 +127,12 @@ wait__(ethr_event *e, int spincount) #else /* --- OSE implementation of events ---------------------------- */ +#ifdef DEBUG +union SIGNAL { + SIGSELECT signo; +}; +#endif + int ethr_event_init(ethr_event *e) { @@ -180,8 +186,26 @@ wait__(ethr_event *e, int spincount) ETHR_ASSERT(val == ETHR_EVENT_OFF__); } - +#if defined(DEBUG) + while (1) { + /* In debug we also receive any signals to make sure that we do + not get any! redir tables should send all to scheduler_1 */ + SIGSELECT sigsel[] = {0}; + union SIGNAL *sig = receive_fsem(OSE_NO_TIMEOUT,sigsel,1); + //ETHR_ASSERT(sig == OS_RCV_FSEM); + if (sig != OS_RCV_FSEM) { + int i; + printf("0x%x: Got signal in wait: %u ",current_process(),sig->signo); + for (i = 0; i < (sigsize(&sig) / sizeof(SIGSELECT)) && i < 5; i++) { + printf("%x ",sig[i+1]); + } + printf("\n"); + } else + break; + } +#else wait_fsem(1); +#endif ETHR_ASSERT(get_fsem(current_process()) == 0); } } -- cgit v1.2.3 From 8ed59e4a9dddf083d2046e1bd58f397221928c0e Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Tue, 15 Oct 2013 18:10:47 +0200 Subject: ose: Change start way to use arguments to beam.smp directly The old way registered a shell command that needed to be executed. This way is more flexible as you can also use the lmconf file to set arguments there. --- erts/lib_src/ose/ethread.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'erts/lib_src') diff --git a/erts/lib_src/ose/ethread.c b/erts/lib_src/ose/ethread.c index 7d5101d115..db20eab99f 100644 --- a/erts/lib_src/ose/ethread.c +++ b/erts/lib_src/ose/ethread.c @@ -96,11 +96,12 @@ union SIGNAL { static PROCESS blockId(void) { static PROCESS bid = (PROCESS)0; - if (bid == 0) { + /* For now we only use the same block. */ + /* if (bid == 0) { bid = create_block("Erlang-VM", 0, 0, 0, 0); } - - return bid; + return bid; */ + return 0; } static void thr_exit_cleanup(ethr_tid *tid, void *res) @@ -141,8 +142,10 @@ static OS_PROCESS(thr_wrapper) * the function return current domain. */ OSADDRESS domain = get_pid_info(current_process(), 16); +#ifdef DEBUG fprintf(stderr,"[0x%x] New process. Bid:0x%x, domain:%d, exec mode:%s\n", current_process(), bid, domain, execMode); +#endif } { @@ -392,10 +395,11 @@ ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg, use_stack_size, /*opts->prio+5*/31, 0, blockId(), NULL, 0, 0); - if (ose_bind_process(tid->id, opts->coreNo)) { + /* For now we do not attempt to bind schedulers to different cores. + if (ose_bind_process(tid->id, opts->coreNo)) { printf("[0x%x] Binding pid 0x%x (%s) to core no %u.\n", current_process(), tid->id, opts->name, opts->coreNo); - } + }*/ /*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 -- cgit v1.2.3 From 5dc2c6bfaed18e9a6cd23abe70be785599b5d9cc Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 21 Oct 2013 17:43:32 +0200 Subject: ose: Change get_envp to ose_get_ppdata for tsd There is a system limit on the number of ppdata that is available but that should not be reached, and ppdata is faster than using get_envp. --- erts/lib_src/ose/ethread.c | 44 ++++++++++---------------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) (limited to 'erts/lib_src') diff --git a/erts/lib_src/ose/ethread.c b/erts/lib_src/ose/ethread.c index db20eab99f..7046cc8d03 100644 --- a/erts/lib_src/ose/ethread.c +++ b/erts/lib_src/ose/ethread.c @@ -115,11 +115,6 @@ static void thr_exit_cleanup(ethr_tid *tid, void *res) ethr_ts_event_destructor__((void *) ethr_get_tse__()); } -/* For debug purpose. The process name will be stored in a per-process pointer - * for quick access. - */ -static OSPPDKEY nameKey = 0; - //static OS_PROCESS(thr_wrapper); static OS_PROCESS(thr_wrapper) { @@ -152,13 +147,6 @@ static OS_PROCESS(thr_wrapper) SIGSELECT sigsel[] = {1,ETHREADWRAPDATASIG}; union SIGNAL *init_msg = receive(sigsel); - { - char **name = (char**)ose_get_ppdata(nameKey); - - *name = (char*)alloc(strlen(init_msg->data.name)+1, 0); - strcpy(*name, init_msg->data.name); - } - thr_func = init_msg->data.thr_func; arg = init_msg->data.arg; @@ -307,8 +295,6 @@ ethr_init(ethr_init_data *id) ETHR_ASSERT(&main_thr_tid == ETHR_GET_OWN_TID__); - ose_create_ppdata("ProcName", &nameKey); - ethr_not_inited__ = 0; return 0; @@ -537,7 +523,7 @@ int ethr_tsd_key_create(ethr_tsd_key *keyp) { ethr_tid *tid = ETHR_GET_OWN_TID__; - ethr_tsd_key key; + char keyname[31]; #if ETHR_XCHK if (ethr_not_inited__) { @@ -552,13 +538,10 @@ ethr_tsd_key_create(ethr_tsd_key *keyp) if (tid->tsd_key_index > 999) return EAGAIN; - /* ethread_tsd_key_YYYYYYYY_XXX\0 */ - key = malloc(sizeof(ethr_tsd_key)+sizeof(char)*(strlen("ethread_tsd_key_0xYYYYYYYY_XXX")+1)); /* What do we do it tds_key_index happens to wrap? Slot search? */ - sprintf(key->key,"ethread_tsd_key_0x%x_%d",tid->id,tid->tsd_key_index++); - key->id = current_process(); + sprintf(keyname,"ethread_tsd_key_0x%x_%d",tid->id,tid->tsd_key_index++); - *keyp = key; + ose_create_ppdata(keyname,keyp); return 0; } @@ -572,20 +555,24 @@ ethr_tsd_key_delete(ethr_tsd_key key) return EACCES; } #endif - free(key); + /* 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 - return set_envp(current_process(), key->key, (OSADDRESS)value)?0:1; + ppdp = (void **)ose_get_ppdata(key); + *ppdp = value; + return 0; } void * @@ -597,7 +584,7 @@ ethr_tsd_get(ethr_tsd_key key) return NULL; } #endif - return (void*)get_envp(current_process(),key->key); + return *(void**)ose_get_ppdata(key); } /* @@ -645,14 +632,3 @@ ethr_abort__(void) { abort(); } - -const char *procName(void); -const char * -procName(void) { - char **procName_p = (char**)ose_get_ppdata(nameKey); - if (procName_p) { - return *procName_p; - } - - return NULL; -} -- cgit v1.2.3 From a6788ea337a2319a2d1a42ee4618553a1c7765bf Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 30 Oct 2013 17:56:37 +0100 Subject: ose: Fix various build environment issues --- erts/lib_src/ose/ethread.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'erts/lib_src') diff --git a/erts/lib_src/ose/ethread.c b/erts/lib_src/ose/ethread.c index 7046cc8d03..01d58e65b2 100644 --- a/erts/lib_src/ose/ethread.c +++ b/erts/lib_src/ose/ethread.c @@ -125,23 +125,30 @@ static OS_PROCESS(thr_wrapper) void *arg; ethr_ts_event *tsep = NULL; +#ifdef DEBUG { PROCESS pid = current_process(); - const char *execMode = get_pid_info(pid, OSE_PI_SUPERVISOR) - ? "Supervisor" - : "User"; + 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 DEBUG +#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 } +#endif { SIGSELECT sigsel[] = {1,ETHREADWRAPDATASIG}; -- cgit v1.2.3 From 8103fed4090e9f1457fb1705e9a4df0821f5db9b Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 31 Oct 2013 14:40:33 +0100 Subject: ose,erts: Specify name for tsd keys This simplified debugging on OSE and also limits the number of ppdata keys that are created when beam is restarted. --- erts/lib_src/ose/ethread.c | 9 +-------- erts/lib_src/pthread/ethread.c | 2 +- erts/lib_src/win/ethread.c | 2 +- 3 files changed, 3 insertions(+), 10 deletions(-) (limited to 'erts/lib_src') diff --git a/erts/lib_src/ose/ethread.c b/erts/lib_src/ose/ethread.c index 01d58e65b2..41c3392677 100644 --- a/erts/lib_src/ose/ethread.c +++ b/erts/lib_src/ose/ethread.c @@ -527,10 +527,8 @@ 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) { - ethr_tid *tid = ETHR_GET_OWN_TID__; - char keyname[31]; #if ETHR_XCHK if (ethr_not_inited__) { @@ -542,11 +540,6 @@ ethr_tsd_key_create(ethr_tsd_key *keyp) return EINVAL; } #endif - if (tid->tsd_key_index > 999) - return EAGAIN; - - /* What do we do it tds_key_index happens to wrap? Slot search? */ - sprintf(keyname,"ethread_tsd_key_0x%x_%d",tid->id,tid->tsd_key_index++); ose_create_ppdata(keyname,keyp); diff --git a/erts/lib_src/pthread/ethread.c b/erts/lib_src/pthread/ethread.c index fb7d135418..7f27b5f29c 100644 --- a/erts/lib_src/pthread/ethread.c +++ b/erts/lib_src/pthread/ethread.c @@ -472,7 +472,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__) { diff --git a/erts/lib_src/win/ethread.c b/erts/lib_src/win/ethread.c index 3abda6de4c..14d0b6deff 100644 --- a/erts/lib_src/win/ethread.c +++ b/erts/lib_src/win/ethread.c @@ -520,7 +520,7 @@ ethr_equal_tids(ethr_tid tid1, ethr_tid tid2) */ int -ethr_tsd_key_create(ethr_tsd_key *keyp) +ethr_tsd_key_create(ethr_tsd_key *keyp, char *keyname) { DWORD key; #if ETHR_XCHK -- cgit v1.2.3 From 2145db903b665622ea885db175c5e606d9f840a4 Mon Sep 17 00:00:00 2001 From: Jonas Karlsson Date: Fri, 22 Nov 2013 09:50:34 +0100 Subject: ose: OSE port related cleanup and fixes Some OSE cross-chains have problems with system includes being used, so for atleast OSE specific parts we use "" instead of <>. --- erts/lib_src/ose/ethread.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'erts/lib_src') diff --git a/erts/lib_src/ose/ethread.c b/erts/lib_src/ose/ethread.c index 41c3392677..f3cb4ed0ec 100644 --- a/erts/lib_src/ose/ethread.c +++ b/erts/lib_src/ose/ethread.c @@ -26,21 +26,21 @@ #include "config.h" #endif -#include +#include "stdio.h" #ifdef ETHR_TIME_WITH_SYS_TIME -# include -# include +# include "time.h" +# include "sys/time.h" #else # ifdef ETHR_HAVE_SYS_TIME_H -# include +# include "sys/time.h" # else -# include +# include "time.h" # endif #endif -#include -#include +#include "sys/types.h" +#include "unistd.h" -#include +#include "limits.h" #define ETHR_INLINE_FUNC_NAME_(X) X ## __ #define ETHREAD_IMPL__ @@ -380,19 +380,16 @@ ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg, /*erts_fprintf(stderr, "creating process %s / stack %d\n", opts->name, use_stack_size);*/ -#if 0 ramlog_printf("[0x%x] process '%s', coreNo = %u\n", current_process(), opts->name, opts->coreNo); -#endif - tid->id = create_process(/*OS_PRI_PROC*/OS_BG_PROC, opts->name, thr_wrapper, - use_stack_size, /*opts->prio+5*/31, 0, - blockId(), NULL, 0, 0); + tid->id = create_process(OS_PRI_PROC, opts->name, thr_wrapper, + use_stack_size, /*opts->prio+5*/24, 0, + get_bid(current_process()), NULL, 0, 0); - /* For now we do not attempt to bind schedulers to different cores. if (ose_bind_process(tid->id, opts->coreNo)) { - printf("[0x%x] Binding pid 0x%x (%s) to core no %u.\n", - current_process(), tid->id, opts->name, opts->coreNo); - }*/ + printf("[0x%x] Binding pid 0x%x (%s) to core no %u.\n", + current_process(), tid->id, opts->name, opts->coreNo); + } /*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 -- cgit v1.2.3 From 6930aacf7236bbf1db67c8ad1bc1953127ac43f9 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Wed, 11 Dec 2013 19:08:10 +0100 Subject: ose: Shutdown cleanly --- erts/lib_src/ose/ethread.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'erts/lib_src') diff --git a/erts/lib_src/ose/ethread.c b/erts/lib_src/ose/ethread.c index f3cb4ed0ec..bde85f9f87 100644 --- a/erts/lib_src/ose/ethread.c +++ b/erts/lib_src/ose/ethread.c @@ -180,7 +180,7 @@ static OS_PROCESS(thr_wrapper) res = result == 0 ? (*thr_func)(arg) : NULL; - thr_exit_cleanup(&my_tid, res); + ethr_thr_exit(&res); } /* internal exports */ -- cgit v1.2.3 From d3b26048bff761f90da7e4ed9ef8453cbc5289b0 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Thu, 30 Jan 2014 18:20:24 +0100 Subject: ose: Remove receive in debug Sometimes scheduler 1 should go in here and it will have signals, so remove this. If needed later a check to see that fsem is used for scheduler 1 is needed. --- erts/lib_src/ose/ethr_event.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'erts/lib_src') diff --git a/erts/lib_src/ose/ethr_event.c b/erts/lib_src/ose/ethr_event.c index 5905fe22a9..87294c98ea 100644 --- a/erts/lib_src/ose/ethr_event.c +++ b/erts/lib_src/ose/ethr_event.c @@ -186,26 +186,8 @@ wait__(ethr_event *e, int spincount) ETHR_ASSERT(val == ETHR_EVENT_OFF__); } -#if defined(DEBUG) - while (1) { - /* In debug we also receive any signals to make sure that we do - not get any! redir tables should send all to scheduler_1 */ - SIGSELECT sigsel[] = {0}; - union SIGNAL *sig = receive_fsem(OSE_NO_TIMEOUT,sigsel,1); - //ETHR_ASSERT(sig == OS_RCV_FSEM); - if (sig != OS_RCV_FSEM) { - int i; - printf("0x%x: Got signal in wait: %u ",current_process(),sig->signo); - for (i = 0; i < (sigsize(&sig) / sizeof(SIGSELECT)) && i < 5; i++) { - printf("%x ",sig[i+1]); - } - printf("\n"); - } else - break; - } -#else wait_fsem(1); -#endif + ETHR_ASSERT(get_fsem(current_process()) == 0); } } -- cgit v1.2.3 From 0f9fd47d9141846950bd439d8401f8a759068136 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 14 Feb 2014 14:41:49 +0100 Subject: ose: Start using ppdata for tse key --- erts/lib_src/ose/ethread.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'erts/lib_src') diff --git a/erts/lib_src/ose/ethread.c b/erts/lib_src/ose/ethread.c index bde85f9f87..da66c27e77 100644 --- a/erts/lib_src/ose/ethread.c +++ b/erts/lib_src/ose/ethread.c @@ -63,7 +63,7 @@ static ethr_tid main_thr_tid; static const char* own_tid_key = "ethread_own_tid"; -char* ethr_ts_event_key__ = "ethread_tse"; +ethr_tsd_key ethr_ts_event_key__; #define ETHREADWRAPDATASIG 1 @@ -173,8 +173,6 @@ static OS_PROCESS(thr_wrapper) } /* pthread mutex api says we have to do this */ - /*erts_fprintf(stderr, "(%s / %d) curr_pid 0x%x / signal_fsem to 0x%x (fsem val %d)\n", - __FUNCTION__, __LINE__, current_process(), current_process(), get_fsem(current_process()));*/ signal_fsem(current_process()); ETHR_ASSERT(get_fsem(current_process()) == 0); @@ -187,12 +185,12 @@ static OS_PROCESS(thr_wrapper) int ethr_set_tse__(ethr_ts_event *tsep) { - return set_envp(current_process(),ethr_ts_event_key__, (OSADDRESS) tsep); + return ethr_tsd_set(ethr_ts_event_key__,(void *) tsep); } ethr_ts_event *ethr_get_tse__(void) { - return (ethr_ts_event *) get_envp(current_process(),ethr_ts_event_key__); + return (ethr_ts_event *) ethr_tsd_get(ethr_ts_event_key__); } #if defined(ETHR_PPC_RUNTIME_CONF__) @@ -296,14 +294,15 @@ ethr_init(ethr_init_data *id) main_thr_tid.tsd_key_index = 0; set_envp(current_process(),own_tid_key,(OSADDRESS)&main_thr_tid); - /*erts_fprintf(stderr, "(%s / %d) curr_pid 0x%x / signal_fsem to 0x%x (fsem_val %d)\n", - __FUNCTION__, __LINE__, current_process(), current_process(), get_fsem(current_process()));*/ 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; -- cgit v1.2.3 From a35d0f5f82f8152f1b953eda039807a7d4f4e9b9 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Sun, 23 Feb 2014 18:26:38 +0100 Subject: ose: Thread priorities configurable from lmconf The pattern used for getting the priority from the lmconf is based on the name of the process created. The pattern is: ERTS_%%PROCESS_NAME%%_PRIO with the %%PROCESS_NAME%% replaced by the prefix of the process the priority applies to. eg: ERTS_SCHEDULER_PRIO=24 applies to processes with name SCHEDULER_1, SCHEDULER_2 etc. --- erts/lib_src/ose/ethread.c | 220 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 211 insertions(+), 9 deletions(-) (limited to 'erts/lib_src') diff --git a/erts/lib_src/ose/ethread.c b/erts/lib_src/ose/ethread.c index da66c27e77..53628382b1 100644 --- a/erts/lib_src/ose/ethread.c +++ b/erts/lib_src/ose/ethread.c @@ -22,6 +22,7 @@ * Author: Lukas Larsson */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -50,10 +51,13 @@ #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 @@ -61,6 +65,16 @@ #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__; @@ -93,6 +107,157 @@ union SIGNAL { * -------------------------------------------------------------------------- */ +/* 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; @@ -328,10 +493,45 @@ ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg, 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; @@ -377,17 +577,18 @@ ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg, else init_msg->data.prep_func_res = NULL; - /*erts_fprintf(stderr, "creating process %s / stack %d\n", opts->name, use_stack_size);*/ + LOG(("ERTS - ethr_thr_create(): Process [0x%x] is creating '%s', coreNo = %u, prio:%u\n", + current_process(), use_name, use_core, use_prio)); - ramlog_printf("[0x%x] process '%s', coreNo = %u\n", - current_process(), opts->name, opts->coreNo); - tid->id = create_process(OS_PRI_PROC, opts->name, thr_wrapper, - use_stack_size, /*opts->prio+5*/24, 0, + 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, opts->coreNo)) { - printf("[0x%x] Binding pid 0x%x (%s) to core no %u.\n", - current_process(), tid->id, opts->name, opts->coreNo); + 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 @@ -418,6 +619,7 @@ ethr_thr_create(ethr_tid *tid, void * (*func)(void *), void *arg, if (ethr_thr_parent_func__) ethr_thr_parent_func__(prep_func_res); + LOG(("ERTS - ethr_thr_create(): Exiting.\n")); return res; } -- cgit v1.2.3 From ad9d36c55fb6c77ce0a6163e009313deaa2d2bb0 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 21 Feb 2014 09:14:34 +0100 Subject: ose: Cleanup of mutex selection defines --- erts/lib_src/common/ethr_mutex.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'erts/lib_src') diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c index 036914af7b..47f2f884af 100644 --- a/erts/lib_src/common/ethr_mutex.c +++ b/erts/lib_src/common/ethr_mutex.c @@ -1249,7 +1249,7 @@ ethr_cond_wait(ethr_cond *cnd, ethr_mutex *mtx) return 0; } -#elif defined(ETHR_PTHREADS) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS) +#elif (defined(ETHR_PTHREADS) || defined(ETHR_OSE_THREADS)) && !defined(ETHR_DBG_WIN_MTX_WITH_PTHREADS) /* -- pthread mutex and condition variables -------------------------------- */ int @@ -1428,6 +1428,8 @@ void LeaveCriticalSection(CRITICAL_SECTION *cs) ETHR_FATAL_ERROR__(res); } +#else +#error "No mutex implementation found" #endif #define ETHR_CND_WAIT__ ((ethr_sint32_t) 0x11dead11) -- cgit v1.2.3 From 494d9125a92658d852e22c429ca61687e0709c09 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Fri, 21 Feb 2014 11:30:41 +0100 Subject: ose: Cleanup cleanup of mutex selection defines --- erts/lib_src/common/ethr_mutex.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'erts/lib_src') diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c index 47f2f884af..72b44033ad 100644 --- a/erts/lib_src/common/ethr_mutex.c +++ b/erts/lib_src/common/ethr_mutex.c @@ -1428,8 +1428,6 @@ void LeaveCriticalSection(CRITICAL_SECTION *cs) ETHR_FATAL_ERROR__(res); } -#else -#error "No mutex implementation found" #endif #define ETHR_CND_WAIT__ ((ethr_sint32_t) 0x11dead11) @@ -1754,6 +1752,8 @@ ethr_cond_destroy(ethr_cond *cnd) return 0; } +#else +#error "No mutex implementation found" #endif /* -- Exported symbols of inline functions --------------------------------- */ -- cgit v1.2.3