simple_malloc.g 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. # This file is part of asmc, a bootstrapping OS with minimal seed
  2. # Copyright (C) 2018 Giovanni Mascellani <gio@debian.org>
  3. # https://gitlab.com/giomasce/asmc
  4. # It is based on
  5. # https://github.com/andrestc/linux-prog/blob/master/ch7/malloc.c,
  6. # translated from C to G by Giovanni Mascellani. A few bugs were also
  7. # fixed and some other changes introduced. It retains the original MIT
  8. # License.
  9. # Copyright (c) 2017 André Carvalho
  10. # Permission is hereby granted, free of charge, to any person obtaining a copy
  11. # of this software and associated documentation files (the "Software"), to deal
  12. # in the Software without restriction, including without limitation the rights
  13. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  14. # copies of the Software, and to permit persons to whom the Software is
  15. # furnished to do so, subject to the following conditions:
  16. # The above copyright notice and this permission notice shall be included in all
  17. # copies or substantial portions of the Software.
  18. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  24. # SOFTWARE.
  25. $head
  26. const MALLOC_MAGIC_ALLOC 0xfeedbeef
  27. const MALLOC_MAGIC_FREE 0xdeadc0de
  28. const MALLOC_SIZE 0
  29. const MALLOC_NEXT 4
  30. const MALLOC_PREV 8
  31. const MALLOC_MAGIC 12
  32. const SIZEOF_MALLOC 16
  33. const ALLOC_UNIT 16384
  34. fun fl_remove 1 {
  35. $b
  36. @b 0 param = ;
  37. if b MALLOC_PREV take ! {
  38. if b MALLOC_NEXT take {
  39. @head b MALLOC_NEXT take = ;
  40. } else {
  41. @head 0 = ;
  42. }
  43. } else {
  44. b MALLOC_PREV take MALLOC_NEXT take_addr b MALLOC_NEXT take = ;
  45. }
  46. if b MALLOC_NEXT take {
  47. b MALLOC_NEXT take MALLOC_PREV take_addr b MALLOC_PREV take = ;
  48. }
  49. }
  50. fun fl_add 1 {
  51. $b
  52. @b 0 param = ;
  53. b MALLOC_MAGIC take MALLOC_MAGIC_FREE == "fl_add: missing magic number" assert_msg ;
  54. b MALLOC_NEXT take_addr 0 = ;
  55. b MALLOC_PREV take_addr 0 = ;
  56. if head ! head b > || {
  57. if head {
  58. head MALLOC_PREV take_addr b = ;
  59. }
  60. b MALLOC_NEXT take_addr head = ;
  61. @head b = ;
  62. } else {
  63. $curr
  64. @curr head = ;
  65. while curr MALLOC_NEXT take curr MALLOC_NEXT take b < && {
  66. @curr curr MALLOC_NEXT take = ;
  67. }
  68. $next
  69. @next curr MALLOC_NEXT take = ;
  70. b MALLOC_NEXT take_addr next = ;
  71. b MALLOC_PREV take_addr curr = ;
  72. curr MALLOC_NEXT take_addr b = ;
  73. next MALLOC_PREV take_addr b = ;
  74. }
  75. }
  76. fun scan_merge 0 {
  77. $curr
  78. @curr head = ;
  79. while curr MALLOC_NEXT take {
  80. $next
  81. @next curr MALLOC_NEXT take = ;
  82. if curr curr MALLOC_SIZE take + SIZEOF_MALLOC + next == {
  83. curr MALLOC_SIZE take_addr curr MALLOC_SIZE take next MALLOC_SIZE take + SIZEOF_MALLOC + = ;
  84. curr MALLOC_NEXT take_addr next MALLOC_NEXT take = ;
  85. if curr MALLOC_NEXT take {
  86. curr MALLOC_NEXT take MALLOC_PREV take_addr curr = ;
  87. }
  88. } else {
  89. @curr curr MALLOC_NEXT take = ;
  90. }
  91. }
  92. }
  93. fun split 2 {
  94. $b
  95. $size
  96. @b 0 param = ;
  97. @size 1 param = ;
  98. $mem_block
  99. @mem_block b SIZEOF_MALLOC + = ;
  100. $newptr
  101. @newptr mem_block size + = ;
  102. newptr MALLOC_SIZE take_addr b MALLOC_SIZE take size - SIZEOF_MALLOC - = ;
  103. newptr MALLOC_MAGIC take_addr MALLOC_MAGIC_FREE = ;
  104. b MALLOC_SIZE take_addr size = ;
  105. newptr ret ;
  106. }
  107. fun check_fl 0 {
  108. $ptr
  109. $prevptr
  110. @ptr head = ;
  111. @prevptr 0 = ;
  112. while ptr {
  113. ptr MALLOC_MAGIC take MALLOC_MAGIC_FREE == "check_fl: wrong magic number" assert_msg ;
  114. ptr MALLOC_SIZE take 0xf & 0 == "check_fl: wrong alignment" assert_msg ;
  115. ptr MALLOC_PREV take prevptr == "check_fl: wrong prev" assert_msg ;
  116. ptr MALLOC_NEXT take 0 == ptr MALLOC_NEXT take ptr > || "check_fl: regions are not increasing" assert_msg ;
  117. ptr MALLOC_NEXT take 0 == ptr MALLOC_NEXT take ptr ptr MALLOC_SIZE take + SIZEOF_MALLOC + >= || "check_fl: adjacent regions are overlapping" assert_msg ;
  118. ptr MALLOC_NEXT take 0 == ptr MALLOC_NEXT take ptr ptr MALLOC_SIZE take + SIZEOF_MALLOC + > || "check_fl: adjacent regions are contiguous" assert_msg ;
  119. @prevptr ptr = ;
  120. @ptr ptr MALLOC_NEXT take = ;
  121. }
  122. }
  123. fun malloc 1 {
  124. $size
  125. @size 0 param = ;
  126. # Make it a multiple of 4
  127. @size size 1 - 0x3 | 1 + = ;
  128. $block_mem
  129. $ptr
  130. $newptr
  131. $alloc_size
  132. if size SIZEOF_MALLOC 2 * + ALLOC_UNIT <= {
  133. @alloc_size ALLOC_UNIT = ;
  134. } else {
  135. @alloc_size size SIZEOF_MALLOC + = ;
  136. }
  137. @ptr head = ;
  138. while ptr {
  139. ptr MALLOC_MAGIC take MALLOC_MAGIC_FREE == "malloc: missing magic number" assert_msg ;
  140. ptr MALLOC_SIZE take 0x3 & 0 == "malloc: error 3" assert_msg ;
  141. if ptr MALLOC_SIZE take size SIZEOF_MALLOC + >= {
  142. @block_mem ptr SIZEOF_MALLOC + = ;
  143. ptr fl_remove ;
  144. @newptr size ptr split = ;
  145. newptr fl_add ;
  146. ptr MALLOC_MAGIC take_addr MALLOC_MAGIC_ALLOC = ;
  147. block_mem 0x3 & 0 == "malloc: error 1" assert_msg ;
  148. block_mem ret ;
  149. } else {
  150. @ptr ptr MALLOC_NEXT take = ;
  151. }
  152. }
  153. @ptr alloc_size platform_allocate = ;
  154. ptr 1024 1024 * 100 * < "too much alloc" assert_msg ;
  155. ptr MALLOC_NEXT take_addr 0 = ;
  156. ptr MALLOC_PREV take_addr 0 = ;
  157. ptr MALLOC_SIZE take_addr alloc_size SIZEOF_MALLOC - = ;
  158. ptr MALLOC_MAGIC take_addr MALLOC_MAGIC_ALLOC = ;
  159. if alloc_size size SIZEOF_MALLOC + > {
  160. @newptr size ptr split = ;
  161. newptr fl_add ;
  162. }
  163. @block_mem ptr SIZEOF_MALLOC + = ;
  164. block_mem 0x3 & 0 == "malloc: error 2" assert_msg ;
  165. block_mem ret ;
  166. }
  167. fun free 1 {
  168. $ptr
  169. @ptr 0 param = ;
  170. if ptr 0 == {
  171. ret ;
  172. }
  173. $b
  174. @b ptr SIZEOF_MALLOC - = ;
  175. b MALLOC_MAGIC take MALLOC_MAGIC_ALLOC == "free: missing magic number" assert_msg ;
  176. b MALLOC_MAGIC take_addr MALLOC_MAGIC_FREE = ;
  177. b fl_add ;
  178. scan_merge ;
  179. # For debugging, it can be helpful to check the state
  180. # of the free list after each call of free
  181. #check_fl ;
  182. }
  183. fun _malloc_get_size 1 {
  184. $ptr
  185. @ptr 0 param = ;
  186. $size
  187. @size ptr SIZEOF_MALLOC - MALLOC_SIZE take = ;
  188. size ret ;
  189. }
  190. fun malloc_stats 0 {
  191. }