btr_remove_node(btrnp);
}
-static void kill_all_decoders(int error)
+static void notify_receivers(int error)
{
int i;
continue;
if (!s->receiver_node)
continue;
- kill_btrn(&s->receiver_node->btrn, &s->receiver_node->task,
- error);
+ task_notify(&s->receiver_node->task, error);
}
}
try_to_close_slot(i);
if (audiod_status != AUDIOD_ON ||
!(stat_task->vss_status & VSS_STATUS_FLAG_PLAYING))
- return kill_all_decoders(-E_NOT_PLAYING);
+ return notify_receivers(E_NOT_PLAYING);
if (!must_start_decoder())
return;
ret = open_receiver(stat_task->current_audio_format_num);
unregister_task(t);
continue;
}
+ if (t->notification != 0) {
+ sched_min_delay(s);
+ break;
+ }
if (!t->pre_select)
continue;
t->pre_select(s, t);
if (t->error >= 0)
call_post_select(s, t);
// PARA_INFO_LOG("%s: %d\n", t->status, t->ret);
+ t->notification = 0;
if (t->error >= 0)
continue;
/*
void register_task(struct sched *s, struct task *t)
{
PARA_INFO_LOG("registering %s (%p)\n", t->status, t);
+ t->notification = 0;
if (!s->pre_select_list.next)
INIT_LIST_HEAD(&s->pre_select_list);
if (!s->post_select_list.next)
return msg;
}
+/**
+ * Set the notification value of a task.
+ *
+ * \param t The task to notify.
+ * \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
+ * 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
+ * taks are immediately called again.
+ *
+ * The notification for a task is reset after the call to its post_select
+ * method.
+ *
+ * \sa \ref task_get_notification().
+ */
+void task_notify(struct task *t, int err)
+{
+ assert(err > 0);
+ if (t->notification == -err) /* ignore subsequent notifications */
+ return;
+ PARA_INFO_LOG("notifying task %s: %s\n", t->status, para_strerror(err));
+ t->notification = -err;
+}
+
+/**
+ * Return the notification value of a task.
+ *
+ * \param t The task to get the notification value from.
+ *
+ * \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.
+ *
+ * \sa \ref task_notify().
+ */
+int task_get_notification(struct task *t)
+{
+ return t->notification;
+}
+
/**
* Set the select timeout to the minimal possible value.
*
struct list_head post_select_node;
/** Descriptive text and current status of the task. */
char status[255];
+ /** If less than zero, the task was notified by another task. */
+ int notification;
};
/**
void register_task(struct sched *s, struct task *t);
int schedule(struct sched *s);
char *get_task_list(struct sched *s);
+void task_notify(struct task *t, int err);
void sched_shutdown(struct sched *s);
+int task_get_notification(struct task *t);
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);