diff options
author | Lukas Larsson <[email protected]> | 2014-02-23 18:26:38 +0100 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2014-02-24 15:16:07 +0100 |
commit | a35d0f5f82f8152f1b953eda039807a7d4f4e9b9 (patch) | |
tree | 0410287577061d3ed630e76608bc865613c2b19d | |
parent | 2bf4f22a9488d94ac1fc3c72a4e9d84151744004 (diff) | |
download | otp-a35d0f5f82f8152f1b953eda039807a7d4f4e9b9.tar.gz otp-a35d0f5f82f8152f1b953eda039807a7d4f4e9b9.tar.bz2 otp-a35d0f5f82f8152f1b953eda039807a7d4f4e9b9.zip |
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.
-rw-r--r-- | erts/emulator/beam/erl_async.c | 14 | ||||
-rw-r--r-- | erts/emulator/beam/erl_process.c | 38 | ||||
-rw-r--r-- | erts/emulator/beam/erl_trace.c | 5 | ||||
-rw-r--r-- | erts/emulator/drivers/ose/ose_signal_drv.c | 2 | ||||
-rw-r--r-- | erts/emulator/sys/ose/default.lmconf | 6 | ||||
-rw-r--r-- | erts/emulator/sys/ose/sys.c | 10 | ||||
-rw-r--r-- | erts/include/internal/ethread.h | 4 | ||||
-rw-r--r-- | erts/lib_src/ose/ethread.c | 220 |
8 files changed, 265 insertions, 34 deletions
diff --git a/erts/emulator/beam/erl_async.c b/erts/emulator/beam/erl_async.c index afb5bc302f..b3dc327704 100644 --- a/erts/emulator/beam/erl_async.c +++ b/erts/emulator/beam/erl_async.c @@ -166,6 +166,7 @@ async_ready_q(Uint sched_id) #endif + void erts_init_async(void) { @@ -226,18 +227,23 @@ erts_init_async(void) thr_opts.suggested_stack_size = erts_async_thread_suggested_stack_size; -#ifdef ETHR_HAVE_THREAD_NICENESS - thr_opts.prio += 2; -#endif #ifdef ETHR_HAVE_THREAD_NAMES - thr_opts.name = "async_thread"; + thr_opts.name = malloc(sizeof(char)*(strlen("async_XXXX")+1)); #endif for (i = 0; i < erts_async_max_threads; i++) { ErtsAsyncQ *aq = async_q(i); + +#ifdef ETHR_HAVE_THREAD_NAMES + sprintf(thr_opts.name, "async_%d", i+1); +#endif + erts_thr_create(&aq->thr_id, async_main, (void*) aq, &thr_opts); } +#ifdef ETHR_HAVE_THREAD_NAMES + free(thr_opts.name); +#endif /* Wait for async threads to initialize... */ erts_mtx_lock(&async->init.data.mtx); diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index a4241c6d43..83856ab983 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -6830,9 +6830,16 @@ erts_start_schedulers(void) opts.detached = 1; +#ifdef ETHR_HAVE_THREAD_NAMES + opts.name = malloc(80); +#endif + #ifdef ERTS_SMP if (erts_runq_supervision_interval) { opts.suggested_stack_size = 16; +#ifdef ETHR_HAVE_THREAD_NAMES + sprintf(opts.name, "runq_supervisor"); +#endif erts_atomic_init_nob(&runq_supervisor_sleeping, 0); if (0 != ethr_event_init(&runq_supervision_event)) erl_exit(1, "Failed to create run-queue supervision event\n"); @@ -6854,17 +6861,13 @@ erts_start_schedulers(void) res = ENOTSUP; } -#ifdef ETHR_HAVE_THREAD_NAMES - opts.name = malloc(sizeof(char)*(strlen("scheduler_XXXX")+1)); -#endif - for (actual = 0; actual < wanted; actual++) { ErtsSchedulerData *esdp = ERTS_SCHEDULER_IX(actual); ASSERT(actual == esdp->no - 1); #ifdef ETHR_HAVE_THREAD_NAMES - sprintf(opts.name,"scheduler_%d", actual+1); + sprintf(opts.name, "scheduler_%d", actual + 1); #endif #ifdef __OSE__ @@ -6872,14 +6875,13 @@ erts_start_schedulers(void) opts.coreNo = (actual+1) % ose_num_cpus(); #endif - res = ethr_thr_create(&esdp->tid, sched_thread_func,(void*)esdp,&opts); + res = ethr_thr_create(&esdp->tid, sched_thread_func, (void*)esdp, &opts); if (res != 0) { break; } - } - + erts_no_schedulers = actual; #ifdef ERTS_DIRTY_SCHEDULERS @@ -6888,12 +6890,18 @@ erts_start_schedulers(void) int ix; for (ix = 0; ix < erts_no_dirty_cpu_schedulers; ix++) { ErtsSchedulerData *esdp = ERTS_DIRTY_CPU_SCHEDULER_IX(ix); +#ifdef ETHR_HAVE_THREAD_NAMES + sprintf(opts.name,"dirty_cpu_scheduler_%d", ix + 1); +#endif res = ethr_thr_create(&esdp->tid,sched_dirty_cpu_thread_func,(void*)esdp,&opts); if (res != 0) erl_exit(1, "Failed to create dirty cpu scheduler thread %d\n", ix); } for (ix = 0; ix < erts_no_dirty_io_schedulers; ix++) { ErtsSchedulerData *esdp = ERTS_DIRTY_IO_SCHEDULER_IX(ix); +#ifdef ETHR_HAVE_THREAD_NAMES + sprintf(opts.name,"dirty_io_scheduler_%d", ix + 1); +#endif res = ethr_thr_create(&esdp->tid,sched_dirty_io_thread_func,(void*)esdp,&opts); if (res != 0) erl_exit(1, "Failed to create dirty io scheduler thread %d\n", ix); @@ -6903,16 +6911,14 @@ erts_start_schedulers(void) #endif ERTS_THR_MEMORY_BARRIER; + #ifdef ETHR_HAVE_THREAD_NAMES - free(opts.name); - opts.name = "aux_thread"; + sprintf(opts.name, "aux"); #endif + #ifdef __OSE__ opts.coreNo = 0; -#endif -#ifdef ETHR_HAVE_THREAD_NICENESS - opts.prio++; -#endif +#endif /* __OSE__ */ res = ethr_thr_create(&aux_tid, aux_thread, NULL, &opts); if (res != 0) @@ -6933,6 +6939,10 @@ erts_start_schedulers(void) actual, actual == 1 ? " was" : "s were"); erts_send_error_to_logger_nogl(dsbufp); } + +#ifdef ETHR_HAVE_THREAD_NAMES + free(opts.name); +#endif } #endif /* ERTS_SMP */ diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c index 43e7435d2a..6978a5f11a 100644 --- a/erts/emulator/beam/erl_trace.c +++ b/erts/emulator/beam/erl_trace.c @@ -3478,12 +3478,11 @@ init_sys_msg_dispatcher(void) sys_message_queue_end = NULL; erts_smp_cnd_init(&smq_cnd); erts_smp_mtx_init(&smq_mtx, "sys_msg_q"); + #ifdef ETHR_HAVE_THREAD_NAMES thr_opts.name = "sys_msg_dispatcher"; #endif -#ifdef ETHR_HAVE_THREAD_NICENESS - thr_opts.prio++; -#endif + erts_smp_thr_create(&sys_msg_dispatcher_tid, sys_msg_dispatcher_func, NULL, diff --git a/erts/emulator/drivers/ose/ose_signal_drv.c b/erts/emulator/drivers/ose/ose_signal_drv.c index 46890a1503..1335bffe18 100644 --- a/erts/emulator/drivers/ose/ose_signal_drv.c +++ b/erts/emulator/drivers/ose/ose_signal_drv.c @@ -29,6 +29,7 @@ #include "erl_driver.h" #include "ose.h" + #ifdef HAVE_OSE_SPI_H #include "ose_spi/ose_spi.h" #endif @@ -363,6 +364,7 @@ static OS_PROCESS(driver_proxy_process) { } } + /** * Init routine for the driver **/ diff --git a/erts/emulator/sys/ose/default.lmconf b/erts/emulator/sys/ose/default.lmconf index 17b7a1e5fa..a66b0ece56 100644 --- a/erts/emulator/sys/ose/default.lmconf +++ b/erts/emulator/sys/ose/default.lmconf @@ -13,6 +13,12 @@ HEAP_SMALL_BUF_INIT_SIZE=64000000 HEAP_LARGE_BUF_THRESHOLD=16000000 HEAP_LOCK_TYPE=2 +ERTS_DEFAULT_PRIO=24 +ERTS_SCHEDULER_PRIO=24 +ERTS_ASYNC_PRIO=22 +ERTS_AUX_PRIO=24 +ERTS_SYS_MSG_DISPATCHER_PRIO=21 + # Setting the environment variable EFS_RESOLVE_TMO on the block to 0. # This will eliminiate delays when trying to open files on not mounted # volumes. diff --git a/erts/emulator/sys/ose/sys.c b/erts/emulator/sys/ose/sys.c index beb7f5944f..88dbd7fcf8 100644 --- a/erts/emulator/sys/ose/sys.c +++ b/erts/emulator/sys/ose/sys.c @@ -50,6 +50,14 @@ #include "efs.h" #include "erl_printf.h" +/* 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 + extern char **environ; static erts_smp_rwmtx_t environ_rwmtx; @@ -68,7 +76,7 @@ static erts_smp_rwmtx_t environ_rwmtx; #include "erl_cpu_topology.h" /* The priority for reader/writer processes */ -#define FD_PROC_PRI 20 +#define FD_PROC_PRI get_pri(current_process()) typedef struct ErtsSysReportExit_ ErtsSysReportExit; struct ErtsSysReportExit_ { diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h index 58b4ef55b6..8512ba5884 100644 --- a/erts/include/internal/ethread.h +++ b/erts/include/internal/ethread.h @@ -217,7 +217,6 @@ typedef OSPPDKEY ethr_tsd_key; #define ETHR_USE_OWN_RWMTX_IMPL__ #define ETHR_USE_OWN_MTX_IMPL__ #define ETHR_HAVE_THREAD_NAMES -#define ETHR_HAVE_THREAD_NICENESS #define ETHR_PPC_HAVE_NO_LWSYNC #undef ETHR_HAVE_NATIVE_SPINLOCKS @@ -510,7 +509,6 @@ typedef struct { int suggested_stack_size; /* kilo words (default sys dependent) */ #ifdef ETHR_OSE_THREADS char *name; - OSPRIORITY prio; U32 coreNo; #endif } ethr_thr_opts; @@ -518,7 +516,7 @@ typedef struct { #if defined(ETHR_OSE_THREADS) /* Default ethr name is big as we want to be able to sprint stuff in there */ #define ETHR_THR_OPTS_DEFAULT_INITER \ - {0, -1, "ethread", get_pri(current_process()), 0} + {0, -1, "ethread", 0} #else #define ETHR_THR_OPTS_DEFAULT_INITER {0, -1} #endif 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; } |