X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=sched.h;h=ede5e67ea2ac042c5765a92e6100bc00ab47e103;hb=be5daec66f163725489f42d512659a8af5c3fd59;hp=0363f0d1f4f79b89bc30078e600db4fc3b66898c;hpb=d46fe38dcada4108ed49a0e621376df0f7913fe3;p=paraslash.git diff --git a/sched.h b/sched.h index 0363f0d1..ede5e67e 100644 --- a/sched.h +++ b/sched.h @@ -1,31 +1,101 @@ +/* Copyright (C) 2006 Andre Noll , see file COPYING. */ + +/** \file sched.h Sched and task structures and exported symbols from sched.c. */ + + +/** + * Paraslash's scheduler. + * + * Designed with KISS in mind. It maintains a list of task structures which is + * extended when a new task is registered. Each task may define a pre_monitor + * function which is called from the scheduler main loop before it calls + * poll(2). Similarly, each task must define a post_monitor function which is + * called after poll(2) returns. + * + * \sa select(2), poll(2). + */ struct sched { - struct timeval now, timeout; - int max_fileno; - fd_set rfds, wfds; - int select_ret; - struct timeval default_timeout; + /** Initial value (in milliseconds) before any pre_monitor call. */ + int default_timeout; + /** The timeout (also in milliseconds) for the next iteration. */ + int timeout; + /** Passed to poll(2). */ + struct pollfd *pfd; + /** Number of elements in the above array, passed to poll(2). */ + unsigned pfd_array_len; + /** Number of fds registered for montitoring so far. */ + unsigned num_pfds; + /** Maps fds to indices of the pfd array. */ + unsigned *pidx; + /** Mumber of elements in the above pidx array. */ + unsigned pidx_array_len; + /** If non-NULL, use this function instead of \ref xpoll(). */ + int (*poll_function)(struct pollfd *fds, nfds_t nfds, int timeout); + /** Tasks which have been registered to the scheduler. */ + struct list_head task_list; }; -struct task { - void *private_data; - unsigned flags; - int ret; - void (*pre_select)(struct sched *s, struct task *t); - void (*post_select)(struct sched *s, struct task *t); - void (*event_handler)(struct task *t); - struct list_head pre_select_node; - struct list_head post_select_node; - char status[MAXLINE]; -}; +struct task; -enum task_flags { - PRE_ADD_TAIL = 1, - POST_ADD_TAIL = 2, +/** Information that must be supplied by callers of \ref task_register(). */ +struct task_info { + /** Used for log messages and by \ref get_task_list(). */ + const char *name; + /** + * Configure watch fds and impose an upper bound on the I/O timeout. + * + * If this is not NULL, the function is called at each iteration of the + * scheduler's main loop. Its purpose is to tell the scheduler that + * certain file descriptors should be monitored for readiness for I/O. + * The function may also lower the scheduler's timeout value (but shall + * never increase it) to impose an upper bound on the waiting time in + * case no file descriptors happen to be ready. + * + * \sa \ref time.c. + */ + void (*pre_monitor)(struct sched *s, void *context); + /** + * Perform I/O on file descriptors which are ready for I/O. + * + * This mandatory hook is called after the system call which monitors + * file descriptors returns. The function should perform non-blocking + * I/O on those file descriptors which are reported as being ready. + * + * If this function returns a negative value, the scheduler unregisters + * the task. + */ + int (*post_monitor)(struct sched *s, void *context); + /** + * This pointer is saved when the task is registered. It is passed to + * ->pre_monitor() and ->post_monitor(). Usually this is a pointer to the + * struct owned by the caller which contains the task pointer. + */ + void *context; }; -void *register_task(struct task *t); -void unregister_task(struct task *t); -int sched(struct sched *s); -void init_sched(void); -char *get_task_list(void); -int kill_task(char *id); +/** + * This is set by the scheduler at the beginning of its main loop. It may be + * used (read-only) from everywhere. As none of the functions called by the + * scheduler are allowed to block, this value should be accurate enough so that + * there is no need to call clock_gettime() directly. + */ +extern const struct timeval *now; + +struct task *task_register(struct task_info *info, struct sched *s); +int schedule(struct sched *s); +void sched_shutdown(struct sched *s); +char *get_task_list(struct sched *s); +void task_notify(struct task *t, int err); +void task_notify_all(struct sched *s, int err); +int task_get_notification(const struct task *t); +int task_status(const struct task *t); +int task_reap(struct task **tptr); +void sched_min_delay(struct sched *s); +void sched_request_timeout(struct timeval *to, struct sched *s); +void sched_request_timeout_ms(long unsigned ms, struct sched *s); +int sched_request_barrier(struct timeval *barrier, struct sched *s); +int sched_request_barrier_or_min_delay(struct timeval *barrier, struct sched *s); +void sched_monitor_readfd(int fd, struct sched *s); +void sched_monitor_writefd(int fd, struct sched *s); +bool sched_read_ok(int fd, const struct sched *s); +bool sched_write_ok(int fd, const struct sched *s);