X-Git-Url: http://git.tuebingen.mpg.de/?a=blobdiff_plain;f=sched.c;h=261809c1d64aa735e8d3324a783806477d5148b0;hb=e3a7e12639c34fd86d48a072beb48add8c498d09;hp=aac8efed1bcf8d897e6aef4d07973f2babc8d4f4;hpb=2bad70d84e763b4d866d7b97dbc1cdc8e030bd45;p=paraslash.git diff --git a/sched.c b/sched.c index aac8efed..261809c1 100644 --- a/sched.c +++ b/sched.c @@ -17,9 +17,9 @@ * The possible states of a task. * * In addition to the states listed here, a task may also enter zombie state. - * This happens when its ->post_select function returns negative, the ->status + * This happens when its ->post_monitor function returns negative, the ->status * field is then set to this return value. Such tasks are not scheduled any - * more (i.e. ->pre_select() and ->post_select() are no longer called), but + * more (i.e. ->pre_monitor() and ->post_monitor() are no longer called), but * they stay on the scheduler task list until \ref task_reap() or * \ref sched_shutdown() is called. */ @@ -46,7 +46,7 @@ struct task { static struct timeval now_struct; const struct timeval *now = &now_struct; -static void sched_preselect(struct sched *s) +static void sched_pre_monitor(struct sched *s) { struct task *t, *tmp; @@ -55,8 +55,8 @@ static void sched_preselect(struct sched *s) continue; if (t->notification != 0) sched_min_delay(s); - if (t->info.pre_select) - t->info.pre_select(s, t->info.context); + if (t->info.pre_monitor) + t->info.pre_monitor(s, t->info.context); } } @@ -72,29 +72,29 @@ static void unlink_and_free_task(struct task *t) } //#define SCHED_DEBUG 1 -static inline void call_post_select(struct sched *s, struct task *t) +static inline void call_post_monitor(struct sched *s, struct task *t) { int ret; #ifndef SCHED_DEBUG - ret = t->info.post_select(s, t->info.context); + ret = t->info.post_monitor(s, t->info.context); #else struct timeval t1, t2, diff; unsigned long pst; clock_get_realtime(&t1); - ret = t->info.post_select(s, t->info.context); + ret = t->info.post_monitor(s, t->info.context); clock_get_realtime(&t2); tv_diff(&t1, &t2, &diff); pst = tv2ms(&diff); if (pst > 50) - PARA_WARNING_LOG("%s: post_select time: %lums\n", + PARA_WARNING_LOG("%s: post_monitor time: %lums\n", t->name, pst); #endif t->status = ret < 0? ret : TS_RUNNING; } -static unsigned sched_post_select(struct sched *s) +static unsigned sched_post_monitor(struct sched *s) { struct task *t, *tmp; unsigned num_running_tasks = 0; @@ -103,7 +103,7 @@ static unsigned sched_post_select(struct sched *s) if (t->status == TS_DEAD) /* task has been reaped */ unlink_and_free_task(t); else if (t->status == TS_RUNNING) { - call_post_select(s, t); /* sets t->status */ + call_post_monitor(s, t); /* sets t->status */ t->notification = 0; if (t->status == TS_RUNNING) num_running_tasks++; @@ -118,9 +118,9 @@ static unsigned sched_post_select(struct sched *s) * \param s Pointer to the scheduler struct. * * This function updates the global \a now pointer, calls all registered - * pre_select hooks which may set the timeout and add any file descriptors to - * the fd sets of \a s. Next, it calls para_select() and makes the result available - * to the registered tasks by calling their post_select hook. + * pre_monitor hooks which may set the timeout and add any file descriptors to + * the fd sets of \a s. Next, it calls para_select() and makes the result + * available to the registered tasks by calling their post_monitor hook. * * \return Zero if no more tasks are left in the task list, negative if the * select function returned an error. @@ -137,12 +137,12 @@ int schedule(struct sched *s) again: FD_ZERO(&s->rfds); FD_ZERO(&s->wfds); - s->select_timeout = s->default_timeout; + s->timeout = s->default_timeout; s->max_fileno = -1; clock_get_realtime(&now_struct); - sched_preselect(s); + sched_pre_monitor(s); ret = s->select_function(s->max_fileno + 1, &s->rfds, &s->wfds, - &s->select_timeout); + s->timeout); if (ret < 0) return ret; if (ret == 0) { @@ -156,7 +156,7 @@ again: FD_ZERO(&s->wfds); } clock_get_realtime(&now_struct); - num_running_tasks = sched_post_select(s); + num_running_tasks = sched_post_monitor(s); if (num_running_tasks == 0) return 0; goto again; @@ -197,7 +197,7 @@ int task_reap(struct task **tptr) /* * With list_for_each_entry_safe() it is only safe to remove the * _current_ list item. Since we are being called from the loop in - * schedule() via some task's ->post_select() function, freeing the + * schedule() via some task's ->post_monitor() function, freeing the * given task here would result in use-after-free bugs in schedule(). * So we only set the task status to TS_DEAD which tells schedule() to * free the task in the next iteration of its loop. @@ -241,7 +241,7 @@ struct task *task_register(struct task_info *info, struct sched *s) { struct task *t = para_malloc(sizeof(*t)); - assert(info->post_select); + assert(info->post_monitor); if (!s->task_list.next) init_list_head(&s->task_list); @@ -288,14 +288,14 @@ char *get_task_list(struct sched *s) * \param err A positive error code. * * Tasks which honor notifications are supposed to call \ref - * task_get_notification() in their post_select function and act on the + * task_get_notification() in their post_monitor function and act on the * returned notification value. * - * If the scheduler detects during its pre_select loop that at least one task - * has been notified, the loop terminates, and the post_select methods of all + * If the scheduler detects during its pre_monitor loop that at least one task + * has been notified, the loop terminates, and the post_monitor methods of all * taks are immediately called again. * - * The notification for a task is reset after the call to its post_select + * The notification for a task is reset after the call to its post_monitor * method. * * \sa \ref task_get_notification(). @@ -316,7 +316,7 @@ void task_notify(struct task *t, int err) * * \return The notification value. If this is negative, the task has been * notified by another task. Tasks are supposed to check for notifications by - * calling this function from their post_select method. + * calling this function from their post_monitor method. * * \sa \ref task_notify(). */ @@ -370,7 +370,7 @@ void task_notify_all(struct sched *s, int err) */ void sched_min_delay(struct sched *s) { - s->select_timeout.tv_sec = s->select_timeout.tv_usec = 0; + s->timeout = 0; } /** @@ -387,8 +387,9 @@ void sched_min_delay(struct sched *s) */ void sched_request_timeout(struct timeval *to, struct sched *s) { - if (tv_diff(&s->select_timeout, to, NULL) > 0) - s->select_timeout = *to; + long unsigned ms = tv2ms(to); + if (s->timeout > ms) + s->timeout = ms; } /** @@ -450,3 +451,45 @@ int sched_request_barrier_or_min_delay(struct timeval *barrier, struct sched *s) sched_request_timeout(&diff, s); return 1; } + +static void sched_fd_set(int fd, fd_set *fds, int *max_fileno) +{ + assert(fd >= 0 && fd < FD_SETSIZE); +#if 0 + { + int flags = fcntl(fd, F_GETFL); + if (!(flags & O_NONBLOCK)) { + PARA_EMERG_LOG("fd %d is a blocking file descriptor\n", fd); + exit(EXIT_FAILURE); + } + } +#endif + FD_SET(fd, fds); + *max_fileno = PARA_MAX(*max_fileno, fd); +} + +/** + * Instruct the scheduler to monitor an fd for readiness for reading. + * + * \param fd The file descriptor. + * \param s The scheduler. + * + * \sa \ref sched_monitor_writefd(). + */ +void sched_monitor_readfd(int fd, struct sched *s) +{ + sched_fd_set(fd, &s->rfds, &s->max_fileno); +} + +/** + * Instruct the scheduler to monitor an fd for readiness for writing. + * + * \param fd The file descriptor. + * \param s The scheduler. + * + * \sa \ref sched_monitor_readfd(). + */ +void sched_monitor_writefd(int fd, struct sched *s) +{ + sched_fd_set(fd, &s->wfds, &s->max_fileno); +}