This repository has been archived by the owner on May 14, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
/
vm.py
101 lines (83 loc) · 2.92 KB
/
vm.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#! /usr/bin/env python
class MemoryException(Exception):
pass
THRESHOLD_FRAGMENTATION_NEEDED=4096*1024
class Chunk:
def __init__(self, addr, size, status):
self.size = size
self.addr = addr
self.next = None
self.prev = None
self.status = status
def find_freechunk(self, size):
if self.status == 'F' and self.size >= size:
if self.size - size >= THRESHOLD_FRAGMENTATION_NEEDED:
c = self.splitme(size)
if c.next and c.next.is_free():
c.merge()
self.status = 'A'
return self
else:
if self.next:
return self.next.find_freechunk(size)
return None
def splitme(self, size, withstatus='F'):
new = Chunk(self.addr+size, self.size-size, withstatus)
self.size = size
new.next = self.next
self.next = new
return new
def merge(self):
c = self.next
while c and c.is_free():
self.size += c.size
c = c.next
self.next = c
def free(self, addr, length):
self.status = 'F'
if self.size != length:
raise MemoryException('Unmapping of partial chunk is not implemented')
self.merge()
def is_free(self):
return self.status == 'F'
def contains(self, addr):
return self.addr <= addr < (self.addr+self.size)
def __repr__(self):
return 'Chunk addr=%#x size=%dM status=%c has_next=%s' % (self.addr,
self.size/1024/1024,
self.status,
self.next != None)
class MemoryManager(object):
def __init__(self, addr, size):
# if size % 4096 != 0:
# raise MemoryException('Size not page-aligned')
self.pool = Chunk(addr, size, 'F')
def allocate(self, chunksize):
# if chunksize % 4096 != 0:
# raise MemoryException('Size not page-aligned')
chunk = self.pool.find_freechunk(chunksize)
return chunk
def free(self, addr, length):
current = self.pool
while current:
if current.contains(addr):
current.free(addr, length)
current = current.next
def show(self):
chunk = self.pool
while chunk:
print chunk
chunk = chunk.next
class VirtualMemory:
def __init__(self, size):
self.mm = None
self.size = size
def new_mapping(self, addr, length, prot, flags):
if not self.mm:
raise MemoryException('Memory not initialized yet')
chunk = self.mm.allocate(length)
return chunk.addr
def release_mapping(self, addr, length):
pass
def set_pool_addr(self, addr):
self.mm = MemoryManager(addr, self.size)