subr_rman.c (45569) | subr_rman.c (45720) |
---|---|
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 * | 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 $ | 29 * $Id: subr_rman.c,v 1.6 1999/04/11 02:27:06 eivind 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> | 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 */ | 65#include <sys/bus.h> /* XXX debugging */ |
66#include <machine/bus.h> 67#include <sys/rman.h> |
|
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); | 68 69static MALLOC_DEFINE(M_RMAN, "rman", "Resource manager"); 70 71struct rman_head rman_head; 72#ifndef NULL_SIMPLELOCKS 73static struct simplelock rman_lock; /* mutex to protect rman_head */ 74#endif 75static int int_rman_activate_resource(struct rman *rm, struct resource *r, 76 struct resource **whohas); |
77static int int_rman_deactivate_resource(struct resource *r); |
|
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; | 78static int int_rman_release_resource(struct rman *rm, struct resource *r); 79 80#define CIRCLEQ_TERMCOND(var, head) (var == (void *)&(head)) 81 82int 83rman_init(struct rman *rm) 84{ 85 static int once; --- 28 unchanged lines hidden (view full) --- 114int 115rman_manage_region(struct rman *rm, u_long start, u_long end) 116{ 117 struct resource *r, *s; 118 119 r = malloc(sizeof *r, M_RMAN, M_NOWAIT); 120 if (r == 0) 121 return ENOMEM; |
122 bzero(r, sizeof *r); |
|
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) { | 123 r->r_sharehead = 0; 124 r->r_start = start; 125 r->r_end = end; 126 r->r_flags = 0; 127 r->r_dev = 0; 128 r->r_rm = rm; 129 130 simple_lock(rm->rm_slock); --- 15 unchanged lines hidden (view full) --- 146int 147rman_fini(struct rman *rm) 148{ 149 struct resource *r; 150 151 simple_lock(rm->rm_slock); 152 for (r = rm->rm_list.cqh_first; !CIRCLEQ_TERMCOND(r, rm->rm_list); 153 r = r->r_link.cqe_next) { |
151 if (r->r_flags & RF_ALLOCATED) | 154 if (r->r_flags & RF_ALLOCATED) { 155 simple_unlock(rm->rm_slock); |
152 return EBUSY; | 156 return EBUSY; |
157 } |
|
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 */ | 158 } 159 160 /* 161 * There really should only be one of these if we are in this 162 * state and the code is working properly, but it can't hurt. 163 */ 164 for (r = rm->rm_list.cqh_first; !CIRCLEQ_TERMCOND(r, rm->rm_list); 165 r = rm->rm_list.cqh_first) { --- 88 unchanged lines hidden (view full) --- 254 * s->r_end > rstart + count - 1, then 255 * we need to split the region into three pieces 256 * (the middle one will get returned to the user). 257 * Otherwise, we are allocating at either the 258 * beginning or the end of s, so we only need to 259 * split it in two. The first case requires 260 * two new allocations; the second requires but one. 261 */ |
257 rv = malloc(sizeof *r, M_RMAN, M_NOWAIT); | 262 rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT); |
258 if (rv == 0) 259 goto out; | 263 if (rv == 0) 264 goto out; |
265 bzero(rv, sizeof *rv); |
|
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; | 266 rv->r_start = rstart; 267 rv->r_end = rstart + count - 1; 268 rv->r_flags = flags | RF_ALLOCATED; 269 rv->r_dev = dev; 270 rv->r_sharehead = 0; |
271 rv->r_rm = rm; |
|
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 } | 272 273 if (s->r_start < rv->r_start && s->r_end > rv->r_end) { 274#ifdef RMAN_DEBUG 275 printf("splitting region in three parts: " 276 "[%#lx, %#lx]; [%#lx, %#lx]; [%#lx, %#lx]\n", 277 s->r_start, rv->r_start - 1, 278 rv->r_start, rv->r_end, 279 rv->r_end + 1, s->r_end); 280#endif /* RMAN_DEBUG */ 281 /* 282 * We are allocating in the middle. 283 */ 284 r = malloc(sizeof *r, M_RMAN, M_NOWAIT); 285 if (r == 0) { 286 free(rv, M_RMAN); 287 rv = 0; 288 goto out; 289 } |
290 bzero(r, sizeof *r); |
|
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; | 291 r->r_start = rv->r_end + 1; 292 r->r_end = s->r_end; 293 r->r_flags = s->r_flags; 294 r->r_dev = 0; 295 r->r_sharehead = 0; |
296 r->r_rm = rm; |
|
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; | 297 s->r_end = rv->r_start - 1; 298 CIRCLEQ_INSERT_AFTER(&rm->rm_list, s, rv, 299 r_link); 300 CIRCLEQ_INSERT_AFTER(&rm->rm_list, rv, r, 301 r_link); 302 } else if (s->r_start == rv->r_start) { 303#ifdef RMAN_DEBUG 304 printf("allocating from the beginning\n"); --- 41 unchanged lines hidden (view full) --- 346 continue; 347 rstart = max(s->r_start, start); 348 rend = min(s->r_end, max(start + count, end)); 349 if (s->r_start >= start && s->r_end <= end 350 && (s->r_end - s->r_start + 1) == count) { 351 rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT); 352 if (rv == 0) 353 goto out; |
354 bzero(rv, sizeof *rv); |
|
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 } | 355 rv->r_start = s->r_start; 356 rv->r_end = s->r_end; 357 rv->r_flags = s->r_flags & 358 (RF_ALLOCATED | RF_SHAREABLE | RF_TIMESHARE); 359 rv->r_dev = dev; 360 rv->r_rm = rm; 361 if (s->r_sharehead == 0) { 362 s->r_sharehead = malloc(sizeof *s->r_sharehead, 363 M_RMAN, M_NOWAIT); 364 if (s->r_sharehead == 0) { 365 free(rv, M_RMAN); 366 rv = 0; 367 goto out; 368 } |
369 bzero(s->r_sharehead, sizeof *s->r_sharehead); |
|
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) | 370 LIST_INIT(s->r_sharehead); 371 LIST_INSERT_HEAD(s->r_sharehead, s, 372 r_sharelink); 373 s->r_flags |= RF_FIRSTSHARE; 374 } 375 rv->r_sharehead = s->r_sharehead; 376 LIST_INSERT_HEAD(s->r_sharehead, rv, r_sharelink); 377 goto out; --- 79 unchanged lines hidden (view full) --- 457 struct resource *whohas; 458 struct rman *rm; 459 460 rm = r->r_rm; 461 for (;;) { 462 simple_lock(rm->rm_slock); 463 rv = int_rman_activate_resource(rm, r, &whohas); 464 if (rv != EBUSY) |
454 return (rv); | 465 return (rv); /* returns with simplelock */ |
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 | 466 467 if (r->r_sharehead == 0) 468 panic("rman_await_resource"); 469 /* 470 * splhigh hopefully will prevent a race between 471 * simple_unlock and tsleep where a process 472 * could conceivably get in and release the resource 473 * before we have a chance to sleep on it. --- 6 unchanged lines hidden (view full) --- 480 splx(s); 481 return rv; 482 } 483 simple_lock(rm->rm_slock); 484 splx(s); 485 } 486} 487 |
477int 478rman_deactivate_resource(struct resource *r) | 488static int 489int_rman_deactivate_resource(struct resource *r) |
479{ 480 struct rman *rm; 481 482 rm = r->r_rm; | 490{ 491 struct rman *rm; 492 493 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 } | 494 r->r_flags &= ~RF_ACTIVE; 495 if (r->r_flags & RF_WANTED) { 496 r->r_flags &= ~RF_WANTED; 497 wakeup(r->r_sharehead); 498 } |
499 return 0; 500} 501 502int 503rman_deactivate_resource(struct resource *r) 504{ 505 struct rman *rm; 506 507 rm = r->r_rm; 508 simple_lock(rm->rm_slock); 509 int_rman_deactivate_resource(r); |
|
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) | 510 simple_unlock(rm->rm_slock); 511 return 0; 512} 513 514static int 515int_rman_release_resource(struct rman *rm, struct resource *r) 516{ 517 struct resource *s, *t; 518 519 if (r->r_flags & RF_ACTIVE) |
499 return EBUSY; | 520 int_rman_deactivate_resource(r); |
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 --- | 521 522 /* 523 * Check for a sharing list first. If there is one, then we don't 524 * have to think as hard. 525 */ 526 if (r->r_sharehead) { 527 /* 528 * If a sharing list exists, then we know there are at --- 84 unchanged lines hidden --- |