ia64/xen-unstable

view xen/common/rangeset.c @ 8609:85d693e6f61a

Arch-specific per-vcpu info should be initialised to zero
when allocating a new vcpu structure, not copied from
CPU0's idle VCPU. Especially now that the idle VCPU itself
is dynamically allocated.

This should fix assertions people have been seeing in
getdomain_info_ctxt() relation to IOPL in eflags.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Jan 14 21:26:40 2006 +0100 (2006-01-14)
parents 364128d29f4e
children 03382076472c
line source
1 /******************************************************************************
2 * rangeset.c
3 *
4 * Creation, maintenance and automatic destruction of per-domain sets of
5 * numeric ranges.
6 *
7 * Copyright (c) 2005, K A Fraser
8 */
10 #include <xen/sched.h>
11 #include <xen/rangeset.h>
13 /* An inclusive range [s,e] and pointer to next range in ascending order. */
14 struct range {
15 struct list_head list;
16 unsigned long s, e;
17 };
19 struct rangeset {
20 /* Owning domain and threaded list of rangesets. */
21 struct list_head rangeset_list;
22 struct domain *domain;
24 /* Ordered list of ranges contained in this set, and protecting lock. */
25 struct list_head range_list;
26 spinlock_t lock;
28 /* Pretty-printing name. */
29 char name[32];
31 /* RANGESETF flags. */
32 unsigned int flags;
33 };
35 /*****************************
36 * Private range functions hide the underlying linked-list implemnetation.
37 */
39 /* Find highest range lower than or containing s. NULL if no such range. */
40 static struct range *find_range(
41 struct rangeset *r, unsigned long s)
42 {
43 struct range *x = NULL, *y;
45 list_for_each_entry ( y, &r->range_list, list )
46 {
47 if ( y->s > s )
48 break;
49 x = y;
50 }
52 return x;
53 }
55 /* Return the lowest range in the set r, or NULL if r is empty. */
56 static struct range *first_range(
57 struct rangeset *r)
58 {
59 if ( list_empty(&r->range_list) )
60 return NULL;
61 return list_entry(r->range_list.next, struct range, list);
62 }
64 /* Return range following x in ascending order, or NULL if x is the highest. */
65 static struct range *next_range(
66 struct rangeset *r, struct range *x)
67 {
68 if ( x->list.next == &r->range_list )
69 return NULL;
70 return list_entry(x->list.next, struct range, list);
71 }
73 /* Insert range y after range x in r. Insert as first range if x is NULL. */
74 static void insert_range(
75 struct rangeset *r, struct range *x, struct range *y)
76 {
77 list_add(&y->list, (x != NULL) ? &x->list : &r->range_list);
78 }
80 /* Remove a range from its list and free it. */
81 static void destroy_range(
82 struct range *x)
83 {
84 list_del(&x->list);
85 xfree(x);
86 }
88 /*****************************
89 * Core public functions
90 */
92 int rangeset_add_range(
93 struct rangeset *r, unsigned long s, unsigned long e)
94 {
95 struct range *x, *y;
96 int rc = 0;
98 spin_lock(&r->lock);
100 x = find_range(r, s);
101 y = find_range(r, e);
103 if ( x == y )
104 {
105 if ( (x == NULL) || ((x->e < s) && ((x->e + 1) != s)) )
106 {
107 x = xmalloc(struct range);
108 if ( x == NULL )
109 {
110 rc = -ENOMEM;
111 goto out;
112 }
114 x->s = s;
115 x->e = e;
117 insert_range(r, y, x);
118 }
119 else if ( x->e < e )
120 x->e = e;
121 }
122 else
123 {
124 if ( x == NULL )
125 {
126 x = first_range(r);
127 x->s = s;
128 }
129 else if ( (x->e < s) && ((x->e + 1) != s) )
130 {
131 x = next_range(r, x);
132 x->s = s;
133 }
135 x->e = (y->e > e) ? y->e : e;
137 for ( ; ; )
138 {
139 y = next_range(r, x);
140 if ( (y == NULL) || (y->e > x->e) )
141 break;
142 destroy_range(y);
143 }
144 }
146 y = next_range(r, x);
147 if ( (y != NULL) && ((x->e + 1) == y->s) )
148 {
149 x->e = y->e;
150 destroy_range(y);
151 }
153 out:
154 spin_unlock(&r->lock);
155 return rc;
156 }
158 int rangeset_remove_range(
159 struct rangeset *r, unsigned long s, unsigned long e)
160 {
161 struct range *x, *y, *t;
162 int rc = 0;
164 spin_lock(&r->lock);
166 x = find_range(r, s);
167 y = find_range(r, e);
169 if ( x == y )
170 {
171 if ( (x == NULL) || (x->e < s) )
172 goto out;
174 if ( (x->s < s) && (x->e > e) )
175 {
176 y = xmalloc(struct range);
177 if ( y == NULL )
178 {
179 rc = -ENOMEM;
180 goto out;
181 }
183 y->s = e + 1;
184 y->e = x->e;
185 x->e = s - 1;
187 insert_range(r, x, y);
188 }
189 else if ( (x->s == s) && (x->e <= e) )
190 destroy_range(x);
191 else if ( x->s == s )
192 x->s = e + 1;
193 else if ( x->e <= e )
194 x->e = s - 1;
195 }
196 else
197 {
198 if ( x == NULL )
199 x = first_range(r);
201 if ( x->s < s )
202 {
203 x->e = s - 1;
204 x = next_range(r, x);
205 }
207 while ( x != y )
208 {
209 t = x;
210 x = next_range(r, x);
211 destroy_range(t);
212 }
214 x->s = e + 1;
215 if ( x->s > x->e )
216 destroy_range(x);
217 }
219 out:
220 spin_unlock(&r->lock);
221 return rc;
222 }
224 int rangeset_contains_range(
225 struct rangeset *r, unsigned long s, unsigned long e)
226 {
227 struct range *x;
228 int contains;
230 spin_lock(&r->lock);
231 x = find_range(r, s);
232 contains = (x && (x->e >= e));
233 spin_unlock(&r->lock);
235 return contains;
236 }
238 int rangeset_add_singleton(
239 struct rangeset *r, unsigned long s)
240 {
241 return rangeset_add_range(r, s, s);
242 }
244 int rangeset_remove_singleton(
245 struct rangeset *r, unsigned long s)
246 {
247 return rangeset_remove_range(r, s, s);
248 }
250 int rangeset_contains_singleton(
251 struct rangeset *r, unsigned long s)
252 {
253 return rangeset_contains_range(r, s, s);
254 }
256 int rangeset_is_empty(
257 struct rangeset *r)
258 {
259 return list_empty(&r->range_list);
260 }
262 struct rangeset *rangeset_new(
263 struct domain *d, char *name, unsigned int flags)
264 {
265 struct rangeset *r;
267 r = xmalloc(struct rangeset);
268 if ( r == NULL )
269 return NULL;
271 spin_lock_init(&r->lock);
272 INIT_LIST_HEAD(&r->range_list);
274 BUG_ON(flags & ~RANGESETF_prettyprint_hex);
275 r->flags = flags;
277 if ( name != NULL )
278 {
279 strncpy(r->name, name, sizeof(r->name));
280 r->name[sizeof(r->name)-1] = '\0';
281 }
282 else
283 {
284 sprintf(r->name, "(no name)");
285 }
287 if ( (r->domain = d) != NULL )
288 {
289 spin_lock(&d->rangesets_lock);
290 list_add(&r->rangeset_list, &d->rangesets);
291 spin_unlock(&d->rangesets_lock);
292 }
294 return r;
295 }
297 void rangeset_destroy(
298 struct rangeset *r)
299 {
300 struct range *x;
302 if ( r == NULL )
303 return;
305 if ( r->domain != NULL )
306 {
307 spin_lock(&r->domain->rangesets_lock);
308 list_del(&r->rangeset_list);
309 spin_unlock(&r->domain->rangesets_lock);
310 }
312 while ( (x = first_range(r)) != NULL )
313 destroy_range(x);
315 xfree(r);
316 }
318 void rangeset_domain_initialise(
319 struct domain *d)
320 {
321 INIT_LIST_HEAD(&d->rangesets);
322 spin_lock_init(&d->rangesets_lock);
323 }
325 void rangeset_domain_destroy(
326 struct domain *d)
327 {
328 struct rangeset *r;
330 while ( !list_empty(&d->rangesets) )
331 {
332 r = list_entry(d->rangesets.next, struct rangeset, rangeset_list);
334 BUG_ON(r->domain != d);
335 r->domain = NULL;
336 list_del(&r->rangeset_list);
338 rangeset_destroy(r);
339 }
340 }
342 /*****************************
343 * Pretty-printing functions
344 */
346 static void print_limit(struct rangeset *r, unsigned long s)
347 {
348 printk((r->flags & RANGESETF_prettyprint_hex) ? "%lx" : "%lu", s);
349 }
351 void rangeset_printk(
352 struct rangeset *r)
353 {
354 int nr_printed = 0;
355 struct range *x;
357 spin_lock(&r->lock);
359 printk("%-10s {", r->name);
361 for ( x = first_range(r); x != NULL; x = next_range(r, x) )
362 {
363 if ( nr_printed++ )
364 printk(",");
365 printk(" ");
366 print_limit(r, x->s);
367 if ( x->s != x->e )
368 {
369 printk("-");
370 print_limit(r, x->e);
371 }
372 }
374 printk(" }");
376 spin_unlock(&r->lock);
377 }
379 void rangeset_domain_printk(
380 struct domain *d)
381 {
382 struct rangeset *r;
384 printk("Rangesets belonging to domain %u:\n", d->domain_id);
386 spin_lock(&d->rangesets_lock);
388 if ( list_empty(&d->rangesets) )
389 printk(" None\n");
391 list_for_each_entry ( r, &d->rangesets, rangeset_list )
392 {
393 printk(" ");
394 rangeset_printk(r);
395 printk("\n");
396 }
398 spin_unlock(&d->rangesets_lock);
399 }