Skip to content

Commit c8bcbc6

Browse files
committed
added alignment + comments
1 parent a0b9ac5 commit c8bcbc6

File tree

2 files changed

+75
-49
lines changed

2 files changed

+75
-49
lines changed

src/MemoryBankManager.cxx

Lines changed: 62 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -12,76 +12,91 @@ MemoryBankManager::~MemoryBankManager() {
1212
int MemoryBankManager::addBank(std::shared_ptr<MemoryBank> bankPtr, std::string name) {
1313

1414
// disable concurrent execution of this function
15-
bankMutex.lock();
16-
15+
std::unique_lock<std::mutex> lock(bankMutex);
16+
1717
try {
1818
if (name.length()==0) {
1919
name=bankPtr->getDescription();
2020
}
2121
banks.push_back({name,bankPtr,{}});
2222
}
2323
catch(...) {
24-
bankMutex.unlock();
2524
return -1;
2625
}
2726

28-
bankMutex.unlock();
2927
return 0;
3028
}
3129

3230

33-
std::shared_ptr<MemoryPagesPool> MemoryBankManager::getPagedPool(size_t pageSize, size_t pageNumber, std::string bankName){
31+
std::shared_ptr<MemoryPagesPool> MemoryBankManager::getPagedPool(size_t pageSize, size_t pageNumber, std::string bankName, int pageAlign, int blockAlign){
3432

35-
// disable concurrent execution of this function
36-
bankMutex.lock();
37-
38-
// look for corresponding named bank
39-
// if not specified, used first one...
40-
unsigned int ix=0;
41-
bool bankFound=false;
42-
if (bankName.size()>0) {
43-
for (ix=0;ix<banks.size();ix++) {
44-
if (banks[ix].name==bankName) {
45-
bankFound=true;
46-
break;
33+
void *baseAddress=nullptr; // base address of bank from which the block is taken
34+
size_t offset=0; // offset of new block (relative to baseAddress)
35+
size_t blockSize=0; // size of new block (in bytes)
36+
37+
// disable concurrent execution of this block
38+
// automatic release of lock when going out of scope
39+
// beginning of locked block
40+
{
41+
std::unique_lock<std::mutex> lock(bankMutex);
42+
43+
// look for corresponding named bank
44+
// if not specified, used first one...
45+
unsigned int ix=0;
46+
bool bankFound=false;
47+
if (bankName.size()>0) {
48+
for (ix=0;ix<banks.size();ix++) {
49+
if (banks[ix].name==bankName) {
50+
bankFound=true;
51+
break;
52+
}
53+
}
54+
} else {
55+
if (banks.size()) {
56+
ix=0;
57+
bankFound=true;
4758
}
4859
}
49-
} else {
50-
if (banks.size()) {
51-
ix=0;
52-
bankFound=true;
60+
if (!bankFound) {
61+
return nullptr;
5362
}
54-
}
55-
if (!bankFound) {
56-
bankMutex.unlock();
57-
return nullptr;
58-
}
5963

60-
// reserve space from big block
61-
size_t offset=0; // offset of new block
62-
void *baseAddress=banks[ix].bank->getBaseAddress(); // base address of bank
63-
size_t blockSize=pageSize*pageNumber; // size of new block
64+
// reserve space from big block
65+
baseAddress=banks[ix].bank->getBaseAddress();
66+
offset=0;
67+
blockSize=pageSize*pageNumber; // this is the maximum space to use... may loose some pages for alignment
6468

65-
// alloc new block after existing ranges already in use
66-
for (auto it=banks[ix].rangesInUse.begin();it!=banks[ix].rangesInUse.end();++it) {
67-
size_t maxOffset=it->offset+it->size;
68-
if (maxOffset>offset) {
69-
offset=maxOffset;
69+
// alloc new block after existing ranges already in use
70+
for (auto it=banks[ix].rangesInUse.begin();it!=banks[ix].rangesInUse.end();++it) {
71+
size_t maxOffset=it->offset+it->size;
72+
if (maxOffset>offset) {
73+
offset=maxOffset;
74+
}
7075
}
71-
}
7276

73-
// check not exceeding bank size
74-
if (offset+blockSize>banks[ix].bank->getSize()) {
75-
bankMutex.unlock();
76-
throw std::bad_alloc();
77+
// align beginning of block as specified
78+
if (blockAlign>0) {
79+
size_t bytesExcess=(((size_t)baseAddress)+offset) % blockAlign;
80+
if (bytesExcess) {
81+
size_t alignOffset=blockAlign-bytesExcess;
82+
offset+=alignOffset; // advance to next aligned address
83+
blockSize-=alignOffset; // decrease block size to respect initial limit
84+
}
85+
}
86+
87+
// check not exceeding bank size
88+
if (offset+blockSize>banks[ix].bank->getSize()) {
89+
throw std::bad_alloc();
90+
}
91+
92+
// keep track of this new block
93+
banks[ix].rangesInUse.push_back({offset,blockSize});
7794
}
78-
79-
// keep track of this new block
80-
banks[ix].rangesInUse.push_back({offset,blockSize});
81-
bankMutex.unlock();
82-
83-
// create pool of pages from it
84-
return std::make_shared<MemoryPagesPool>(pageSize,pageNumber,&(((char *)baseAddress)[offset]),blockSize);
95+
// end of locked block
96+
97+
// create pool of pages from new block
98+
return std::make_shared<MemoryPagesPool>(pageSize,pageNumber,&(((char *)baseAddress)[offset]),blockSize,nullptr,pageAlign);
8599
}
86100

101+
// a global MemoryBankManager instance
87102
MemoryBankManager theMemoryBankManager;

src/MemoryBankManager.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,21 @@ class MemoryBankManager {
2121
~MemoryBankManager(); // destructor
2222

2323
int addBank(std::shared_ptr<MemoryBank> bankPtr, std::string name=""); // add a named memory bank to the manager. By default, takes name from bank description
24-
std::shared_ptr<MemoryPagesPool> getPagedPool(size_t pageSize, size_t pageNumber, std::string bankName=""); // get a pool of pages from the manager
24+
25+
// get a pool of pages from the manager, using the banks available
26+
// parameters:
27+
// - pageSize: size of one page (in bytes)
28+
// - pageNumber: number of pages requested
29+
// - bankName: name of the bank from which to create the pool. If not specified, using the first bank.
30+
// - pageAlign: alignment of first page in pool
31+
// - blockAlign: alignment of beginning of big memory block from which pool is created
32+
// NB: trivial implementation, once a region from a bank has been used, it can not be reused after the corresponding pool of pages has been release
33+
// ... don't want to deal with fragmentation etc
34+
std::shared_ptr<MemoryPagesPool> getPagedPool(size_t pageSize, size_t pageNumber, std::string bankName="", int pageAlign=0, int blockAlign=0);
2535

2636
// a struct to define a memory range
2737
struct memoryRange {
28-
size_t offset; // beginning of memory range (bytes)
38+
size_t offset; // beginning of memory range (bytes, counted from beginning of block)
2939
size_t size; // size of memory range (bytes)
3040
};
3141

@@ -42,6 +52,7 @@ class MemoryBankManager {
4252
std::mutex bankMutex; // instance mutex to handle concurrent access to public methods
4353
};
4454

55+
// a global MemoryBankManager instance
4556
extern MemoryBankManager theMemoryBankManager;
4657

4758
#endif // #ifndef _MEMORYBANKMANAGER_H

0 commit comments

Comments
 (0)