Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 210279
b: refs/heads/master
c: 8a2e8e5
h: refs/heads/master
i:
  210277: fce57e1
  210275: 505d78d
  210271: f9009b9
v: v3
  • Loading branch information
Tejun Heo committed Aug 25, 2010
1 parent a5b56b1 commit fe2322f
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 18 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: e41e704bc4f49057fc68b643108366e6e6781aa3
refs/heads/master: 8a2e8e5dec7e29c56a46ba176c664ab6a3d04118
16 changes: 9 additions & 7 deletions trunk/include/linux/workqueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,20 @@ typedef void (*work_func_t)(struct work_struct *work);

enum {
WORK_STRUCT_PENDING_BIT = 0, /* work item is pending execution */
WORK_STRUCT_CWQ_BIT = 1, /* data points to cwq */
WORK_STRUCT_LINKED_BIT = 2, /* next work is linked to this one */
WORK_STRUCT_DELAYED_BIT = 1, /* work item is delayed */
WORK_STRUCT_CWQ_BIT = 2, /* data points to cwq */
WORK_STRUCT_LINKED_BIT = 3, /* next work is linked to this one */
#ifdef CONFIG_DEBUG_OBJECTS_WORK
WORK_STRUCT_STATIC_BIT = 3, /* static initializer (debugobjects) */
WORK_STRUCT_COLOR_SHIFT = 4, /* color for workqueue flushing */
WORK_STRUCT_STATIC_BIT = 4, /* static initializer (debugobjects) */
WORK_STRUCT_COLOR_SHIFT = 5, /* color for workqueue flushing */
#else
WORK_STRUCT_COLOR_SHIFT = 3, /* color for workqueue flushing */
WORK_STRUCT_COLOR_SHIFT = 4, /* color for workqueue flushing */
#endif

WORK_STRUCT_COLOR_BITS = 4,

WORK_STRUCT_PENDING = 1 << WORK_STRUCT_PENDING_BIT,
WORK_STRUCT_DELAYED = 1 << WORK_STRUCT_DELAYED_BIT,
WORK_STRUCT_CWQ = 1 << WORK_STRUCT_CWQ_BIT,
WORK_STRUCT_LINKED = 1 << WORK_STRUCT_LINKED_BIT,
#ifdef CONFIG_DEBUG_OBJECTS_WORK
Expand All @@ -59,8 +61,8 @@ enum {

/*
* Reserve 7 bits off of cwq pointer w/ debugobjects turned
* off. This makes cwqs aligned to 128 bytes which isn't too
* excessive while allowing 15 workqueue flush colors.
* off. This makes cwqs aligned to 256 bytes and allows 15
* workqueue flush colors.
*/
WORK_STRUCT_FLAG_BITS = WORK_STRUCT_COLOR_SHIFT +
WORK_STRUCT_COLOR_BITS,
Expand Down
30 changes: 20 additions & 10 deletions trunk/kernel/workqueue.c
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,7 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
struct global_cwq *gcwq;
struct cpu_workqueue_struct *cwq;
struct list_head *worklist;
unsigned int work_flags;
unsigned long flags;

debug_work_activate(work);
Expand Down Expand Up @@ -990,14 +991,17 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq,
BUG_ON(!list_empty(&work->entry));

cwq->nr_in_flight[cwq->work_color]++;
work_flags = work_color_to_flags(cwq->work_color);

if (likely(cwq->nr_active < cwq->max_active)) {
cwq->nr_active++;
worklist = gcwq_determine_ins_pos(gcwq, cwq);
} else
} else {
work_flags |= WORK_STRUCT_DELAYED;
worklist = &cwq->delayed_works;
}

insert_work(cwq, work, worklist, work_color_to_flags(cwq->work_color));
insert_work(cwq, work, worklist, work_flags);

spin_unlock_irqrestore(&gcwq->lock, flags);
}
Expand Down Expand Up @@ -1666,33 +1670,38 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq)
struct list_head *pos = gcwq_determine_ins_pos(cwq->gcwq, cwq);

move_linked_works(work, pos, NULL);
__clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work));
cwq->nr_active++;
}

/**
* cwq_dec_nr_in_flight - decrement cwq's nr_in_flight
* @cwq: cwq of interest
* @color: color of work which left the queue
* @delayed: for a delayed work
*
* A work either has completed or is removed from pending queue,
* decrement nr_in_flight of its cwq and handle workqueue flushing.
*
* CONTEXT:
* spin_lock_irq(gcwq->lock).
*/
static void cwq_dec_nr_in_flight(struct cpu_workqueue_struct *cwq, int color)
static void cwq_dec_nr_in_flight(struct cpu_workqueue_struct *cwq, int color,
bool delayed)
{
/* ignore uncolored works */
if (color == WORK_NO_COLOR)
return;

cwq->nr_in_flight[color]--;
cwq->nr_active--;

if (!list_empty(&cwq->delayed_works)) {
/* one down, submit a delayed one */
if (cwq->nr_active < cwq->max_active)
cwq_activate_first_delayed(cwq);
if (!delayed) {
cwq->nr_active--;
if (!list_empty(&cwq->delayed_works)) {
/* one down, submit a delayed one */
if (cwq->nr_active < cwq->max_active)
cwq_activate_first_delayed(cwq);
}
}

/* is flush in progress and are we at the flushing tip? */
Expand Down Expand Up @@ -1823,7 +1832,7 @@ __acquires(&gcwq->lock)
hlist_del_init(&worker->hentry);
worker->current_work = NULL;
worker->current_cwq = NULL;
cwq_dec_nr_in_flight(cwq, work_color);
cwq_dec_nr_in_flight(cwq, work_color, false);
}

/**
Expand Down Expand Up @@ -2388,7 +2397,8 @@ static int try_to_grab_pending(struct work_struct *work)
debug_work_deactivate(work);
list_del_init(&work->entry);
cwq_dec_nr_in_flight(get_work_cwq(work),
get_work_color(work));
get_work_color(work),
*work_data_bits(work) & WORK_STRUCT_DELAYED);
ret = 1;
}
}
Expand Down

0 comments on commit fe2322f

Please sign in to comment.