File 0176-erts-Scheduler-pollset-migration-only-when-single-pr.patch of Package erlang

From c89cbee31536fa5897a74f4d8e0e2d8bde860a6d Mon Sep 17 00:00:00 2001
From: Andrew Bennett <potatosaladx@meta.com>
Date: Thu, 23 Oct 2025 14:50:48 -0500
Subject: [PATCH] [erts] Scheduler pollset migration only when single process
 enif_select

---
 erts/emulator/sys/common/erl_check_io.c | 40 +++++++++++++++++++------
 1 file changed, 31 insertions(+), 9 deletions(-)

diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c
index 7f87ed57d2..3914e003a7 100644
--- a/erts/emulator/sys/common/erl_check_io.c
+++ b/erts/emulator/sys/common/erl_check_io.c
@@ -200,6 +200,7 @@ typedef struct {
     EventStateFlags flags;
     int count;                    /* Number of times this fd has triggered
                                      without being deselected. */
+    Eterm last_select_pid;        /* Last process that called enif_select */
 } ErtsDrvEventState;
 
 struct drv_ev_state_shared {
@@ -290,6 +291,7 @@ static ERTS_INLINE int grow_drv_ev_state(ErtsSysFdType fd) {
                         sizeof(ErtsDrvEventState) * (new_len - old_len));
             for (i = old_len; i < new_len; i++) {
                 drv_ev_state.v[i].fd = (ErtsSysFdType) i;
+                drv_ev_state.v[i].last_select_pid = NIL;
             }
             erts_atomic_set_nob(&drv_ev_state.len, new_len);
             for (i=0; i<ERTS_CHECK_IO_DRV_EV_STATE_LOCK_CNT; i++) {
@@ -333,6 +335,8 @@ static ERTS_INLINE ErtsDrvEventState* new_drv_ev_state(ErtsDrvEventState *state,
     tmpl.active_events = 0;
     tmpl.type = ERTS_EV_TYPE_NONE;
     tmpl.flags = 0;
+    tmpl.count = 0;
+    tmpl.last_select_pid = NIL;
 
     return  (ErtsDrvEventState *) safe_hash_put(&drv_ev_state.tab, (void *) &tmpl);
 }
@@ -922,6 +926,7 @@ deselect(ErtsDrvEventState *state, int mode)
 	state->type = ERTS_EV_TYPE_NONE;
 	state->flags = ERTS_EV_FLAG_CLEAR;
         state->count = 0;
+        state->last_select_pid = NIL;
     } else {
         ErtsPollEvents new_events =
             erts_io_control(state, ERTS_POLL_OP_MOD, state->active_events);
@@ -1248,6 +1253,7 @@ enif_select_x(ErlNifEnv* env,
     ErtsDrvSelectDataState *free_select = NULL;
     ErtsNifSelectDataState *free_nif = NULL;
     ErtsPollEvents new_events = 0;
+    const Eterm recipient = pid ? pid->pid : env->proc->common.id;
 #ifdef DEBUG_PRINT_MODE
     char tmp_buff[255];
 #endif
@@ -1340,15 +1346,24 @@ enif_select_x(ErlNifEnv* env,
     old_events = state->events;
 
     if (on) {
+        ASSERT(is_internal_pid(recipient));
+
         if (state->type == ERTS_EV_TYPE_NONE)
             ctl_op = ERTS_POLL_OP_ADD;
 #if ERTS_POLL_USE_SCHEDULER_POLLING
-        else {    
-            if (!(state->flags & ERTS_EV_FLAG_SCHEDULER) &&
-                !(state->flags & ERTS_EV_FLAG_FALLBACK) &&
-                 (ctl_events & ERTS_POLL_EV_IN)) {
-                if (erts_sched_poll_enabled() && (state->flags & ERTS_EV_FLAG_NIF_SELECT) &&
-                    state->count++ > 10) {
+        else if (ctl_events & ERTS_POLL_EV_IN) {
+            if ((state->flags & (ERTS_EV_FLAG_SCHEDULER |
+                                 ERTS_EV_FLAG_FALLBACK |
+                                 ERTS_EV_FLAG_NIF_SELECT)) == ERTS_EV_FLAG_NIF_SELECT
+                && erts_sched_poll_enabled()) {
+                /* Check if this is a different process than last time.
+                 * If so, reset the counter to prevent scheduler pollset migration
+                 * in multi-process scenarios (e.g., multiple socket:accept callers). */
+                if (state->last_select_pid != recipient) {
+                    state->count = 0;
+                    state->last_select_pid = recipient;
+                }
+                else if (++(state->count) > 10) {
                     int wake_poller = 0;
                     DEBUG_PRINT_FD("moving to scheduler ps", state);
                     new_events = erts_poll_control(get_scheduler_pollset(), fd, ERTS_POLL_OP_ADD,
@@ -1359,7 +1374,7 @@ enif_select_x(ErlNifEnv* env,
                     old_events = state->events;
                 }
             }
-            if (ctl_events & ERTS_POLL_EV_IN) {
+            {
                 ErtsSchedulerData *esdp = erts_get_scheduler_data();
                 erts_io_clear_nif_select(fd, state);
                 /* Clear the marker in scheduler data so that the scheduler
@@ -1408,6 +1423,8 @@ enif_select_x(ErlNifEnv* env,
         if (state->type == ERTS_EV_TYPE_NIF && !old_events) {
             state->type = ERTS_EV_TYPE_NONE;
             state->flags = 0;
+            state->count = 0;
+            state->last_select_pid = NIL;
             state->driver.nif->in.pid = NIL;
             state->driver.nif->out.pid = NIL;
             state->driver.nif->err.pid = NIL;
@@ -1421,8 +1438,6 @@ enif_select_x(ErlNifEnv* env,
 	   || state->type == ERTS_EV_TYPE_NONE);
 
     if (on) {
-        const Eterm recipient = pid ? pid->pid : env->proc->common.id;
-        ASSERT(is_internal_pid(recipient));
         if (!state->driver.nif)
             state->driver.nif = alloc_nif_select_data();
         if (state->type == ERTS_EV_TYPE_NONE) {
@@ -1497,6 +1512,7 @@ enif_select_x(ErlNifEnv* env,
                 ret |= ERL_NIF_SELECT_STOP_SCHEDULED;
             }
             state->count = 0;
+            state->last_select_pid = NIL;
             state->flags &= ~ERTS_EV_FLAG_WANT_ERROR;
         }
         else
@@ -1777,6 +1793,8 @@ steal_pending_stop_use(erts_dsprintf_buf_t *dsbufp, ErlDrvPort ix,
         }
         state->type = ERTS_EV_TYPE_NONE;
         state->flags = 0;
+        state->count = 0;
+        state->last_select_pid = NIL;
         state->driver.stop.drv_ptr = NULL;
     }
     else {
@@ -1816,6 +1834,8 @@ steal_pending_stop_nif(erts_dsprintf_buf_t *dsbufp, ErtsResource* resource,
         enif_release_resource(state->driver.stop.resource->data);
         state->type = ERTS_EV_TYPE_NONE;
         state->flags = 0;
+        state->count = 0;
+        state->last_select_pid = NIL;
         state->driver.stop.resource = NULL;
     }
     else {
@@ -2014,6 +2034,7 @@ erts_check_io(ErtsPollThread *psi, ErtsMonotonicTime timeout_time, int poll_only
                 erts_poll_control(get_scheduler_pollset(), fd, ERTS_POLL_OP_DEL, 0, &wake_poller);
                 state->flags &= ~(ERTS_EV_FLAG_SCHEDULER|ERTS_EV_FLAG_IN_SCHEDULER);
                 state->count = 0;
+                state->last_select_pid = NIL;
             }
 #endif
         } else {
@@ -2034,6 +2055,7 @@ erts_check_io(ErtsPollThread *psi, ErtsMonotonicTime timeout_time, int poll_only
                     state->flags &= ~(ERTS_EV_FLAG_IN_SCHEDULER|ERTS_EV_FLAG_SCHEDULER);
                     state->active_events &= ~ERTS_POLL_EV_IN;
                     state->count = 0;
+                    state->last_select_pid = NIL;
                 }
             } else
 #endif
-- 
2.51.0

openSUSE Build Service is sponsored by