1/*
2 * Copyright 1998 Massachusetts Institute of Technology
3 *
4 * Permission to use, copy, modify, and distribute this software and
5 * its documentation for any purpose and without fee is hereby
6 * granted, provided that both the above copyright notice and this
7 * permission notice appear in all copies, that both the above
8 * copyright notice and this permission notice appear in all
--- 12 unchanged lines hidden (view full) ---
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id: subr_rman.c,v 1.5 1999/03/29 08:30:17 dfr Exp $
30 */
31
32/*
33 * The kernel resource manager. This code is responsible for keeping track
34 * of hardware resources which are apportioned out to various drivers.
35 * It does not actually assign those resources, and it is not expected
36 * that end-device drivers will call into this code directly. Rather,
37 * the code which implements the buses that those devices are attached to,
--- 19 unchanged lines hidden (view full) ---
57 * permitted.
58 */
59
60#include <sys/param.h>
61#include <sys/systm.h>
62#include <sys/kernel.h>
63#include <sys/lock.h>
64#include <sys/malloc.h>
65#include <sys/rman.h>
66#include <sys/bus.h> /* XXX debugging */
67
68static MALLOC_DEFINE(M_RMAN, "rman", "Resource manager");
69
70struct rman_head rman_head;
71#ifndef NULL_SIMPLELOCKS
72static struct simplelock rman_lock; /* mutex to protect rman_head */
73#endif
74static int int_rman_activate_resource(struct rman *rm, struct resource *r,
75 struct resource **whohas);
76static int int_rman_release_resource(struct rman *rm, struct resource *r);
77
78#define CIRCLEQ_TERMCOND(var, head) (var == (void *)&(head))
79
80int
81rman_init(struct rman *rm)
82{
83 static int once;
--- 28 unchanged lines hidden (view full) ---
112int
113rman_manage_region(struct rman *rm, u_long start, u_long end)
114{
115 struct resource *r, *s;
116
117 r = malloc(sizeof *r, M_RMAN, M_NOWAIT);
118 if (r == 0)
119 return ENOMEM;
120 r->r_sharehead = 0;
121 r->r_start = start;
122 r->r_end = end;
123 r->r_flags = 0;
124 r->r_dev = 0;
125 r->r_rm = rm;
126
127 simple_lock(rm->rm_slock);
--- 15 unchanged lines hidden (view full) ---
143int
144rman_fini(struct rman *rm)
145{
146 struct resource *r;
147
148 simple_lock(rm->rm_slock);
149 for (r = rm->rm_list.cqh_first; !CIRCLEQ_TERMCOND(r, rm->rm_list);
150 r = r->r_link.cqe_next) {
151 if (r->r_flags & RF_ALLOCATED)
152 return EBUSY;
153 }
154
155 /*
156 * There really should only be one of these if we are in this
157 * state and the code is working properly, but it can't hurt.
158 */
159 for (r = rm->rm_list.cqh_first; !CIRCLEQ_TERMCOND(r, rm->rm_list);
160 r = rm->rm_list.cqh_first) {
--- 88 unchanged lines hidden (view full) ---
249 * s->r_end > rstart + count - 1, then
250 * we need to split the region into three pieces
251 * (the middle one will get returned to the user).
252 * Otherwise, we are allocating at either the
253 * beginning or the end of s, so we only need to
254 * split it in two. The first case requires
255 * two new allocations; the second requires but one.
256 */
257 rv = malloc(sizeof *r, M_RMAN, M_NOWAIT);
258 if (rv == 0)
259 goto out;
260 rv->r_start = rstart;
261 rv->r_end = rstart + count - 1;
262 rv->r_flags = flags | RF_ALLOCATED;
263 rv->r_dev = dev;
264 rv->r_sharehead = 0;
265
266 if (s->r_start < rv->r_start && s->r_end > rv->r_end) {
267#ifdef RMAN_DEBUG
268 printf("splitting region in three parts: "
269 "[%#lx, %#lx]; [%#lx, %#lx]; [%#lx, %#lx]\n",
270 s->r_start, rv->r_start - 1,
271 rv->r_start, rv->r_end,
272 rv->r_end + 1, s->r_end);
273#endif /* RMAN_DEBUG */
274 /*
275 * We are allocating in the middle.
276 */
277 r = malloc(sizeof *r, M_RMAN, M_NOWAIT);
278 if (r == 0) {
279 free(rv, M_RMAN);
280 rv = 0;
281 goto out;
282 }
283 r->r_start = rv->r_end + 1;
284 r->r_end = s->r_end;
285 r->r_flags = s->r_flags;
286 r->r_dev = 0;
287 r->r_sharehead = 0;
288 s->r_end = rv->r_start - 1;
289 CIRCLEQ_INSERT_AFTER(&rm->rm_list, s, rv,
290 r_link);
291 CIRCLEQ_INSERT_AFTER(&rm->rm_list, rv, r,
292 r_link);
293 } else if (s->r_start == rv->r_start) {
294#ifdef RMAN_DEBUG
295 printf("allocating from the beginning\n");
--- 41 unchanged lines hidden (view full) ---
337 continue;
338 rstart = max(s->r_start, start);
339 rend = min(s->r_end, max(start + count, end));
340 if (s->r_start >= start && s->r_end <= end
341 && (s->r_end - s->r_start + 1) == count) {
342 rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT);
343 if (rv == 0)
344 goto out;
345 rv->r_start = s->r_start;
346 rv->r_end = s->r_end;
347 rv->r_flags = s->r_flags &
348 (RF_ALLOCATED | RF_SHAREABLE | RF_TIMESHARE);
349 rv->r_dev = dev;
350 rv->r_rm = rm;
351 if (s->r_sharehead == 0) {
352 s->r_sharehead = malloc(sizeof *s->r_sharehead,
353 M_RMAN, M_NOWAIT);
354 if (s->r_sharehead == 0) {
355 free(rv, M_RMAN);
356 rv = 0;
357 goto out;
358 }
359 LIST_INIT(s->r_sharehead);
360 LIST_INSERT_HEAD(s->r_sharehead, s,
361 r_sharelink);
362 s->r_flags |= RF_FIRSTSHARE;
363 }
364 rv->r_sharehead = s->r_sharehead;
365 LIST_INSERT_HEAD(s->r_sharehead, rv, r_sharelink);
366 goto out;
--- 79 unchanged lines hidden (view full) ---
446 struct resource *whohas;
447 struct rman *rm;
448
449 rm = r->r_rm;
450 for (;;) {
451 simple_lock(rm->rm_slock);
452 rv = int_rman_activate_resource(rm, r, &whohas);
453 if (rv != EBUSY)
454 return (rv);
455
456 if (r->r_sharehead == 0)
457 panic("rman_await_resource");
458 /*
459 * splhigh hopefully will prevent a race between
460 * simple_unlock and tsleep where a process
461 * could conceivably get in and release the resource
462 * before we have a chance to sleep on it.
--- 6 unchanged lines hidden (view full) ---
469 splx(s);
470 return rv;
471 }
472 simple_lock(rm->rm_slock);
473 splx(s);
474 }
475}
476
477int
478rman_deactivate_resource(struct resource *r)
479{
480 struct rman *rm;
481
482 rm = r->r_rm;
483 simple_lock(rm->rm_slock);
484 r->r_flags &= ~RF_ACTIVE;
485 if (r->r_flags & RF_WANTED) {
486 r->r_flags &= ~RF_WANTED;
487 wakeup(r->r_sharehead);
488 }
489 simple_unlock(rm->rm_slock);
490 return 0;
491}
492
493static int
494int_rman_release_resource(struct rman *rm, struct resource *r)
495{
496 struct resource *s, *t;
497
498 if (r->r_flags & RF_ACTIVE)
499 return EBUSY;
500
501 /*
502 * Check for a sharing list first. If there is one, then we don't
503 * have to think as hard.
504 */
505 if (r->r_sharehead) {
506 /*
507 * If a sharing list exists, then we know there are at
--- 84 unchanged lines hidden ---
2 * Copyright 1998 Massachusetts Institute of Technology
3 *
4 * Permission to use, copy, modify, and distribute this software and
5 * its documentation for any purpose and without fee is hereby
6 * granted, provided that both the above copyright notice and this
7 * permission notice appear in all copies, that both the above
8 * copyright notice and this permission notice appear in all
--- 12 unchanged lines hidden (view full) ---
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id: subr_rman.c,v 1.5 1999/03/29 08:30:17 dfr Exp $
30 */
31
32/*
33 * The kernel resource manager. This code is responsible for keeping track
34 * of hardware resources which are apportioned out to various drivers.
35 * It does not actually assign those resources, and it is not expected
36 * that end-device drivers will call into this code directly. Rather,
37 * the code which implements the buses that those devices are attached to,
--- 19 unchanged lines hidden (view full) ---
57 * permitted.
58 */
59
60#include <sys/param.h>
61#include <sys/systm.h>
62#include <sys/kernel.h>
63#include <sys/lock.h>
64#include <sys/malloc.h>
65#include <sys/rman.h>
66#include <sys/bus.h> /* XXX debugging */
67
68static MALLOC_DEFINE(M_RMAN, "rman", "Resource manager");
69
70struct rman_head rman_head;
71#ifndef NULL_SIMPLELOCKS
72static struct simplelock rman_lock; /* mutex to protect rman_head */
73#endif
74static int int_rman_activate_resource(struct rman *rm, struct resource *r,
75 struct resource **whohas);
76static int int_rman_release_resource(struct rman *rm, struct resource *r);
77
78#define CIRCLEQ_TERMCOND(var, head) (var == (void *)&(head))
79
80int
81rman_init(struct rman *rm)
82{
83 static int once;
--- 28 unchanged lines hidden (view full) ---
112int
113rman_manage_region(struct rman *rm, u_long start, u_long end)
114{
115 struct resource *r, *s;
116
117 r = malloc(sizeof *r, M_RMAN, M_NOWAIT);
118 if (r == 0)
119 return ENOMEM;
120 r->r_sharehead = 0;
121 r->r_start = start;
122 r->r_end = end;
123 r->r_flags = 0;
124 r->r_dev = 0;
125 r->r_rm = rm;
126
127 simple_lock(rm->rm_slock);
--- 15 unchanged lines hidden (view full) ---
143int
144rman_fini(struct rman *rm)
145{
146 struct resource *r;
147
148 simple_lock(rm->rm_slock);
149 for (r = rm->rm_list.cqh_first; !CIRCLEQ_TERMCOND(r, rm->rm_list);
150 r = r->r_link.cqe_next) {
151 if (r->r_flags & RF_ALLOCATED)
152 return EBUSY;
153 }
154
155 /*
156 * There really should only be one of these if we are in this
157 * state and the code is working properly, but it can't hurt.
158 */
159 for (r = rm->rm_list.cqh_first; !CIRCLEQ_TERMCOND(r, rm->rm_list);
160 r = rm->rm_list.cqh_first) {
--- 88 unchanged lines hidden (view full) ---
249 * s->r_end > rstart + count - 1, then
250 * we need to split the region into three pieces
251 * (the middle one will get returned to the user).
252 * Otherwise, we are allocating at either the
253 * beginning or the end of s, so we only need to
254 * split it in two. The first case requires
255 * two new allocations; the second requires but one.
256 */
257 rv = malloc(sizeof *r, M_RMAN, M_NOWAIT);
258 if (rv == 0)
259 goto out;
260 rv->r_start = rstart;
261 rv->r_end = rstart + count - 1;
262 rv->r_flags = flags | RF_ALLOCATED;
263 rv->r_dev = dev;
264 rv->r_sharehead = 0;
265
266 if (s->r_start < rv->r_start && s->r_end > rv->r_end) {
267#ifdef RMAN_DEBUG
268 printf("splitting region in three parts: "
269 "[%#lx, %#lx]; [%#lx, %#lx]; [%#lx, %#lx]\n",
270 s->r_start, rv->r_start - 1,
271 rv->r_start, rv->r_end,
272 rv->r_end + 1, s->r_end);
273#endif /* RMAN_DEBUG */
274 /*
275 * We are allocating in the middle.
276 */
277 r = malloc(sizeof *r, M_RMAN, M_NOWAIT);
278 if (r == 0) {
279 free(rv, M_RMAN);
280 rv = 0;
281 goto out;
282 }
283 r->r_start = rv->r_end + 1;
284 r->r_end = s->r_end;
285 r->r_flags = s->r_flags;
286 r->r_dev = 0;
287 r->r_sharehead = 0;
288 s->r_end = rv->r_start - 1;
289 CIRCLEQ_INSERT_AFTER(&rm->rm_list, s, rv,
290 r_link);
291 CIRCLEQ_INSERT_AFTER(&rm->rm_list, rv, r,
292 r_link);
293 } else if (s->r_start == rv->r_start) {
294#ifdef RMAN_DEBUG
295 printf("allocating from the beginning\n");
--- 41 unchanged lines hidden (view full) ---
337 continue;
338 rstart = max(s->r_start, start);
339 rend = min(s->r_end, max(start + count, end));
340 if (s->r_start >= start && s->r_end <= end
341 && (s->r_end - s->r_start + 1) == count) {
342 rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT);
343 if (rv == 0)
344 goto out;
345 rv->r_start = s->r_start;
346 rv->r_end = s->r_end;
347 rv->r_flags = s->r_flags &
348 (RF_ALLOCATED | RF_SHAREABLE | RF_TIMESHARE);
349 rv->r_dev = dev;
350 rv->r_rm = rm;
351 if (s->r_sharehead == 0) {
352 s->r_sharehead = malloc(sizeof *s->r_sharehead,
353 M_RMAN, M_NOWAIT);
354 if (s->r_sharehead == 0) {
355 free(rv, M_RMAN);
356 rv = 0;
357 goto out;
358 }
359 LIST_INIT(s->r_sharehead);
360 LIST_INSERT_HEAD(s->r_sharehead, s,
361 r_sharelink);
362 s->r_flags |= RF_FIRSTSHARE;
363 }
364 rv->r_sharehead = s->r_sharehead;
365 LIST_INSERT_HEAD(s->r_sharehead, rv, r_sharelink);
366 goto out;
--- 79 unchanged lines hidden (view full) ---
446 struct resource *whohas;
447 struct rman *rm;
448
449 rm = r->r_rm;
450 for (;;) {
451 simple_lock(rm->rm_slock);
452 rv = int_rman_activate_resource(rm, r, &whohas);
453 if (rv != EBUSY)
454 return (rv);
455
456 if (r->r_sharehead == 0)
457 panic("rman_await_resource");
458 /*
459 * splhigh hopefully will prevent a race between
460 * simple_unlock and tsleep where a process
461 * could conceivably get in and release the resource
462 * before we have a chance to sleep on it.
--- 6 unchanged lines hidden (view full) ---
469 splx(s);
470 return rv;
471 }
472 simple_lock(rm->rm_slock);
473 splx(s);
474 }
475}
476
477int
478rman_deactivate_resource(struct resource *r)
479{
480 struct rman *rm;
481
482 rm = r->r_rm;
483 simple_lock(rm->rm_slock);
484 r->r_flags &= ~RF_ACTIVE;
485 if (r->r_flags & RF_WANTED) {
486 r->r_flags &= ~RF_WANTED;
487 wakeup(r->r_sharehead);
488 }
489 simple_unlock(rm->rm_slock);
490 return 0;
491}
492
493static int
494int_rman_release_resource(struct rman *rm, struct resource *r)
495{
496 struct resource *s, *t;
497
498 if (r->r_flags & RF_ACTIVE)
499 return EBUSY;
500
501 /*
502 * Check for a sharing list first. If there is one, then we don't
503 * have to think as hard.
504 */
505 if (r->r_sharehead) {
506 /*
507 * If a sharing list exists, then we know there are at
--- 84 unchanged lines hidden ---