aboutsummaryrefslogtreecommitdiffstats
path: root/erts
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2014-02-23 18:26:38 +0100
committerLukas Larsson <[email protected]>2014-02-24 15:16:07 +0100
commita35d0f5f82f8152f1b953eda039807a7d4f4e9b9 (patch)
tree0410287577061d3ed630e76608bc865613c2b19d /erts
parent2bf4f22a9488d94ac1fc3c72a4e9d84151744004 (diff)
downloadotp-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.
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/erl_async.c14
-rw-r--r--erts/emulator/beam/erl_process.c38
-rw-r--r--erts/emulator/beam/erl_trace.c5
-rw-r--r--erts/emulator/drivers/ose/ose_signal_drv.c2
-rw-r--r--erts/emulator/sys/ose/default.lmconf6
-rw-r--r--erts/emulator/sys/ose/sys.c10
-rw-r--r--erts/include/internal/ethread.h4
-rw-r--r--erts/lib_src/ose/ethread.c220
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;
}