[MEDIUM] indicate a reason for a task wakeup

It's very frequent to require some information about the
reason why a task is running. Some flags have been added
so that a task now knows if it got woken up due to I/O
completion, timeout, etc...
This commit is contained in:
Willy Tarreau 2008-08-29 18:19:04 +02:00
parent 75cf17ee30
commit fdccded0e8
8 changed files with 38 additions and 23 deletions

View File

@ -40,13 +40,14 @@ extern struct task *last_timer; /* optimization: last queued timer */
/* perform minimal initializations, report 0 in case of error, 1 if OK. */ /* perform minimal initializations, report 0 in case of error, 1 if OK. */
int init_task(); int init_task();
/* puts the task <t> in run queue <q>, and returns <t> */ /* puts the task <t> in run queue with reason flags <f>, and returns <t> */
struct task *__task_wakeup(struct task *t); struct task *__task_wakeup(struct task *t);
static inline struct task *task_wakeup(struct task *t) static inline struct task *task_wakeup(struct task *t, unsigned int f)
{ {
if (t->state == TASK_RUNNING) if (likely(!(t->state & TASK_IN_RUNQUEUE)))
return t; __task_wakeup(t);
return __task_wakeup(t); t->state |= f;
return t;
} }
/* removes the task <t> from the run queue if it was in it. /* removes the task <t> from the run queue if it was in it.
@ -54,8 +55,8 @@ static inline struct task *task_wakeup(struct task *t)
*/ */
static inline struct task *task_sleep(struct task *t) static inline struct task *task_sleep(struct task *t)
{ {
if (t->state == TASK_RUNNING) { if (t->state & TASK_IN_RUNQUEUE) {
t->state = TASK_IDLE; t->state = TASK_SLEEPING;
eb32_delete(&t->eb); eb32_delete(&t->eb);
run_queue--; run_queue--;
if (likely(t->nice)) if (likely(t->nice))
@ -87,7 +88,7 @@ static inline struct task *task_dequeue(struct task *t)
static inline struct task *task_delete(struct task *t) static inline struct task *task_delete(struct task *t)
{ {
task_dequeue(t); task_dequeue(t);
if (t->state == TASK_RUNNING) { if (t->state & TASK_IN_RUNQUEUE) {
run_queue--; run_queue--;
if (likely(t->nice)) if (likely(t->nice))
niced_tasks--; niced_tasks--;
@ -102,7 +103,7 @@ static inline struct task *task_delete(struct task *t)
static inline struct task *task_init(struct task *t) static inline struct task *task_init(struct task *t)
{ {
t->eb.node.leaf_p = NULL; t->eb.node.leaf_p = NULL;
t->state = TASK_IDLE; t->state = TASK_SLEEPING;
t->nice = 0; t->nice = 0;
return t; return t;
} }

View File

@ -29,13 +29,25 @@
#include <common/mini-clist.h> #include <common/mini-clist.h>
/* values for task->state */ /* values for task->state */
#define TASK_IDLE 0 #define TASK_SLEEPING 0x00 /* task sleeping */
#define TASK_RUNNING 1 #define TASK_IN_RUNQUEUE 0x01 /* the task is in the run queue */
#define TASK_WOKEN_INIT 0x02 /* woken up for initialisation purposes */
#define TASK_WOKEN_TIMER 0x04 /* woken up because of expired timer */
#define TASK_WOKEN_IO 0x08 /* woken up because of completed I/O */
#define TASK_WOKEN_SIGNAL 0x10 /* woken up by a system signal */
#define TASK_WOKEN_MSG 0x20 /* woken up by another task's message */
#define TASK_WOKEN_RES 0x40 /* woken up because of available resource */
#define TASK_WOKEN_OTHER 0x80 /* woken up for an unspecified reason */
/* use this to check a task state or to clean it up before queueing */
#define TASK_WOKEN_ANY (TASK_WOKEN_OTHER|TASK_WOKEN_INIT|TASK_WOKEN_TIMER| \
TASK_WOKEN_IO|TASK_WOKEN_SIGNAL|TASK_WOKEN_MSG| \
TASK_WOKEN_RES)
/* The base for all tasks */ /* The base for all tasks */
struct task { struct task {
struct eb32_node eb; /* ebtree node used to hold the task in the wait queue */ struct eb32_node eb; /* ebtree node used to hold the task in the wait queue */
int state; /* task state : IDLE or RUNNING */ int state; /* task state : bit field of TASK_* */
unsigned int expire; /* next expiration time for this task */ unsigned int expire; /* next expiration time for this task */
void (*process)(struct task *t, int *next); /* the function which processes the task */ void (*process)(struct task *t, int *next); /* the function which processes the task */
void *context; /* the task's context */ void *context; /* the task's context */

View File

@ -73,7 +73,7 @@ static int redistribute_pending(struct server *s)
sess->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET); sess->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
pendconn_free(pc); pendconn_free(pc);
task_wakeup(sess->task); task_wakeup(sess->task, TASK_WOKEN_RES);
xferred++; xferred++;
} }
} }
@ -102,7 +102,7 @@ static int check_for_pending(struct server *s)
p->sess->srv = s; p->sess->srv = s;
sess = p->sess; sess = p->sess;
pendconn_free(p); pendconn_free(p);
task_wakeup(sess->task); task_wakeup(sess->task, TASK_WOKEN_RES);
} }
return xferred; return xferred;
} }
@ -404,7 +404,7 @@ static int event_srv_chk_w(int fd)
} }
} }
out_wakeup: out_wakeup:
task_wakeup(t); task_wakeup(t, TASK_WOKEN_IO);
out_nowake: out_nowake:
EV_FD_CLR(fd, DIR_WR); /* nothing more to write */ EV_FD_CLR(fd, DIR_WR); /* nothing more to write */
fdtab[fd].ev &= ~FD_POLL_OUT; fdtab[fd].ev &= ~FD_POLL_OUT;
@ -512,7 +512,7 @@ static int event_srv_chk_r(int fd)
fdtab[fd].state = FD_STERROR; fdtab[fd].state = FD_STERROR;
EV_FD_CLR(fd, DIR_RD); EV_FD_CLR(fd, DIR_RD);
task_wakeup(t); task_wakeup(t, TASK_WOKEN_IO);
fdtab[fd].ev &= ~FD_POLL_IN; fdtab[fd].ev &= ~FD_POLL_IN;
return 1; return 1;
} }

