Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5490077 authored by Tejun Heo's avatar Tejun Heo
Browse files

workqueue: introduce WORK_OFFQ_FLAG_*



Low WORK_STRUCT_FLAG_BITS bits of work_struct->data contain
WORK_STRUCT_FLAG_* and flush color.  If the work item is queued, the
rest point to the cpu_workqueue with WORK_STRUCT_CWQ set; otherwise,
WORK_STRUCT_CWQ is clear and the bits contain the last CPU number -
either a real CPU number or one of WORK_CPU_*.

Scheduled addition of mod_delayed_work[_on]() requires an additional
flag, which is used only while a work item is off queue.  There are
more than enough bits to represent off-queue CPU number on both 32 and
64bits.  This patch introduces WORK_OFFQ_FLAG_* which occupy the lower
part of the @work->data high bits while off queue.  This patch doesn't
define any actual OFFQ flag yet.

Off-queue CPU number is now shifted by WORK_OFFQ_CPU_SHIFT, which adds
the number of bits used by OFFQ flags to WORK_STRUCT_FLAG_SHIFT, to
make room for OFFQ flags.

To avoid shift width warning with large WORK_OFFQ_FLAG_BITS, ulong
cast is added to WORK_STRUCT_NO_CPU and, just in case, BUILD_BUG_ON()
to check that there are enough bits to accomodate off-queue CPU number
is added.

This patch doesn't make any functional difference.

Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent bf4ede01
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -68,9 +68,15 @@ enum {
	WORK_STRUCT_FLAG_BITS	= WORK_STRUCT_COLOR_SHIFT +
				  WORK_STRUCT_COLOR_BITS,

	/* data contains off-queue information when !WORK_STRUCT_CWQ */
	WORK_OFFQ_FLAG_BASE	= WORK_STRUCT_FLAG_BITS,
	WORK_OFFQ_FLAG_BITS	= 0,
	WORK_OFFQ_CPU_SHIFT	= WORK_OFFQ_FLAG_BASE + WORK_OFFQ_FLAG_BITS,

	/* convenience constants */
	WORK_STRUCT_FLAG_MASK	= (1UL << WORK_STRUCT_FLAG_BITS) - 1,
	WORK_STRUCT_WQ_DATA_MASK = ~WORK_STRUCT_FLAG_MASK,
	WORK_STRUCT_NO_CPU	= WORK_CPU_NONE << WORK_STRUCT_FLAG_BITS,
	WORK_STRUCT_NO_CPU	= (unsigned long)WORK_CPU_NONE << WORK_OFFQ_CPU_SHIFT,

	/* bit mask for work_busy() return values */
	WORK_BUSY_PENDING	= 1 << 0,
+9 −5
Original line number Diff line number Diff line
@@ -533,9 +533,9 @@ static int work_next_color(int color)
}

/*
 * A work's data points to the cwq with WORK_STRUCT_CWQ set while the
 * work is on queue.  Once execution starts, WORK_STRUCT_CWQ is
 * cleared and the work data contains the cpu number it was last on.
 * While queued, %WORK_STRUCT_CWQ is set and non flag bits of a work's data
 * contain the pointer to the queued cwq.  Once execution starts, the flag
 * is cleared and the high bits contain OFFQ flags and CPU number.
 *
 * set_work_cwq(), set_work_cpu_and_clear_pending() and clear_work_data()
 * can be used to set the cwq, cpu or clear work->data.  These functions
@@ -565,7 +565,7 @@ static void set_work_cwq(struct work_struct *work,
static void set_work_cpu_and_clear_pending(struct work_struct *work,
					   unsigned int cpu)
{
	set_work_data(work, cpu << WORK_STRUCT_FLAG_BITS, 0);
	set_work_data(work, (unsigned long)cpu << WORK_OFFQ_CPU_SHIFT, 0);
}

static void clear_work_data(struct work_struct *work)
@@ -592,7 +592,7 @@ static struct global_cwq *get_work_gcwq(struct work_struct *work)
		return ((struct cpu_workqueue_struct *)
			(data & WORK_STRUCT_WQ_DATA_MASK))->pool->gcwq;

	cpu = data >> WORK_STRUCT_FLAG_BITS;
	cpu = data >> WORK_OFFQ_CPU_SHIFT;
	if (cpu == WORK_CPU_NONE)
		return NULL;

@@ -3724,6 +3724,10 @@ static int __init init_workqueues(void)
	unsigned int cpu;
	int i;

	/* make sure we have enough bits for OFFQ CPU number */
	BUILD_BUG_ON((1LU << (BITS_PER_LONG - WORK_OFFQ_CPU_SHIFT)) <
		     WORK_CPU_LAST);

	cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP);
	cpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN);