+/* Move tasks along towards death. Any tasks on dead_tasks
+ * will definitely have no remaining references in any
+ * CPU buffers at this point, because we use two lists,
+ * and to have reached the list, it must have gone through
+ * one full sync already.
+ */
+void process_task_mortuary(void)
+{
+ struct list_head * pos;
+ struct list_head * pos2;
+ struct task_struct * task;
+
+ spin_lock(&task_mortuary);
+
+ list_for_each_safe(pos, pos2, &dead_tasks) {
+ task = list_entry(pos, struct task_struct, tasks);
+ list_del(&task->tasks);
+ free_task(task);
+ }
+
+ list_for_each_safe(pos, pos2, &dying_tasks) {
+ task = list_entry(pos, struct task_struct, tasks);
+ list_del(&task->tasks);
+ list_add_tail(&task->tasks, &dead_tasks);
+ }
+
+ spin_unlock(&task_mortuary);
+}
+
+
+static void mark_done(int cpu)
+{
+ int i;
+
+ cpu_set(cpu, marked_cpus);
+
+ for_each_online_cpu(i) {
+ if (!cpu_isset(i, marked_cpus))
+ return;
+ }
+
+ /* All CPUs have been processed at least once,
+ * we can process the mortuary once
+ */
+ process_task_mortuary();
+
+ cpus_clear(marked_cpus);
+}
+
+
+/* FIXME: this is not sufficient if we implement syscall barrier backtrace
+ * traversal, the code switch to sb_sample_start at first kernel enter/exit
+ * switch so we need a fifth state and some special handling in sync_buffer()
+ */
+typedef enum {
+ sb_bt_ignore = -2,
+ sb_buffer_start,
+ sb_bt_start,
+ sb_sample_start,
+} sync_buffer_state;
+