View File

@ -409,7 +409,7 @@ int event_accept(int fd) {
* priorities to tasks. * priorities to tasks.
*/ */
if (p->mode != PR_MODE_HEALTH) if (p->mode != PR_MODE_HEALTH)
task_wakeup(t); task_wakeup(t, TASK_WOKEN_INIT);
p->feconn++; /* beconn will be increased later */ p->feconn++; /* beconn will be increased later */
if (p->feconn > p->feconn_max) if (p->feconn > p->feconn_max)

View File

@ -520,7 +520,7 @@ int uxst_event_accept(int fd) {
t->expire = s->req->rex; t->expire = s->req->rex;
} }
task_wakeup(t); task_wakeup(t, TASK_WOKEN_INIT);
l->nbconn++; /* warning! right now, it's up to the handler to decrease this */ l->nbconn++; /* warning! right now, it's up to the handler to decrease this */
if (l->nbconn >= l->maxconn) { if (l->nbconn >= l->maxconn) {

View File

@ -77,7 +77,7 @@ void process_srv_queue(struct server *s)
struct session *sess = pendconn_get_next_sess(s, p); struct session *sess = pendconn_get_next_sess(s, p);
if (sess == NULL) if (sess == NULL)
break; break;
task_wakeup(sess->task); task_wakeup(sess->task, TASK_WOKEN_RES);
} }
} }

View File

@ -239,7 +239,7 @@ int stream_sock_read(int fd) {
if (!(b->flags & BF_READ_ACTIVITY)) if (!(b->flags & BF_READ_ACTIVITY))
goto out_skip_wakeup; goto out_skip_wakeup;
out_wakeup: out_wakeup:
task_wakeup(fdtab[fd].owner); task_wakeup(fdtab[fd].owner, TASK_WOKEN_IO);
out_skip_wakeup: out_skip_wakeup:
fdtab[fd].ev &= ~FD_POLL_IN; fdtab[fd].ev &= ~FD_POLL_IN;
@ -411,7 +411,7 @@ int stream_sock_write(int fd) {
if (!(b->flags & BF_WRITE_ACTIVITY)) if (!(b->flags & BF_WRITE_ACTIVITY))
goto out_skip_wakeup; goto out_skip_wakeup;
out_wakeup: out_wakeup:
task_wakeup(fdtab[fd].owner); task_wakeup(fdtab[fd].owner, TASK_WOKEN_IO);
out_skip_wakeup: out_skip_wakeup:
fdtab[fd].ev &= ~FD_POLL_OUT; fdtab[fd].ev &= ~FD_POLL_OUT;

View File

@ -149,7 +149,8 @@ struct task *__task_wakeup(struct task *t)
t->eb.key += offset; t->eb.key += offset;
} }
t->state = TASK_RUNNING; /* clear state flags at the same time */
t->state = TASK_IN_RUNQUEUE;
eb32_insert(&rqueue[ticks_to_tree(t->eb.key)], &t->eb); eb32_insert(&rqueue[ticks_to_tree(t->eb.key)], &t->eb);
return t; return t;
@ -229,6 +230,7 @@ void wake_expired_tasks(int *next)
/* detach the task from the queue and add the task to the run queue */ /* detach the task from the queue and add the task to the run queue */
eb = eb32_next(eb); eb = eb32_next(eb);
__task_wakeup(task); __task_wakeup(task);
task->state |= TASK_WOKEN_TIMER;
} }
tree = (tree + 1) & TIMER_TREE_MASK; tree = (tree + 1) & TIMER_TREE_MASK;
} while (((tree - now_tree) & TIMER_TREE_MASK) < TIMER_TREES/2); } while (((tree - now_tree) & TIMER_TREE_MASK) < TIMER_TREES/2);
@ -286,7 +288,7 @@ void process_runnable_tasks(int *next)
run_queue--; run_queue--;
if (likely(t->nice)) if (likely(t->nice))
niced_tasks--; niced_tasks--;
t->state = TASK_IDLE; t->state &= ~TASK_IN_RUNQUEUE;
task_dequeue(t); task_dequeue(t);
t->process(t, &temp); t->process(t, &temp);