X-Git-Url: https://git.liburcu.org/?a=blobdiff_plain;f=urcu%2Fworkqueue-fifo.h;h=e2dd72f0c1dc66c47069c8b1f7292ff74938ee5c;hb=b19099feed421e7f4c97b207f0f7779c5eae5b52;hp=13d9278a5beca9baa46ea9ef3cc7f3b1981091e0;hpb=8a2c74fefc366e219bc09c4a4ebd7bacd5cb83e5;p=urcu.git diff --git a/urcu/workqueue-fifo.h b/urcu/workqueue-fifo.h index 13d9278..e2dd72f 100644 --- a/urcu/workqueue-fifo.h +++ b/urcu/workqueue-fifo.h @@ -67,7 +67,9 @@ struct urcu_workqueue { /* Maximum number of work entries (approximate). 0 means infinite. */ unsigned long nr_work_max; unsigned long nr_work; /* Current number of work items */ - bool shutdown; /* Shutdown performed */ + + int worker_flags; /* Worker flags */ + int shutdown; /* Shutdown performed */ }; struct urcu_worker { @@ -91,7 +93,8 @@ enum urcu_worker_flags { static inline void urcu_workqueue_init(struct urcu_workqueue *queue, - unsigned long max_queue_len) + unsigned long max_queue_len, + int worker_flags) { __cds_wfcq_init(&queue->head, &queue->tail); urcu_wait_queue_init(&queue->waitqueue); @@ -156,14 +159,14 @@ void __urcu_workqueue_wakeup_all(struct urcu_workqueue *queue) static inline void urcu_worker_init(struct urcu_workqueue *queue, - struct urcu_worker *worker, int flags) + struct urcu_worker *worker) { cds_wfcq_init(&worker->head, &worker->tail); - worker->flags = flags; urcu_wait_node_init(&worker->wait_node, URCU_WAIT_RUNNING); worker->own = NULL; worker->wait_node.node.next = NULL; worker->queue = queue; + worker->flags = queue->worker_flags; } static inline @@ -499,4 +502,31 @@ void urcu_workqueue_shutdown(struct urcu_workqueue *queue) __urcu_workqueue_wakeup_all(queue); } +/* + * Use to let dispatcher steal work from the entire queue in case of + * stall. The "worker" parameter need to be intialized, but is usually + * not registered. + */ +static inline +bool urcu_workqueue_steal_all(struct urcu_workqueue *queue, + struct urcu_worker *worker) +{ + struct urcu_worker *sibling; + bool has_work = false; + + if (worker->flags & URCU_WORKER_STEAL) { + rcu_read_lock(); + /* Steal from each worker */ + cds_list_for_each_entry_rcu(sibling, &queue->sibling_head, + sibling_node) + has_work |= ___urcu_grab_work(worker, &sibling->head, + &sibling->tail, 1); + rcu_read_unlock(); + } + + /* Steal from global workqueue */ + has_work |= ___urcu_grab_work(worker, &queue->head, &queue->tail, 0); + return has_work; +} + #endif /* _URCU_WORKQUEUE_FIFO_H */