diff options
-rw-r--r-- | include/litmus/ikglp_lock.h | 2 | ||||
-rw-r--r-- | litmus/ikglp_lock.c | 65 |
2 files changed, 61 insertions, 6 deletions
diff --git a/include/litmus/ikglp_lock.h b/include/litmus/ikglp_lock.h index 2558a382446c..dd4f14e4eaff 100644 --- a/include/litmus/ikglp_lock.h +++ b/include/litmus/ikglp_lock.h | |||
@@ -118,7 +118,7 @@ struct ikglp_queue_info | |||
118 | struct ikglp_affinity_ops | 118 | struct ikglp_affinity_ops |
119 | { | 119 | { |
120 | struct fifo_queue* (*advise_enqueue)(struct ikglp_affinity* aff, struct task_struct* t); // select FIFO | 120 | struct fifo_queue* (*advise_enqueue)(struct ikglp_affinity* aff, struct task_struct* t); // select FIFO |
121 | ikglp_wait_state_t* (*advise_steal)(struct ikglp_affinity* aff); // select steal from FIFO | 121 | ikglp_wait_state_t* (*advise_steal)(struct ikglp_affinity* aff, struct fifo_queue* dst); // select steal from FIFO |
122 | ikglp_donee_heap_node_t* (*advise_donee_selection)(struct ikglp_affinity* aff, struct task_struct* t); // select a donee | 122 | ikglp_donee_heap_node_t* (*advise_donee_selection)(struct ikglp_affinity* aff, struct task_struct* t); // select a donee |
123 | ikglp_wait_state_t* (*advise_doner_to_fq)(struct ikglp_affinity* aff, struct fifo_queue* dst); // select a donor to move to PQ | 123 | ikglp_wait_state_t* (*advise_doner_to_fq)(struct ikglp_affinity* aff, struct fifo_queue* dst); // select a donor to move to PQ |
124 | 124 | ||
diff --git a/litmus/ikglp_lock.c b/litmus/ikglp_lock.c index 9ae71422d813..1ce6572eddcb 100644 --- a/litmus/ikglp_lock.c +++ b/litmus/ikglp_lock.c | |||
@@ -1281,7 +1281,7 @@ int ikglp_unlock(struct litmus_lock* l) | |||
1281 | 1281 | ||
1282 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | 1282 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING |
1283 | fq_wait = (sem->aff_obs) ? | 1283 | fq_wait = (sem->aff_obs) ? |
1284 | sem->aff_obs->ops->advise_steal(sem->aff_obs) : | 1284 | sem->aff_obs->ops->advise_steal(sem->aff_obs, fq) : |
1285 | ikglp_find_hp_waiter_to_steal(sem); | 1285 | ikglp_find_hp_waiter_to_steal(sem); |
1286 | #else | 1286 | #else |
1287 | fq_wait = ikglp_find_hp_waiter_to_steal(sem); | 1287 | fq_wait = ikglp_find_hp_waiter_to_steal(sem); |
@@ -1932,7 +1932,8 @@ struct fifo_queue* gpu_ikglp_advise_enqueue(struct ikglp_affinity* aff, struct t | |||
1932 | //return(sem->shortest_fifo_queue); | 1932 | //return(sem->shortest_fifo_queue); |
1933 | } | 1933 | } |
1934 | 1934 | ||
1935 | ikglp_wait_state_t* gpu_ikglp_advise_steal(struct ikglp_affinity* aff) | 1935 | ikglp_wait_state_t* gpu_ikglp_advise_steal(struct ikglp_affinity* aff, |
1936 | struct fifo_queue* dst) | ||
1936 | { | 1937 | { |
1937 | struct ikglp_semaphore *sem = ikglp_from_lock(aff->obs.lock); | 1938 | struct ikglp_semaphore *sem = ikglp_from_lock(aff->obs.lock); |
1938 | 1939 | ||
@@ -2127,11 +2128,64 @@ out: | |||
2127 | return(donee_node); | 2128 | return(donee_node); |
2128 | } | 2129 | } |
2129 | 2130 | ||
2131 | |||
2132 | |||
2133 | static void __find_closest_donor(int target_gpu, | ||
2134 | struct binheap_node* donor_node, | ||
2135 | ikglp_wait_state_t** cur_closest, | ||
2136 | int* cur_dist) | ||
2137 | { | ||
2138 | ikglp_wait_state_t *this_donor = | ||
2139 | binheap_entry(donor_node, ikglp_wait_state_t, node); | ||
2140 | |||
2141 | int this_dist = | ||
2142 | gpu_migration_distance(target_gpu, tsk_rt(this_donor->task)->last_gpu); | ||
2143 | |||
2144 | if(this_dist < *cur_dist) { | ||
2145 | // take this donor | ||
2146 | *cur_dist = this_dist; | ||
2147 | *cur_closest = this_donor; | ||
2148 | } | ||
2149 | else if(this_dist == *cur_dist) { | ||
2150 | // priority tie-break. Even though this is a pre-order traversal, | ||
2151 | // this is a heap, not a binary tree, so we still need to do a priority | ||
2152 | // comparision. | ||
2153 | if(!(*cur_closest) || | ||
2154 | litmus->compare(this_donor->task, (*cur_closest)->task)) { | ||
2155 | *cur_dist = this_dist; | ||
2156 | *cur_closest = this_donor; | ||
2157 | } | ||
2158 | } | ||
2159 | |||
2160 | if(donor_node->left) __find_closest_donor(target_gpu, donor_node->left, cur_closest, cur_dist); | ||
2161 | if(donor_node->right) __find_closest_donor(target_gpu, donor_node->right, cur_closest, cur_dist); | ||
2162 | } | ||
2163 | |||
2130 | ikglp_wait_state_t* gpu_ikglp_advise_doner_to_fq(struct ikglp_affinity* aff, struct fifo_queue* fq) | 2164 | ikglp_wait_state_t* gpu_ikglp_advise_doner_to_fq(struct ikglp_affinity* aff, struct fifo_queue* fq) |
2131 | { | 2165 | { |
2132 | // TODO: MAKE THIS SMARTER | 2166 | // Huristic strategy: Find donor with the closest affinity to fq. |
2167 | // Tie-break on priority. | ||
2168 | |||
2169 | // We need to iterate over all the donors to do this. Unfortunatly, | ||
2170 | // our donors are organized in a heap. We'll visit each node with a | ||
2171 | // recurisve call. This is realitively safe since there are only sem->m | ||
2172 | // donors, at most. We won't recurse too deeply to have to worry about | ||
2173 | // our stack. (even with 128 CPUs, our nest depth is at most 7 deep). | ||
2174 | |||
2133 | struct ikglp_semaphore *sem = ikglp_from_lock(aff->obs.lock); | 2175 | struct ikglp_semaphore *sem = ikglp_from_lock(aff->obs.lock); |
2134 | ikglp_wait_state_t* donor = binheap_top_entry(&sem->donors, ikglp_wait_state_t, node); | 2176 | ikglp_wait_state_t *donor = NULL; |
2177 | int distance = MIG_NONE; | ||
2178 | int gpu = replica_to_gpu(aff, ikglp_get_idx(sem, fq)); | ||
2179 | ikglp_wait_state_t* default_donor = binheap_top_entry(&sem->donors, ikglp_wait_state_t, node); | ||
2180 | |||
2181 | __find_closest_donor(gpu, sem->donors.root, &donor, &distance); | ||
2182 | |||
2183 | TRACE_CUR("Selected %s/%d as donor (distance = %d) " | ||
2184 | "(non-aff wanted %s/%d)\n", | ||
2185 | donor->task->comm, donor->task->pid, | ||
2186 | distance, | ||
2187 | default_donor->task->comm, default_donor->task->pid); | ||
2188 | |||
2135 | return(donor); | 2189 | return(donor); |
2136 | } | 2190 | } |
2137 | 2191 | ||
@@ -2331,7 +2385,8 @@ struct fifo_queue* simple_gpu_ikglp_advise_enqueue(struct ikglp_affinity* aff, s | |||
2331 | return to_enqueue; | 2385 | return to_enqueue; |
2332 | } | 2386 | } |
2333 | 2387 | ||
2334 | ikglp_wait_state_t* simple_gpu_ikglp_advise_steal(struct ikglp_affinity* aff) | 2388 | ikglp_wait_state_t* simple_gpu_ikglp_advise_steal(struct ikglp_affinity* aff, |
2389 | struct fifo_queue* dst) | ||
2335 | { | 2390 | { |
2336 | struct ikglp_semaphore *sem = ikglp_from_lock(aff->obs.lock); | 2391 | struct ikglp_semaphore *sem = ikglp_from_lock(aff->obs.lock); |
2337 | // TRACE_CUR("Simple GPU ikglp advise_steal invoked\n"); | 2392 | // TRACE_CUR("Simple GPU ikglp advise_steal invoked\n"); |