《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

238 lines
9.2 KiB

  1. #! /usr/bin/env python
  2. import random
  3. from optparse import OptionParser
  4. class malloc:
  5. def __init__(self, size, start, headerSize, policy, order, coalesce, align):
  6. # size of space
  7. self.size = size
  8. # info about pretend headers
  9. self.headerSize = headerSize
  10. # init free list
  11. self.freelist = []
  12. self.freelist.append((start, size))
  13. # keep track of ptr to size mappings
  14. self.sizemap = {}
  15. # policy
  16. self.policy = policy
  17. assert(self.policy in ['FIRST', 'BEST', 'WORST'])
  18. # list ordering
  19. self.returnPolicy = order
  20. assert(self.returnPolicy in ['ADDRSORT', 'SIZESORT+', 'SIZESORT-', 'INSERT-FRONT', 'INSERT-BACK'])
  21. # this does a ridiculous full-list coalesce, but that is ok
  22. self.coalesce = coalesce
  23. # alignment (-1 if no alignment)
  24. self.align = align
  25. assert(self.align == -1 or self.align > 0)
  26. def addToMap(self, addr, size):
  27. assert(addr not in self.sizemap)
  28. self.sizemap[addr] = size
  29. # print 'adding', addr, 'to map of size', size
  30. def malloc(self, size):
  31. if self.align != -1:
  32. left = size % self.align
  33. if left != 0:
  34. diff = self.align - left
  35. else:
  36. diff = 0
  37. # print 'aligning: adding %d to %d' % (diff, size)
  38. size += diff
  39. size += self.headerSize
  40. bestIdx = -1
  41. if self.policy == 'BEST':
  42. bestSize = self.size + 1
  43. elif self.policy == 'WORST' or self.policy == 'FIRST':
  44. bestSize = -1
  45. count = 0
  46. for i in range(len(self.freelist)):
  47. eaddr, esize = self.freelist[i][0], self.freelist[i][1]
  48. count += 1
  49. if esize >= size and ((self.policy == 'BEST' and esize < bestSize) or
  50. (self.policy == 'WORST' and esize > bestSize) or
  51. (self.policy == 'FIRST')):
  52. bestAddr = eaddr
  53. bestSize = esize
  54. bestIdx = i
  55. if self.policy == 'FIRST':
  56. break
  57. if bestIdx != -1:
  58. if bestSize > size:
  59. # print 'SPLIT', bestAddr, size
  60. self.freelist[bestIdx] = (bestAddr + size, bestSize - size)
  61. self.addToMap(bestAddr, size)
  62. elif bestSize == size:
  63. # print 'PERFECT MATCH (no split)', bestAddr, size
  64. self.freelist.pop(bestIdx)
  65. self.addToMap(bestAddr, size)
  66. else:
  67. abort('should never get here')
  68. return (bestAddr, count)
  69. # print '*** FAILED TO FIND A SPOT', size
  70. return (-1, count)
  71. def free(self, addr):
  72. # simple back on end of list, no coalesce
  73. if addr not in self.sizemap:
  74. return -1
  75. size = self.sizemap[addr]
  76. if self.returnPolicy == 'INSERT-BACK':
  77. self.freelist.append((addr, size))
  78. elif self.returnPolicy == 'INSERT-FRONT':
  79. self.freelist.insert(0, (addr, size))
  80. elif self.returnPolicy == 'ADDRSORT':
  81. self.freelist.append((addr, size))
  82. self.freelist = sorted(self.freelist, key=lambda e: e[0])
  83. elif self.returnPolicy == 'SIZESORT+':
  84. self.freelist.append((addr, size))
  85. self.freelist = sorted(self.freelist, key=lambda e: e[1], reverse=False)
  86. elif self.returnPolicy == 'SIZESORT-':
  87. self.freelist.append((addr, size))
  88. self.freelist = sorted(self.freelist, key=lambda e: e[1], reverse=True)
  89. # not meant to be an efficient or realistic coalescing...
  90. if self.coalesce == True:
  91. self.newlist = []
  92. self.curr = self.freelist[0]
  93. for i in range(1, len(self.freelist)):
  94. eaddr, esize = self.freelist[i]
  95. if eaddr == (self.curr[0] + self.curr[1]):
  96. self.curr = (self.curr[0], self.curr[1] + esize)
  97. else:
  98. self.newlist.append(self.curr)
  99. self.curr = eaddr, esize
  100. self.newlist.append(self.curr)
  101. self.freelist = self.newlist
  102. del self.sizemap[addr]
  103. return 0
  104. def dump(self):
  105. print 'Free List [ Size %d ]: ' % len(self.freelist),
  106. for e in self.freelist:
  107. print '[ addr:%d sz:%d ]' % (e[0], e[1]),
  108. print ''
  109. #
  110. # main program
  111. #
  112. parser = OptionParser()
  113. parser.add_option('-s', '--seed', default=0, help='the random seed', action='store', type='int', dest='seed')
  114. parser.add_option('-S', '--size', default=100, help='size of the heap', action='store', type='int', dest='heapSize')
  115. parser.add_option('-b', '--baseAddr', default=1000, help='base address of heap', action='store', type='int', dest='baseAddr')
  116. parser.add_option('-H', '--headerSize', default=0, help='size of the header', action='store', type='int', dest='headerSize')
  117. parser.add_option('-a', '--alignment', default=-1, help='align allocated units to size; -1->no align', action='store', type='int', dest='alignment')
  118. parser.add_option('-p', '--policy', default='BEST', help='list search (BEST, WORST, FIRST)', action='store', type='string', dest='policy')
  119. parser.add_option('-l', '--listOrder', default='ADDRSORT', help='list order (ADDRSORT, SIZESORT+, SIZESORT-, INSERT-FRONT, INSERT-BACK)', action='store', type='string', dest='order')
  120. parser.add_option('-C', '--coalesce', default=False, help='coalesce the free list?', action='store_true', dest='coalesce')
  121. parser.add_option('-n', '--numOps', default=10, help='number of random ops to generate', action='store', type='int', dest='opsNum')
  122. parser.add_option('-r', '--range', default=10, help='max alloc size', action='store', type='int', dest='opsRange')
  123. parser.add_option('-P', '--percentAlloc',default=50, help='percent of ops that are allocs', action='store', type='int', dest='opsPAlloc')
  124. parser.add_option('-A', '--allocList', default='', help='instead of random, list of ops (+10,-0,etc)', action='store', type='string', dest='opsList')
  125. parser.add_option('-c', '--compute', default=False, help='compute answers for me', action='store_true', dest='solve')
  126. (options, args) = parser.parse_args()
  127. m = malloc(int(options.heapSize), int(options.baseAddr), int(options.headerSize),
  128. options.policy, options.order, options.coalesce, options.alignment)
  129. percent = int(options.opsPAlloc) / 100.0
  130. random.seed(int(options.seed))
  131. p = {}
  132. L = []
  133. assert(percent > 0)
  134. if options.opsList == '':
  135. c = 0
  136. j = 0
  137. while j < int(options.opsNum):
  138. pr = False
  139. if random.random() < percent:
  140. size = int(random.random() * int(options.opsRange)) + 1
  141. ptr, cnt = m.malloc(size)
  142. if ptr != -1:
  143. p[c] = ptr
  144. L.append(c)
  145. print 'ptr[%d] = Alloc(%d)' % (c, size),
  146. if options.solve == True:
  147. print ' returned %d (searched %d elements)' % (ptr + options.headerSize, cnt)
  148. else:
  149. print ' returned ?'
  150. c += 1
  151. j += 1
  152. pr = True
  153. else:
  154. if len(p) > 0:
  155. # pick random one to delete
  156. d = int(random.random() * len(L))
  157. rc = m.free(p[L[d]])
  158. print 'Free(ptr[%d])' % L[d],
  159. if options.solve == True:
  160. print 'returned %d' % rc
  161. else:
  162. print 'returned ?'
  163. del p[L[d]]
  164. del L[d]
  165. # print 'DEBUG p', p
  166. # print 'DEBUG L', L
  167. pr = True
  168. j += 1
  169. if pr:
  170. if options.solve == True:
  171. m.dump()
  172. else:
  173. print 'List? '
  174. print ''
  175. else:
  176. c = 0
  177. for op in options.opsList.split(','):
  178. if op[0] == '+':
  179. # allocation!
  180. size = int(op.split('+')[1])
  181. ptr, cnt = m.malloc(size)
  182. if ptr != -1:
  183. p[c] = ptr
  184. print 'ptr[%d] = Alloc(%d)' % (c, size),
  185. if options.solve == True:
  186. print ' returned %d (searched %d elements)' % (ptr, cnt)
  187. else:
  188. print ' returned ?'
  189. c += 1
  190. elif op[0] == '-':
  191. # free
  192. index = int(op.split('-')[1])
  193. if index >= len(p):
  194. print 'Invalid Free: Skipping'
  195. continue
  196. print 'Free(ptr[%d])' % index,
  197. rc = m.free(p[index])
  198. if options.solve == True:
  199. print 'returned %d' % rc
  200. else:
  201. print 'returned ?'
  202. else:
  203. abort('badly specified operand: must be +Size or -Index')
  204. if options.solve == True:
  205. m.dump()
  206. else:
  207. print 'List?'
  208. print ''