MAJOR: applet: applet scheduler rework.
In order to authorize call of appctx_wakeup on running task:
- from within the task handler itself.
- in futur, from another thread.
The appctx is considered paused as default after running the handler.
The handler should explicitly call appctx_wakeup to be re-called.
When the appctx_free is called on a running handler. The real
free is postponed at the end of the handler process.
diff --git a/src/applet.c b/src/applet.c
index f5bc79d..324dfd3 100644
--- a/src/applet.c
+++ b/src/applet.c
@@ -24,22 +24,22 @@
unsigned int applets_active_queue = 0;
struct list applet_active_queue = LIST_HEAD_INIT(applet_active_queue);
-struct list applet_cur_queue = LIST_HEAD_INIT(applet_cur_queue);
void applet_run_active()
{
- struct appctx *curr;
+ struct appctx *curr, *next;
struct stream_interface *si;
+ struct list applet_cur_queue = LIST_HEAD_INIT(applet_cur_queue);
- if (LIST_ISEMPTY(&applet_active_queue))
- return;
-
- /* move active queue to run queue */
- applet_active_queue.n->p = &applet_cur_queue;
- applet_active_queue.p->n = &applet_cur_queue;
-
- applet_cur_queue = applet_active_queue;
- LIST_INIT(&applet_active_queue);
+ curr = LIST_NEXT(&applet_active_queue, typeof(curr), runq);
+ while (&curr->runq != &applet_active_queue) {
+ next = LIST_NEXT(&curr->runq, typeof(next), runq);
+ LIST_DEL(&curr->runq);
+ curr->state = APPLET_RUNNING;
+ LIST_ADDQ(&applet_cur_queue, &curr->runq);
+ applets_active_queue--;
+ curr = next;
+ }
/* The list is only scanned from the head. This guarantees that if any
* applet removes another one, there is no side effect while walking
@@ -70,7 +70,20 @@
if (applet_cur_queue.n == &curr->runq) {
/* curr was left in the list, move it back to the active list */
LIST_DEL(&curr->runq);
- LIST_ADDQ(&applet_active_queue, &curr->runq);
+ LIST_INIT(&curr->runq);
+ if (curr->state & APPLET_WANT_DIE) {
+ curr->state = APPLET_SLEEPING;
+ __appctx_free(curr);
+ }
+ else {
+ if (curr->state & APPLET_WOKEN_UP) {
+ curr->state = APPLET_SLEEPING;
+ __appctx_wakeup(curr);
+ }
+ else {
+ curr->state = APPLET_SLEEPING;
+ }
+ }
}
}
}
diff --git a/src/stream.c b/src/stream.c
index 3781ac7..4e34f38 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -1061,7 +1061,6 @@
/* Stops the applet sheduling, in case of the init function miss
* some data.
*/
- appctx_pause(appctx);
si_applet_stop_get(&s->si[1]);
/* Call initialisation. */
diff --git a/src/stream_interface.c b/src/stream_interface.c
index 47ba8c1..52e2df4 100644
--- a/src/stream_interface.c
+++ b/src/stream_interface.c
@@ -1369,16 +1369,6 @@
/* update the stream-int, channels, and possibly wake the stream up */
stream_int_notify(si);
-
- /* Get away from the active list if we can't work anymore.
- * We also do that if the main task has already scheduled, because it
- * saves a useless wakeup/pause/wakeup cycle causing one useless call
- * per session on average.
- */
- if (task_in_rq(si_task(si)) ||
- (((si->flags & (SI_FL_WANT_PUT|SI_FL_WAIT_ROOM)) != SI_FL_WANT_PUT) &&
- ((si->flags & (SI_FL_WANT_GET|SI_FL_WAIT_DATA)) != SI_FL_WANT_GET)))
- appctx_pause(si_appctx(si));
}
@@ -1393,8 +1383,6 @@
if (((si->flags & (SI_FL_WANT_PUT|SI_FL_WAIT_ROOM)) == SI_FL_WANT_PUT) ||
((si->flags & (SI_FL_WANT_GET|SI_FL_WAIT_DATA)) == SI_FL_WANT_GET))
appctx_wakeup(si_appctx(si));
- else
- appctx_pause(si_appctx(si));
}
/*