struct task *task_run_applet(struct task *t, void *context, unsigned short state);
-
-static int inline appctx_res_wakeup(struct appctx *appctx);
+int appctx_buf_available(void *arg);
/* Initializes all required fields for a new appctx. Note that it does the
appctx->t->context = appctx;
LIST_INIT(&appctx->buffer_wait.list);
appctx->buffer_wait.target = appctx;
- appctx->buffer_wait.wakeup_cb = (int (*)(void *))appctx_res_wakeup;
+ appctx->buffer_wait.wakeup_cb = appctx_buf_available;
HA_ATOMIC_ADD(&nb_applets, 1);
}
return appctx;
task_wakeup(appctx->t, TASK_WOKEN_OTHER);
}
-/* Callback used to wake up an applet when a buffer is available. The applet
- * <appctx> is woken up is if it is not already in the list of "active"
- * applets. This functions returns 1 is the stream is woken up, otherwise it
- * returns 0. If task is running we request we check if woken was already
- * requested */
-static inline int appctx_res_wakeup(struct appctx *appctx)
-{
- int ret;
-
- /* To detect if we have already been waken or not, we now that
- * if the state contains TASK_RUNNING, but not just TASK_RUNNING.
- * This is racy, but that's OK. At worst we will wake a little more
- * tasks than necessary when a buffer is available.
- */
- ret = ((appctx->state & TASK_RUNNING) != 0) &&
- ((appctx->state != TASK_RUNNING));
- task_wakeup(appctx->t, TASK_WOKEN_OTHER);
- return ret;
-}
-
-
#endif /* _PROTO_APPLET_H */
/*
unsigned int nb_applets = 0;
+/* Callback used to wake up an applet when a buffer is available. The applet
+ * <appctx> is woken up if an input buffer was requested for the associated
+ * stream interface. In this case the buffer is immediately allocated and the
+ * function returns 1. Otherwise it returns 0. Note that this automatically
+ * covers multiple wake-up attempts by ensuring that the same buffer will not
+ * be accounted for multiple times.
+ */
+int appctx_buf_available(void *arg)
+{
+ struct appctx *appctx = arg;
+ struct stream_interface *si = appctx->owner;
+
+ /* allocation requested ? */
+ if (!(si->flags & SI_FL_WAIT_ROOM) || c_size(si_ic(si)) || si_ic(si)->pipe)
+ return 0;
+
+ /* allocation possible now ? */
+ if (!b_alloc_margin(&si_ic(si)->buf, global.tune.reserved_bufs))
+ return 0;
+
+ si->flags &= ~SI_FL_WAIT_ROOM;
+ task_wakeup(appctx->t, TASK_WOKEN_RES);
+ return 1;
+}
+
+/* Default applet handler */
struct task *task_run_applet(struct task *t, void *context, unsigned short state)
{
struct appctx *app = context;