| 1 |
|
| 2 | |
| 3 | * async.h: Asynchronous function calls for boot performance
|
| 4 | *
|
| 5 | * (C) Copyright 2009 Intel Corporation
|
| 6 | * Author: Arjan van de Ven <[email protected]>
|
| 7 |
|
| 8 | #ifndef __ASYNC_H__
|
| 9 | #define __ASYNC_H__
|
| 10 |
|
| 11 | #include <linux/types.h>
|
| 12 | #include <linux/list.h>
|
| 13 | #include <linux/numa.h>
|
| 14 | #include <linux/device.h>
|
| 15 |
|
| 16 | typedef u64 async_cookie_t;
|
| 17 | typedef void (*async_func_t) (void *data, async_cookie_t cookie);
|
| 18 | struct async_domain {
|
| 19 | struct list_head pending;
|
| 20 | unsigned registered:1;
|
| 21 | };
|
| 22 |
|
| 23 | |
| 24 | * domain participates in global async_synchronize_full
|
| 25 |
|
| 26 | #define ASYNC_DOMAIN(_name) \
|
| 27 | struct async_domain _name = { .pending = LIST_HEAD_INIT(_name.pending), \
|
| 28 | .registered = 1 }
|
| 29 |
|
| 30 | |
| 31 | * domain is free to go out of scope as soon as all pending work is
|
| 32 | * complete, this domain does not participate in async_synchronize_full
|
| 33 |
|
| 34 | #define ASYNC_DOMAIN_EXCLUSIVE(_name) \
|
| 35 | struct async_domain _name = { .pending = LIST_HEAD_INIT(_name.pending), \
|
| 36 | .registered = 0 }
|
| 37 |
|
| 38 | async_cookie_t async_schedule_node(async_func_t func, void *data,
|
| 39 | int node);
|
| 40 | async_cookie_t async_schedule_node_domain(async_func_t func, void *data,
|
| 41 | int node,
|
| 42 | struct async_domain *domain);
|
| 43 |
|
| 44 | |
| 45 | * async_schedule - schedule a function for asynchronous execution
|
| 46 | * @func: function to execute asynchronously
|
| 47 | * @data: data pointer to pass to the function
|
| 48 | *
|
| 49 | * Returns an async_cookie_t that may be used for checkpointing later.
|
| 50 | * Note: This function may be called from atomic or non-atomic contexts.
|
| 51 |
|
| 52 | static inline async_cookie_t async_schedule(async_func_t func, void *data)
|
| 53 | {
|
| 54 | return async_schedule_node(func, data, NUMA_NO_NODE);
|
| 55 | }
|
| 56 |
|
| 57 | |
| 58 | * async_schedule_domain - schedule a function for asynchronous execution within a certain domain
|
| 59 | * @func: function to execute asynchronously
|
| 60 | * @data: data pointer to pass to the function
|
| 61 | * @domain: the domain
|
| 62 | *
|
| 63 | * Returns an async_cookie_t that may be used for checkpointing later.
|
| 64 | * @domain may be used in the async_synchronize_*_domain() functions to
|
| 65 | * wait within a certain synchronization domain rather than globally.
|
| 66 | * Note: This function may be called from atomic or non-atomic contexts.
|
| 67 |
|
| 68 | static inline async_cookie_t
|
| 69 | async_schedule_domain(async_func_t func, void *data,
|
| 70 | struct async_domain *domain)
|
| 71 | {
|
| 72 | return async_schedule_node_domain(func, data, NUMA_NO_NODE, domain);
|
| 73 | }
|
| 74 |
|
| 75 | |
| 76 | * async_schedule_dev - A device specific version of async_schedule
|
| 77 | * @func: function to execute asynchronously
|
| 78 | * @dev: device argument to be passed to function
|
| 79 | *
|
| 80 | * Returns an async_cookie_t that may be used for checkpointing later.
|
| 81 | * @dev is used as both the argument for the function and to provide NUMA
|
| 82 | * context for where to run the function. By doing this we can try to
|
| 83 | * provide for the best possible outcome by operating on the device on the
|
| 84 | * CPUs closest to the device.
|
| 85 | * Note: This function may be called from atomic or non-atomic contexts.
|
| 86 |
|
| 87 | static inline async_cookie_t
|
| 88 | async_schedule_dev(async_func_t func, struct device *dev)
|
| 89 | {
|
| 90 | return async_schedule_node(func, dev, dev_to_node(dev));
|
| 91 | }
|
| 92 |
|
| 93 | bool async_schedule_dev_nocall(async_func_t func, struct device *dev);
|
| 94 |
|
| 95 | |
| 96 | * async_schedule_dev_domain - A device specific version of async_schedule_domain
|
| 97 | * @func: function to execute asynchronously
|
| 98 | * @dev: device argument to be passed to function
|
| 99 | * @domain: the domain
|
| 100 | *
|
| 101 | * Returns an async_cookie_t that may be used for checkpointing later.
|
| 102 | * @dev is used as both the argument for the function and to provide NUMA
|
| 103 | * context for where to run the function. By doing this we can try to
|
| 104 | * provide for the best possible outcome by operating on the device on the
|
| 105 | * CPUs closest to the device.
|
| 106 | * @domain may be used in the async_synchronize_*_domain() functions to
|
| 107 | * wait within a certain synchronization domain rather than globally.
|
| 108 | * Note: This function may be called from atomic or non-atomic contexts.
|
| 109 |
|
| 110 | static inline async_cookie_t
|
| 111 | async_schedule_dev_domain(async_func_t func, struct device *dev,
|
| 112 | struct async_domain *domain)
|
| 113 | {
|
| 114 | return async_schedule_node_domain(func, dev, dev_to_node(dev), domain);
|
| 115 | }
|
| 116 |
|
| 117 | extern void async_synchronize_full(void);
|
| 118 | extern void async_synchronize_full_domain(struct async_domain *domain);
|
| 119 | extern void async_synchronize_cookie(async_cookie_t cookie);
|
| 120 | extern void async_synchronize_cookie_domain(async_cookie_t cookie,
|
| 121 | struct async_domain *domain);
|
| 122 | extern bool current_is_async(void);
|
| 123 | extern void async_init(void);
|
| 124 | #endif
|