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 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; }
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)); }
static void NBufferEmpty(Pool pool, Buffer buffer, Addr init, Addr limit) { AVERT(Pool, pool); AVERT(Buffer, buffer); AVER(BufferIsReady(buffer)); AVER(init <= limit); NOTREACHED; /* can't create buffers, so they shouldn't trip */ }
void BufferSetAllocAddr(Buffer buffer, Addr addr) { AVERT(Buffer, buffer); /* Can't check Addr */ AVER(BufferIsReady(buffer)); AVER(buffer->base <= addr); AVER(buffer->poolLimit >= addr); buffer->ap_s.init = addr; buffer->ap_s.alloc = addr; }
void BufferDetach(Buffer buffer, Pool pool) { AVERT(Buffer, buffer); AVER(BufferIsReady(buffer)); if (!BufferIsReset(buffer)) { Addr init, limit; Size spare; buffer->mode |= BufferModeTRANSITION; /* Ask the owning pool to do whatever it needs to before the */ /* buffer is detached (e.g. copy buffer state into pool state). */ Method(Pool, pool, bufferEmpty)(pool, buffer); /* run any class-specific detachment method */ Method(Buffer, buffer, detach)(buffer); init = BufferGetInit(buffer); limit = BufferLimit(buffer); spare = AddrOffset(init, limit); buffer->emptySize += spare; if (buffer->isMutator) { ArenaGlobals(buffer->arena)->emptyMutatorSize += spare; ArenaGlobals(buffer->arena)->allocMutatorSize += AddrOffset(buffer->base, init); } else { ArenaGlobals(buffer->arena)->emptyInternalSize += spare; } /* Reset the buffer. */ buffer->base = (Addr)0; buffer->initAtFlip = (Addr)0; buffer->ap_s.init = (mps_addr_t)0; buffer->ap_s.alloc = (mps_addr_t)0; buffer->ap_s.limit = (mps_addr_t)0; buffer->poolLimit = (Addr)0; buffer->mode &= ~(BufferModeATTACHED|BufferModeFLIPPED|BufferModeTRANSITION); EVENT2(BufferEmpty, buffer, spare); } }
static void MVFFBufferEmpty(Pool pool, Buffer buffer, Addr base, Addr limit) { MVFF mvff; AVERT(Pool, pool); mvff = Pool2MVFF(pool); AVERT(MVFF, mvff); AVERT(Buffer, buffer); AVER(BufferIsReady(buffer)); AVER(base <= limit); if (base == limit) return; MVFFAddToFreeList(&base, &limit, mvff); MVFFFreeSegs(mvff, base, limit); return; }
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); }