API.ob07 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. (*
  2. BSD 2-Clause License
  3. Copyright (c) 2018, 2020-2022, Anton Krotov
  4. All rights reserved.
  5. *)
  6. MODULE API;
  7. IMPORT SYSTEM, K := KOSAPI;
  8. CONST
  9. eol* = 0DX + 0AX;
  10. BIT_DEPTH* = 32;
  11. MAX_SIZE = 16 * 400H;
  12. HEAP_SIZE = 1 * 100000H;
  13. _new = 1;
  14. _dispose = 2;
  15. SizeOfHeader = 36;
  16. TYPE
  17. CRITICAL_SECTION = ARRAY 2 OF INTEGER;
  18. VAR
  19. heap, endheap: INTEGER;
  20. pockets: ARRAY MAX_SIZE DIV 32 + 1 OF INTEGER;
  21. CriticalSection: CRITICAL_SECTION;
  22. multi: BOOLEAN;
  23. base*: INTEGER;
  24. PROCEDURE [stdcall] zeromem* (dwords: INTEGER; adr: INTEGER);
  25. BEGIN
  26. SYSTEM.CODE(
  27. 0FCH, (* cld *)
  28. 031H, 0C0H, (* xor eax, eax *)
  29. 057H, (* push edi *)
  30. 08BH, 07DH, 00CH, (* mov edi, dword [ebp + 12] *)
  31. 08BH, 04DH, 008H, (* mov ecx, dword [ebp + 8] *)
  32. 0F3H, 0ABH, (* rep stosd *)
  33. 05FH (* pop edi *)
  34. )
  35. END zeromem;
  36. PROCEDURE mem_commit* (adr, size: INTEGER);
  37. VAR
  38. tmp: INTEGER;
  39. BEGIN
  40. FOR tmp := adr TO adr + size - 1 BY 4096 DO
  41. SYSTEM.PUT(tmp, 0)
  42. END
  43. END mem_commit;
  44. PROCEDURE switch_task;
  45. BEGIN
  46. K.sysfunc2(68, 1)
  47. END switch_task;
  48. PROCEDURE futex_create (ptr: INTEGER): INTEGER;
  49. RETURN K.sysfunc3(77, 0, ptr)
  50. END futex_create;
  51. PROCEDURE futex_wait (futex, value, timeout: INTEGER);
  52. BEGIN
  53. K.sysfunc5(77, 2, futex, value, timeout)
  54. END futex_wait;
  55. PROCEDURE futex_wake (futex, number: INTEGER);
  56. BEGIN
  57. K.sysfunc4(77, 3, futex, number)
  58. END futex_wake;
  59. PROCEDURE EnterCriticalSection* (VAR CriticalSection: CRITICAL_SECTION);
  60. BEGIN
  61. switch_task;
  62. futex_wait(CriticalSection[0], 1, 10000);
  63. CriticalSection[1] := 1
  64. END EnterCriticalSection;
  65. PROCEDURE LeaveCriticalSection* (VAR CriticalSection: CRITICAL_SECTION);
  66. BEGIN
  67. CriticalSection[1] := 0;
  68. futex_wake(CriticalSection[0], 1)
  69. END LeaveCriticalSection;
  70. PROCEDURE InitializeCriticalSection* (VAR CriticalSection: CRITICAL_SECTION);
  71. BEGIN
  72. CriticalSection[0] := futex_create(SYSTEM.ADR(CriticalSection[1]));
  73. CriticalSection[1] := 0
  74. END InitializeCriticalSection;
  75. PROCEDURE __NEW (size: INTEGER): INTEGER;
  76. VAR
  77. res, idx, temp: INTEGER;
  78. BEGIN
  79. IF size <= MAX_SIZE THEN
  80. idx := ASR(size, 5);
  81. res := pockets[idx];
  82. IF res # 0 THEN
  83. SYSTEM.GET(res, pockets[idx]);
  84. SYSTEM.PUT(res, size);
  85. INC(res, 4)
  86. ELSE
  87. temp := 0;
  88. IF heap + size >= endheap THEN
  89. IF K.sysfunc2(18, 16) > ASR(HEAP_SIZE, 10) THEN
  90. temp := K.sysfunc3(68, 12, HEAP_SIZE)
  91. ELSE
  92. temp := 0
  93. END;
  94. IF temp # 0 THEN
  95. mem_commit(temp, HEAP_SIZE);
  96. heap := temp;
  97. endheap := heap + HEAP_SIZE
  98. ELSE
  99. temp := -1
  100. END
  101. END;
  102. IF (heap # 0) & (temp # -1) THEN
  103. SYSTEM.PUT(heap, size);
  104. res := heap + 4;
  105. heap := heap + size
  106. ELSE
  107. res := 0
  108. END
  109. END
  110. ELSE
  111. IF K.sysfunc2(18, 16) > ASR(size, 10) THEN
  112. res := K.sysfunc3(68, 12, size);
  113. IF res # 0 THEN
  114. mem_commit(res, size);
  115. SYSTEM.PUT(res, size);
  116. INC(res, 4)
  117. END
  118. ELSE
  119. res := 0
  120. END
  121. END;
  122. IF (res # 0) & (size <= MAX_SIZE) THEN
  123. zeromem(ASR(size, 2) - 1, res)
  124. END
  125. RETURN res
  126. END __NEW;
  127. PROCEDURE __DISPOSE (ptr: INTEGER): INTEGER;
  128. VAR
  129. size, idx: INTEGER;
  130. BEGIN
  131. DEC(ptr, 4);
  132. SYSTEM.GET(ptr, size);
  133. IF size <= MAX_SIZE THEN
  134. idx := ASR(size, 5);
  135. SYSTEM.PUT(ptr, pockets[idx]);
  136. pockets[idx] := ptr
  137. ELSE
  138. size := K.sysfunc3(68, 13, ptr)
  139. END
  140. RETURN 0
  141. END __DISPOSE;
  142. PROCEDURE NEW_DISPOSE (func, arg: INTEGER): INTEGER;
  143. VAR
  144. res: INTEGER;
  145. BEGIN
  146. IF multi THEN
  147. EnterCriticalSection(CriticalSection)
  148. END;
  149. IF func = _new THEN
  150. res := __NEW(arg)
  151. ELSIF func = _dispose THEN
  152. res := __DISPOSE(arg)
  153. END;
  154. IF multi THEN
  155. LeaveCriticalSection(CriticalSection)
  156. END
  157. RETURN res
  158. END NEW_DISPOSE;
  159. PROCEDURE _NEW* (size: INTEGER): INTEGER;
  160. RETURN NEW_DISPOSE(_new, size)
  161. END _NEW;
  162. PROCEDURE _DISPOSE* (ptr: INTEGER): INTEGER;
  163. RETURN NEW_DISPOSE(_dispose, ptr)
  164. END _DISPOSE;
  165. PROCEDURE exit* (p1: INTEGER);
  166. BEGIN
  167. K.sysfunc1(-1)
  168. END exit;
  169. PROCEDURE exit_thread* (p1: INTEGER);
  170. BEGIN
  171. K.sysfunc1(-1)
  172. END exit_thread;
  173. PROCEDURE OutStr (pchar: INTEGER);
  174. VAR
  175. c: CHAR;
  176. BEGIN
  177. IF pchar # 0 THEN
  178. REPEAT
  179. SYSTEM.GET(pchar, c);
  180. IF c # 0X THEN
  181. K.OutChar(c)
  182. END;
  183. INC(pchar)
  184. UNTIL c = 0X
  185. END
  186. END OutStr;
  187. PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER);
  188. BEGIN
  189. IF lpCaption # 0 THEN
  190. K.OutLn;
  191. OutStr(lpCaption);
  192. K.OutChar(":");
  193. K.OutLn
  194. END;
  195. OutStr(lpText);
  196. IF lpCaption # 0 THEN
  197. K.OutLn
  198. END
  199. END DebugMsg;
  200. PROCEDURE init* (import_, code: INTEGER);
  201. BEGIN
  202. multi := FALSE;
  203. base := code - SizeOfHeader;
  204. K.sysfunc2(68, 11);
  205. InitializeCriticalSection(CriticalSection);
  206. K._init(import_)
  207. END init;
  208. PROCEDURE SetMultiThr* (value: BOOLEAN);
  209. BEGIN
  210. multi := value
  211. END SetMultiThr;
  212. PROCEDURE GetTickCount* (): INTEGER;
  213. RETURN K.sysfunc2(26, 9) * 10
  214. END GetTickCount;
  215. PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER;
  216. RETURN 0
  217. END dllentry;
  218. PROCEDURE sofinit*;
  219. END sofinit;
  220. END API.