Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 206229
b: refs/heads/master
c: d320c03
h: refs/heads/master
i:
  206227: 3f1ba9d
v: v3
  • Loading branch information
Tejun Heo committed Jun 29, 2010
1 parent 57b700d commit 4bbd42e
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 29 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b71ab8c2025caef8db719aa41af0ed735dc543cd
refs/heads/master: d320c03830b17af64e4547075003b1eeb274bc6c
40 changes: 29 additions & 11 deletions trunk/include/linux/workqueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,31 @@ enum {
WQ_DFL_ACTIVE = WQ_MAX_ACTIVE / 2,
};

/*
* System-wide workqueues which are always present.
*
* system_wq is the one used by schedule[_delayed]_work[_on]().
* Multi-CPU multi-threaded. There are users which expect relatively
* short queue flush time. Don't queue works which can run for too
* long.
*
* system_long_wq is similar to system_wq but may host long running
* works. Queue flushing might take relatively long.
*
* system_nrt_wq is non-reentrant and guarantees that any given work
* item is never executed in parallel by multiple CPUs. Queue
* flushing might take relatively long.
*/
extern struct workqueue_struct *system_wq;
extern struct workqueue_struct *system_long_wq;
extern struct workqueue_struct *system_nrt_wq;

extern struct workqueue_struct *
__create_workqueue_key(const char *name, unsigned int flags, int max_active,
struct lock_class_key *key, const char *lock_name);
__alloc_workqueue_key(const char *name, unsigned int flags, int max_active,
struct lock_class_key *key, const char *lock_name);

#ifdef CONFIG_LOCKDEP
#define __create_workqueue(name, flags, max_active) \
#define alloc_workqueue(name, flags, max_active) \
({ \
static struct lock_class_key __key; \
const char *__lock_name; \
Expand All @@ -247,21 +266,20 @@ __create_workqueue_key(const char *name, unsigned int flags, int max_active,
else \
__lock_name = #name; \
\
__create_workqueue_key((name), (flags), (max_active), \
&__key, __lock_name); \
__alloc_workqueue_key((name), (flags), (max_active), \
&__key, __lock_name); \
})
#else
#define __create_workqueue(name, flags, max_active) \
__create_workqueue_key((name), (flags), (max_active), NULL, NULL)
#define alloc_workqueue(name, flags, max_active) \
__alloc_workqueue_key((name), (flags), (max_active), NULL, NULL)
#endif

#define create_workqueue(name) \
__create_workqueue((name), WQ_RESCUER, 1)
alloc_workqueue((name), WQ_RESCUER, 1)
#define create_freezeable_workqueue(name) \
__create_workqueue((name), \
WQ_FREEZEABLE | WQ_SINGLE_CPU | WQ_RESCUER, 1)
alloc_workqueue((name), WQ_FREEZEABLE | WQ_SINGLE_CPU | WQ_RESCUER, 1)
#define create_singlethread_workqueue(name) \
__create_workqueue((name), WQ_SINGLE_CPU | WQ_RESCUER, 1)
alloc_workqueue((name), WQ_SINGLE_CPU | WQ_RESCUER, 1)

extern void destroy_workqueue(struct workqueue_struct *wq);

Expand Down
42 changes: 25 additions & 17 deletions trunk/kernel/workqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,13 @@ struct workqueue_struct {
#endif
};

struct workqueue_struct *system_wq __read_mostly;
struct workqueue_struct *system_long_wq __read_mostly;
struct workqueue_struct *system_nrt_wq __read_mostly;
EXPORT_SYMBOL_GPL(system_wq);
EXPORT_SYMBOL_GPL(system_long_wq);
EXPORT_SYMBOL_GPL(system_nrt_wq);

#define for_each_busy_worker(worker, i, pos, gcwq) \
for (i = 0; i < BUSY_WORKER_HASH_SIZE; i++) \
hlist_for_each_entry(worker, pos, &gcwq->busy_hash[i], hentry)
Expand Down Expand Up @@ -2306,8 +2313,6 @@ int cancel_delayed_work_sync(struct delayed_work *dwork)
}
EXPORT_SYMBOL(cancel_delayed_work_sync);

static struct workqueue_struct *keventd_wq __read_mostly;

