aboutsummaryrefslogtreecommitdiffstats
path: root/litmus/ikglp_lock.c
diff options
context:
space:
mode:
Diffstat (limited to 'litmus/ikglp_lock.c')
-rw-r--r--litmus/ikglp_lock.c126
1 files changed, 63 insertions, 63 deletions
diff --git a/litmus/ikglp_lock.c b/litmus/ikglp_lock.c
index b7e23029b849..2b50fb1c05fd 100644
--- a/litmus/ikglp_lock.c
+++ b/litmus/ikglp_lock.c
@@ -1184,7 +1184,7 @@ int ikglp_unlock(struct litmus_lock* l)
1184 unsigned long flags = 0, real_flags; 1184 unsigned long flags = 0, real_flags;
1185 1185
1186 int err = 0; 1186 int err = 0;
1187 1187
1188#ifdef CONFIG_LITMUS_DGL_SUPPORT 1188#ifdef CONFIG_LITMUS_DGL_SUPPORT
1189 dgl_lock = litmus->get_dgl_spinlock(t); 1189 dgl_lock = litmus->get_dgl_spinlock(t);
1190#endif 1190#endif
@@ -1193,14 +1193,14 @@ int ikglp_unlock(struct litmus_lock* l)
1193 lock_global_irqsave(dgl_lock, flags); // TODO: Push this deeper 1193 lock_global_irqsave(dgl_lock, flags); // TODO: Push this deeper
1194 lock_fine_irqsave(&sem->lock, flags); 1194 lock_fine_irqsave(&sem->lock, flags);
1195 1195
1196 1196
1197 fq = ikglp_get_queue(sem, t); // returns NULL if 't' is not owner. 1197 fq = ikglp_get_queue(sem, t); // returns NULL if 't' is not owner.
1198 1198
1199 if (!fq) { 1199 if (!fq) {
1200 err = -EINVAL; 1200 err = -EINVAL;
1201 goto out; 1201 goto out;
1202 } 1202 }
1203 1203
1204 TRACE_TASK(t, "Freeing replica %d.\n", ikglp_get_idx(sem, fq)); 1204 TRACE_TASK(t, "Freeing replica %d.\n", ikglp_get_idx(sem, fq));
1205 1205
1206 1206
@@ -1900,7 +1900,7 @@ struct fifo_queue* gpu_ikglp_advise_enqueue(struct ikglp_affinity* aff, struct t
1900 (est_len < min_len) || /* i-th queue has shortest length */ 1900 (est_len < min_len) || /* i-th queue has shortest length */
1901 ((est_len == min_len) && /* equal lengths, but one has fewer over-all users */ 1901 ((est_len == min_len) && /* equal lengths, but one has fewer over-all users */
1902 (*(aff->q_info[i].nr_cur_users) < min_nr_users))) { 1902 (*(aff->q_info[i].nr_cur_users) < min_nr_users))) {
1903 1903
1904 shortest = &aff->q_info[i]; 1904 shortest = &aff->q_info[i];
1905 min_len = est_len; 1905 min_len = est_len;
1906 min_nr_users = *(aff->q_info[i].nr_cur_users); 1906 min_nr_users = *(aff->q_info[i].nr_cur_users);
@@ -1920,7 +1920,7 @@ struct fifo_queue* gpu_ikglp_advise_enqueue(struct ikglp_affinity* aff, struct t
1920 } 1920 }
1921 } 1921 }
1922 } 1922 }
1923 1923
1924 if(shortest->q->count >= sem->max_fifo_len) { 1924 if(shortest->q->count >= sem->max_fifo_len) {
1925 TRACE_CUR("selected fq %d is too long, but returning it anyway.\n", 1925 TRACE_CUR("selected fq %d is too long, but returning it anyway.\n",
1926 ikglp_get_idx(sem, shortest->q)); 1926 ikglp_get_idx(sem, shortest->q));
@@ -1963,24 +1963,24 @@ static ikglp_donee_heap_node_t* pick_donee(struct ikglp_affinity* aff,
1963 struct task_struct *donee; 1963 struct task_struct *donee;
1964 ikglp_donee_heap_node_t *donee_node; 1964 ikglp_donee_heap_node_t *donee_node;
1965 struct task_struct *mth_highest = ikglp_mth_highest(sem); 1965 struct task_struct *mth_highest = ikglp_mth_highest(sem);
1966 1966
1967 lt_t now = litmus_clock(); 1967 lt_t now = litmus_clock();
1968 1968
1969// TRACE_CUR("fq %d: mth_highest: %s/%d, deadline = %d: (donor) = ??? ", 1969// TRACE_CUR("fq %d: mth_highest: %s/%d, deadline = %d: (donor) = ??? ",
1970// ikglp_get_idx(sem, fq), 1970// ikglp_get_idx(sem, fq),
1971// mth_highest->comm, mth_highest->pid, 1971// mth_highest->comm, mth_highest->pid,
1972// (int)get_deadline(mth_highest) - now); 1972// (int)get_deadline(mth_highest) - now);
1973 1973
1974 if(fq->owner && 1974 if(fq->owner &&
1975 fq->donee_heap_node.donor_info == NULL && 1975 fq->donee_heap_node.donor_info == NULL &&
1976 mth_highest != fq->owner && 1976 mth_highest != fq->owner &&
1977 litmus->__compare(mth_highest, BASE, fq->owner, BASE)) { 1977 litmus->__compare(mth_highest, BASE, fq->owner, BASE)) {
1978 donee = fq->owner; 1978 donee = fq->owner;
1979 donee_node = &(fq->donee_heap_node); 1979 donee_node = &(fq->donee_heap_node);
1980 *dist_from_head = 0; 1980 *dist_from_head = 0;
1981 1981
1982 BUG_ON(donee != donee_node->task); 1982 BUG_ON(donee != donee_node->task);
1983 1983
1984 TRACE_CUR("picked owner of fq %d as donee\n", 1984 TRACE_CUR("picked owner of fq %d as donee\n",
1985 ikglp_get_idx(sem, fq)); 1985 ikglp_get_idx(sem, fq));
1986 1986
@@ -1988,8 +1988,8 @@ static ikglp_donee_heap_node_t* pick_donee(struct ikglp_affinity* aff,
1988 } 1988 }
1989 else if(waitqueue_active(&fq->wait)) { 1989 else if(waitqueue_active(&fq->wait)) {
1990 struct list_head *pos; 1990 struct list_head *pos;
1991 1991
1992 1992
1993// TRACE_CUR("fq %d: owner: %s/%d, deadline = %d: (donor) = %s/%d " 1993// TRACE_CUR("fq %d: owner: %s/%d, deadline = %d: (donor) = %s/%d "
1994// "(mth_highest != fq->owner) = %d " 1994// "(mth_highest != fq->owner) = %d "
1995// "(mth_highest > fq->owner) = %d\n", 1995// "(mth_highest > fq->owner) = %d\n",
@@ -2001,16 +2001,16 @@ static ikglp_donee_heap_node_t* pick_donee(struct ikglp_affinity* aff,
2001// (fq->donee_heap_node.donor_info) ? fq->donee_heap_node.donor_info->task->pid : -1, 2001// (fq->donee_heap_node.donor_info) ? fq->donee_heap_node.donor_info->task->pid : -1,
2002// (mth_highest != fq->owner), 2002// (mth_highest != fq->owner),
2003// (litmus->__compare(mth_highest, BASE, fq->owner, BASE))); 2003// (litmus->__compare(mth_highest, BASE, fq->owner, BASE)));
2004 2004
2005 2005
2006 *dist_from_head = 1; 2006 *dist_from_head = 1;
2007 2007
2008 // iterating from the start of the queue is nice since this means 2008 // iterating from the start of the queue is nice since this means
2009 // the donee will be closer to obtaining a resource. 2009 // the donee will be closer to obtaining a resource.
2010 list_for_each(pos, &fq->wait.task_list) { 2010 list_for_each(pos, &fq->wait.task_list) {
2011 wait_queue_t *fq_wait = list_entry(pos, wait_queue_t, task_list); 2011 wait_queue_t *fq_wait = list_entry(pos, wait_queue_t, task_list);
2012 ikglp_wait_state_t *wait = container_of(fq_wait, ikglp_wait_state_t, fq_node); 2012 ikglp_wait_state_t *wait = container_of(fq_wait, ikglp_wait_state_t, fq_node);
2013 2013
2014// TRACE_CUR("fq %d: waiter %d: %s/%d, deadline = %d (donor) = %s/%d " 2014// TRACE_CUR("fq %d: waiter %d: %s/%d, deadline = %d (donor) = %s/%d "
2015// "(mth_highest != wait->task) = %d " 2015// "(mth_highest != wait->task) = %d "
2016// "(mth_highest > wait->task) = %d\n", 2016// "(mth_highest > wait->task) = %d\n",
@@ -2021,40 +2021,40 @@ static ikglp_donee_heap_node_t* pick_donee(struct ikglp_affinity* aff,
2021// (wait->donee_heap_node.donor_info) ? wait->donee_heap_node.donor_info->task->comm : "nil", 2021// (wait->donee_heap_node.donor_info) ? wait->donee_heap_node.donor_info->task->comm : "nil",
2022// (wait->donee_heap_node.donor_info) ? wait->donee_heap_node.donor_info->task->pid : -1, 2022// (wait->donee_heap_node.donor_info) ? wait->donee_heap_node.donor_info->task->pid : -1,
2023// (mth_highest != wait->task), 2023// (mth_highest != wait->task),
2024// (litmus->__compare(mth_highest, BASE, wait->task, BASE))); 2024// (litmus->__compare(mth_highest, BASE, wait->task, BASE)));
2025 2025
2026 2026
2027 if(!has_donor(fq_wait) && 2027 if(!has_donor(fq_wait) &&
2028 mth_highest != wait->task && 2028 mth_highest != wait->task &&
2029 litmus->__compare(mth_highest, BASE, wait->task, BASE)) { 2029 litmus->__compare(mth_highest, BASE, wait->task, BASE)) {
2030 donee = (struct task_struct*) fq_wait->private; 2030 donee = (struct task_struct*) fq_wait->private;
2031 donee_node = &wait->donee_heap_node; 2031 donee_node = &wait->donee_heap_node;
2032 2032
2033 BUG_ON(donee != donee_node->task); 2033 BUG_ON(donee != donee_node->task);
2034 2034
2035 TRACE_CUR("picked waiter in fq %d as donee\n", 2035 TRACE_CUR("picked waiter in fq %d as donee\n",
2036 ikglp_get_idx(sem, fq)); 2036 ikglp_get_idx(sem, fq));
2037 2037
2038 goto out; 2038 goto out;
2039 } 2039 }
2040 ++(*dist_from_head); 2040 ++(*dist_from_head);
2041 } 2041 }
2042 } 2042 }
2043 2043
2044 donee = NULL; 2044 donee = NULL;
2045 donee_node = NULL; 2045 donee_node = NULL;
2046 *dist_from_head = sem->max_fifo_len + 1; 2046 *dist_from_head = sem->max_fifo_len + 1;
2047 2047
2048 TRACE_CUR("Found no one to be donee in fq %d!\n", ikglp_get_idx(sem, fq)); 2048 TRACE_CUR("Found no one to be donee in fq %d!\n", ikglp_get_idx(sem, fq));
2049 2049
2050out: 2050out:
2051 2051
2052 TRACE_CUR("Candidate donee for fq %d is %s/%d (dist_from_head = %d)\n", 2052 TRACE_CUR("Candidate donee for fq %d is %s/%d (dist_from_head = %d)\n",
2053 ikglp_get_idx(sem, fq), 2053 ikglp_get_idx(sem, fq),
2054 (donee) ? (donee)->comm : "nil", 2054 (donee) ? (donee)->comm : "nil",
2055 (donee) ? (donee)->pid : -1, 2055 (donee) ? (donee)->pid : -1,
2056 *dist_from_head); 2056 *dist_from_head);
2057 2057
2058 return donee_node; 2058 return donee_node;
2059} 2059}
2060 2060
@@ -2074,10 +2074,10 @@ ikglp_donee_heap_node_t* gpu_ikglp_advise_donee_selection(
2074 ikglp_donee_heap_node_t *donee_node; 2074 ikglp_donee_heap_node_t *donee_node;
2075 gpu_migration_dist_t distance; 2075 gpu_migration_dist_t distance;
2076 int start, i, j; 2076 int start, i, j;
2077 2077
2078 ikglp_donee_heap_node_t *default_donee; 2078 ikglp_donee_heap_node_t *default_donee;
2079 ikglp_wait_state_t *default_donee_donor_info; 2079 ikglp_wait_state_t *default_donee_donor_info;
2080 2080
2081 if(tsk_rt(donor)->last_gpu < 0) { 2081 if(tsk_rt(donor)->last_gpu < 0) {
2082 // no affinity. just return the min prio, like standard IKGLP 2082 // no affinity. just return the min prio, like standard IKGLP
2083 // TODO: Find something closer to the head of the queue?? 2083 // TODO: Find something closer to the head of the queue??
@@ -2086,8 +2086,8 @@ ikglp_donee_heap_node_t* gpu_ikglp_advise_donee_selection(
2086 node); 2086 node);
2087 goto out; 2087 goto out;
2088 } 2088 }
2089 2089
2090 2090
2091 // Temporarily break any donation relation the default donee (the lowest 2091 // Temporarily break any donation relation the default donee (the lowest
2092 // prio task in the FIFO queues) to make it eligible for selection below. 2092 // prio task in the FIFO queues) to make it eligible for selection below.
2093 // 2093 //
@@ -2095,40 +2095,40 @@ ikglp_donee_heap_node_t* gpu_ikglp_advise_donee_selection(
2095 // the default donee throug affinity-aware selection, before returning 2095 // the default donee throug affinity-aware selection, before returning
2096 // from this function so we don't screw up our heap ordering. 2096 // from this function so we don't screw up our heap ordering.
2097 // The standard IKGLP algorithm will steal the donor relationship if needed. 2097 // The standard IKGLP algorithm will steal the donor relationship if needed.
2098 default_donee = binheap_top_entry(&sem->donees, ikglp_donee_heap_node_t, node); 2098 default_donee = binheap_top_entry(&sem->donees, ikglp_donee_heap_node_t, node);
2099 default_donee_donor_info = default_donee->donor_info; // back-up donor relation 2099 default_donee_donor_info = default_donee->donor_info; // back-up donor relation
2100 default_donee->donor_info = NULL; // temporarily break any donor relation. 2100 default_donee->donor_info = NULL; // temporarily break any donor relation.
2101 2101
2102 // initialize our search 2102 // initialize our search
2103 donee_node = NULL; 2103 donee_node = NULL;
2104 distance = MIG_NONE; 2104 distance = MIG_NONE;
2105 2105
2106 // TODO: The below search logic may work well for locating nodes to steal 2106 // TODO: The below search logic may work well for locating nodes to steal
2107 // when an FQ goes idle. Validate this code and apply it to stealing. 2107 // when an FQ goes idle. Validate this code and apply it to stealing.
2108 2108
2109 // begin search with affinity GPU. 2109 // begin search with affinity GPU.
2110 start = gpu_to_base_replica(aff, tsk_rt(donor)->last_gpu); 2110 start = gpu_to_base_replica(aff, tsk_rt(donor)->last_gpu);
2111 i = start; 2111 i = start;
2112 do { // "for each gpu" / "for each aff->nr_rsrc" 2112 do { // "for each gpu" / "for each aff->nr_rsrc"
2113 gpu_migration_dist_t temp_distance = gpu_migration_distance(start, i); 2113 gpu_migration_dist_t temp_distance = gpu_migration_distance(start, i);
2114 2114
2115 // only interested in queues that will improve our distance 2115 // only interested in queues that will improve our distance
2116 if(temp_distance < distance || donee_node == NULL) { 2116 if(temp_distance < distance || donee_node == NULL) {
2117 int dist_from_head = sem->max_fifo_len + 1; 2117 int dist_from_head = sem->max_fifo_len + 1;
2118 2118
2119 TRACE_CUR("searching for donor on GPU %d", i); 2119 TRACE_CUR("searching for donor on GPU %d", i);
2120 2120
2121 // visit each queue and pick a donee. bail as soon as we find 2121 // visit each queue and pick a donee. bail as soon as we find
2122 // one for this class. 2122 // one for this class.
2123 2123
2124 for(j = 0; j < aff->nr_simult; ++j) { 2124 for(j = 0; j < aff->nr_simult; ++j) {
2125 int temp_dist_from_head; 2125 int temp_dist_from_head;
2126 ikglp_donee_heap_node_t *temp_donee_node; 2126 ikglp_donee_heap_node_t *temp_donee_node;
2127 struct fifo_queue *fq; 2127 struct fifo_queue *fq;
2128 2128
2129 fq = &(sem->fifo_queues[i + j*aff->nr_rsrc]); 2129 fq = &(sem->fifo_queues[i + j*aff->nr_rsrc]);
2130 temp_donee_node = pick_donee(aff, fq, &temp_dist_from_head); 2130 temp_donee_node = pick_donee(aff, fq, &temp_dist_from_head);
2131 2131
2132 if(temp_dist_from_head < dist_from_head) 2132 if(temp_dist_from_head < dist_from_head)
2133 { 2133 {
2134 // we check all the FQs for this GPU to spread priorities 2134 // we check all the FQs for this GPU to spread priorities
@@ -2137,7 +2137,7 @@ ikglp_donee_heap_node_t* gpu_ikglp_advise_donee_selection(
2137 dist_from_head = temp_dist_from_head; 2137 dist_from_head = temp_dist_from_head;
2138 } 2138 }
2139 } 2139 }
2140 2140
2141 if(dist_from_head != sem->max_fifo_len + 1) { 2141 if(dist_from_head != sem->max_fifo_len + 1) {
2142 TRACE_CUR("found donee %s/%d and is the %d-th waiter.\n", 2142 TRACE_CUR("found donee %s/%d and is the %d-th waiter.\n",
2143 donee_node->task->comm, donee_node->task->pid, 2143 donee_node->task->comm, donee_node->task->pid,
@@ -2151,23 +2151,23 @@ ikglp_donee_heap_node_t* gpu_ikglp_advise_donee_selection(
2151 TRACE_CUR("skipping GPU %d (distance = %d, best donor " 2151 TRACE_CUR("skipping GPU %d (distance = %d, best donor "
2152 "distance = %d)\n", i, temp_distance, distance); 2152 "distance = %d)\n", i, temp_distance, distance);
2153 } 2153 }
2154 2154
2155 i = (i+1 < aff->nr_rsrc) ? i+1 : 0; // increment with wrap-around 2155 i = (i+1 < aff->nr_rsrc) ? i+1 : 0; // increment with wrap-around
2156 } while (i != start); 2156 } while (i != start);
2157 2157
2158 2158
2159 // restore old donor info state. 2159 // restore old donor info state.
2160 default_donee->donor_info = default_donee_donor_info; 2160 default_donee->donor_info = default_donee_donor_info;
2161 2161
2162 if(!donee_node) { 2162 if(!donee_node) {
2163 donee_node = default_donee; 2163 donee_node = default_donee;
2164 2164
2165 TRACE_CUR("Could not find a donee. We have to steal one.\n"); 2165 TRACE_CUR("Could not find a donee. We have to steal one.\n");
2166 WARN_ON(default_donee->donor_info == NULL); 2166 WARN_ON(default_donee->donor_info == NULL);
2167 } 2167 }
2168 2168
2169out: 2169out:
2170 2170
2171 TRACE_CUR("Selected donee %s/%d on fq %d (GPU %d) for %s/%d with affinity for GPU %d\n", 2171 TRACE_CUR("Selected donee %s/%d on fq %d (GPU %d) for %s/%d with affinity for GPU %d\n",
2172 donee_node->task->comm, donee_node->task->pid, 2172 donee_node->task->comm, donee_node->task->pid,
2173 ikglp_get_idx(sem, donee_node->fq), 2173 ikglp_get_idx(sem, donee_node->fq),
@@ -2186,15 +2186,15 @@ static void __find_closest_donor(int target_gpu,
2186{ 2186{
2187 ikglp_wait_state_t *this_donor = 2187 ikglp_wait_state_t *this_donor =
2188 binheap_entry(donor_node, ikglp_wait_state_t, node); 2188 binheap_entry(donor_node, ikglp_wait_state_t, node);
2189 2189
2190 int this_dist = 2190 int this_dist =
2191 gpu_migration_distance(target_gpu, tsk_rt(this_donor->task)->last_gpu); 2191 gpu_migration_distance(target_gpu, tsk_rt(this_donor->task)->last_gpu);
2192 2192
2193// TRACE_CUR("%s/%d: dist from target = %d\n", 2193// TRACE_CUR("%s/%d: dist from target = %d\n",
2194// this_donor->task->comm, 2194// this_donor->task->comm,
2195// this_donor->task->pid, 2195// this_donor->task->pid,
2196// this_dist); 2196// this_dist);
2197 2197
2198 if(this_dist < *cur_dist) { 2198 if(this_dist < *cur_dist) {
2199 // take this donor 2199 // take this donor
2200 *cur_dist = this_dist; 2200 *cur_dist = this_dist;
@@ -2210,7 +2210,7 @@ static void __find_closest_donor(int target_gpu,
2210 *cur_closest = this_donor; 2210 *cur_closest = this_donor;
2211 } 2211 }
2212 } 2212 }
2213 2213
2214 if(donor_node->left) __find_closest_donor(target_gpu, donor_node->left, cur_closest, cur_dist); 2214 if(donor_node->left) __find_closest_donor(target_gpu, donor_node->left, cur_closest, cur_dist);
2215 if(donor_node->right) __find_closest_donor(target_gpu, donor_node->right, cur_closest, cur_dist); 2215 if(donor_node->right) __find_closest_donor(target_gpu, donor_node->right, cur_closest, cur_dist);
2216} 2216}
@@ -2219,21 +2219,21 @@ ikglp_wait_state_t* gpu_ikglp_advise_donor_to_fq(struct ikglp_affinity* aff, str
2219{ 2219{
2220 // Huristic strategy: Find donor with the closest affinity to fq. 2220 // Huristic strategy: Find donor with the closest affinity to fq.
2221 // Tie-break on priority. 2221 // Tie-break on priority.
2222 2222
2223 // We need to iterate over all the donors to do this. Unfortunatly, 2223 // We need to iterate over all the donors to do this. Unfortunatly,
2224 // our donors are organized in a heap. We'll visit each node with a 2224 // our donors are organized in a heap. We'll visit each node with a
2225 // recurisve call. This is realitively safe since there are only sem->m 2225 // recurisve call. This is realitively safe since there are only sem->m
2226 // donors, at most. We won't recurse too deeply to have to worry about 2226 // donors, at most. We won't recurse too deeply to have to worry about
2227 // our stack. (even with 128 CPUs, our nest depth is at most 7 deep). 2227 // our stack. (even with 128 CPUs, our nest depth is at most 7 deep).
2228 2228
2229 struct ikglp_semaphore *sem = ikglp_from_lock(aff->obs.lock); 2229 struct ikglp_semaphore *sem = ikglp_from_lock(aff->obs.lock);
2230 ikglp_wait_state_t *donor = NULL; 2230 ikglp_wait_state_t *donor = NULL;
2231 int distance = MIG_NONE; 2231 int distance = MIG_NONE;
2232 int gpu = replica_to_gpu(aff, ikglp_get_idx(sem, fq)); 2232 int gpu = replica_to_gpu(aff, ikglp_get_idx(sem, fq));
2233 ikglp_wait_state_t* default_donor = binheap_top_entry(&sem->donors, ikglp_wait_state_t, node); 2233 ikglp_wait_state_t* default_donor = binheap_top_entry(&sem->donors, ikglp_wait_state_t, node);
2234 2234
2235 __find_closest_donor(gpu, sem->donors.root, &donor, &distance); 2235 __find_closest_donor(gpu, sem->donors.root, &donor, &distance);
2236 2236
2237 TRACE_CUR("Selected donor %s/%d (distance = %d) to move to fq %d " 2237 TRACE_CUR("Selected donor %s/%d (distance = %d) to move to fq %d "
2238 "(non-aff wanted %s/%d). differs = %d\n", 2238 "(non-aff wanted %s/%d). differs = %d\n",
2239 donor->task->comm, donor->task->pid, 2239 donor->task->comm, donor->task->pid,
@@ -2242,7 +2242,7 @@ ikglp_wait_state_t* gpu_ikglp_advise_donor_to_fq(struct ikglp_affinity* aff, str
2242 default_donor->task->comm, default_donor->task->pid, 2242 default_donor->task->comm, default_donor->task->pid,
2243 (donor->task != default_donor->task) 2243 (donor->task != default_donor->task)
2244 ); 2244 );
2245 2245
2246 return(donor); 2246 return(donor);
2247} 2247}
2248 2248