Re: [PATCH] sched/kthread: Complain loudly when others violate ourflags

From: Peter Zijlstra
Date: Fri Sep 30 2011 - 05:23:43 EST





> static void flush_gcwq(struct global_cwq *gcwq)
> {
> struct work_struct *work, *nw;
> struct worker *worker, *n;
> LIST_HEAD(non_affine_works);
>
> spin_lock_irq(&gcwq->lock);
> list_for_each_entry_safe(work, nw, &gcwq->worklist, entry) {
> struct workqueue_struct *wq = get_work_cwq(work)->wq;
>
> if (wq->flags & WQ_NON_AFFINE)
> list_move(&work->entry, &non_affine_works);
> }
>
> while (!list_empty(&gcwq->worklist)) {
> int nr_works = 0;
>
> list_for_each_entry(work, &gcwq->worklist, entry) {
> send_mayday(work);
> nr_works++;
> }
>
> list_for_each_entry(worker, &gcwq->idle_list, entry) {
> if (!nr_works--)
> break;
> wake_up_process(worker->task);
> }
>
> spin_unlock_irq(&gcwq->lock);
>
> if (need_to_create_worker(gcwq)) {
> worker = create_worker(gcwq, true);
> if (worker)
> start_worker(worker);
> }
>
> wait_event_timeout(gcwq->idle_wait,
> gcwq->nr_idle == gcwq->nr_workers, HZ/10);
>
> spin_lock_irq(&gcwq->lock);
> }

We could probably replace that loop with one of the flush/barrier
thingies, but I got lost and wanted to post something. Using a proper
flush would also get rid of that icky waitqueue.

>
> WARN_ON(gcwq->nr_workers != gcwq->nr_idle);
>
> list_for_each_entry_safe(worker, n, &gcwq->idle_list, entry)
> destroy_worker(worker);
>
> WARN_ON(gcwq->nr_workers || gcwq->nr_idle);
>
> spin_unlock_irq(&gcwq->lock);
>
> gcwq = get_gcwq(get_cpu());
> spin_lock_irq(&gcwq->lock);
> list_for_each_entry_safe(work, nw, &non_affine_works, entry) {
> list_del_init(&work->entry);
> ___queue_work(get_work_cwq(work)->wq, gcwq, work);
> }
> spin_unlock_irq(&gcwq->lock);
> put_cpu();
> }
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/