00001
00045 #ifndef WORKQUEUE_H_INCLUDED
00046 #define WORKQUEUE_H_INCLUDED
00047
00048 #include <types.h>
00049 #include <slist.h>
00050 #include <util.h>
00051 #include <interrupt.h>
00052
00054 typedef void (*workqueue_callback_t)(void *data);
00055
00057 struct workqueue_item
00058 {
00059 workqueue_callback_t callback;
00060 void *data;
00061 struct slist_node node;
00062 };
00063
00065 struct workqueue
00066 {
00067 struct slist list;
00068 };
00069
00070
00071 #ifdef __cplusplus
00072 extern "C" {
00073 #endif
00074
00075
00081 static inline void workqueue_init(struct workqueue *queue)
00082 {
00083
00084 assert(queue);
00085
00086
00087 slist_init(&queue->list);
00088 }
00089
00102 static inline void workqueue_init_item(
00103 struct workqueue_item *item,
00104 workqueue_callback_t callback,
00105 void *data)
00106 {
00107
00108 item->node.next = NULL;
00109
00110 item->callback = callback;
00111 item->data = data;
00112 }
00113
00122 static inline bool workqueue_is_empty(struct workqueue *queue)
00123 {
00124
00125 assert(queue);
00126
00127 return slist_is_empty(&queue->list);
00128 }
00129
00135 static inline bool workqueue_item_is_queued(struct workqueue_item *item)
00136 {
00137 return item->node.next != NULL;
00138 }
00139
00155 static inline void workqueue_add_item(
00156 struct workqueue *queue,
00157 struct workqueue_item *item)
00158 {
00159 unsigned long iflags;
00160
00161
00162 assert(queue);
00163 assert(item);
00164
00165 assert(item->callback);
00166
00167 assert(item->node.next == NULL);
00168
00169 iflags = cpu_irq_save();
00170 slist_insert_tail(&queue->list, &item->node);
00171 cpu_irq_restore(iflags);
00172 }
00173
00191 static inline void workqueue_add_item_safe(
00192 struct workqueue *queue,
00193 struct workqueue_item *item)
00194 {
00195 unsigned long iflags;
00196
00197
00198 assert(queue);
00199 assert(item);
00200
00201 assert(item->callback);
00202
00203 iflags = cpu_irq_save();
00204 if (!workqueue_item_is_queued(item))
00205 slist_insert_tail(&queue->list, &item->node);
00206 cpu_irq_restore(iflags);
00207 }
00208
00220 static inline struct workqueue_item *workqueue_remove_item(
00221 struct workqueue *queue)
00222 {
00223 struct workqueue_item *item;
00224 unsigned long iflags;
00225
00226
00227 assert(queue);
00228
00229 iflags = cpu_irq_save();
00230 if (!workqueue_is_empty(queue)) {
00231 item = slist_pop_head(&queue->list, struct workqueue_item, node);
00232
00233 item->node.next = NULL;
00234 } else {
00235 item = NULL;
00236 }
00237 cpu_irq_restore(iflags);
00238
00239 return item;
00240 }
00241
00251 inline static void workqueue_move_item(
00252 struct workqueue *source,
00253 struct workqueue *dest)
00254 {
00255
00256 assert(source);
00257 assert(dest);
00258
00259
00260 workqueue_add_item(dest, workqueue_remove_item(source));
00261 }
00262
00269 inline static void *workqueue_get_data(struct workqueue_item *item)
00270 {
00271 assert(item);
00272
00273 return item->data;
00274 }
00275
00276
00287 inline static void workqueue_do_one_item(struct workqueue *queue)
00288 {
00289 struct workqueue_item *item;
00290
00291
00292 assert(queue);
00293
00294
00295 item = workqueue_remove_item(queue);
00296 if (item)
00297 item->callback(workqueue_get_data(item));
00298 }
00299
00300
00301 #ifdef __cplusplus
00302 }
00303 #endif
00304
00305
00306 #endif