thread.inc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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 Win32
  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. var
  21. dataindex : dword;
  22. { import the necessary stuff from windows }
  23. function TlsAlloc : DWord;external 'kernel32' name 'TlsAlloc';
  24. function TlsGetValue(dwTlsIndex : DWord) : pointer;
  25. external 'kernel32' name 'TlsGetValue';
  26. function TlsSetValue(dwTlsIndex : DWord;lpTlsValue : pointer) : LongBool;
  27. external 'kernel32' name 'TlsSetValue';
  28. function TlsFree(dwTlsIndex : DWord) : LongBool;
  29. external 'kernel32' name 'TlsFree';
  30. function CreateThread(lpThreadAttributes : pointer;
  31. dwStackSize : DWord; lpStartAddress : pointer;lpParameter : pointer;
  32. dwCreationFlags : DWord;var lpThreadId : DWord) : THandle;
  33. external 'kernel32' name 'CreateThread';
  34. procedure ExitThread(dwExitCode : DWord);
  35. external 'kernel32' name 'ExitThread';
  36. procedure init_threadvar(var offset : dword;size : dword);[public,alias: 'FPC_INIT_THREADVAR'];
  37. begin
  38. offset:=threadvarblocksize;
  39. inc(threadvarblocksize,size);
  40. end;
  41. function relocate_threadvar(offset : dword) : pointer;[public,alias: 'FPC_RELOCATE_THREADVAR'];
  42. begin
  43. relocate_threadvar:=TlsGetValue(dataindex)+offset;
  44. end;
  45. procedure AllocateThreadVars;
  46. var
  47. threadvars : pointer;
  48. begin
  49. { we've to allocate the memory from windows }
  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. threadvars:=pointer(GlobalAlloc(GMEM_FIXED or GMEM_ZEROINIT,
  55. threadvarblocksize));
  56. TlsSetValue(dataindex,threadvars);
  57. end;
  58. procedure InitThread;
  59. begin
  60. InitFPU;
  61. { we don't need to set the data to 0 because we did this with }
  62. { the fillchar above, but it looks nicer }
  63. { ExceptAddrStack and ExceptObjectStack are threadvars }
  64. { so every thread has its on exception handling capabilities }
  65. InitExceptions;
  66. InOutRes:=0;
  67. ErrNo:=0;
  68. end;
  69. procedure DoneThread;
  70. var
  71. threadvars : pointer;
  72. begin
  73. { release thread vars }
  74. threadvars:=TlsGetValue(dataindex);
  75. GlobalFree(threadvars);
  76. end;
  77. function ThreadMain(param : pointer) : dword;stdcall;
  78. var
  79. ti : tthreadinfo;
  80. begin
  81. {$ifdef DEBUG_MT}
  82. writeln('New thread started, initialising ...');
  83. {$endif DEBUG_MT}
  84. AllocateThreadVars;
  85. InitThread;
  86. ti:=pthreadinfo(param)^;
  87. dispose(pthreadinfo(param));
  88. {$ifdef DEBUG_MT}
  89. writeln('Jumping to thread function');
  90. {$endif DEBUG_MT}
  91. ThreadMain:=ti.f(ti.p);
  92. end;
  93. function BeginThread(sa : Pointer;stacksize : dword;
  94. ThreadFunction : tthreadfunc;p : pointer;creationFlags : dword;
  95. var ThreadId : DWord) : DWord;
  96. var
  97. ti : pthreadinfo;
  98. begin
  99. {$ifdef DEBUG_MT}
  100. writeln('Creating new thread');
  101. {$endif DEBUG_MT}
  102. IsMultithreaded:=true;
  103. { the only way to pass data to the newly created thread }
  104. { in a MT safe way, is to use the heap }
  105. new(ti);
  106. ti^.f:=ThreadFunction;
  107. ti^.p:=p;
  108. {$ifdef DEBUG_MT}
  109. writeln('Starting new thread');
  110. {$endif DEBUG_MT}
  111. BeginThread:=CreateThread(sa,stacksize,@ThreadMain,ti,
  112. creationflags,threadid);
  113. end;
  114. function BeginThread(ThreadFunction : tthreadfunc) : DWord;
  115. var
  116. dummy : dword;
  117. begin
  118. BeginThread:=BeginThread(nil,0,ThreadFunction,nil,0,dummy);
  119. end;
  120. function BeginThread(ThreadFunction : tthreadfunc;p : pointer) : DWord;
  121. var
  122. dummy : dword;
  123. begin
  124. BeginThread:=BeginThread(nil,0,ThreadFunction,p,0,dummy);
  125. end;
  126. function BeginThread(ThreadFunction : tthreadfunc;p : pointer;
  127. var ThreadId : DWord) : DWord;
  128. begin
  129. BeginThread:=BeginThread(nil,0,ThreadFunction,p,0,ThreadId);
  130. end;
  131. procedure EndThread(ExitCode : DWord);
  132. begin
  133. DoneThread;
  134. ExitThread(ExitCode);
  135. end;
  136. procedure EndThread;
  137. begin
  138. EndThread(0);
  139. end;
  140. { we implement these procedures for win32 by importing them }
  141. { directly from windows }
  142. procedure InitCriticalsection(var cs : tcriticalsection);
  143. begin
  144. end;
  145. procedure DoneCriticalsection(var cs : tcriticalsection);
  146. begin
  147. end;
  148. procedure EnterCriticalsection(var cs : tcriticalsection);
  149. begin
  150. end;
  151. procedure LeaveCriticalsection(var cs : tcriticalsection);
  152. begin
  153. end;
  154. {
  155. procedure InitCriticalSection(var cs : tcriticalsection);
  156. external 'kernel32' name 'InitializeCriticalSection';
  157. procedure DoneCriticalSection(var cs : tcriticalsection);
  158. external 'kernel32' name 'DeleteCriticalSection';
  159. procedure EnterCriticalSection(var cs : tcriticalsection);
  160. external 'kernel32' name 'EnterCriticalSection';
  161. procedure LeaveCriticalSection(var cs : tcriticalsection);
  162. external 'kernel32' name 'LeaveCriticalSection';
  163. }
  164. {
  165. $Log$
  166. Revision 1.1 2001-01-01 19:06:36 florian
  167. + initial release
  168. }