diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2013-10-30 18:30:58 -0400 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2014-03-03 10:07:32 -0500 |
commit | 39b8d26fb9bba4984d4d912cb8a31e04d99fb3d5 (patch) | |
tree | 7f5f9b25967d5dfae72cbf2f83c751126fb9736b /include | |
parent | d377bc02d8b79f89a28e39c70a934c499f6c2347 (diff) |
Add ikglp.
Adds an implementation of the ikglp. Supports both affinity and
nesting of other locks within the ikglp (the ikglp itself must
be an outer-most lock).
Diffstat (limited to 'include')
-rw-r--r-- | include/litmus/ikglp_lock.h | 233 | ||||
-rw-r--r-- | include/litmus/rt_param.h | 12 |
2 files changed, 245 insertions, 0 deletions
diff --git a/include/litmus/ikglp_lock.h b/include/litmus/ikglp_lock.h new file mode 100644 index 000000000000..c85c8c280299 --- /dev/null +++ b/include/litmus/ikglp_lock.h | |||
@@ -0,0 +1,233 @@ | |||
1 | #ifndef LITMUS_IKGLP_H | ||
2 | #define LITMUS_IKGLP_H | ||
3 | |||
4 | #include <litmus/litmus.h> | ||
5 | #include <litmus/binheap.h> | ||
6 | #include <litmus/locking.h> | ||
7 | |||
8 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | ||
9 | #include <litmus/kexclu_affinity.h> | ||
10 | struct ikglp_affinity; | ||
11 | #endif | ||
12 | |||
13 | typedef struct ikglp_heap_node | ||
14 | { | ||
15 | struct task_struct *task; | ||
16 | struct binheap_node node; | ||
17 | } ikglp_heap_node_t; | ||
18 | |||
19 | struct fifo_queue; | ||
20 | struct ikglp_wait_state; | ||
21 | struct fifo_queue; | ||
22 | |||
23 | typedef struct ikglp_donee_heap_node | ||
24 | { | ||
25 | struct task_struct *task; | ||
26 | struct fifo_queue *fq; | ||
27 | |||
28 | /* cross-linked with ikglp_wait_state_t of donor */ | ||
29 | struct ikglp_wait_state *donor_info; | ||
30 | |||
31 | struct binheap_node node; | ||
32 | } ikglp_donee_heap_node_t; | ||
33 | |||
34 | typedef enum ikglp_states | ||
35 | { | ||
36 | IKGLP_INVL = 0, | ||
37 | IKGLP_FQ, | ||
38 | IKGLP_PQ, | ||
39 | IKGLP_DONOR | ||
40 | } ikglp_states_t; | ||
41 | |||
42 | /* | ||
43 | Maintains the state of a request as it goes through the IKGLP. | ||
44 | There are three exclusive wait states: | ||
45 | (1) as a donor | ||
46 | (2) in the PQ | ||
47 | (3) in the FQ | ||
48 | */ | ||
49 | typedef struct ikglp_wait_state { | ||
50 | struct task_struct *task; /* pointer back to the requesting task */ | ||
51 | |||
52 | ikglp_states_t cur_q; | ||
53 | /* data for x-highest-prio tasks */ | ||
54 | ikglp_heap_node_t global_heap_node; | ||
55 | |||
56 | /* TODO: put these fields in an appropriate union since wait | ||
57 | states are exclusive. */ | ||
58 | |||
59 | /** Data for whilst in FIFO Queue **/ | ||
60 | wait_queue_t fq_node; | ||
61 | struct fifo_queue *fq; | ||
62 | ikglp_donee_heap_node_t donee_heap_node; | ||
63 | |||
64 | /** Data for whilst in PQ **/ | ||
65 | ikglp_heap_node_t pq_node; | ||
66 | |||
67 | /** Data for whilst a donor **/ | ||
68 | /* cross-linked with donee's ikglp_donee_heap_node_t */ | ||
69 | ikglp_donee_heap_node_t *donee_info; | ||
70 | struct nested_info prio_donation; | ||
71 | struct binheap_node node; | ||
72 | } ikglp_wait_state_t; | ||
73 | |||
74 | /* struct for FIFO mutex with priority inheritance */ | ||
75 | struct fifo_queue | ||
76 | { | ||
77 | wait_queue_head_t wait; | ||
78 | struct task_struct* owner; | ||
79 | |||
80 | /* used for bookkeepping */ | ||
81 | ikglp_heap_node_t global_heap_node; | ||
82 | ikglp_donee_heap_node_t donee_heap_node; | ||
83 | |||
84 | struct task_struct* hp_waiter; | ||
85 | unsigned int count; /* number of waiters + holder */ | ||
86 | |||
87 | struct nested_info nest; | ||
88 | |||
89 | /* Asserted if owner has 'virtually' unlocked the FIFO's replica. | ||
90 | * See rule B2 in Brandenburg's "Virtually Exclusive Resources" | ||
91 | * tech report MPI_SWS-2012-005. | ||
92 | * | ||
93 | * In this implementation, allows the FIFO queue to temporarily | ||
94 | * grow by one past it's maximum size. | ||
95 | */ | ||
96 | unsigned int is_vunlocked:1; | ||
97 | }; | ||
98 | |||
99 | /* Main IKGLP data structure. */ | ||
100 | struct ikglp_semaphore | ||
101 | { | ||
102 | struct litmus_lock litmus_lock; | ||
103 | |||
104 | raw_spinlock_t lock; | ||
105 | raw_spinlock_t real_lock; | ||
106 | |||
107 | unsigned int nr_replicas; /* AKA k */ | ||
108 | unsigned int max_fifo_len; /* max len of a fifo queue */ | ||
109 | |||
110 | unsigned int max_in_fifos; | ||
111 | unsigned int nr_in_fifos; | ||
112 | |||
113 | struct binheap top_m; /* min heap, base prio */ | ||
114 | unsigned int top_m_size; /* number of nodes in top_m */ | ||
115 | |||
116 | struct binheap not_top_m; /* max heap, ordered by base priority */ | ||
117 | |||
118 | struct binheap donees; /* min-heap, ordered by base priority */ | ||
119 | |||
120 | /* cached value - pointer to shortest fifo queue */ | ||
121 | struct fifo_queue *shortest_fifo_queue; | ||
122 | |||
123 | /* data structures for holding requests */ | ||
124 | struct fifo_queue *fifo_queues; /* array nr_replicas in length */ | ||
125 | struct binheap priority_queue; /* max-heap, ordered by base priority */ | ||
126 | struct binheap donors; /* max-heap, ordered by base priority */ | ||
127 | |||
128 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | ||
129 | struct ikglp_affinity *aff_obs; /* pointer to affinity observer */ | ||
130 | #endif | ||
131 | }; | ||
132 | |||
133 | static inline struct ikglp_semaphore* ikglp_from_lock(struct litmus_lock* lock) | ||
134 | { | ||
135 | return container_of(lock, struct ikglp_semaphore, litmus_lock); | ||
136 | } | ||
137 | |||
138 | int ikglp_lock(struct litmus_lock* l); | ||
139 | int ikglp_unlock(struct litmus_lock* l); | ||
140 | void ikglp_virtual_unlock(struct litmus_lock* l, struct task_struct* t); | ||
141 | void ikglp_budget_exhausted(struct litmus_lock* l, struct task_struct* t); | ||
142 | |||
143 | int ikglp_close(struct litmus_lock* l); | ||
144 | void ikglp_free(struct litmus_lock* l); | ||
145 | struct litmus_lock* ikglp_new(unsigned int m, struct litmus_lock_ops*, | ||
146 | void* __user arg); | ||
147 | |||
148 | #ifdef CONFIG_LITMUS_AFFINITY_LOCKING | ||
149 | struct ikglp_queue_info | ||
150 | { | ||
151 | struct fifo_queue* q; | ||
152 | lt_t estimated_len; | ||
153 | unsigned int *nr_cur_users; | ||
154 | unsigned int *nr_aff_users; | ||
155 | }; | ||
156 | |||
157 | /* routines for IKGLP to call to get advice on queueing operations */ | ||
158 | typedef struct fifo_queue* (*advise_enqueue_t)(struct ikglp_affinity* aff, | ||
159 | struct task_struct* t); | ||
160 | typedef ikglp_wait_state_t* (*advise_steal_t)(struct ikglp_affinity* aff, | ||
161 | struct fifo_queue* dst); | ||
162 | typedef ikglp_donee_heap_node_t* (*advise_donee_t)(struct ikglp_affinity* aff, | ||
163 | struct task_struct* t); | ||
164 | typedef ikglp_wait_state_t* (*advise_donor_t)(struct ikglp_affinity* aff, | ||
165 | struct fifo_queue* dst); | ||
166 | |||
167 | /* routines for IKGLP to notify the affinity observer about changes in mutex state */ | ||
168 | typedef void (*notify_enqueue_t)(struct ikglp_affinity* aff, | ||
169 | struct fifo_queue* fq, struct task_struct* t); | ||
170 | typedef void (*notify_dequeue_t)(struct ikglp_affinity* aff, | ||
171 | struct fifo_queue* fq, struct task_struct* t); | ||
172 | typedef void (*notify_acquire_t)(struct ikglp_affinity* aff, | ||
173 | struct fifo_queue* fq, struct task_struct* t); | ||
174 | typedef void (*notify_free_t)(struct ikglp_affinity* aff, | ||
175 | struct fifo_queue* fq, struct task_struct* t); | ||
176 | typedef int (*notify_exit_t)(struct ikglp_affinity* aff, | ||
177 | struct task_struct* t); | ||
178 | |||
179 | /* convert a replica # to a GPU (includes offsets & simult user folding) */ | ||
180 | typedef int (*replica_to_resource_t)(struct ikglp_affinity* aff, | ||
181 | struct fifo_queue* fq); | ||
182 | |||
183 | struct ikglp_affinity_ops | ||
184 | { | ||
185 | advise_enqueue_t advise_enqueue; | ||
186 | advise_steal_t advise_steal; | ||
187 | advise_donee_t advise_donee_selection; | ||
188 | advise_donor_t advise_donor_to_fq; | ||
189 | |||
190 | notify_enqueue_t notify_enqueue; | ||
191 | notify_dequeue_t notify_dequeue; | ||
192 | notify_acquire_t notify_acquired; | ||
193 | notify_free_t notify_freed; | ||
194 | notify_exit_t notify_exit; | ||
195 | |||
196 | replica_to_resource_t replica_to_resource; | ||
197 | }; | ||
198 | |||
199 | struct ikglp_affinity | ||
200 | { | ||
201 | struct affinity_observer obs; | ||
202 | struct ikglp_affinity_ops *ops; | ||
203 | struct ikglp_queue_info *q_info; | ||
204 | unsigned int *nr_cur_users_on_rsrc; | ||
205 | unsigned int *nr_aff_on_rsrc; | ||
206 | unsigned int offset; | ||
207 | unsigned int nr_simult; | ||
208 | unsigned int nr_rsrc; | ||
209 | |||
210 | unsigned int relax_max_fifo_len:1; | ||
211 | }; | ||
212 | |||
213 | static inline struct ikglp_affinity* ikglp_aff_obs_from_aff_obs( | ||
214 | struct affinity_observer* aff_obs) | ||
215 | { | ||
216 | return container_of(aff_obs, struct ikglp_affinity, obs); | ||
217 | } | ||
218 | |||
219 | int ikglp_aff_obs_close(struct affinity_observer*); | ||
220 | void ikglp_aff_obs_free(struct affinity_observer*); | ||
221 | |||
222 | #ifdef CONFIG_LITMUS_NVIDIA | ||
223 | struct affinity_observer* ikglp_gpu_aff_obs_new( | ||
224 | struct affinity_observer_ops* aff, | ||
225 | void* __user arg); | ||
226 | struct affinity_observer* ikglp_simple_gpu_aff_obs_new( | ||
227 | struct affinity_observer_ops* aff, | ||
228 | void* __user arg); | ||
229 | #endif /* end LITMUS_NVIDIA */ | ||
230 | |||
231 | #endif /* end LITMUS_AFFINITY_LOCKING */ | ||
232 | |||
233 | #endif | ||
diff --git a/include/litmus/rt_param.h b/include/litmus/rt_param.h index 966f197041dc..9a1193383f56 100644 --- a/include/litmus/rt_param.h +++ b/include/litmus/rt_param.h | |||
@@ -98,6 +98,18 @@ struct affinity_observer_args | |||
98 | int lock_od; | 98 | int lock_od; |
99 | }; | 99 | }; |
100 | 100 | ||
101 | #define IKGLP_M_IN_FIFOS (0u) | ||
102 | #define IKGLP_UNLIMITED_IN_FIFOS (~0u) | ||
103 | #define IKGLP_OPTIMAL_FIFO_LEN (0u) | ||
104 | #define IKGLP_UNLIMITED_FIFO_LEN (~0u) | ||
105 | |||
106 | struct ikglp_args | ||
107 | { | ||
108 | unsigned int nr_replicas; | ||
109 | unsigned int max_in_fifos; | ||
110 | unsigned int max_fifo_len; | ||
111 | }; | ||
112 | |||
101 | /* The definition of the data that is shared between the kernel and real-time | 113 | /* The definition of the data that is shared between the kernel and real-time |
102 | * tasks via a shared page (see litmus/ctrldev.c). | 114 | * tasks via a shared page (see litmus/ctrldev.c). |
103 | * | 115 | * |