Skip to content

Commit 268e276

Browse files
committed
VM (new pixeltower): 空闲块列表
1 parent ec42112 commit 268e276

5 files changed

Lines changed: 190 additions & 14 deletions

File tree

include/openminecraft/mem/om_mem_prealloc.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,15 @@ class OMHeap
1515
void expand(void *target);
1616
void shrink(void *target);
1717

18+
uint64_t currentSizeAllocated();
19+
20+
bool vaild(void *p)
21+
{
22+
return p >= block && p < heapTop;
23+
}
24+
1825
void *block;
26+
void *heapTop;
1927

2028
private:
2129
log::OMLogger logger;
@@ -24,7 +32,6 @@ class OMHeap
2432

2533
void activate(void *p, uint64_t length);
2634
void deactivate(void *p, uint64_t length);
27-
void *heapTop;
2835
};
2936
} // namespace openminecraft::mem
3037

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef OM_PIXELTOWER_HEAP_HPP
2+
#define OM_PIXELTOWER_HEAP_HPP
3+
4+
#include "openminecraft/log/om_log_common.hpp"
5+
#include "openminecraft/mem/om_mem_prealloc.hpp"
6+
#include <cstdint>
7+
#include <mutex>
8+
#include <vector>
9+
namespace openminecraft::vm::pixeltower::v0
10+
{
11+
struct OMHeapEmptyBlock
12+
{
13+
void *ptr;
14+
uint64_t length;
15+
};
16+
17+
class OMPixelTowerHeap
18+
{
19+
public:
20+
OMPixelTowerHeap(uint64_t minSize, uint64_t maxSize);
21+
~OMPixelTowerHeap();
22+
23+
void *allocate(uint64_t length);
24+
void deallocate(void *ptr, uint64_t length);
25+
void debug();
26+
void merge();
27+
28+
private:
29+
mem::OMHeap *heap;
30+
std::mutex emptyBlockMutex;
31+
std::vector<OMHeapEmptyBlock> emptyBlocks;
32+
log::OMLogger logger;
33+
};
34+
} // namespace openminecraft::vm::pixeltower::v0
35+
36+
#endif

src/boot/entrypoint.cpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,13 @@
3535
#include "openminecraft/util/om_util_result.hpp"
3636
#include "openminecraft/util/om_util_version.hpp"
3737
#include "openminecraft/vfs/om_vfs_base.hpp"
38-
#include "openminecraft/vm/bytecode/om_bytecode_checker.hpp"
39-
#include "openminecraft/vm/bytecode/om_bytecode_descriptor.hpp"
40-
#include "openminecraft/vm/classfile/om_class_file.hpp"
38+
#include "openminecraft/vm/pixeltower/v0/om_pixeltower_heap.hpp"
4139
#include <SDL3/SDL.h>
4240
#include <boost/stacktrace.hpp>
4341
#include <fmt/format.h>
4442

4543
using namespace openminecraft;
46-
using namespace openminecraft::vm::classfile;
47-
using namespace openminecraft::vm::bytecode;
44+
using namespace openminecraft::vm;
4845
using namespace openminecraft::binary::hash;
4946
using namespace std::chrono_literals;
5047

@@ -118,8 +115,6 @@ int boot(std::vector<std::string> args)
118115
SDL_Quit();
119116

120117
bool recovermode = false;
121-
mem::OMHeap heap(0ul, 8ull * 1024 * 1024 * 1024);
122-
heap.init();
123118

