Skip to content

Commit 9fdb04c

Browse files
committed
async: replace list of active domains with global list of pending items
Global synchronization - async_synchronize_full() - is currently implemented by keeping a list of all active registered domains and syncing them one by one until no domain is active. While this isn't necessarily a complex scheme, it can easily be simplified by keeping global list of the pending items of all registered active domains instead of list of domains and simply using the globl pending list the same way as domain syncing. This patch replaces async_domains with async_global_pending and update lowest_in_progress() to use the global pending list if @Domain is %NULL. async_synchronize_full_domain(NULL) is now allowed and equivalent to async_synchronize_full(). As no one is calling with NULL domain, this doesn't affect any existing users. async_register_mutex is no longer necessary and dropped. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Arjan van de Ven <arjan@linux.intel.com> Cc: Dan Williams <djbw@fb.com> Cc: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 5272279 commit 9fdb04c

1 file changed

Lines changed: 29 additions & 34 deletions

File tree

kernel/async.c

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,13 @@ static async_cookie_t next_cookie = 1;
6464
#define MAX_WORK 32768
6565
#define ASYNC_COOKIE_MAX ULLONG_MAX /* infinity cookie */
6666

67+
static LIST_HEAD(async_global_pending); /* pending from all registered doms */
6768
static ASYNC_DOMAIN(async_dfl_domain);
68-
static LIST_HEAD(async_domains);
6969
static DEFINE_SPINLOCK(async_lock);
70-
static DEFINE_MUTEX(async_register_mutex);
7170

7271
struct async_entry {
73-
struct list_head list;
72+
struct list_head domain_list;
73+
struct list_head global_list;
7474
struct work_struct work;
7575
async_cookie_t cookie;
7676
async_func_ptr *func;
@@ -84,15 +84,25 @@ static atomic_t entry_count;
8484

8585
static async_cookie_t lowest_in_progress(struct async_domain *domain)
8686
{
87+
struct async_entry *first = NULL;
8788
async_cookie_t ret = ASYNC_COOKIE_MAX;
8889
unsigned long flags;
8990

9091
spin_lock_irqsave(&async_lock, flags);
91-
if (!list_empty(&domain->pending)) {
92-
struct async_entry *first = list_first_entry(&domain->pending,
93-
struct async_entry, list);
94-
ret = first->cookie;
92+
93+
if (domain) {
94+
if (!list_empty(&domain->pending))
95+
first = list_first_entry(&domain->pending,
96+
struct async_entry, domain_list);
97+
} else {
98+
if (!list_empty(&async_global_pending))
99+
first = list_first_entry(&async_global_pending,
100+
struct async_entry, global_list);
95101
}
102+
103+
if (first)
104+
ret = first->cookie;
105+
96106
spin_unlock_irqrestore(&async_lock, flags);
97107
return ret;
98108
}
@@ -106,7 +116,6 @@ static void async_run_entry_fn(struct work_struct *work)
106116
container_of(work, struct async_entry, work);
107117
unsigned long flags;
108118
ktime_t uninitialized_var(calltime), delta, rettime;
109-
struct async_domain *domain = entry->domain;
110119

111120
/* 1) run (and print duration) */
112121
if (initcall_debug && system_state == SYSTEM_BOOTING) {
@@ -127,9 +136,8 @@ static void async_run_entry_fn(struct work_struct *work)
127136

128137
/* 2) remove self from the pending queues */
129138
spin_lock_irqsave(&async_lock, flags);
130-
list_del(&entry->list);
131-
if (domain->registered && list_empty(&domain->pending))
132-
list_del_init(&domain->node);
139+
list_del_init(&entry->domain_list);
140+
list_del_init(&entry->global_list);
133141

134142
/* 3) free the entry */
135143
kfree(entry);
@@ -170,10 +178,14 @@ static async_cookie_t __async_schedule(async_func_ptr *ptr, void *data, struct a
170178
entry->domain = domain;
171179

172180
spin_lock_irqsave(&async_lock, flags);
181+
182+
/* allocate cookie and queue */
173183
newcookie = entry->cookie = next_cookie++;
174-
if (domain->registered && list_empty(&domain->pending))
175-
list_add_tail(&domain->node, &async_domains);
176-
list_add_tail(&entry->list, &domain->pending);
184+
185+
list_add_tail(&entry->domain_list, &domain->pending);
186+
if (domain->registered)
187+
list_add_tail(&entry->global_list, &async_global_pending);
188+
177189
atomic_inc(&entry_count);
178190
spin_unlock_irqrestore(&async_lock, flags);
179191

@@ -226,18 +238,7 @@ EXPORT_SYMBOL_GPL(async_schedule_domain);
226238
*/
227239
void async_synchronize_full(void)
228240
{
229-
mutex_lock(&async_register_mutex);
230-
do {
231-
struct async_domain *domain = NULL;
232-
233-
spin_lock_irq(&async_lock);
234-
if (!list_empty(&async_domains))
235-
domain = list_first_entry(&async_domains, typeof(*domain), node);
236-
spin_unlock_irq(&async_lock);
237-
238-
async_synchronize_cookie_domain(ASYNC_COOKIE_MAX, domain);
239-
} while (!list_empty(&async_domains));
240-
mutex_unlock(&async_register_mutex);
241+
async_synchronize_full_domain(NULL);
241242
}
242243
EXPORT_SYMBOL_GPL(async_synchronize_full);
243244

@@ -252,13 +253,10 @@ EXPORT_SYMBOL_GPL(async_synchronize_full);
252253
*/
253254
void async_unregister_domain(struct async_domain *domain)
254255
{
255-
mutex_lock(&async_register_mutex);
256256
spin_lock_irq(&async_lock);
257-
WARN_ON(!domain->registered || !list_empty(&domain->node) ||
258-
!list_empty(&domain->pending));
257+
WARN_ON(!domain->registered || !list_empty(&domain->pending));
259258
domain->registered = 0;
260259
spin_unlock_irq(&async_lock);
261-
mutex_unlock(&async_register_mutex);
262260
}
263261
EXPORT_SYMBOL_GPL(async_unregister_domain);
264262

@@ -278,7 +276,7 @@ EXPORT_SYMBOL_GPL(async_synchronize_full_domain);
278276
/**
279277
* async_synchronize_cookie_domain - synchronize asynchronous function calls within a certain domain with cookie checkpointing
280278
* @cookie: async_cookie_t to use as checkpoint
281-
* @domain: the domain to synchronize
279+
* @domain: the domain to synchronize (%NULL for all registered domains)
282280
*
283281
* This function waits until all asynchronous function calls for the
284282
* synchronization domain specified by @domain submitted prior to @cookie
@@ -288,9 +286,6 @@ void async_synchronize_cookie_domain(async_cookie_t cookie, struct async_domain
288286
{
289287
ktime_t uninitialized_var(starttime), delta, endtime;
290288

291-
if (!domain)
292-
return;
293-
294289
if (initcall_debug && system_state == SYSTEM_BOOTING) {
295290
printk(KERN_DEBUG "async_waiting @ %i\n", task_pid_nr(current));
296291
starttime = ktime_get();

0 commit comments

Comments
 (0)