thread.inc 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. {
  2. $Id$
  3. This file is part of the Free Pascal run time library.
  4. Copyright (c) 2001 by the Free Pascal development team.
  5. Multithreading implementation for Linux
  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. {$ifdef MT}
  13. const
  14. DefaultStackSize = 16384;
  15. threadvarblocksize : dword = 0;
  16. type
  17. pthreadinfo = ^tthreadinfo;
  18. tthreadinfo = record
  19. f : tthreadfunc;
  20. p : pointer;
  21. end;
  22. var
  23. dataindex : pointer;
  24. procedure init_threadvar(var offset : dword;size : dword);[public,alias: 'FPC_INIT_THREADVAR'];
  25. begin
  26. offset:=threadvarblocksize;
  27. inc(threadvarblocksize,size);
  28. end;
  29. function relocate_threadvar(offset : dword) : pointer;[public,alias: 'FPC_RELOCATE_THREADVAR'];
  30. begin
  31. Relocate_ThreadVar := DataIndex + Offset;
  32. end;
  33. procedure AllocateThreadVars;
  34. begin
  35. { we've to allocate the memory from system }
  36. { because the FPC heap management uses }
  37. { exceptions which use threadvars but }
  38. { these aren't allocated yet ... }
  39. { allocate room on the heap for the thread vars }
  40. DataIndex:=Pointer(Sys_mmap(0,threadvarblocksize,3,MAP_PRIVATE+MAP_ANONYMOUS,-1,0));
  41. FillChar(DataIndex^,threadvarblocksize,0);
  42. end;
  43. procedure ReleaseThreadVars;
  44. begin
  45. Sys_munmap(Longint(dataindex),threadvarblocksize);
  46. end;
  47. procedure InitThread;
  48. begin
  49. ResetFPU;
  50. { we don't need to set the data to 0 because we did this with }
  51. { the fillchar above, but it looks nicer }
  52. { ExceptAddrStack and ExceptObjectStack are threadvars }
  53. { so every thread has its on exception handling capabilities }
  54. InitExceptions;
  55. InOutRes:=0;
  56. // ErrNo:=0;
  57. end;
  58. procedure DoneThread;
  59. begin
  60. { release thread vars }
  61. ReleaseThreadVars;
  62. end;
  63. function ThreadMain(param : pointer) : longint;cdecl;
  64. var
  65. ti : tthreadinfo;
  66. begin
  67. {$ifdef DEBUG_MT}
  68. writeln('New thread started, initialising ...');
  69. {$endif DEBUG_MT}
  70. AllocateThreadVars;
  71. InitThread;
  72. ti:=pthreadinfo(param)^;
  73. dispose(pthreadinfo(param));
  74. {$ifdef DEBUG_MT}
  75. writeln('Jumping to thread function');
  76. {$endif DEBUG_MT}
  77. ThreadMain:=ti.f(ti.p);
  78. end;
  79. function BeginThread(sa : Pointer;stacksize : dword;
  80. ThreadFunction : tthreadfunc;p : pointer;
  81. creationFlags : dword; var ThreadId : DWord) : DWord;
  82. var
  83. ti : pthreadinfo;
  84. FStackPointer : pointer;
  85. Flags : longint;
  86. begin
  87. {$ifdef DEBUG_MT}
  88. writeln('Creating new thread');
  89. {$endif DEBUG_MT}
  90. IsMultithread:=true;
  91. { the only way to pass data to the newly created thread }
  92. { in a MT safe way, is to use the heap }
  93. new(ti);
  94. ti^.f:=ThreadFunction;
  95. ti^.p:=p;
  96. {$ifdef DEBUG_MT}
  97. writeln('Starting new thread');
  98. {$endif DEBUG_MT}
  99. Flags := CLONE_VM + CLONE_FS + CLONE_FILES + CLONE_SIGHAND + SIGCHLD;
  100. { Setup stack }
  101. Getmem(pointer(FStackPointer),StackSize);
  102. inc(FStackPointer,StackSize);
  103. { Clone }
  104. ThreadID:=Clone(@ThreadMain,pointer(FStackPointer),Flags,ti);
  105. end;
  106. function BeginThread(ThreadFunction : tthreadfunc) : DWord;
  107. var
  108. dummy : dword;
  109. begin
  110. BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,nil,0,dummy);
  111. end;
  112. function BeginThread(ThreadFunction : tthreadfunc;p : pointer) : DWord;
  113. var
  114. dummy : dword;
  115. begin
  116. BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,p,0,dummy);
  117. end;
  118. function BeginThread(ThreadFunction : tthreadfunc;p : pointer;var ThreadId : DWord) : DWord;
  119. begin
  120. BeginThread:=BeginThread(nil,DefaultStackSize,ThreadFunction,p,0,ThreadId);
  121. end;
  122. procedure EndThread(ExitCode : DWord);
  123. begin
  124. DoneThread;
  125. Sys_Exit(ExitCode);
  126. end;
  127. procedure EndThread;
  128. begin
  129. EndThread(0);
  130. end;
  131. procedure InitCriticalSection(var cs : TRTLCriticalSection);
  132. begin
  133. end;
  134. procedure DoneCriticalSection(var cs : TRTLCriticalSection);
  135. begin
  136. end;
  137. procedure EnterCriticalSection(var cs : TRTLCriticalSection);
  138. begin
  139. end;
  140. procedure LeaveCriticalSection(var cs : TRTLCriticalSection);
  141. begin
  142. end;
  143. {$endif MT}
  144. {
  145. $Log$
  146. Revision 1.2 2001-10-23 21:51:03 peter
  147. * criticalsection renamed to rtlcriticalsection for kylix compatibility
  148. Revision 1.1 2001/10/17 10:27:47 marco
  149. * Moved to unix/ since there is nothing linux specific about it.
  150. Revision 1.1 2001/10/14 13:33:20 peter
  151. * start of thread support for linux
  152. }