diff options
Diffstat (limited to 'kernel/workqueue.c')
| -rw-r--r-- | kernel/workqueue.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/kernel/workqueue.c b/kernel/workqueue.c index e163e7a7f5e5..56814902bc56 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -1514,6 +1514,90 @@ bool queue_work_on(int cpu, struct workqueue_struct *wq, | |||
| 1514 | } | 1514 | } |
| 1515 | EXPORT_SYMBOL(queue_work_on); | 1515 | EXPORT_SYMBOL(queue_work_on); |
| 1516 | 1516 | ||
| 1517 | /** | ||
| 1518 | * workqueue_select_cpu_near - Select a CPU based on NUMA node | ||
| 1519 | * @node: NUMA node ID that we want to select a CPU from | ||
| 1520 | * | ||
| 1521 | * This function will attempt to find a "random" cpu available on a given | ||
| 1522 | * node. If there are no CPUs available on the given node it will return | ||
| 1523 | * WORK_CPU_UNBOUND indicating that we should just schedule to any | ||
| 1524 | * available CPU if we need to schedule this work. | ||
| 1525 | */ | ||
| 1526 | static int workqueue_select_cpu_near(int node) | ||
| 1527 | { | ||
| 1528 | int cpu; | ||
| 1529 | |||
| 1530 | /* No point in doing this if NUMA isn't enabled for workqueues */ | ||
| 1531 | if (!wq_numa_enabled) | ||
| 1532 | return WORK_CPU_UNBOUND; | ||
| 1533 | |||
| 1534 | /* Delay binding to CPU if node is not valid or online */ | ||
| 1535 | if (node < 0 || node >= MAX_NUMNODES || !node_online(node)) | ||
| 1536 | return WORK_CPU_UNBOUND; | ||
| 1537 | |||
| 1538 | /* Use local node/cpu if we are already there */ | ||
| 1539 | cpu = raw_smp_processor_id(); | ||
| 1540 | if (node == cpu_to_node(cpu)) | ||
| 1541 | return cpu; | ||
| 1542 | |||
| 1543 | /* Use "random" otherwise know as "first" online CPU of node */ | ||
| 1544 | cpu = cpumask_any_and(cpumask_of_node(node), cpu_online_mask); | ||
| 1545 | |||
| 1546 | /* If CPU is valid return that, otherwise just defer */ | ||
| 1547 | return cpu < nr_cpu_ids ? cpu : WORK_CPU_UNBOUND; | ||
| 1548 | } | ||
| 1549 | |||
| 1550 | /** | ||
| 1551 | * queue_work_node - queue work on a "random" cpu for a given NUMA node | ||
| 1552 | * @node: NUMA node that we are targeting the work for | ||
| 1553 | * @wq: workqueue to use | ||
| 1554 | * @work: work to queue | ||
| 1555 | * | ||
| 1556 | * We queue the work to a "random" CPU within a given NUMA node. The basic | ||
| 1557 | * idea here is to provide a way to somehow associate work with a given | ||
| 1558 | * NUMA node. | ||
| 1559 | * | ||
| 1560 | * This function will only make a best effort attempt at getting this onto | ||
| 1561 | * the right NUMA node. If no node is requested or the requested node is | ||
| 1562 | * offline then we just fall back to standard queue_work behavior. | ||
| 1563 | * | ||
| 1564 | * Currently the "random" CPU ends up being the first available CPU in the | ||
| 1565 | * intersection of cpu_online_mask and the cpumask of the node, unless we | ||
| 1566 | * are running on the node. In that case we just use the current CPU. | ||
| 1567 | * | ||
| 1568 | * Return: %false if @work was already on a queue, %true otherwise. | ||
| 1569 | */ | ||
| 1570 | bool queue_work_node(int node, struct workqueue_struct *wq, | ||
| 1571 | struct work_struct *work) | ||
| 1572 | { | ||
| 1573 | unsigned long flags; | ||
| 1574 | bool ret = false; | ||
| 1575 | |||
| 1576 | /* | ||
| 1577 | * This current implementation is specific to unbound workqueues. | ||
| 1578 | * Specifically we only return the first available CPU for a given | ||
| 1579 | * node instead of cycling through individual CPUs within the node. | ||
| 1580 | * | ||
| 1581 | * If this is used with a per-cpu workqueue then the logic in | ||
| 1582 | * workqueue_select_cpu_near would need to be updated to allow for | ||
| 1583 | * some round robin type logic. | ||
| 1584 | */ | ||
| 1585 | WARN_ON_ONCE(!(wq->flags & WQ_UNBOUND)); | ||
| 1586 | |||
| 1587 | local_irq_save(flags); | ||
| 1588 | |||
| 1589 | if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) { | ||
| 1590 | int cpu = workqueue_select_cpu_near(node); | ||
| 1591 | |||
| 1592 | __queue_work(cpu, wq, work); | ||
| 1593 | ret = true; | ||
| 1594 | } | ||
| 1595 | |||
| 1596 | local_irq_restore(flags); | ||
| 1597 | return ret; | ||
| 1598 | } | ||
| 1599 | EXPORT_SYMBOL_GPL(queue_work_node); | ||
| 1600 | |||
| 1517 | void delayed_work_timer_fn(struct timer_list *t) | 1601 | void delayed_work_timer_fn(struct timer_list *t) |
| 1518 | { | 1602 | { |
| 1519 | struct delayed_work *dwork = from_timer(dwork, t, timer); | 1603 | struct delayed_work *dwork = from_timer(dwork, t, timer); |