/**
* schedule_work - put work task in global workqueue
* @work: job to be done
Expand All @@ -2321,7 +2326,7 @@ static struct workqueue_struct *keventd_wq __read_mostly;
*/
int schedule_work(struct work_struct *work)
{
return queue_work(keventd_wq, work);
return queue_work(system_wq, work);
}
EXPORT_SYMBOL(schedule_work);

Expand All @@ -2334,7 +2339,7 @@ EXPORT_SYMBOL(schedule_work);
*/
int schedule_work_on(int cpu, struct work_struct *work)
{
return queue_work_on(cpu, keventd_wq, work);
return queue_work_on(cpu, system_wq, work);
}
EXPORT_SYMBOL(schedule_work_on);

Expand All @@ -2349,7 +2354,7 @@ EXPORT_SYMBOL(schedule_work_on);
int schedule_delayed_work(struct delayed_work *dwork,
unsigned long delay)
{
return queue_delayed_work(keventd_wq, dwork, delay);
return queue_delayed_work(system_wq, dwork, delay);
}
EXPORT_SYMBOL(schedule_delayed_work);

Expand Down Expand Up @@ -2382,7 +2387,7 @@ EXPORT_SYMBOL(flush_delayed_work);
int schedule_delayed_work_on(int cpu,
struct delayed_work *dwork, unsigned long delay)
{
return queue_delayed_work_on(cpu, keventd_wq, dwork, delay);
return queue_delayed_work_on(cpu, system_wq, dwork, delay);
}
EXPORT_SYMBOL(schedule_delayed_work_on);

Expand Down Expand Up @@ -2447,7 +2452,7 @@ int schedule_on_each_cpu(work_func_t func)
*/
void flush_scheduled_work(void)
{
flush_workqueue(keventd_wq);
flush_workqueue(system_wq);
}
EXPORT_SYMBOL(flush_scheduled_work);

Expand Down Expand Up @@ -2479,7 +2484,7 @@ EXPORT_SYMBOL_GPL(execute_in_process_context);

int keventd_up(void)
{
return keventd_wq != NULL;
return system_wq != NULL;
}

static struct cpu_workqueue_struct *alloc_cwqs(void)
Expand Down Expand Up @@ -2539,15 +2544,16 @@ static int wq_clamp_max_active(int max_active, const char *name)
return clamp_val(max_active, 1, WQ_MAX_ACTIVE);
}

struct workqueue_struct *__create_workqueue_key(const char *name,
unsigned int flags,
int max_active,
struct lock_class_key *key,
const char *lock_name)
struct workqueue_struct *__alloc_workqueue_key(const char *name,
unsigned int flags,
int max_active,
struct lock_class_key *key,
const char *lock_name)
{
struct workqueue_struct *wq;
unsigned int cpu;

max_active = max_active ?: WQ_DFL_ACTIVE;
max_active = wq_clamp_max_active(max_active, name);

wq = kzalloc(sizeof(*wq), GFP_KERNEL);
Expand Down Expand Up @@ -2626,7 +2632,7 @@ struct workqueue_struct *__create_workqueue_key(const char *name,
}
return NULL;
}
EXPORT_SYMBOL_GPL(__create_workqueue_key);
EXPORT_SYMBOL_GPL(__alloc_workqueue_key);

/**
* destroy_workqueue - safely terminate a workqueue
Expand Down Expand Up @@ -2910,7 +2916,7 @@ static int __cpuinit trustee_thread(void *__gcwq)
continue;

debug_work_activate(rebind_work);
insert_work(get_cwq(gcwq->cpu, keventd_wq), rebind_work,
insert_work(get_cwq(gcwq->cpu, system_wq), rebind_work,
worker->scheduled.next,
work_color_to_flags(WORK_NO_COLOR));
}
Expand Down Expand Up @@ -3287,6 +3293,8 @@ void __init init_workqueues(void)
spin_unlock_irq(&gcwq->lock);
}

keventd_wq = __create_workqueue("events", 0, WQ_DFL_ACTIVE);
BUG_ON(!keventd_wq);
system_wq = alloc_workqueue("events", 0, 0);
system_long_wq = alloc_workqueue("events_long", 0, 0);
system_nrt_wq = alloc_workqueue("events_nrt", WQ_NON_REENTRANT, 0);
BUG_ON(!system_wq || !system_long_wq || !system_nrt_wq);
}

0 comments on commit 4bbd42e

Please sign in to comment.