diff options
| author | Nick Barnes | 2001-10-31 14:40:56 +0000 |
|---|---|---|
| committer | Nick Barnes | 2001-10-31 14:40:56 +0000 |
| commit | 7acfca905d76140f4cc0b09c9a12de237de364cd (patch) | |
| tree | 3ed8babfa3a73d30f29e08ca5d5adcda4ca4e826 /mps/code/pool.c | |
| parent | b7ce4893f9902d57cd67ac9a92fa6c3d5a8fc833 (diff) | |
| download | emacs-7acfca905d76140f4cc0b09c9a12de237de364cd.tar.gz emacs-7acfca905d76140f4cc0b09c9a12de237de364cd.zip | |
Branch imports for masters.
Copied from Perforce
Change: 23678
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code/pool.c')
| -rw-r--r-- | mps/code/pool.c | 576 |
1 files changed, 576 insertions, 0 deletions
diff --git a/mps/code/pool.c b/mps/code/pool.c new file mode 100644 index 00000000000..b02f41f638b --- /dev/null +++ b/mps/code/pool.c | |||
| @@ -0,0 +1,576 @@ | |||
| 1 | /* impl.c.pool: POOL IMPLEMENTATION | ||
| 2 | * | ||
| 3 | * $HopeName: MMsrc!pool.c(trunk.75) $ | ||
| 4 | * Copyright (C) 2001 Harlequin Limited. All rights reserved. | ||
| 5 | * | ||
| 6 | * DESIGN | ||
| 7 | * | ||
| 8 | * .design: See design.mps.class-interface and design.mps.pool. | ||
| 9 | * | ||
| 10 | * PURPOSE | ||
| 11 | * | ||
| 12 | * .purpose: This is the implementation of the generic pool interface. | ||
| 13 | * There are three sorts of functions provided: | ||
| 14 | * .purpose.support: Support functions for manipulating and accessing | ||
| 15 | * Pool and PoolClass objects (create, destroy, check, various | ||
| 16 | * accessors, and other miscellaneous functions). | ||
| 17 | * .purpose.dispatch: Dispatch functions that implement the generic | ||
| 18 | * function dispatch mechanism for Pool Classes (PoolAlloc, PoolFix, | ||
| 19 | * etc.). | ||
| 20 | * .purpose.core: A selection of default, trivial, or useful methods | ||
| 21 | * that Pool Classes can use as the implementations for some of their | ||
| 22 | * methods (such as PoolTrivWhiten, PoolNoFix, etc.). | ||
| 23 | * | ||
| 24 | * SOURCES | ||
| 25 | * | ||
| 26 | * .source: See .design also. PoolStruct and PoolClassStruct, the | ||
| 27 | * central types for this module, are defined in impl.h.mpmst, the | ||
| 28 | * corresponding abstract types in impl.h.mpmtypes. Declarations and | ||
| 29 | * prototypes are in impl.h.mpm. Several functions have macro versions | ||
| 30 | * defined in impl.h.mpm. */ | ||
| 31 | |||
| 32 | #include "mpm.h" | ||
| 33 | |||
| 34 | SRCID(pool, "$HopeName: MMsrc!pool.c(trunk.75) $"); | ||
| 35 | |||
| 36 | |||
| 37 | /* PoolClassCheck -- check a pool class */ | ||
| 38 | |||
| 39 | Bool PoolClassCheck(PoolClass class) | ||
| 40 | { | ||
| 41 | CHECKL(ProtocolClassCheck(&class->protocol)); | ||
| 42 | CHECKL(class->name != NULL); /* Should be <=6 char C identifier */ | ||
| 43 | CHECKL(class->size >= sizeof(PoolStruct)); | ||
| 44 | /* Offset of generic Pool within class-specific instance cannot be */ | ||
| 45 | /* greater than the size of the class-specific portion of the instance */ | ||
| 46 | CHECKL(class->offset <= (size_t)(class->size - sizeof(PoolStruct))); | ||
| 47 | CHECKL(AttrCheck(class->attr)); | ||
| 48 | CHECKL(FUNCHECK(class->init)); | ||
| 49 | CHECKL(FUNCHECK(class->finish)); | ||
| 50 | CHECKL(FUNCHECK(class->alloc)); | ||
| 51 | CHECKL(FUNCHECK(class->free)); | ||
| 52 | CHECKL(FUNCHECK(class->bufferFill)); | ||
| 53 | CHECKL(FUNCHECK(class->bufferEmpty)); | ||
| 54 | CHECKL(FUNCHECK(class->whiten)); | ||
| 55 | CHECKL(FUNCHECK(class->grey)); | ||
| 56 | CHECKL(FUNCHECK(class->scan)); | ||
| 57 | CHECKL(FUNCHECK(class->fix)); | ||
| 58 | CHECKL(FUNCHECK(class->reclaim)); | ||
| 59 | CHECKL(FUNCHECK(class->rampBegin)); | ||
| 60 | CHECKL(FUNCHECK(class->rampEnd)); | ||
| 61 | CHECKL(FUNCHECK(class->framePush)); | ||
| 62 | CHECKL(FUNCHECK(class->framePop)); | ||
| 63 | CHECKL(FUNCHECK(class->framePopPending)); | ||
| 64 | CHECKL(FUNCHECK(class->walk)); | ||
| 65 | CHECKL(FUNCHECK(class->describe)); | ||
| 66 | CHECKS(PoolClass, class); | ||
| 67 | return TRUE; | ||
| 68 | } | ||
| 69 | |||
| 70 | |||
| 71 | /* PoolCheck -- check the generic part of a pool */ | ||
| 72 | |||
| 73 | Bool PoolCheck(Pool pool) | ||
| 74 | { | ||
| 75 | /* Checks ordered as per struct decl in impl.h.mpmst.pool */ | ||
| 76 | CHECKS(Pool, pool); | ||
| 77 | /* Break modularity for checking efficiency */ | ||
| 78 | CHECKL(pool->serial < ArenaGlobals(pool->arena)->poolSerial); | ||
| 79 | CHECKD(PoolClass, pool->class); | ||
| 80 | CHECKU(Arena, pool->arena); | ||
| 81 | CHECKL(RingCheck(&pool->arenaRing)); | ||
| 82 | CHECKL(RingCheck(&pool->bufferRing)); | ||
| 83 | /* Cannot check pool->bufferSerial */ | ||
| 84 | CHECKL(RingCheck(&pool->segRing)); | ||
| 85 | CHECKL(AlignCheck(pool->alignment)); | ||
| 86 | /* normally pool->format iff pool->class->attr&AttrFMT, but not */ | ||
| 87 | /* during pool initialization */ | ||
| 88 | if (pool->format != NULL) { | ||
| 89 | CHECKL((pool->class->attr & AttrFMT) != 0); | ||
| 90 | } | ||
| 91 | CHECKL(pool->fillMutatorSize >= 0.0); | ||
| 92 | CHECKL(pool->emptyMutatorSize >= 0.0); | ||
| 93 | CHECKL(pool->fillInternalSize >= 0.0); | ||
| 94 | CHECKL(pool->emptyInternalSize >= 0.0); | ||
| 95 | return TRUE; | ||
| 96 | } | ||
| 97 | |||
| 98 | |||
| 99 | /* PoolInit, PoolInitV -- initialize a pool | ||
| 100 | * | ||
| 101 | * Initialize the generic fields of the pool and calls class-specific | ||
| 102 | * init. See design.mps.pool.align. */ | ||
| 103 | |||
| 104 | Res PoolInit(Pool pool, Arena arena, PoolClass class, ...) | ||
| 105 | { | ||
| 106 | Res res; | ||
| 107 | va_list args; | ||
| 108 | va_start(args, class); | ||
| 109 | res = PoolInitV(pool, arena, class, args); | ||
| 110 | va_end(args); | ||
| 111 | return res; | ||
| 112 | } | ||
| 113 | |||
| 114 | Res PoolInitV(Pool pool, Arena arena, PoolClass class, va_list args) | ||
| 115 | { | ||
| 116 | Res res; | ||
| 117 | Word classId; | ||
| 118 | Globals globals; | ||
| 119 | |||
| 120 | AVER(pool != NULL); | ||
| 121 | AVERT(Arena, arena); | ||
| 122 | AVERT(PoolClass, class); | ||
| 123 | globals = ArenaGlobals(arena); | ||
| 124 | |||
| 125 | pool->class = class; | ||
| 126 | /* label the pool class with its name */ | ||
| 127 | if (!class->labelled) { | ||
| 128 | /* We could still get multiple labelling if multiple instances of */ | ||
| 129 | /* the pool class get created simultaneously, but it's not worth */ | ||
| 130 | /* putting another lock in the code. */ | ||
| 131 | class->labelled = TRUE; | ||
| 132 | classId = EventInternString(class->name); | ||
| 133 | /* @@@@ this breaks design.mps.type.addr.use */ | ||
| 134 | EventLabelAddr((Addr)class, classId); | ||
| 135 | } | ||
| 136 | |||
| 137 | pool->arena = arena; | ||
| 138 | RingInit(&pool->arenaRing); | ||
| 139 | RingInit(&pool->bufferRing); | ||
| 140 | RingInit(&pool->segRing); | ||
| 141 | pool->bufferSerial = (Serial)0; | ||
| 142 | pool->alignment = MPS_PF_ALIGN; | ||
| 143 | pool->format = NULL; | ||
| 144 | pool->fix = class->fix; | ||
| 145 | pool->fillMutatorSize = 0.0; | ||
| 146 | pool->emptyMutatorSize = 0.0; | ||
| 147 | pool->fillInternalSize = 0.0; | ||
| 148 | pool->emptyInternalSize = 0.0; | ||
| 149 | |||
| 150 | /* Initialise signature last; see design.mps.sig */ | ||
| 151 | pool->sig = PoolSig; | ||
| 152 | pool->serial = globals->poolSerial; | ||
| 153 | ++(globals->poolSerial); | ||
| 154 | |||
| 155 | AVERT(Pool, pool); | ||
| 156 | |||
| 157 | /* Do class-specific initialization. */ | ||
| 158 | res = (*class->init)(pool, args); | ||
| 159 | if (res != ResOK) | ||
| 160 | goto failInit; | ||
| 161 | |||
| 162 | /* Add initialized pool to list of pools in arena. */ | ||
| 163 | RingAppend(&globals->poolRing, &pool->arenaRing); | ||
| 164 | |||
| 165 | return ResOK; | ||
| 166 | |||
| 167 | failInit: | ||
| 168 | pool->sig = SigInvalid; /* Leave arena->poolSerial incremented */ | ||
| 169 | RingFinish(&pool->segRing); | ||
| 170 | RingFinish(&pool->bufferRing); | ||
| 171 | RingFinish(&pool->arenaRing); | ||
| 172 | return res; | ||
| 173 | } | ||
| 174 | |||
| 175 | |||
| 176 | /* PoolCreate, PoolCreateV: Allocate and initialise pool */ | ||
| 177 | |||
| 178 | Res PoolCreate(Pool *poolReturn, Arena arena, | ||
| 179 | PoolClass class, ...) | ||
| 180 | { | ||
| 181 | Res res; | ||
| 182 | va_list args; | ||
| 183 | va_start(args, class); | ||
| 184 | res = PoolCreateV(poolReturn, arena, class, args); | ||
| 185 | va_end(args); | ||
| 186 | return res; | ||
| 187 | } | ||
| 188 | |||
| 189 | Res PoolCreateV(Pool *poolReturn, Arena arena, | ||
| 190 | PoolClass class, va_list args) | ||
| 191 | { | ||
| 192 | Res res; | ||
| 193 | Pool pool; | ||
| 194 | void *base; | ||
| 195 | |||
| 196 | AVER(poolReturn != NULL); | ||
| 197 | AVERT(Arena, arena); | ||
| 198 | AVERT(PoolClass, class); | ||
| 199 | |||
| 200 | /* .space.alloc: Allocate the pool instance structure with the size */ | ||
| 201 | /* requested in the pool class. See .space.free */ | ||
| 202 | res = ControlAlloc(&base, arena, class->size, | ||
| 203 | /* withReservoirPermit */ FALSE); | ||
| 204 | if (res != ResOK) | ||
| 205 | goto failControlAlloc; | ||
| 206 | |||
| 207 | /* base is the address of the class-specific pool structure. */ | ||
| 208 | /* We calculate the address of the generic pool structure within the */ | ||
| 209 | /* instance by using the offset information from the class. */ | ||
| 210 | pool = (Pool)PointerAdd(base, class->offset); | ||
| 211 | |||
| 212 | /* Initialize the pool. */ | ||
| 213 | res = PoolInitV(pool, arena, class, args); | ||
| 214 | if (res != ResOK) | ||
| 215 | goto failPoolInit; | ||
| 216 | |||
| 217 | *poolReturn = pool; | ||
| 218 | return ResOK; | ||
| 219 | |||
| 220 | failPoolInit: | ||
| 221 | ControlFree(arena, base, class->size); | ||
| 222 | failControlAlloc: | ||
| 223 | return res; | ||
| 224 | } | ||
| 225 | |||
| 226 | |||
| 227 | /* PoolFinish -- Finish pool including class-specific and generic fields. */ | ||
| 228 | |||
| 229 | void PoolFinish(Pool pool) | ||
| 230 | { | ||
| 231 | AVERT(Pool, pool); | ||
| 232 | |||
| 233 | /* Do any class-specific finishing. */ | ||
| 234 | (*pool->class->finish)(pool); | ||
| 235 | |||
| 236 | /* Detach the pool from the arena, and unsig it. */ | ||
| 237 | RingRemove(&pool->arenaRing); | ||
| 238 | pool->sig = SigInvalid; | ||
| 239 | |||
| 240 | RingFinish(&pool->segRing); | ||
| 241 | RingFinish(&pool->bufferRing); | ||
| 242 | RingFinish(&pool->arenaRing); | ||
| 243 | |||
| 244 | EVENT_P(PoolFinish, pool); | ||
| 245 | } | ||
| 246 | |||
| 247 | |||
| 248 | /* PoolDestroy -- Finish and free pool. */ | ||
| 249 | |||
| 250 | void PoolDestroy(Pool pool) | ||
| 251 | { | ||
| 252 | PoolClass class; | ||
| 253 | Arena arena; | ||
| 254 | Addr base; | ||
| 255 | |||
| 256 | AVERT(Pool, pool); | ||
| 257 | |||
| 258 | class = pool->class; /* } In case PoolFinish changes these */ | ||
| 259 | arena = pool->arena; /* } */ | ||
| 260 | |||
| 261 | /* Finish the pool instance structure. */ | ||
| 262 | PoolFinish(pool); | ||
| 263 | |||
| 264 | /* .space.free: Free the pool instance structure. See .space.alloc */ | ||
| 265 | base = AddrSub((Addr)pool, (Size)(class->offset)); | ||
| 266 | ControlFree(arena, base, (Size)(class->size)); | ||
| 267 | } | ||
| 268 | |||
| 269 | |||
| 270 | /* PoolDefaultBufferClass -- return the buffer class used by the pool */ | ||
| 271 | |||
| 272 | BufferClass PoolDefaultBufferClass(Pool pool) | ||
| 273 | { | ||
| 274 | AVERT(Pool, pool); | ||
| 275 | return (*pool->class->bufferClass)(); | ||
| 276 | } | ||
| 277 | |||
| 278 | |||
| 279 | /* PoolAlloc -- allocate a block of memory from a pool */ | ||
| 280 | |||
| 281 | Res PoolAlloc(Addr *pReturn, Pool pool, Size size, | ||
| 282 | Bool withReservoirPermit) | ||
| 283 | { | ||
| 284 | Res res; | ||
| 285 | |||
| 286 | AVER(pReturn != NULL); | ||
| 287 | AVERT(Pool, pool); | ||
| 288 | AVER((pool->class->attr & AttrALLOC) != 0); | ||
| 289 | AVER(size > 0); | ||
| 290 | AVER(BoolCheck(withReservoirPermit)); | ||
| 291 | |||
| 292 | res = (*pool->class->alloc)(pReturn, pool, size, withReservoirPermit); | ||
| 293 | if (res != ResOK) | ||
| 294 | return res; | ||
| 295 | /* Make sure that the allocated address was in the pool's memory. */ | ||
| 296 | /* .hasaddr.critical: The PoolHasAddr check is expensive, and in */ | ||
| 297 | /* allocation-bound programs this is on the critical path. */ | ||
| 298 | AVER_CRITICAL(PoolHasAddr(pool, *pReturn)); | ||
| 299 | |||
| 300 | /* All PoolAllocs should advance the allocation clock, so we count */ | ||
| 301 | /* it all in the fillMutatorSize field. */ | ||
| 302 | pool->fillMutatorSize += size; | ||
| 303 | ArenaGlobals(PoolArena(pool))->fillMutatorSize += size; | ||
| 304 | |||
| 305 | EVENT_PAW(PoolAlloc, pool, *pReturn, size); | ||
| 306 | |||
| 307 | return ResOK; | ||
| 308 | } | ||
| 309 | |||
| 310 | |||
| 311 | /* PoolFree -- deallocate a block of memory allocated from the pool */ | ||
| 312 | |||
| 313 | void PoolFree(Pool pool, Addr old, Size size) | ||
| 314 | { | ||
| 315 | AVERT(Pool, pool); | ||
| 316 | AVER((pool->class->attr & AttrFREE) != 0); | ||
| 317 | AVER(old != NULL); | ||
| 318 | /* The pool methods should check that old is in pool. */ | ||
| 319 | AVER(size > 0); | ||
| 320 | (*pool->class->free)(pool, old, size); | ||
| 321 | |||
| 322 | EVENT_PAW(PoolFree, pool, old, size); | ||
| 323 | } | ||
| 324 | |||
| 325 | |||
| 326 | Res PoolAccess(Pool pool, Seg seg, Addr addr, | ||
| 327 | AccessSet mode, MutatorFaultContext context) | ||
| 328 | { | ||
| 329 | AVERT(Pool, pool); | ||
| 330 | AVERT(Seg, seg); | ||
| 331 | AVER(SegBase(seg) <= addr); | ||
| 332 | AVER(addr < SegLimit(seg)); | ||
| 333 | /* Can't check mode as there is no check method */ | ||
| 334 | /* Can't check MutatorFaultContext as there is no check method */ | ||
| 335 | |||
| 336 | return (*pool->class->access)(pool, seg, addr, mode, context); | ||
| 337 | } | ||
| 338 | |||
| 339 | |||
| 340 | /* PoolWhiten, PoolGrey, PoolBlacken -- change color of a segment in the pool */ | ||
| 341 | |||
| 342 | Res PoolWhiten(Pool pool, Trace trace, Seg seg) | ||
| 343 | { | ||
| 344 | AVERT(Pool, pool); | ||
| 345 | AVERT(Trace, trace); | ||
| 346 | AVERT(Seg, seg); | ||
| 347 | AVER(PoolArena(pool) == trace->arena); | ||
| 348 | AVER(SegPool(seg) == pool); | ||
| 349 | return (*pool->class->whiten)(pool, trace, seg); | ||
| 350 | } | ||
| 351 | |||
| 352 | void PoolGrey(Pool pool, Trace trace, Seg seg) | ||
| 353 | { | ||
| 354 | AVERT(Pool, pool); | ||
| 355 | AVERT(Trace, trace); | ||
| 356 | AVERT(Seg, seg); | ||
| 357 | AVER(pool->arena == trace->arena); | ||
| 358 | AVER(SegPool(seg) == pool); | ||
| 359 | (*pool->class->grey)(pool, trace, seg); | ||
| 360 | } | ||
| 361 | |||
| 362 | void PoolBlacken(Pool pool, TraceSet traceSet, Seg seg) | ||
| 363 | { | ||
| 364 | AVERT(Pool, pool); | ||
| 365 | AVERT(TraceSet, traceSet); | ||
| 366 | AVERT(Seg, seg); | ||
| 367 | AVER(SegPool(seg) == pool); | ||
| 368 | (*pool->class->blacken)(pool, traceSet, seg); | ||
| 369 | } | ||
| 370 | |||
| 371 | |||
| 372 | /* PoolScan -- scan a segment in the pool */ | ||
| 373 | |||
| 374 | Res PoolScan(Bool *totalReturn, ScanState ss, Pool pool, Seg seg) | ||
| 375 | { | ||
| 376 | AVER(totalReturn != NULL); | ||
| 377 | AVERT(ScanState, ss); | ||
| 378 | AVERT(Pool, pool); | ||
| 379 | AVERT(Seg, seg); | ||
| 380 | AVER(ss->arena == pool->arena); | ||
| 381 | |||
| 382 | /* The segment must belong to the pool. */ | ||
| 383 | AVER(pool == SegPool(seg)); | ||
| 384 | |||
| 385 | /* We actually want to check that the rank we are scanning at */ | ||
| 386 | /* (ss->rank) is at least as big as all the ranks in */ | ||
| 387 | /* the segment (SegRankSet(seg)). It is tricky to check that, */ | ||
| 388 | /* so we only check that either ss->rank is in the segment's */ | ||
| 389 | /* ranks, or that ss->rank is exact. */ | ||
| 390 | /* See impl.c.trace.scan.conservative */ | ||
| 391 | AVER(ss->rank == RankEXACT || RankSetIsMember(SegRankSet(seg), ss->rank)); | ||
| 392 | |||
| 393 | /* Should only scan segments which contain grey objects. */ | ||
| 394 | AVER(TraceSetInter(SegGrey(seg), ss->traces) != TraceSetEMPTY); | ||
| 395 | |||
| 396 | return (*pool->class->scan)(totalReturn, ss, pool, seg); | ||
| 397 | } | ||
| 398 | |||
| 399 | |||
| 400 | /* PoolFix* -- fix a reference to an object in this pool | ||
| 401 | * | ||
| 402 | * See impl.h.mpm for macro version; see design.mps.pool.req.fix. */ | ||
| 403 | |||
| 404 | Res (PoolFix)(Pool pool, ScanState ss, Seg seg, Addr *refIO) | ||
| 405 | { | ||
| 406 | AVERT(Pool, pool); | ||
| 407 | AVERT(ScanState, ss); | ||
| 408 | AVERT(Seg, seg); | ||
| 409 | AVER(pool == SegPool(seg)); | ||
| 410 | AVER(refIO != NULL); | ||
| 411 | |||
| 412 | /* Should only be fixing references to white segments. */ | ||
| 413 | AVER(TraceSetInter(SegWhite(seg), ss->traces) != TraceSetEMPTY); | ||
| 414 | |||
| 415 | return PoolFix(pool, ss, seg, refIO); | ||
| 416 | } | ||
| 417 | |||
| 418 | void PoolFixEmergency(Pool pool, ScanState ss, Seg seg, Addr *refIO) | ||
| 419 | { | ||
| 420 | Res res; | ||
| 421 | |||
| 422 | AVERT(Pool, pool); | ||
| 423 | AVERT(ScanState, ss); | ||
| 424 | AVERT(Seg, seg); | ||
| 425 | AVER(pool == SegPool(seg)); | ||
| 426 | AVER(refIO != NULL); | ||
| 427 | |||
| 428 | /* Should only be fixing references to white segments. */ | ||
| 429 | AVER(TraceSetInter(SegWhite(seg), ss->traces) != TraceSetEMPTY); | ||
| 430 | |||
| 431 | res = (pool->class->fixEmergency)(pool, ss, seg, refIO); | ||
| 432 | AVER(res == ResOK); | ||
| 433 | } | ||
| 434 | |||
| 435 | |||
| 436 | /* PoolReclaim -- reclaim a segment in the pool */ | ||
| 437 | |||
| 438 | void PoolReclaim(Pool pool, Trace trace, Seg seg) | ||
| 439 | { | ||
| 440 | AVERT_CRITICAL(Pool, pool); | ||
| 441 | AVERT_CRITICAL(Trace, trace); | ||
| 442 | AVERT_CRITICAL(Seg, seg); | ||
| 443 | AVER_CRITICAL(pool->arena == trace->arena); | ||
| 444 | AVER_CRITICAL(SegPool(seg) == pool); | ||
| 445 | |||
| 446 | /* There shouldn't be any grey things left for this trace. */ | ||
| 447 | AVER_CRITICAL(!TraceSetIsMember(SegGrey(seg), trace)); | ||
| 448 | /* Should only be reclaiming segments which are still white. */ | ||
| 449 | AVER_CRITICAL(TraceSetIsMember(SegWhite(seg), trace)); | ||
| 450 | |||
| 451 | (*pool->class->reclaim)(pool, trace, seg); | ||
| 452 | } | ||
| 453 | |||
| 454 | |||
| 455 | /* PoolWalk -- walk objects in this pool */ | ||
| 456 | |||
| 457 | void PoolWalk(Pool pool, Seg seg, FormattedObjectsStepMethod f, | ||
| 458 | void *p, Size s) | ||
| 459 | { | ||
| 460 | AVERT(Pool, pool); | ||
| 461 | AVERT(Seg, seg); | ||
| 462 | AVER(FUNCHECK(f)); | ||
| 463 | /* p and s are arbitrary values, hence can't be checked. */ | ||
| 464 | |||
| 465 | (*pool->class->walk)(pool, seg, f, p, s); | ||
| 466 | } | ||
| 467 | |||
| 468 | |||
| 469 | /* PoolDescribe -- describe a pool */ | ||
| 470 | |||
| 471 | Res PoolDescribe(Pool pool, mps_lib_FILE *stream) | ||
| 472 | { | ||
| 473 | Res res; | ||
| 474 | Ring node, nextNode; | ||
| 475 | |||
| 476 | if (!CHECKT(Pool, pool)) return ResFAIL; | ||
| 477 | if (stream == NULL) return ResFAIL; | ||
| 478 | |||
| 479 | res = WriteF(stream, | ||
| 480 | "Pool $P ($U) {\n", (WriteFP)pool, (WriteFU)pool->serial, | ||
| 481 | " class $P (\"$S\")\n", | ||
| 482 | (WriteFP)pool->class, pool->class->name, | ||
| 483 | " arena $P ($U)\n", | ||
| 484 | (WriteFP)pool->arena, (WriteFU)pool->arena->serial, | ||
| 485 | " alignment $W\n", (WriteFW)pool->alignment, | ||
| 486 | NULL); | ||
| 487 | if (res != ResOK) return res; | ||
| 488 | if (NULL != pool->format) { | ||
| 489 | res = FormatDescribe(pool->format, stream); | ||
| 490 | if (res != ResOK) return res; | ||
| 491 | } | ||
| 492 | res = WriteF(stream, | ||
| 493 | " fillMutatorSize $UKb\n", | ||
| 494 | (WriteFU)(pool->fillMutatorSize / 1024), | ||
| 495 | " emptyMutatorSize $UKb\n", | ||
| 496 | (WriteFU)(pool->emptyMutatorSize / 1024), | ||
| 497 | " fillInternalSize $UKb\n", | ||
| 498 | (WriteFU)(pool->fillInternalSize / 1024), | ||
| 499 | " emptyInternalSize $UKb\n", | ||
| 500 | (WriteFU)(pool->emptyInternalSize / 1024), | ||
| 501 | NULL); | ||
| 502 | if (res != ResOK) return res; | ||
| 503 | |||
| 504 | res = (*pool->class->describe)(pool, stream); | ||
| 505 | if (res != ResOK) return res; | ||
| 506 | |||
| 507 | RING_FOR(node, &pool->bufferRing, nextNode) { | ||
| 508 | Buffer buffer = RING_ELT(Buffer, poolRing, node); | ||
| 509 | res = BufferDescribe(buffer, stream); | ||
| 510 | if (res != ResOK) return res; | ||
| 511 | } | ||
| 512 | |||
| 513 | res = WriteF(stream, | ||
| 514 | "} Pool $P ($U)\n", (WriteFP)pool, (WriteFU)pool->serial, | ||
| 515 | NULL); | ||
| 516 | if (res != ResOK) return res; | ||
| 517 | |||
| 518 | return ResOK; | ||
| 519 | } | ||
| 520 | |||
| 521 | |||
| 522 | /* PoolFormat | ||
| 523 | * | ||
| 524 | * Returns the format of the pool (the format of objects in the pool). | ||
| 525 | * If the pool is unformatted or doesn't declare a format then this | ||
| 526 | * function returns FALSE and does not update *formatReturn. Otherwise | ||
| 527 | * this function returns TRUE and *formatReturn is updated to be the | ||
| 528 | * pool's format. */ | ||
| 529 | |||
| 530 | Bool PoolFormat(Format *formatReturn, Pool pool) | ||
| 531 | { | ||
| 532 | AVER(formatReturn != NULL); | ||
| 533 | AVERT(Pool, pool); | ||
| 534 | |||
| 535 | if (pool->format) { | ||
| 536 | *formatReturn = pool->format; | ||
| 537 | return TRUE; | ||
| 538 | } | ||
| 539 | return FALSE; | ||
| 540 | } | ||
| 541 | |||
| 542 | |||
| 543 | /* PoolOfAddr -- return the pool containing the given address | ||
| 544 | * | ||
| 545 | * If the address points to a page assigned to a pool, this returns TRUE | ||
| 546 | * and sets *poolReturn to that pool. Otherwise, it returns FALSE, and | ||
| 547 | * *poolReturn is unchanged. */ | ||
| 548 | |||
| 549 | Bool PoolOfAddr(Pool *poolReturn, Arena arena, Addr addr) | ||
| 550 | { | ||
| 551 | Tract tract; | ||
| 552 | |||
| 553 | AVER(poolReturn != NULL); | ||
| 554 | AVERT(Arena, arena); | ||
| 555 | |||
| 556 | if (TractOfAddr(&tract, arena, addr)) { | ||
| 557 | *poolReturn = TractPool(tract); | ||
| 558 | return TRUE; | ||
| 559 | } | ||
| 560 | |||
| 561 | return FALSE; | ||
| 562 | } | ||
| 563 | |||
| 564 | |||
| 565 | Bool PoolHasAddr(Pool pool, Addr addr) | ||
| 566 | { | ||
| 567 | Pool addrPool; | ||
| 568 | Arena arena; | ||
| 569 | Bool managed; | ||
| 570 | |||
| 571 | AVERT(Pool, pool); | ||
| 572 | |||
| 573 | arena = PoolArena(pool); | ||
| 574 | managed = PoolOfAddr(&addrPool, arena, addr); | ||
| 575 | return (managed && addrPool == pool); | ||
| 576 | } | ||