From 049611f98d67f11f8e06fe0b0fc50eb8ca1925d8 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 8 Jun 2016 14:56:31 +0200 Subject: No GC on dirty IO schedulers --- erts/emulator/beam/erl_process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c index c0b1d7246c..5193be85b4 100644 --- a/erts/emulator/beam/erl_process.c +++ b/erts/emulator/beam/erl_process.c @@ -10082,7 +10082,7 @@ Process *erts_schedule(ErtsSchedulerData *esdp, Process *p, int calls) } } - if (ERTS_IS_GC_DESIRED(p)) { + if (ERTS_IS_GC_DESIRED(p) && !ERTS_SCHEDULER_IS_DIRTY_IO(esdp)) { if (!(state & ERTS_PSFLG_EXITING) && !(p->flags & (F_DELAY_GC|F_DISABLE_GC))) { int cost = scheduler_gc_proc(p, reds); calls += cost; -- cgit v1.2.3 From 77192f7f32d4bbe293a6e8cb9da79b8a6dd6b181 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Wed, 8 Jun 2016 14:58:33 +0200 Subject: Replace enif_is_on_dirty_scheduler() with enif_thread_type() --- erts/doc/src/erl_nif.xml | 29 ++++++++++++++-------- erts/emulator/beam/erl_nif.c | 19 ++++++++------ erts/emulator/beam/erl_nif.h | 11 ++++++++ erts/emulator/beam/erl_nif_api_funcs.h | 4 +-- .../test/dirty_nif_SUITE_data/dirty_nif_SUITE.c | 11 +++++--- 5 files changed, 50 insertions(+), 24 deletions(-) diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index 4efd155b09..b2e2254a65 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -1101,15 +1101,6 @@ typedef enum { Erlang operators =:= and =/=.

- intenif_is_on_dirty_scheduler(ErlNifEnv* env) - Check to see if executing on a dirty scheduler thread - -

Check to see if the current NIF is executing on a dirty scheduler thread. If - executing on a dirty scheduler thread true returned; otherwise false.

-

This function can only be used from a NIF-calling thread, and with an - environment corresponding to currently executing processes.

-
-
intenif_is_pid(ErlNifEnv* env, ERL_NIF_TERM term) Determine if a term is a pid

Return true if term is a pid.

@@ -1820,7 +1811,25 @@ enif_map_iterator_destroy(env, &iter);

Same as erl_drv_thread_self.

- + intenif_thread_type(void) + Determine type of current thread + +

Determine the type of currently executing thread. A positive value + indicates a scheduler thread while a negative value or zero indicates + another type of thread. Currently the following specific types exist + (which may be extended in the future):

+ + ERL_NIF_THR_UNDEFINED +

Undefined thread that is not a scheduler thread.

+ ERL_NIF_THR_NORMAL_SCHEDULER +

A normal scheduler thread.

+ ERL_NIF_THR_DIRTY_CPU_SCHEDULER +

A dirty CPU scheduler thread.

+ ERL_NIF_THR_DIRTY_IO_SCHEDULER +

A dirty I/O scheduler thread.

+
+
+
ErlNifTimeenif_time_offset(ErlNifTimeUnit time_unit) Get current Time Offset diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c index 4fd82bad10..039f97ef43 100644 --- a/erts/emulator/beam/erl_nif.c +++ b/erts/emulator/beam/erl_nif.c @@ -2658,18 +2658,21 @@ done: } int -enif_is_on_dirty_scheduler(ErlNifEnv* env) +enif_thread_type(void) { - int scheduler; - Process *c_p; + ErtsSchedulerData *esdp = erts_get_scheduler_data(); - execution_state(env, &c_p, &scheduler); + if (!esdp) + return ERL_NIF_THR_UNDEFINED; + + if (!ERTS_SCHEDULER_IS_DIRTY(esdp)) + return ERL_NIF_THR_NORMAL_SCHEDULER; - if (!c_p || !scheduler) - erts_exit(ERTS_ABORT_EXIT, "enif_is_on_dirty_scheduler: " - "Invalid env"); + if (ERTS_SCHEDULER_IS_DIRTY_CPU(esdp)) + return ERL_NIF_THR_DIRTY_CPU_SCHEDULER; - return scheduler < 0; + ASSERT(ERTS_SCHEDULER_IS_DIRTY_IO(esdp)); + return ERL_NIF_THR_DIRTY_IO_SCHEDULER; } /* Maps */ diff --git a/erts/emulator/beam/erl_nif.h b/erts/emulator/beam/erl_nif.h index da7a754757..494971e118 100644 --- a/erts/emulator/beam/erl_nif.h +++ b/erts/emulator/beam/erl_nif.h @@ -209,6 +209,17 @@ typedef enum { ERL_NIF_BIN2TERM_SAFE = 0x20000000 } ErlNifBinaryToTerm; +/* + * Return values from enif_thread_type(). Negative values + * reserved for specific types of non-scheduler threads. + * Positive values reserved for scheduler thread types. + */ + +#define ERL_NIF_THR_UNDEFINED 0 +#define ERL_NIF_THR_NORMAL_SCHEDULER 1 +#define ERL_NIF_THR_DIRTY_CPU_SCHEDULER 2 +#define ERL_NIF_THR_DIRTY_IO_SCHEDULER 3 + #if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) # define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS typedef struct { diff --git a/erts/emulator/beam/erl_nif_api_funcs.h b/erts/emulator/beam/erl_nif_api_funcs.h index b211ab4b16..9a8f216773 100644 --- a/erts/emulator/beam/erl_nif_api_funcs.h +++ b/erts/emulator/beam/erl_nif_api_funcs.h @@ -173,7 +173,7 @@ ERL_NIF_API_FUNC_DECL(int, enif_get_local_port, (ErlNifEnv* env, ERL_NIF_TERM, E ERL_NIF_API_FUNC_DECL(int, enif_term_to_binary, (ErlNifEnv *env, ERL_NIF_TERM term, ErlNifBinary *bin)); ERL_NIF_API_FUNC_DECL(size_t, enif_binary_to_term, (ErlNifEnv *env, const unsigned char* data, size_t sz, ERL_NIF_TERM *term, unsigned int opts)); ERL_NIF_API_FUNC_DECL(int, enif_port_command, (ErlNifEnv *env, const ErlNifPort* to_port, ErlNifEnv *msg_env, ERL_NIF_TERM msg)); -ERL_NIF_API_FUNC_DECL(int,enif_is_on_dirty_scheduler,(ErlNifEnv*)); +ERL_NIF_API_FUNC_DECL(int,enif_thread_type,(void)); ERL_NIF_API_FUNC_DECL(int,enif_snprintf,(char * buffer, size_t size, const char *format, ...)); /* @@ -330,7 +330,7 @@ ERL_NIF_API_FUNC_DECL(int,enif_snprintf,(char * buffer, size_t size, const char # define enif_term_to_binary ERL_NIF_API_FUNC_MACRO(enif_term_to_binary) # define enif_binary_to_term ERL_NIF_API_FUNC_MACRO(enif_binary_to_term) # define enif_port_command ERL_NIF_API_FUNC_MACRO(enif_port_command) -# define enif_is_on_dirty_scheduler ERL_NIF_API_FUNC_MACRO(enif_is_on_dirty_scheduler) +# define enif_thread_type ERL_NIF_API_FUNC_MACRO(enif_thread_type) # define enif_snprintf ERL_NIF_API_FUNC_MACRO(enif_snprintf) /* diff --git a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c index e38bececde..d92933a096 100644 --- a/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c +++ b/erts/emulator/test/dirty_nif_SUITE_data/dirty_nif_SUITE.c @@ -48,7 +48,8 @@ static ERL_NIF_TERM dirty_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[ char s[10]; ErlNifBinary b; if (have_dirty_schedulers()) { - assert(enif_is_on_dirty_scheduler(env)); + assert(ERL_NIF_THR_DIRTY_CPU_SCHEDULER == enif_thread_type() + || ERL_NIF_THR_DIRTY_IO_SCHEDULER == enif_thread_type()); } assert(argc == 3); enif_get_int(env, argv[0], &n); @@ -65,7 +66,7 @@ static ERL_NIF_TERM call_dirty_nif(ErlNifEnv* env, int argc, const ERL_NIF_TERM int n; char s[10]; ErlNifBinary b; - assert(!enif_is_on_dirty_scheduler(env)); + assert(ERL_NIF_THR_NORMAL_SCHEDULER == enif_thread_type()); if (argc != 3) return enif_make_badarg(env); if (have_dirty_schedulers()) { @@ -151,7 +152,8 @@ dirty_sleeper(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ErlNifPid pid; ErlNifEnv* msg_env = NULL; - assert(enif_is_on_dirty_scheduler(env)); + assert(ERL_NIF_THR_DIRTY_CPU_SCHEDULER == enif_thread_type() + || ERL_NIF_THR_DIRTY_IO_SCHEDULER == enif_thread_type()); /* If we get a pid argument, it indicates a process involved in the test wants a message from us. Prior to the sleep we send a 'ready' @@ -221,7 +223,8 @@ static ERL_NIF_TERM dirty_heap_access_nif(ErlNifEnv* env, int argc, const ERL_NI { ERL_NIF_TERM res = enif_make_list(env, 0); int i; - assert(enif_is_on_dirty_scheduler(env)); + assert(ERL_NIF_THR_DIRTY_CPU_SCHEDULER == enif_thread_type() + || ERL_NIF_THR_DIRTY_IO_SCHEDULER == enif_thread_type()); for (i = 0; i < 1000; i++) res = enif_make_list_cell(env, enif_make_copy(env, argv[0]), res); -- cgit v1.2.3