diff options
| author | Andrew Morton <akpm@osdl.org> | 2004-03-15 15:19:41 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-03-15 15:19:41 -0800 |
| commit | 2139597d56ba1bcc7348a0f71716f9dcfbdcb848 (patch) | |
| tree | 62670017cfa65d0f4cd8bef161cb077486272ebe /kernel/workqueue.c | |
| parent | b9b52730c0c103b677e29e723ce0db878003d496 (diff) | |
[PATCH] flush_workqueue(): detect excessive nesting
Add a debug check for workqueues nested more than three deep via the
direct-run-workqueue() path.
Diffstat (limited to 'kernel/workqueue.c')
| -rw-r--r-- | kernel/workqueue.c | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 6ca72d53d9ca..9cbfa8e69ac6 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -47,6 +47,7 @@ struct cpu_workqueue_struct { struct workqueue_struct *wq; task_t *thread; + int run_depth; /* Detect run_workqueue() recursion depth */ } ____cacheline_aligned; /* @@ -129,6 +130,13 @@ static inline void run_workqueue(struct cpu_workqueue_struct *cwq) * done. */ spin_lock_irqsave(&cwq->lock, flags); + cwq->run_depth++; + if (cwq->run_depth > 3) { + /* morton gets to eat his hat */ + printk("%s: recursion depth exceeded: %d\n", + __FUNCTION__, cwq->run_depth); + dump_stack(); + } while (!list_empty(&cwq->worklist)) { struct work_struct *work = list_entry(cwq->worklist.next, struct work_struct, entry); @@ -146,6 +154,7 @@ static inline void run_workqueue(struct cpu_workqueue_struct *cwq) cwq->remove_sequence++; wake_up(&cwq->work_done); } + cwq->run_depth--; spin_unlock_irqrestore(&cwq->lock, flags); } @@ -275,6 +284,7 @@ struct workqueue_struct *create_workqueue(const char *name) wq = kmalloc(sizeof(*wq), GFP_KERNEL); if (!wq) return NULL; + memset(wq, 0, sizeof(*wq)); for (cpu = 0; cpu < NR_CPUS; cpu++) { if (!cpu_online(cpu)) |
