You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by cl...@apache.org on 2022/02/03 07:55:05 UTC

[qpid-proton] branch main updated: PROTON-2472: prevent early consumption of ready list on EINTR

This is an automated email from the ASF dual-hosted git repository.

cliffjansen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git


The following commit(s) were added to refs/heads/main by this push:
     new 3a063e3  PROTON-2472: prevent early consumption of ready list on EINTR
3a063e3 is described below

commit 3a063e363c6a3a8807ac82955c5bb60926d6f0dd
Author: Cliff Jansen <cl...@apache.org>
AuthorDate: Wed Feb 2 23:54:29 2022 -0800

    PROTON-2472: prevent early consumption of ready list on EINTR
---
 c/src/proactor/epoll-internal.h |  2 +-
 c/src/proactor/epoll.c          | 41 ++++++++++++++++-------------------------
 2 files changed, 17 insertions(+), 26 deletions(-)

diff --git a/c/src/proactor/epoll-internal.h b/c/src/proactor/epoll-internal.h
index 8db12a1..79dddaa 100644
--- a/c/src/proactor/epoll-internal.h
+++ b/c/src/proactor/epoll-internal.h
@@ -192,7 +192,7 @@ struct pn_proactor_t {
   tslot_t *last_earmark;
   task_t *sched_ready_first;
   task_t *sched_ready_last;
-  task_t *sched_ready_current; // TODO: remove or use for sceduling priority or fairness
+  bool sched_ready_pending;
   unsigned int sched_ready_count;
   task_t *resched_first;
   task_t *resched_last;
diff --git a/c/src/proactor/epoll.c b/c/src/proactor/epoll.c
index 6a243be..1ff68ef 100644
--- a/c/src/proactor/epoll.c
+++ b/c/src/proactor/epoll.c
@@ -250,8 +250,8 @@ void task_init(task_t *tsk, task_type_t t, pn_proactor_t *p) {
  * are needed to cross or reconcile the two portions of the list.
  */
 
-// Call with sched lock held.
-static void pop_ready_task(task_t *tsk) {
+// Call with sched lock held and sched_ready_count > 0.
+static task_t *sched_ready_pop_front(pn_proactor_t *p) {
   // every task on the sched_ready_list is either currently running,
   // or to be scheduled.  schedule() will not "see" any of the ready_next
   // pointers until ready and working have transitioned to 0
@@ -262,22 +262,19 @@ static void pop_ready_task(task_t *tsk) {
   // !ready .. schedule() .. on ready_list .. on sched_ready_list .. working task .. !sched_ready && !ready
   //
   // Intervening locks at each transition ensures ready_next has memory coherence throughout the ready task scheduling cycle.
-  // TODO: sched_ready list changed to sequential processing.  Review need for sched_ready_current.
-  pn_proactor_t *p = tsk->proactor;
-  if (tsk == p->sched_ready_current)
-    p->sched_ready_current = tsk->ready_next;
-  assert (tsk == p->sched_ready_first);
   assert (p->sched_ready_count);
+  task_t *tsk = p->sched_ready_first;
   p->sched_ready_count--;
   if (tsk == p->sched_ready_last) {
     p->sched_ready_first = p->sched_ready_last = NULL;
   } else {
     p->sched_ready_first = tsk->ready_next;
   }
-  if (!p->sched_ready_first) {
-    p->sched_ready_last = NULL;
-    assert(p->sched_ready_count == 0);
+  if (p->sched_ready_count == 0) {
+    assert(!p->sched_ready_first);
+    p->sched_ready_pending = false;
   }
+  return tsk;
 }
 
 // Call only as the poller task that has already called schedule_ready_list() and already
@@ -2273,8 +2270,6 @@ static void schedule_ready_list(pn_proactor_t *p) {
     if (!p->sched_ready_first)
       p->sched_ready_first = p->ready_list_first;
     p->sched_ready_last = p->ready_list_last;
-    if (!p->sched_ready_current)
-      p->sched_ready_current = p->sched_ready_first;
     p->ready_list_first = p->ready_list_last = NULL;
 
     // Track sched_ready_count to know how many threads may be needed.
@@ -2403,17 +2398,14 @@ static task_t *next_runnable(pn_proactor_t *p, tslot_t *ts) {
     }
   }
 
-  // rest of sched_ready list
-  while (p->sched_ready_count) {
-    tsk = p->sched_ready_current;
+  // sched_ready list tasks deferred in poller_do_epoll()
+  while (p->sched_ready_pending) {
+    tsk = sched_ready_pop_front(p);
     assert(tsk->ready); // eventfd_mutex required post ready set and pre move to sched_ready_list
     if (post_ready(p, tsk)) {
-      pop_ready_task(tsk);  // updates sched_ready_current
       assert(!tsk->runnables_idx && !tsk->runner);
       assign_thread(ts, tsk);
       return tsk;
-    } else {
-      pop_ready_task(tsk);
     }
   }
 
@@ -2501,7 +2493,7 @@ static pn_event_batch_t *next_event_batch(pn_proactor_t* p, bool can_block) {
 static bool poller_do_epoll(struct pn_proactor_t* p, tslot_t *ts, bool can_block) {
   // As poller with lots to do, be mindful of hogging the sched lock.  Release when making kernel calls.
   assert(!p->resched_cutoff);
-  assert(!p->sched_ready_first);
+  assert(!p->sched_ready_first && !p->sched_ready_pending);
   int n_events;
   task_t *tsk;
   bool unpolled_work = false;
@@ -2608,21 +2600,20 @@ static bool poller_do_epoll(struct pn_proactor_t* p, tslot_t *ts, bool can_block
   if (warm_tries < 0)
     warm_tries = 0;
 
-  task_t *ctsk = p->sched_ready_current;
   int max_runnables = p->runnables_capacity;
   while (p->sched_ready_count && p->n_runnables < max_runnables && warm_tries) {
-    assert(ctsk);
+    task_t *ctsk = sched_ready_pop_front(p);
     tsk = post_ready(p, ctsk);
-    pop_ready_task(ctsk);
     warm_tries--;
     if (tsk)
       make_runnable(tsk);
-    ctsk = ctsk->ready_next;
   }
-  p->sched_ready_current = ctsk;
+  // sched_ready list is now either consumed or partially deferred.
+  // Allow next_runnable() to see any remaining sched_ready tasks.
+  p->sched_ready_pending = p->sched_ready_count > 0;
 
   while (p->resched_cutoff && p->n_runnables < max_runnables && warm_tries) {
-    ctsk = resched_pop_front(p);
+    task_t *ctsk = resched_pop_front(p);
     assert(ctsk->runner == RESCHEDULE_PLACEHOLDER && !ctsk->runnables_idx);
     ctsk->runner = NULL;  // Allow task to run again.
     warm_tries--;

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org