!LIST_ISEMPTY(&task_per_thread[tid].task_list));
}
+/* adds list item <item> to work list <work> and wake up the associated task */
+static inline void work_list_add(struct work_list *work, struct list *item)
+{
+ LIST_ADDQ_LOCKED(&work->head, item);
+ task_wakeup(work->task, TASK_WOKEN_OTHER);
+}
+
+struct work_list *work_list_create(int nbthread,
+ struct task *(*fct)(struct task *, void *, unsigned short),
+ void *arg);
+
+void work_list_destroy(struct work_list *work, int nbthread);
+
/*
* This does 3 things :
* - wake up all expired tasks
* expire timer. The scheduler will requeue the task at the proper location.
*/
+
+/* A work_list is a thread-safe way to enqueue some work to be run on another
+ * thread. It consists of a list, a task and a general-purpose argument.
+ * A work is appended to the list by atomically adding a list element to the
+ * list and waking up the associated task, which is done using work_add(). The
+ * caller must be careful about how operations are run as it will definitely
+ * happen that the element being enqueued is processed by the other thread
+ * before the call returns. Some locking conventions between the caller and the
+ * callee might sometimes be necessary. The task is always woken up with reason
+ * TASK_WOKEN_OTHER and a context pointing to the work_list entry.
+ */
+struct work_list {
+ struct list head;
+ struct task *task;
+ void *arg;
+};
+
#endif /* _TYPES_TASK_H */
/*
activity[tid].long_rq++;
}
+/* create a work list array for <nbthread> threads, using tasks made of
+ * function <fct>. The context passed to the function will be the pointer to
+ * the thread's work list, which will contain a copy of argument <arg>. The
+ * wake up reason will be TASK_WOKEN_OTHER. The pointer to the work_list array
+ * is returned on success, otherwise NULL on failure.
+ */
+struct work_list *work_list_create(int nbthread,
+ struct task *(*fct)(struct task *, void *, unsigned short),
+ void *arg)
+{
+ struct work_list *wl;
+ int i;
+
+ wl = calloc(nbthread, sizeof(*wl));
+ if (!wl)
+ goto fail;
+
+ for (i = 0; i < nbthread; i++) {
+ LIST_INIT(&wl[i].head);
+ wl[i].task = task_new(1UL << i);
+ if (!wl[i].task)
+ goto fail;
+ wl[i].task->process = fct;
+ wl[i].task->context = &wl[i];
+ wl[i].arg = arg;
+ }
+ return wl;
+
+ fail:
+ work_list_destroy(wl, nbthread);
+ return NULL;
+}
+
+/* destroy work list <work> */
+void work_list_destroy(struct work_list *work, int nbthread)
+{
+ int t;
+
+ if (!work)
+ return;
+ for (t = 0; t < nbthread; t++)
+ task_destroy(work[t].task);
+ free(work);
+}
+
/*
* Delete every tasks before running the master polling loop
*/