+ tv_add(now, &(struct timeval)EMBRACE(0, 200 * 1000),
+ &a->restart_barrier);
+}
+
+static void writer_cleanup(struct writer_node *wn)
+{
+ struct writer *w;
+
+ if (!wn)
+ return;
+ w = writers + wn->writer_num;
+ PARA_INFO_LOG("closing %s\n", writer_names[wn->writer_num]);
+ w->close(wn);
+ btr_free_node(wn->btrn);
+}
+
+static void close_writers(struct slot_info *s)
+{
+ struct audio_format_info *a;
+ int i;
+
+ if (s->format < 0)
+ return;
+ assert(s->wns);
+ a = afi + s->format;
+ if (a->num_writers == 0)
+ writer_cleanup(s->wns);
+ else {
+ for (i = 0; i < a->num_writers; i++)
+ writer_cleanup(s->wns + i);
+ }
+ free(s->wns);
+ s->wns = NULL;
+}
+
+static void close_filters(struct slot_info *s)
+{
+ int i;
+ struct audio_format_info *a = afi + s->format;
+ if (a->num_filters == 0)
+ return;
+ for (i = 0; i < a->num_filters; i++) {
+ struct filter_node *fn = s->fns + i;
+ struct filter *f;
+
+ if (!fn)
+ continue;
+ f = filters + fn->filter_num;
+ if (f->close)
+ f->close(fn);
+ btr_free_node(fn->btrn);
+ }
+ free(s->fns);
+ s->fns = NULL;
+}
+
+/*
+ * Whenever a task commits suicide by returning from post_select with t->error
+ * < 0, it also removes its btr node. We do exactly that to kill a running
+ * task. Note that the scheduler checks t->error also _before_ each pre/post
+ * select call, so the victim will never be scheduled again.
+ */
+static void kill_btrn(struct btr_node *btrn, struct task *t, int error)
+{
+ if (t->error < 0)
+ return;
+ t->error = error;
+ btr_remove_node(btrn);