Subversion Repositories Kolibri OS

Rev

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

  1. (*
  2.     Copyright 2016, 2017, 2018 Anton Krotov
  3.  
  4.     This program is free software: you can redistribute it and/or modify
  5.     it under the terms of the GNU Lesser General Public License as published by
  6.     the Free Software Foundation, either version 3 of the License, or
  7.     (at your option) any later version.
  8.  
  9.     This program is distributed in the hope that it will be useful,
  10.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.     GNU Lesser General Public License for more details.
  13.  
  14.     You should have received a copy of the GNU Lesser General Public License
  15.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  16. *)
  17.  
  18. MODULE API;
  19.  
  20. IMPORT sys := SYSTEM;
  21.  
  22.  
  23. CONST
  24.  
  25.     MAX_SIZE  = 16 * 400H;
  26.     HEAP_SIZE =  1 * 100000H;
  27.  
  28.     _new = 1;
  29.     _dispose = 2;
  30.  
  31.  
  32. TYPE
  33.  
  34.     CRITICAL_SECTION = ARRAY 2 OF INTEGER;
  35.  
  36.  
  37. VAR
  38.  
  39.     heap, endheap: INTEGER;
  40.     pockets: ARRAY MAX_SIZE DIV 32 + 1 OF INTEGER;
  41.  
  42.     CriticalSection: CRITICAL_SECTION;
  43.  
  44.  
  45. PROCEDURE [stdcall] zeromem* (size, adr: INTEGER);
  46. BEGIN
  47.     sys.CODE("578B7D0C8B4D0833C09CFCF3AB9D5F")
  48. END zeromem;
  49.  
  50.  
  51. PROCEDURE mem_commit* (adr, size: INTEGER);
  52. VAR
  53.     tmp: INTEGER;
  54. BEGIN
  55.     FOR tmp := adr TO adr + size - 1 BY 4096 DO
  56.         sys.PUT(tmp, 0)
  57.     END
  58. END mem_commit;
  59.  
  60.  
  61. PROCEDURE strncmp* (a, b, n: INTEGER): INTEGER;
  62. VAR
  63.     A, B: CHAR;
  64.     Res: INTEGER;
  65. BEGIN
  66.     Res := 0;
  67.     WHILE n > 0 DO
  68.         sys.GET(a, A); INC(a);
  69.         sys.GET(b, B); INC(b);
  70.         DEC(n);
  71.         IF A # B THEN
  72.             Res := ORD(A) - ORD(B);
  73.             n := 0
  74.         ELSIF A = 0X THEN
  75.             n := 0
  76.         END
  77.     END
  78.     RETURN Res
  79. END strncmp;
  80.  
  81.  
  82. PROCEDURE [stdcall] sysfunc1* (arg1: INTEGER): INTEGER;
  83. BEGIN
  84.     sys.CODE("8B4508");           (* mov     eax, [ebp + 08h] *)
  85.     sys.CODE("CD40");             (* int     40h              *)
  86.     sys.CODE("C9");               (* leave                    *)
  87.     sys.CODE("C20400");           (* ret     04h              *)
  88.     RETURN 0
  89. END sysfunc1;
  90.  
  91.  
  92. PROCEDURE [stdcall] sysfunc2* (arg1, arg2: INTEGER): INTEGER;
  93. BEGIN
  94.     sys.CODE("53");               (* push    ebx              *)
  95.     sys.CODE("8B4508");           (* mov     eax, [ebp + 08h] *)
  96.     sys.CODE("8B5D0C");           (* mov     ebx, [ebp + 0Ch] *)
  97.     sys.CODE("CD40");             (* int     40h              *)
  98.     sys.CODE("5B");               (* pop     ebx              *)
  99.     sys.CODE("C9");               (* leave                    *)
  100.     sys.CODE("C20800");           (* ret     08h              *)
  101.     RETURN 0
  102. END sysfunc2;
  103.  
  104.  
  105. PROCEDURE [stdcall] sysfunc3* (arg1, arg2, arg3: INTEGER): INTEGER;
  106. BEGIN
  107.     sys.CODE("53");               (* push    ebx              *)
  108.     sys.CODE("8B4508");           (* mov     eax, [ebp + 08h] *)
  109.     sys.CODE("8B5D0C");           (* mov     ebx, [ebp + 0Ch] *)
  110.     sys.CODE("8B4D10");           (* mov     ecx, [ebp + 10h] *)
  111.     sys.CODE("CD40");             (* int     40h              *)
  112.     sys.CODE("5B");               (* pop     ebx              *)
  113.     sys.CODE("C9");               (* leave                    *)
  114.     sys.CODE("C20C00");           (* ret     0Ch              *)
  115.     RETURN 0
  116. END sysfunc3;
  117.  
  118.  
  119. PROCEDURE [stdcall] sysfunc4* (arg1, arg2, arg3, arg4: INTEGER): INTEGER;
  120. BEGIN
  121.     sys.CODE("53");               (* push    ebx              *)
  122.     sys.CODE("8B4508");           (* mov     eax, [ebp + 08h] *)
  123.     sys.CODE("8B5D0C");           (* mov     ebx, [ebp + 0Ch] *)
  124.     sys.CODE("8B4D10");           (* mov     ecx, [ebp + 10h] *)
  125.     sys.CODE("8B5514");           (* mov     edx, [ebp + 14h] *)
  126.     sys.CODE("CD40");             (* int     40h              *)
  127.     sys.CODE("5B");               (* pop     ebx              *)
  128.     sys.CODE("C9");               (* leave                    *)
  129.     sys.CODE("C21000");           (* ret     10h              *)
  130.     RETURN 0
  131. END sysfunc4;
  132.  
  133.  
  134. PROCEDURE [stdcall] sysfunc5* (arg1, arg2, arg3, arg4, arg5: INTEGER): INTEGER;
  135. BEGIN
  136.     sys.CODE("53");               (* push    ebx              *)
  137.     sys.CODE("56");               (* push    esi              *)
  138.     sys.CODE("8B4508");           (* mov     eax, [ebp + 08h] *)
  139.     sys.CODE("8B5D0C");           (* mov     ebx, [ebp + 0Ch] *)
  140.     sys.CODE("8B4D10");           (* mov     ecx, [ebp + 10h] *)
  141.     sys.CODE("8B5514");           (* mov     edx, [ebp + 14h] *)
  142.     sys.CODE("8B7518");           (* mov     esi, [ebp + 18h] *)
  143.     sys.CODE("CD40");             (* int     40h              *)
  144.     sys.CODE("5E");               (* pop     esi              *)
  145.     sys.CODE("5B");               (* pop     ebx              *)
  146.     sys.CODE("C9");               (* leave                    *)
  147.     sys.CODE("C21400");           (* ret     14h              *)
  148.     RETURN 0
  149. END sysfunc5;
  150.  
  151.  
  152. PROCEDURE switch_task;
  153. VAR
  154.     res: INTEGER;
  155. BEGIN
  156.     res := sysfunc2(68, 1)
  157. END switch_task;
  158.  
  159.  
  160. PROCEDURE futex_create (ptr: INTEGER): INTEGER;
  161.     RETURN sysfunc3(77, 0, ptr)
  162. END futex_create;
  163.  
  164.  
  165. PROCEDURE futex_wait (futex, value, timeout: INTEGER);
  166. VAR
  167.     res: INTEGER;
  168. BEGIN
  169.     res := sysfunc5(77, 2, futex, value, timeout)
  170. END futex_wait;
  171.  
  172.  
  173. PROCEDURE futex_wake (futex, number: INTEGER);
  174. VAR
  175.     res: INTEGER;
  176. BEGIN
  177.     res := sysfunc4(77, 3, futex, number)
  178. END futex_wake;
  179.  
  180.  
  181. PROCEDURE EnterCriticalSection* (VAR CriticalSection: CRITICAL_SECTION);
  182. BEGIN
  183.     switch_task;
  184.     futex_wait(CriticalSection[0], 1, 10000);
  185.     CriticalSection[1] := 1
  186. END EnterCriticalSection;
  187.  
  188.  
  189. PROCEDURE LeaveCriticalSection* (VAR CriticalSection: CRITICAL_SECTION);
  190. BEGIN
  191.     CriticalSection[1] := 0;
  192.     futex_wake(CriticalSection[0], 1)
  193. END LeaveCriticalSection;
  194.  
  195.  
  196. PROCEDURE InitializeCriticalSection* (VAR CriticalSection: CRITICAL_SECTION);
  197. BEGIN
  198.     CriticalSection[0] := futex_create(sys.ADR(CriticalSection[1]));
  199.     CriticalSection[1] := 0
  200. END InitializeCriticalSection;
  201.  
  202.  
  203. PROCEDURE __NEW (size: INTEGER): INTEGER;
  204. VAR
  205.     res, idx, temp: INTEGER;
  206. BEGIN
  207.     IF size <= MAX_SIZE THEN
  208.         idx := ASR(size, 5);
  209.         res := pockets[idx];
  210.         IF res # 0 THEN
  211.             sys.GET(res, pockets[idx]);
  212.             sys.PUT(res, size);
  213.             INC(res, 4)
  214.         ELSE
  215.             temp := 0;
  216.             IF heap + size >= endheap THEN
  217.                 IF sysfunc2(18, 16) > ASR(HEAP_SIZE, 10) THEN
  218.                     temp := sysfunc3(68, 12, HEAP_SIZE)
  219.                 ELSE
  220.                     temp := 0
  221.                 END;
  222.                 IF temp # 0 THEN
  223.                     mem_commit(temp, HEAP_SIZE);
  224.                     heap := temp;
  225.                     endheap := heap + HEAP_SIZE
  226.                 ELSE
  227.                     temp := -1
  228.                 END
  229.             END;
  230.             IF (heap # 0) & (temp # -1) THEN
  231.                 sys.PUT(heap, size);
  232.                 res := heap + 4;
  233.                 heap := heap + size
  234.             ELSE
  235.                 res := 0
  236.             END
  237.         END
  238.     ELSE
  239.         IF sysfunc2(18, 16) > ASR(size, 10) THEN
  240.             res := sysfunc3(68, 12, size);
  241.             IF res # 0 THEN
  242.                 mem_commit(res, size);
  243.                 sys.PUT(res, size);
  244.                 INC(res, 4)
  245.             END
  246.         ELSE
  247.             res := 0
  248.         END
  249.     END;
  250.     IF (res # 0) & (size <= MAX_SIZE) THEN
  251.         zeromem(ASR(size, 2) - 1, res)
  252.     END
  253.     RETURN res
  254. END __NEW;
  255.  
  256.  
  257. PROCEDURE __DISPOSE (ptr: INTEGER): INTEGER;
  258. VAR
  259.     size, idx: INTEGER;
  260. BEGIN
  261.     DEC(ptr, 4);
  262.     sys.GET(ptr, size);
  263.     IF size <= MAX_SIZE THEN
  264.         idx := ASR(size, 5);
  265.         sys.PUT(ptr, pockets[idx]);
  266.         pockets[idx] := ptr
  267.     ELSE
  268.         size := sysfunc3(68, 13, ptr)
  269.     END
  270.     RETURN 0
  271. END __DISPOSE;
  272.  
  273.  
  274. PROCEDURE NEW_DISPOSE (func, arg: INTEGER): INTEGER;
  275. VAR
  276.     res: INTEGER;
  277. BEGIN
  278.     EnterCriticalSection(CriticalSection);
  279.  
  280.     IF func = _new THEN
  281.         res := __NEW(arg)
  282.     ELSIF func = _dispose THEN
  283.         res := __DISPOSE(arg)
  284.     END;
  285.  
  286.     LeaveCriticalSection(CriticalSection)
  287.     RETURN res
  288. END NEW_DISPOSE;
  289.  
  290.  
  291. PROCEDURE _NEW* (size: INTEGER): INTEGER;
  292.     RETURN NEW_DISPOSE(_new, size)
  293. END _NEW;
  294.  
  295.  
  296. PROCEDURE _DISPOSE* (ptr: INTEGER): INTEGER;
  297.     RETURN NEW_DISPOSE(_dispose, ptr)
  298. END _DISPOSE;
  299.  
  300.  
  301. PROCEDURE ExitProcess* (p1: INTEGER);
  302. BEGIN
  303.     p1 := sysfunc1(-1)
  304. END ExitProcess;
  305.  
  306.  
  307. PROCEDURE ExitThread* (p1: INTEGER);
  308. BEGIN
  309.     p1 := sysfunc1(-1)
  310. END ExitThread;
  311.  
  312.  
  313. PROCEDURE OutChar (c: CHAR);
  314. VAR
  315.     res: INTEGER;
  316. BEGIN
  317.     res := sysfunc3(63, 1, ORD(c))
  318. END OutChar;
  319.  
  320.  
  321. PROCEDURE DebugMsg* (lpText, lpCaption: INTEGER);
  322. VAR
  323.     c: CHAR;
  324. BEGIN
  325.     IF lpCaption # 0 THEN
  326.         OutChar(0DX);
  327.         OutChar(0AX);
  328.         REPEAT
  329.             sys.GET(lpCaption, c);
  330.             IF c # 0X THEN
  331.                 OutChar(c)
  332.             END;
  333.             INC(lpCaption)
  334.         UNTIL c = 0X;
  335.         OutChar(":");
  336.         OutChar(0DX);
  337.         OutChar(0AX)
  338.     END;
  339.     REPEAT
  340.         sys.GET(lpText, c);
  341.         IF c # 0X THEN
  342.             OutChar(c)
  343.         END;
  344.         INC(lpText)
  345.     UNTIL c = 0X;
  346.     IF lpCaption # 0 THEN
  347.         OutChar(0DX);
  348.         OutChar(0AX)
  349.     END
  350. END DebugMsg;
  351.  
  352.  
  353. PROCEDURE init* (p1: INTEGER);
  354. BEGIN
  355.     p1 := sysfunc2(68, 11);
  356.     InitializeCriticalSection(CriticalSection)
  357. END init;
  358.  
  359.  
  360. END API.