thread.inc 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 1999-2000 by the Free Pascal development team.
  5. Multithreading implementation for OS/2
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. const
  13. ThreadVarBlockSize: dword = 0;
  14. type
  15. TThreadInfo = record
  16. F: TThreadFunc;
  17. P: pointer;
  18. end;
  19. PThreadInfo = ^TThreadInfo;
  20. PPointer = ^pointer;
  21. var
  22. (* Pointer to an allocated dword space within the local thread *)
  23. (* memory area. Pointer to the real memory block allocated for *)
  24. (* thread vars in this block is then stored in this dword. *)
  25. DataIndex: PPointer;
  26. { import the necessary stuff from the OS }
  27. function DosAllocThreadLocalMemory (Count: cardinal; var P: pointer): longint;
  28. cdecl; external 'DOSCALLS' index 454;
  29. function DosFreeThreadLocalMemory (P: pointer): longint; cdecl;
  30. external 'DOSCALLS' index 455;
  31. function DosCreateThread (var TID: longint; Address: TThreadEntry;
  32. aParam: pointer; Flags: longint; StackSize: longint): longint; cdecl;
  33. external 'DOSCALLS' index 311;
  34. procedure DosExit (Action, Result: longint); cdecl;
  35. external 'DOSCALLS' index 233;
  36. procedure Init_ThreadVar (var TVOffset: dword; Size: dword);
  37. [public, alias: 'FPC_INIT_THREADVAR'];
  38. begin
  39. TVOffset := ThreadVarBlockSize;
  40. Inc (ThreadVarBlockSize, Size);
  41. end;
  42. function Relocate_ThreadVar (TVOffset: dword): pointer;
  43. [public,alias: 'FPC_RELOCATE_THREADVAR'];
  44. begin
  45. Relocate_ThreadVar := DataIndex + TVOffset;
  46. end;
  47. procedure AllocateThreadVars;
  48. begin
  49. { we've to allocate the memory from the OS }
  50. { because the FPC heap management uses }
  51. { exceptions which use threadvars but }
  52. { these aren't allocated yet ... }
  53. { allocate room on the heap for the thread vars }
  54. if DosAllocMem (DataIndex^, ThreadVarBlockSize, ) <> 0 then RunError (8);
  55. end;
  56. procedure InitThread;
  57. begin
  58. InitFPU;
  59. { we don't need to set the data to 0 because we did this with }
  60. { the fillchar above, but it looks nicer }
  61. { ExceptAddrStack and ExceptObjectStack are threadvars }
  62. { so every thread has its on exception handling capabilities }
  63. InitExceptions;
  64. InOutRes := 0;
  65. ErrNo := 0;
  66. end;
  67. procedure DoneThread;
  68. begin
  69. { release thread vars }
  70. DosFreeMem (DataIndex^);
  71. end;
  72. function ThreadMain (Param: pointer): dword; cdecl
  73. var
  74. TI: TThreadInfo;
  75. begin
  76. {$ifdef DEBUG_MT}
  77. WriteLn ('New thread started, initialising ...');
  78. {$endif DEBUG_MT}
  79. AllocateThreadVars;
  80. InitThread;
  81. TI := PThreadInfo (Param)^;
  82. Dispose (PThreadInfo (Param));
  83. {$ifdef DEBUG_MT}
  84. WriteLn ('Jumping to thread function');
  85. {$endif DEBUG_MT}
  86. ThreadMain := TI.F (TI.P);
  87. end;
  88. function BeginThread (SA: pointer; StackSize: dword;
  89. ThreadFunction: TThreadFunc; P: pointer; CreationFlags: dword;
  90. var ThreadID: dword): dword;
  91. var
  92. TI: PThreadInfo;
  93. begin
  94. {$ifdef DEBUG_MT}
  95. WriteLn ('Creating new thread');
  96. {$endif DEBUG_MT}
  97. IsMultiThreaded := true;
  98. { the only way to pass data to the newly created thread }
  99. { in a MT safe way, is to use the heap }
  100. New (TI);
  101. TI^.F := ThreadFunction;
  102. TI^.P := P;
  103. {$ifdef DEBUG_MT}
  104. WriteLn ('Starting new thread');
  105. {$endif DEBUG_MT}
  106. BeginThread := CreateThread (sa,stacksize,@ThreadMain,ti,
  107. creationflags,threadid);
  108. end;
  109. function BeginThread (ThreadFunction: TThreadFunc): dword;
  110. var
  111. Dummy: dword;
  112. begin
  113. BeginThread := BeginThread (nil, 0, ThreadFunction, nil, 0, Dummy);
  114. end;
  115. function BeginThread (ThreadFunction: TThreadFunc; P: pointer): dword;
  116. var
  117. Dummy: dword;
  118. begin
  119. BeginThread := BeginThread (nil, 0, ThreadFunction, P, 0, Dummy);
  120. end;
  121. function BeginThread (ThreadFunction: TThreadFunc; P: pointer;
  122. var ThreadID: dword): dword;
  123. begin
  124. BeginThread := BeginThread (nil, 0, ThreadFunction, P, 0, ThreadID);
  125. end;
  126. procedure EndThread (ExitCode: dword);
  127. begin
  128. DoneThread;
  129. DosExit (0, ExitCode);
  130. end;
  131. procedure EndThread;
  132. begin
  133. EndThread (0);
  134. end;
  135. procedure InitCriticalSection (var cs : tcriticalsection);
  136. begin
  137. end;
  138. procedure DoneCriticalsection(var cs : tcriticalsection);
  139. begin
  140. end;
  141. procedure EnterCriticalsection(var cs : tcriticalsection);
  142. begin
  143. end;
  144. procedure LeaveCriticalsection(var cs : tcriticalsection);
  145. begin
  146. end;
  147. {
  148. $Log$
  149. Revision 1.1 2001-01-23 20:38:59 hajny
  150. + beginning of the OS/2 version
  151. Revision 1.1 2001/01/01 19:06:36 florian
  152. + initial release
  153. }