127 lines
3.6 KiB
C
127 lines
3.6 KiB
C
#include "simple_frame_pool.H"
|
|
#include "console.H"
|
|
#include "utils.H"
|
|
#include "assert.H"
|
|
|
|
SimpleFramePool::SimpleFramePool(unsigned long _base_frame_no,
|
|
unsigned long _nframes,
|
|
unsigned long _info_frame_no)
|
|
{
|
|
// Bitmap must fit in a single frame!
|
|
assert(_nframes <= FRAME_SIZE * 8);
|
|
|
|
base_frame_no = _base_frame_no;
|
|
nframes = _nframes;
|
|
nFreeFrames = _nframes;
|
|
info_frame_no = _info_frame_no;
|
|
|
|
// If _info_frame_no is zero then we keep management info in the first
|
|
//frame, else we use the provided frame to keep management info
|
|
if(info_frame_no == 0) {
|
|
bitmap = (unsigned char *) (base_frame_no * FRAME_SIZE);
|
|
} else {
|
|
bitmap = (unsigned char *) (info_frame_no * FRAME_SIZE);
|
|
}
|
|
|
|
// Number of frames must be "fill" the bitmap!
|
|
assert ((nframes % 8 ) == 0);
|
|
|
|
|
|
// Everything ok. Proceed to mark all bits in the bitmap
|
|
for(int i=0; i*8 < _nframes; i++) {
|
|
bitmap[i] = 0xFF;
|
|
}
|
|
|
|
// Mark the first frame as being used if it is being used
|
|
if(_info_frame_no == 0) {
|
|
bitmap[0] = 0x7F;
|
|
nFreeFrames--;
|
|
}
|
|
|
|
Console::puts("Frame Pool initialized\n");
|
|
}
|
|
|
|
unsigned long SimpleFramePool::get_frame()
|
|
{
|
|
|
|
// Any frames left to allocate?
|
|
assert(nFreeFrames > 0);
|
|
|
|
// Find a frame that is not being used and return its frame index.
|
|
// Mark that frame as being used in the bitmap.
|
|
unsigned int frame_no = base_frame_no;
|
|
|
|
unsigned int i = 0;
|
|
while (bitmap[i] == 0x0) {
|
|
i++;
|
|
}
|
|
|
|
frame_no += i * 8;
|
|
|
|
unsigned char mask = 0x80;
|
|
while ((mask & bitmap[i]) == 0) {
|
|
mask = mask >> 1;
|
|
frame_no++;
|
|
}
|
|
nFreeFrames--;
|
|
|
|
// Update bitmap
|
|
bitmap[i] = bitmap[i] ^ mask;
|
|
|
|
return (frame_no);
|
|
}
|
|
|
|
void SimpleFramePool::mark_inaccessible(unsigned long _base_frame_no,
|
|
unsigned long _nframes)
|
|
{
|
|
// Mark all frames in the range as being used.
|
|
int i ;
|
|
for(i = _base_frame_no; i < _base_frame_no + _nframes; i++){
|
|
mark_inaccessible(i);
|
|
}
|
|
nFreeFrames -= _nframes;
|
|
}
|
|
|
|
void SimpleFramePool::mark_inaccessible(unsigned long _frame_no)
|
|
{
|
|
// Let's first do a range check.
|
|
assert ((_frame_no >= base_frame_no) && (_frame_no < base_frame_no + nframes));
|
|
|
|
unsigned int bitmap_index = (_frame_no - base_frame_no) / 8;
|
|
unsigned char mask = 0x80 >> ((_frame_no - base_frame_no) % 8);
|
|
|
|
// Is the frame being used already?
|
|
assert((bitmap[bitmap_index] & mask) != 0);
|
|
|
|
// Update bitmap
|
|
bitmap[bitmap_index] ^= mask;
|
|
nFreeFrames--;
|
|
}
|
|
|
|
void SimpleFramePool::release_frame(unsigned long _frame_no)
|
|
{
|
|
// -- WE LEAVE THE IMPLEMENTATION OF THIS FUNCTION TO YOU.
|
|
// NOTE: Keep in mind that you first need to identify the correct frame pool.
|
|
// The function is static, and you are only given a frame number. You do have
|
|
// to figure out which frame pool this frame belongs to before you can call the
|
|
// frame-pool-specific release_frame function.
|
|
|
|
|
|
#ifdef JUST_AS_EXAMPLE
|
|
// Inside the frame-pool specific release_frame function we mark the frame
|
|
// as released as follows:
|
|
|
|
unsigned int bitmap_index = (_frame_no - base_frame_no) / 8;
|
|
unsigned char mask = 0x80 >> ((_frame_no - base_frame_no) % 8);
|
|
|
|
if((bitmap[bitmap_index] & mask) != 0) {
|
|
Console::puts("Error, Frame being released is not being used\n");
|
|
assert(false);
|
|
}
|
|
|
|
bitmap[bitmap_index] ^= mask;
|
|
|
|
nFreeFrames++;
|
|
#endif
|
|
}
|
|
|