Res BufferFill(Addr *pReturn, Buffer buffer, Size size) { Res res; Pool pool; Addr base, limit, next; AVER(pReturn != NULL); AVERT(Buffer, buffer); AVER(size > 0); AVER(SizeIsAligned(size, BufferPool(buffer)->alignment)); AVER(BufferIsReady(buffer)); pool = BufferPool(buffer); /* If we're here because the buffer was trapped, then we attempt */ /* the allocation here. */ if (!BufferIsReset(buffer) && buffer->ap_s.limit == (Addr)0) { /* .fill.unflip: If the buffer is flipped then we unflip the buffer. */ if (buffer->mode & BufferModeFLIPPED) { BufferSetUnflipped(buffer); } /* .fill.logged: If the buffer is logged then we leave it logged. */ next = AddrAdd(buffer->ap_s.alloc, size); if (next > (Addr)buffer->ap_s.alloc && next <= (Addr)buffer->poolLimit) { buffer->ap_s.alloc = next; if (buffer->mode & BufferModeLOGGED) { EVENT3(BufferReserve, buffer, buffer->ap_s.init, size); } *pReturn = buffer->ap_s.init; return ResOK; } } /* There really isn't enough room for the allocation now. */ AVER(AddrAdd(buffer->ap_s.alloc, size) > buffer->poolLimit || AddrAdd(buffer->ap_s.alloc, size) < (Addr)buffer->ap_s.alloc); BufferDetach(buffer, pool); /* Ask the pool for some memory. */ res = Method(Pool, pool, bufferFill)(&base, &limit, pool, buffer, size); if (res != ResOK) return res; /* Set up the buffer to point at the memory given by the pool */ /* and do the allocation that was requested by the client. */ BufferAttach(buffer, base, limit, base, size); if (buffer->mode & BufferModeLOGGED) { EVENT3(BufferReserve, buffer, buffer->ap_s.init, size); } *pReturn = base; return res; }
Bool BufferCommit(Buffer buffer, Addr p, Size size) { AVERT(Buffer, buffer); AVER(size > 0); AVER(SizeIsAligned(size, BufferPool(buffer)->alignment)); AVER(!BufferIsReady(buffer)); /* <design/collection#.flip>. */ /* .commit.before: If a flip occurs before this point, when the */ /* pool reads "initAtFlip" it will point below the object, so it */ /* will be trashed and the commit must fail when trip is called. */ AVER(p == buffer->ap_s.init); AVER(AddrAdd(buffer->ap_s.init, size) == buffer->ap_s.alloc); /* .commit.update: Atomically update the init pointer to declare */ /* that the object is initialized (though it may be invalid if a */ /* flip occurred). */ buffer->ap_s.init = buffer->ap_s.alloc; /* .improve.memory-barrier: Memory barrier here on the DEC Alpha */ /* (and other relaxed memory order architectures). */ /* .commit.after: If a flip occurs at this point, the pool will */ /* see "initAtFlip" above the object, which is valid, so it will */ /* be collected. The commit must succeed when trip is called. */ /* The pointer "p" will have been fixed up. */ /* TODO: Check the above assertion and explain why it is so. */ /* .commit.trip: Trip the buffer if a flip has occurred. */ if (buffer->ap_s.limit == 0) return BufferTrip(buffer, p, size); /* No flip occurred, so succeed. */ return TRUE; }
Res BufferFramePop(Buffer buffer, AllocFrame frame) { Pool pool; AVERT(Buffer, buffer); /* frame is of an abstract type & can't be checked */ pool = BufferPool(buffer); return Method(Pool, pool, framePop)(pool, buffer, frame); }
void BufferFinish(Buffer buffer) { AVERT(Buffer, buffer); AVER(BufferIsReady(buffer)); BufferDetach(buffer, BufferPool(buffer)); /* FIXME: Should be in BufferAbsFinish? */ Method(Inst, buffer, finish)(MustBeA(Inst, buffer)); }
void BufferReassignSeg(Buffer buffer, Seg seg) { AVERT(Buffer, buffer); AVERT(Seg, seg); AVER(!BufferIsReset(buffer)); AVER(BufferBase(buffer) >= SegBase(seg)); AVER(BufferLimit(buffer) <= SegLimit(seg)); AVER(BufferPool(buffer) == SegPool(seg)); Method(Buffer, buffer, reassignSeg)(buffer, seg); }
void BufferRampReset(Buffer buffer) { Pool pool; AVERT(Buffer, buffer); if (buffer->rampCount == 0) return; pool = BufferPool(buffer); AVERT(Pool, pool); do Method(Pool, pool, rampEnd)(pool, buffer); while(--buffer->rampCount > 0); }
Res BufferRampEnd(Buffer buffer) { Pool pool; AVERT(Buffer, buffer); if (buffer->rampCount == 0) return ResFAIL; --buffer->rampCount; pool = BufferPool(buffer); AVERT(Pool, pool); Method(Pool, pool, rampEnd)(pool, buffer); return ResOK; }
void BufferRampBegin(Buffer buffer, AllocPattern pattern) { Pool pool; AVERT(Buffer, buffer); AVERT(AllocPattern, pattern); ++buffer->rampCount; AVER(buffer->rampCount > 0); pool = BufferPool(buffer); AVERT(Pool, pool); Method(Pool, pool, rampBegin)(pool, buffer, pattern == &AllocPatternRampCollectAllStruct); }
Res BufferFramePush(AllocFrame *frameReturn, Buffer buffer) { Pool pool; AVERT(Buffer, buffer); AVER(frameReturn != NULL); /* Process any flip */ if (!BufferIsReset(buffer) && buffer->ap_s.limit == (Addr)0) { /* .fill.unflip: If the buffer is flipped then we unflip the buffer. */ if (buffer->mode & BufferModeFLIPPED) { BufferSetUnflipped(buffer); } } pool = BufferPool(buffer); return Method(Pool, pool, framePush)(frameReturn, pool, buffer); }
static void SNCBufFinish(Buffer buffer) { BufferClass super; SNCBuf sncbuf; SNC snc; Pool pool; AVERT(Buffer, buffer); sncbuf = BufferSNCBuf(buffer); AVERT(SNCBuf, sncbuf); pool = BufferPool(buffer); snc = PoolSNC(pool); /* Put any segments which haven't bee popped onto the free list */ sncPopPartialSegChain(snc, buffer, NULL); sncbuf->sig = SigInvalid; /* finish the superclass fields last */ super = BUFFER_SUPERCLASS(SNCBufClass); super->finish(buffer); }
Res BufferReserve(Addr *pReturn, Buffer buffer, Size size) { Addr next; AVER(pReturn != NULL); AVERT(Buffer, buffer); AVER(size > 0); AVER(SizeIsAligned(size, BufferPool(buffer)->alignment)); AVER(BufferIsReady(buffer)); /* <design/check/#.common> */ /* Is there enough room in the unallocated portion of the buffer to */ /* satisfy the request? If so, just increase the alloc marker and */ /* return a pointer to the area below it. */ next = AddrAdd(buffer->ap_s.alloc, size); if (next > (Addr)buffer->ap_s.alloc && next <= (Addr)buffer->ap_s.limit) { buffer->ap_s.alloc = next; *pReturn = buffer->ap_s.init; return ResOK; } /* If the buffer can't accommodate the request, call "fill". */ return BufferFill(pReturn, buffer, size); }
Bool BufferTrip(Buffer buffer, Addr p, Size size) { Pool pool; AVERT(Buffer, buffer); AVER(p != 0); AVER(size > 0); AVER(SizeIsAligned(size, buffer->alignment)); /* The limit field should be zero, because that's how trip gets */ /* called. See .commit.trip. */ AVER(buffer->ap_s.limit == 0); /* Of course we should be trapped. */ AVER(BufferIsTrapped(buffer)); /* The init and alloc fields should be equal at this point, because */ /* the step .commit.update has happened. */ AVER(buffer->ap_s.init == buffer->ap_s.alloc); /* The p parameter points at the base address of the allocated */ /* block, the end of which should now coincide with the init and */ /* alloc fields. */ /* Note that we don't _really_ care about p too much. We don't */ /* do anything else with it apart from these checks. (in particular */ /* it seems like the algorithms could be modified to cope with the */ /* case of the object having been copied between Commit updating i */ /* and testing limit) */ AVER(AddrAdd(p, size) == buffer->ap_s.init); pool = BufferPool(buffer); AVER(PoolHasAddr(pool, p)); /* .trip.unflip: If the flip occurred before commit set "init" */ /* to "alloc" (see .commit.before) then the object is invalid */ /* (won't've been scanned) so undo the allocation and fail commit. */ /* Otherwise (see .commit.after) the object is valid (will've been */ /* scanned) so commit can simply succeed. */ if ((buffer->mode & BufferModeFLIPPED) && buffer->ap_s.init != buffer->initAtFlip) { /* Reset just enough state for Reserve/Fill to work. */ /* The buffer is left trapped and we leave the untrapping */ /* for the next reserve (which goes out of line to Fill */ /* (.fill.unflip) because the buffer is still trapped) */ buffer->ap_s.init = p; buffer->ap_s.alloc = p; return FALSE; } /* Emit event including class if logged */ if (buffer->mode & BufferModeLOGGED) { Bool b; Format format; Addr clientClass; b = PoolFormat(&format, buffer->pool); if (b) { clientClass = format->klass(p); } else { clientClass = (Addr)0; } EVENT4(BufferCommit, buffer, p, size, clientClass); } return TRUE; }