aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/async.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/async.c')
-rw-r--r--kernel/async.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/kernel/async.c b/kernel/async.c
index a1d585c351d6..6f34904a0b53 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -86,18 +86,27 @@ static atomic_t entry_count;
86 */ 86 */
87static async_cookie_t __lowest_in_progress(struct async_domain *running) 87static async_cookie_t __lowest_in_progress(struct async_domain *running)
88{ 88{
89 async_cookie_t first_running = next_cookie; /* infinity value */
90 async_cookie_t first_pending = next_cookie; /* ditto */
89 struct async_entry *entry; 91 struct async_entry *entry;
90 92
93 /*
94 * Both running and pending lists are sorted but not disjoint.
95 * Take the first cookies from both and return the min.
96 */
91 if (!list_empty(&running->domain)) { 97 if (!list_empty(&running->domain)) {
92 entry = list_first_entry(&running->domain, typeof(*entry), list); 98 entry = list_first_entry(&running->domain, typeof(*entry), list);
93 return entry->cookie; 99 first_running = entry->cookie;
94 } 100 }
95 101
96 list_for_each_entry(entry, &async_pending, list) 102 list_for_each_entry(entry, &async_pending, list) {
97 if (entry->running == running) 103 if (entry->running == running) {
98 return entry->cookie; 104 first_pending = entry->cookie;
105 break;
106 }
107 }
99 108
100 return next_cookie; /* "infinity" value */ 109 return min(first_running, first_pending);
101} 110}
102 111
103static async_cookie_t lowest_in_progress(struct async_domain *running) 112static async_cookie_t lowest_in_progress(struct async_domain *running)
@@ -118,13 +127,17 @@ static void async_run_entry_fn(struct work_struct *work)
118{ 127{
119 struct async_entry *entry = 128 struct async_entry *entry =
120 container_of(work, struct async_entry, work); 129 container_of(work, struct async_entry, work);
130 struct async_entry *pos;
121 unsigned long flags; 131 unsigned long flags;
122 ktime_t uninitialized_var(calltime), delta, rettime; 132 ktime_t uninitialized_var(calltime), delta, rettime;
123 struct async_domain *running = entry->running; 133 struct async_domain *running = entry->running;
124 134
125 /* 1) move self to the running queue */ 135 /* 1) move self to the running queue, make sure it stays sorted */
126 spin_lock_irqsave(&async_lock, flags); 136 spin_lock_irqsave(&async_lock, flags);
127 list_move_tail(&entry->list, &running->domain); 137 list_for_each_entry_reverse(pos, &running->domain, list)
138 if (entry->cookie < pos->cookie)
139 break;
140 list_move_tail(&entry->list, &pos->list);
128 spin_unlock_irqrestore(&async_lock, flags); 141 spin_unlock_irqrestore(&async_lock, flags);
129 142
130 /* 2) run (and print duration) */ 143 /* 2) run (and print duration) */