These shortcuts let the scheduler skip any subsequent ->pre_select()
calls as well as the actual call to select(2) if the current task's
->pre_select() requested a zero timeout.
This idea turned out to be dubios at best. The main problem is that
->post_select no longer knows whether ->pre_select() and select()
have been called. For example, if ->pre_select() monitors some file
descriptor, ->post_select() might find it not ready for I/O even when
it actually is because ->pre_select() or select() was optimized away.
Another problem are tasks whose ->post_select() method expects that
->pre_select() sets some variable in a shared data structure.
This patch removes the scheduler optimizations so that all
->pre_select() methods of all tasks are called once per scheduler
interval.
static void sched_preselect(struct sched *s)
{
struct task *t, *tmp;
static void sched_preselect(struct sched *s)
{
struct task *t, *tmp;
list_for_each_entry_safe(t, tmp, &s->pre_select_list, pre_select_node) {
list_for_each_entry_safe(t, tmp, &s->pre_select_list, pre_select_node) {
- if (t->error < 0) {
- unregister_task(t);
- continue;
- }
- if (t->notification != 0) {
+ if (t->notification != 0)
- break;
- }
- if (!t->pre_select)
- continue;
- t->pre_select(s, t);
- if (timeout_is_zero(s))
- break;
+ if (t->pre_select)
+ t->pre_select(s, t);
s->max_fileno = -1;
gettimeofday(now, NULL);
sched_preselect(s);
s->max_fileno = -1;
gettimeofday(now, NULL);
sched_preselect(s);
- if (list_empty(&s->pre_select_list) && list_empty(&s->post_select_list))
- return 0;
- if (!timeout_is_zero(s)) {
- ret = s->select_function(s->max_fileno + 1, &s->rfds, &s->wfds,
- &s->select_timeout);
- if (ret < 0)
- return ret;
- if (ret == 0) {
- /*
- * APUE: Be careful not to check the descriptor sets on return
- * unless the return value is greater than zero. The return
- * state of the descriptor sets is implementation dependent if
- * either a signal is caught or the timer expires.
- */
- FD_ZERO(&s->rfds);
- FD_ZERO(&s->wfds);
- }
- gettimeofday(now, NULL);
- } else {
+ ret = s->select_function(s->max_fileno + 1, &s->rfds, &s->wfds,
+ &s->select_timeout);
+ if (ret < 0)
+ return ret;
+ if (ret == 0) {
+ /*
+ * APUE: Be careful not to check the descriptor sets on return
+ * unless the return value is greater than zero. The return
+ * state of the descriptor sets is implementation dependent if
+ * either a signal is caught or the timer expires.
+ */
FD_ZERO(&s->rfds);
FD_ZERO(&s->wfds);
}
FD_ZERO(&s->rfds);
FD_ZERO(&s->wfds);
}
+ gettimeofday(now, NULL);
sched_post_select(s);
if (list_empty(&s->pre_select_list) && list_empty(&s->post_select_list))
return 0;
sched_post_select(s);
if (list_empty(&s->pre_select_list) && list_empty(&s->post_select_list))
return 0;