Subversion Repositories Kolibri OS

Rev

Rev 7983 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. (*
  2.     BSD 2-Clause License
  3.  
  4.     Copyright (c) 2018, 2020, Anton Krotov
  5.     All rights reserved.
  6. *)
  7.  
  8. MODULE API;
  9.  
  10. IMPORT SYSTEM, K := KOSAPI;
  11.  
  12.  
  13. CONST
  14.  
  15.     eol* = 0DX + 0AX;
  16.  
  17.     MAX_SIZE  = 16 * 400H;
  18.     HEAP_SIZE =  1 * 100000H;
  19.  
  20.     _new = 1;
  21.     _dispose = 2;
  22.  
  23.     SizeOfHeader = 36;
  24.  
  25.  
  26. TYPE
  27.  
  28.     CRITICAL_SECTION = ARRAY 2 OF INTEGER;
  29.  
  30.  
  31. VAR
  32.  
  33.     heap, endheap: INTEGER;
  34.     pockets: ARRAY MAX_SIZE DIV 32 + 1 OF INTEGER;
  35.  
  36.     CriticalSection: CRITICAL_SECTION;
  37.  
  38.     _import*, multi: BOOLEAN;
  39.  
  40.     base*: INTEGER;
  41.  
  42.  
  43. PROCEDURE [stdcall] zeromem* (dwords: INTEGER; adr: INTEGER);
  44. BEGIN
  45.     SYSTEM.CODE(
  46.     0FCH,               (*  cld                            *)
  47.     031H, 0C0H,         (*  xor     eax, eax               *)
  48.     057H,               (*  push    edi                    *)
  49.     08BH, 07DH, 00CH,   (*  mov     edi, dword [ebp + 12]  *)
  50.     08BH, 04DH, 008H,   (*  mov     ecx, dword [ebp +  8]  *)
  51.     0F3H, 0ABH,         (*  rep     stosd                  *)
  52.     05FH                (*  pop     edi                    *)
  53.     )
  54. END zeromem;
  55.  
  56.  
  57. PROCEDURE mem_commit* (adr, size: INTEGER);
  58. VAR
  59.     tmp: INTEGER;
  60. BEGIN
  61.     FOR tmp := adr TO adr + size - 1 BY 4096 DO
  62.         SYSTEM.PUT(tmp, 0)
  63.     END
  64. END mem_commit;
  65.  
  66.  
  67. PROCEDURE switch_task;
  68. BEGIN
  69.     K.sysfunc2(68, 1)
  70. END switch_task;
  71.  
  72.  
  73. PROCEDURE futex_create (ptr: INTEGER): INTEGER;
  74.     RETURN K.sysfunc3(77, 0, ptr)
  75. END futex_create;
  76.  
  77.  
  78. PROCEDURE futex_wait (futex, value, timeout: INTEGER);
  79. BEGIN
  80.     K.sysfunc5(77, 2, futex, value, timeout)
  81. END futex_wait;
  82.  
  83.  
  84. PROCEDURE futex_wake (futex, number: INTEGER);
  85. BEGIN
  86.     K.sysfunc4(77, 3, futex, number)
  87. END futex_wake;
  88.  
  89.  
  90. PROCEDURE EnterCriticalSection* (VAR CriticalSection: CRITICAL_SECTION);
  91. BEGIN
  92.     switch_task;
  93.     futex_wait(CriticalSection[0], 1, 10000);
  94.     CriticalSection[1] := 1
  95. END EnterCriticalSection;
  96.  
  97.  
  98. PROCEDURE LeaveCriticalSection* (VAR CriticalSection: CRITICAL_SECTION);
  99. BEGIN
  100.     CriticalSection[1] := 0;
  101.     futex_wake(CriticalSection[0], 1)
  102. END LeaveCriticalSection;
  103.  
  104.  
  105. PROCEDURE InitializeCriticalSection* (VAR CriticalSection: CRITICAL_SECTION);
  106. BEGIN
  107.     CriticalSection[0] := futex_create(SYSTEM.ADR(CriticalSection[1]));
  108.     CriticalSection[1] := 0
  109. END InitializeCriticalSection;
  110.  
  111.  
  112. PROCEDURE __NEW (size: INTEGER): INTEGER;
  113. VAR
  114.     res, idx, temp: INTEGER;
  115. BEGIN
  116.     IF size <= MAX_SIZE THEN
  117.         idx := ASR(size, 5);
  118.         res := pockets[idx];
  119.         IF res # 0 THEN
  120.             SYSTEM.GET(res, pockets[idx]);
  121.             SYSTEM.PUT(res, size);
  122.             INC(res, 4)
  123.         ELSE
  124.             temp := 0;
  125.             IF heap + size >= endheap THEN
  126.                 IF K.sysfunc2(18, 16) > ASR(HEAP_SIZE, 10) THEN
  127.                     temp := K.sysfunc3(68, 12, HEAP_SIZE)
  128.                 ELSE
  129.                     temp := 0
  130.                 END;
  131.                 IF temp # 0 THEN
  132.                     mem_commit(temp, HEAP_SIZE);
  133.                     heap := temp;
  134.                     endheap := heap + HEAP_SIZE
  135.                 ELSE
  136.                     temp := -1
  137.                 END
  138.             END;
  139.             IF (heap # 0) & (temp # -1) THEN
  140.                 SYSTEM.PUT(heap, size);
  141.                 res := heap + 4;
  142.                 heap := heap + size
  143.             ELSE
  144.                 res := 0
  145.             END
  146.         END
  147.     ELSE
  148.         IF K.sysfunc2(18, 16) > ASR(size, 10) THEN
  149.             res := K.sysfunc3(68, 12, size);
  150.             IF res # 0 THEN
  151.                 mem_commit(res, size);
  152.                 SYSTEM.PUT(res, size);
  153.                 INC(res, 4)
  154.             END
  155.         ELSE
  156.             res := 0
  157.         END
  158.     END;
  159.     IF (res # 0) & (size <= MAX_SIZE) THEN
  160.         zeromem(ASR(size, 2) - 1, res)
  161.     END
  162.     RETURN res
  163. END __NEW;
  164.  
  165.  
  166. PROCEDURE __DISPOSE (ptr: INTEGER): INTEGER;
  167. VAR
  168.     size, idx: INTEGER;
  169. BEGIN
  170.     DEC(ptr, 4);
  171.     SYSTEM.GET(ptr, size);
  172.     IF size <= MAX_SIZE THEN
  173.         idx := ASR(size, 5);
  174.         SYSTEM.PUT(ptr, pockets[idx]);
  175.         pockets[idx] := ptr
  176.     ELSE
  177.         size := K.sysfunc3(68, 13, ptr)
  178.     END
  179.     RETURN 0
  180. END __DISPOSE;
  181.  
  182.  
  183. PROCEDURE NEW_DISPOSE (func, arg: INTEGER): INTEGER;
  184. VAR
  185.     res: INTEGER;
  186.  
  187. BEGIN
  188.     IF multi THEN
  189.         EnterCriticalSection(CriticalSection)
  190.     END;
  191.  
  192.     IF func = _new THEN
  193.         res := __NEW(arg)
  194.     ELSIF func = _dispose THEN
  195.         res := __DISPOSE(arg)
  196.     END;
  197.  
  198.     IF multi THEN
  199.         LeaveCriticalSection(CriticalSection)
  200.     END
  201.  
  202.     RETURN res
  203. END NEW_DISPOSE;
  204.  
  205.  
  206. PROCEDURE _NEW* (size: INTEGER): INTEGER;
  207.     RETURN NEW_DISPOSE(_new, size)
  208. END _NEW;
  209.  
  210.  
  211. PROCEDURE _DISPOSE* (ptr: INTEGER): INTEGER;
  212.     RETURN NEW_DISPOSE(_dispose, ptr)
  213. END _DISPOSE;
  214.  
  215.  
  216. PROCEDURE exit* (p1: INTEGER);
  217. BEGIN
  218.     K.sysfunc1(-1)
  219. END exit;
  220.  
  221.  
  222. PROCEDURE exit_thread* (p1: INTEGER);
  223. BEGIN
  224.     K.sysfunc1(-1)
  225. END exit_thread;
  226.  
  227.  
  228. PROCEDURE OutChar (c: CHAR);
  229. BEGIN
  230.     K.sysfunc3(63, 1, ORD(c))
  231. END OutChar;
  232.  
  233.  
  234. PROCEDURE OutLn;
  235. BEGIN
  236.     OutChar(0DX);
  237.     OutChar(0AX)
  238. END OutLn;
  239.  
  240.  
  241. PROCEDURE OutStr (pchar: INTEGER);
  242. VAR
  243.     c: CHAR;
  244. BEGIN
  245.     IF pchar # 0 THEN
  246.         REPEAT
  247.             SYSTEM.GET(pchar, c);
  248.             IF c # 0X THEN
  249.                 OutChar(c)
  250.             END;
  251.             INC(pchar)
  252.         UNTIL c = 0X
  253.     END
  254. END OutStr;
  255.  
  256.  
  257. PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER);
  258. BEGIN
  259.     IF lpCaption # 0 THEN
  260.         OutLn;
  261.         OutStr(lpCaption);
  262.         OutChar(":");
  263.         OutLn
  264.     END;
  265.     OutStr(lpText);
  266.     IF lpCaption # 0 THEN
  267.         OutLn
  268.     END
  269. END DebugMsg;
  270.  
  271.  
  272. PROCEDURE OutString (s: ARRAY OF CHAR);
  273. VAR
  274.     i: INTEGER;
  275. BEGIN
  276.     i := 0;
  277.     WHILE (i < LEN(s)) & (s[i] # 0X) DO
  278.         OutChar(s[i]);
  279.         INC(i)
  280.     END
  281. END OutString;
  282.  
  283.  
  284. PROCEDURE imp_error;
  285. BEGIN
  286.     OutString("import error: ");
  287.     IF K.imp_error.error = 1 THEN
  288.         OutString("can't load '"); OutString(K.imp_error.lib)
  289.     ELSIF K.imp_error.error = 2 THEN
  290.         OutString("not found '"); OutString(K.imp_error.proc); OutString("' in '"); OutString(K.imp_error.lib)
  291.     END;
  292.     OutString("'");
  293.     OutLn
  294. END imp_error;
  295.  
  296.  
  297. PROCEDURE init* (import_, code: INTEGER);
  298. BEGIN
  299.     multi := FALSE;
  300.     base := code - SizeOfHeader;
  301.     K.sysfunc2(68, 11);
  302.     InitializeCriticalSection(CriticalSection);
  303.     K._init;
  304.     _import := (K.dll_Load(import_) = 0) & (K.imp_error.error = 0);
  305.     IF ~_import THEN
  306.         imp_error
  307.     END
  308. END init;
  309.  
  310.  
  311. PROCEDURE SetMultiThr* (value: BOOLEAN);
  312. BEGIN
  313.     multi := value
  314. END SetMultiThr;
  315.  
  316.  
  317. PROCEDURE GetTickCount* (): INTEGER;
  318.     RETURN K.sysfunc2(26, 9) * 10
  319. END GetTickCount;
  320.  
  321.  
  322. PROCEDURE dllentry* (hinstDLL, fdwReason, lpvReserved: INTEGER): INTEGER;
  323.     RETURN 0
  324. END dllentry;
  325.  
  326.  
  327. PROCEDURE sofinit*;
  328. END sofinit;
  329.  
  330.  
  331. END API.