124119
if (setjmp(recoverBuffer) == 0)
125120
{
@@ -151,11 +146,24 @@ int boot(std::vector<std::string> args)
151146
mem::castorice::printres();
152147
break;
153148
case "memtest"_hash: {
154-
heap.expand(static_cast<uint8_t *>(heap.block) + 255);
155-
auto i = static_cast<int *>(heap.block);
156-
i[0] = 33550336;
157-
logger->debug("heap write : {}", i[0]);
158-
heap.shrink(heap.block);
149+
pixeltower::v0::OMPixelTowerHeap heap(0, 1ul * 1024 * 1024 * 1024);
150+
std::vector<void *> targets;
151+
for (int i = 0; i < 2048; i++)
152+
{
153+
targets.push_back(heap.allocate(1024));
154+
}
155+
156+
srand(time(nullptr));
157+
while (!targets.empty())
158+
{
159+
auto idx = rand() % targets.size();
160+
heap.deallocate(targets[idx], 1024);
161+
targets.erase(targets.begin() + idx);
162+
if (targets.size() % 64 == 0)
163+
{
164+
heap.debug();
165+
}
166+
}
159167

160168
commandBuffer.clear();
161169

src/mem/om_mem_prealloc.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "openminecraft/mem/om_mem_prealloc.hpp"
2+
#include <new>
23

34
namespace openminecraft::mem
45
{
@@ -11,11 +12,16 @@ void OMHeap::init()
1112
}
1213
expand(static_cast<uint8_t *>(block) + minSize);
1314
}
15+
uint64_t OMHeap::currentSizeAllocated()
16+
{
17+
return (size_t)heapTop - (size_t)block;
18+
}
1419
void OMHeap::expand(void *target)
1520
{
16-
if (target < block || target <= heapTop)
21+
if (target < block || target <= heapTop || ((size_t)target - (size_t)block) > maxSize)
1722
{
1823
logger.error("target is not valid!");
24+
throw std::bad_alloc();
1925
}
2026

2127
activate(heapTop, (size_t)target - (size_t)heapTop);
@@ -26,6 +32,7 @@ void OMHeap::shrink(void *target)
2632
if (target < block || target >= heapTop)
2733
{
2834
logger.error("target is not valid!");
35+
throw std::bad_alloc();
2936
}
3037

3138
deactivate(target, (size_t)heapTop - (size_t)target);
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
#include "openminecraft/vm/pixeltower/v0/om_pixeltower_heap.hpp"
2+
#include "openminecraft/mem/om_mem_prealloc.hpp"
3+
#include <algorithm>
4+
#include <mutex>
5+
6+
namespace openminecraft::vm::pixeltower::v0
7+
{
8+
OMPixelTowerHeap::OMPixelTowerHeap(uint64_t minSize, uint64_t maxSize) : logger("OMPixelTowerHeap", this)
9+
{
10+
heap = new mem::OMHeap(minSize, maxSize);
11+
heap->init();
12+
emptyBlocks.push_back({heap->block, heap->currentSizeAllocated()});
13+
}
14+
OMPixelTowerHeap::~OMPixelTowerHeap()
15+
{
16+
delete heap;
17+
}
18+
19+
void *OMPixelTowerHeap::allocate(uint64_t length)
20+
{
21+
// force 8-byte alignment
22+
if (length % 8 != 0)
23+
{
24+
length = length + 8 - (length % 8);
25+
}
26+
27+
alloc:
28+
std::lock_guard<std::mutex> g(emptyBlockMutex);
29+
for (auto it = emptyBlocks.begin(); it != emptyBlocks.end(); ++it)
30+
{
31+
if (it->length >= length) // available blocks found
32+
{
33+
void *target = it->ptr;
34+
it->ptr = static_cast<uint8_t *>(it->ptr) + length;
35+
it->length -= length;
36+
if (it->length == 0 && emptyBlocks.size() > 1)
37+
{
38+
emptyBlocks.erase(it);
39+
}
40+
return target;
41+
}
42+
}
43+
44+
logger.debug("expands heap space from {} ...", heap->currentSizeAllocated());
45+
heap->expand(static_cast<uint8_t *>(heap->heapTop) + 1ul * 1024 * 1024); // expand, 1MB larger heap
46+
emptyBlocks.back().length += 1ul * 1024 * 1024;
47+
logger.debug("to {}", heap->currentSizeAllocated());
48+
49+
goto alloc;
50+
}
51+
void OMPixelTowerHeap::debug()
52+
{
53+
logger.info("{} bytes allocated", heap->currentSizeAllocated());
54+
uint64_t t = 0;
55+
for (auto p : emptyBlocks)
56+
{
57+
t += p.length;
58+
}
59+
logger.info("{} bytes free", t);
60+
}
61+
void OMPixelTowerHeap::deallocate(void *ptr, uint64_t length)
62+
{
63+
if (!heap->vaild(ptr))
64+
{
65+
logger.error("{} not vaild!", ptr);
66+
return;
67+
}
68+
for (auto it = emptyBlocks.begin(); it != emptyBlocks.end(); ++it)
69+
{
70+
if (it->ptr > ptr)
71+
{
72+
continue;
73+
}
74+
75+
emptyBlockMutex.lock();
76+
emptyBlocks.insert(it, {ptr, length});
77+
emptyBlockMutex.unlock();
78+
goto merge;
79+
}
80+
81+
// first object
82+
emptyBlockMutex.lock();
83+
emptyBlocks.insert(emptyBlocks.begin(), {ptr, length});
84+
emptyBlockMutex.unlock();
85+
86+
merge:
87+
merge();
88+
}
89+
90+
void OMPixelTowerHeap::merge()
91+
{
92+
std::lock_guard<std::mutex> g(emptyBlockMutex);
93+
std::sort(emptyBlocks.begin(), emptyBlocks.end(),
94+
[](const OMHeapEmptyBlock &b1, const OMHeapEmptyBlock &b2) { return b1.ptr < b2.ptr; });
95+
96+
auto it1 = emptyBlocks.begin();
97+
auto it2 = emptyBlocks.begin();
98+
++it2;
99+
while (true)
100+
{
101+
if (it2 == emptyBlocks.end())
102+
{
103+
break;
104+
}
105+
106+
if (static_cast<uint8_t *>(it1->ptr) + it1->length == it2->ptr) // link!
107+
{
108+
it1->length += it2->length;
109+
it2 = emptyBlocks.erase(it2);
110+
}
111+
else
112+
{
113+
++it1;
114+
++it2;
115+
}
116+
}
117+
}
118+
} // namespace openminecraft::vm::pixeltower::v0

0 commit comments

Comments
 (0)