{$MODE OBJFPC} { -*- delphi -*- } {$INCLUDE settings.inc} // compiled with: fpc test.pas -dDEBUG -Co -Cr -CR -Ct -O- -g -gt -gl -gh -Sa -veiwnhb program test; uses sysutils, linux; // need to implement clone, as in ~/bin/fpc/trunk/src/rtl/linux/linux.pp // https://github.com/lattera/glibc/blob/416bf844227d37b043b16be28c9523eeaecd3de3/sysdeps/unix/sysv/linux/x86_64/clone.S // https://bugs.freepascal.org/view.php?id=24611 function LinuxCloneInitManager(): Boolean; begin Result := False; end; function LinuxCloneDoneManager(): Boolean; begin Result := True; end; function LinuxCloneBeginThread(SignalAction: Pointer; StackSize: SizeUInt; ThreadFunction: TThreadFunc; P: Pointer; CreationFlags: DWord; var ThreadID: TThreadID): TThreadID; begin Result := 0; clone(); end; procedure LinuxCloneEndThread(ExitCode: DWord); begin end; function LinuxCloneSuspendThread(ThreadID: TThreadID): DWord; begin Result := 0; end; function LinuxCloneResumeThread(ThreadID: TThreadID): DWord; begin Result := 0; end; function LinuxCloneKillThread(ThreadID: TThreadID): DWord; begin Result := 0; end; function LinuxCloneCloseThread(ThreadID: TThreadID): DWord; begin Result := 0; end; procedure LinuxCloneThreadSwitch(); begin end; function LinuxCloneWaitForThreadTerminate(ThreadID: TThreadID; Timeout: Longint): DWord; // milliseconds, 0 = no timeout begin Result := 0; end; function LinuxCloneThreadSetPriority(ThreadID: TThreadID; Priority: Longint): Boolean; // -15..15, 0=normal begin Result := False; end; function LinuxCloneThreadGetPriority(ThreadID: TThreadID): Longint; begin Result := 0; end; function LinuxCloneGetCurrentThreadID(): TThreadID; begin Result := 0; end; procedure LinuxCloneInitCriticalSection(var CriticalSection); begin end; procedure LinuxCloneDoneCriticalSection(var CriticalSection); begin end; procedure LinuxCloneEnterCriticalSection(var CriticalSection); begin end; function LinuxCloneTryEnterCriticalSection(var CriticalSection): Longint; begin Result := 0; end; procedure LinuxCloneLeaveCriticalSection(var CriticalSection); begin end; procedure LinuxCloneInitThreadVar(var Offset: DWord; Size: DWord); begin end; function LinuxCloneRelocateThreadVar(Offset: DWord): Pointer; begin Result := nil end; procedure LinuxCloneAllocateThreadVars(); begin end; procedure LinuxCloneReleaseThreadVars(); begin end; function LinuxCloneBasicEventCreate(EventAttributes: Pointer; ManualReset, InitialState: Boolean; const Name: AnsiString): PEventState; begin Result := nil; end; procedure LinuxCloneBasicEventDestroy(State: PEventState); begin end; procedure LinuxCloneBasicEventResetEvent(State: PEventState); begin end; procedure LinuxCloneBasicEventSetEvent(State: PEventState); begin end; function LinuxCloneBasicEventWaitFor(Timeout: Cardinal; State: PEventState): Longint; begin Result := 0; end; function LinuxCloneRTLEventCreate: PRTLEvent; begin Result := nil; end; procedure LinuxCloneRTLEventDestroy(Event: PRTLEvent); begin end; procedure LinuxCloneRTLEventSetEvent(Event: PRTLEvent); begin end; procedure LinuxCloneRTLEventResetEvent(Event: PRTLEvent); begin end; procedure LinuxCloneRTLEventWaitFor(Event: PRTLEvent); begin end; procedure LinuxCloneRTLEventWaitForTimeout(Event: PRTLEvent; Timeout: Longint); begin end; function LinuxCloneSemaphoreInit(): Pointer; begin Result := nil; end; procedure LinuxCloneSemaphoreDestroy(const Semaphore: Pointer); begin end; procedure LinuxCloneSemaphorePost(const Semaphore: Pointer); begin end; procedure LinuxCloneSemaphoreWait(const Semaphore: Pointer); begin end; const LinuxCloneThreadManager: TThreadManager = ( InitManager: @LinuxCloneInitManager; DoneManager: @LinuxCloneDoneManager; BeginThread: @LinuxCloneBeginThread; EndThread: @LinuxCloneEndThread; SuspendThread: @LinuxCloneSuspendThread; ResumeThread: @LinuxCloneResumeThread; KillThread: @LinuxCloneKillThread; CloseThread: @LinuxCloneCloseThread; ThreadSwitch: @LinuxCloneThreadSwitch; WaitForThreadTerminate: @LinuxCloneWaitForThreadTerminate; ThreadSetPriority: @LinuxCloneThreadSetPriority; ThreadGetPriority: @LinuxCloneThreadGetPriority; GetCurrentThreadID: @LinuxCloneGetCurrentThreadID; InitCriticalSection: @LinuxCloneInitCriticalSection; DoneCriticalSection: @LinuxCloneDoneCriticalSection; EnterCriticalSection: @LinuxCloneEnterCriticalSection; TryEnterCriticalSection: @LinuxCloneTryEnterCriticalSection; LeaveCriticalSection: @LinuxCloneLeaveCriticalSection; InitThreadVar: @LinuxCloneInitThreadVar; RelocateThreadVar: @LinuxCloneRelocateThreadVar; AllocateThreadVars: @LinuxCloneAllocateThreadVars; ReleaseThreadVars: @LinuxCloneReleaseThreadVars; BasicEventCreate: @LinuxCloneBasicEventCreate; BasicEventDestroy: @LinuxCloneBasicEventDestroy; BasicEventResetEvent: @LinuxCloneBasicEventResetEvent; BasicEventSetEvent: @LinuxCloneBasicEventSetEvent; BasicEventWaitFor: @LinuxCloneBasicEventWaitFor; RTLEventCreate: @LinuxCloneRTLEventCreate; RTLEventDestroy: @LinuxCloneRTLEventDestroy; RTLEventSetEvent: @LinuxCloneRTLEventSetEvent; RTLEventResetEvent: @LinuxCloneRTLEventResetEvent; RTLEventWaitFor: @LinuxCloneRTLEventWaitFor; RTLEventWaitForTimeout: @LinuxCloneRTLEventWaitForTimeout; SemaphoreInit: @LinuxCloneSemaphoreInit; SemaphoreDestroy: @LinuxCloneSemaphoreDestroy; SemaphorePost: @LinuxCloneSemaphorePost; SemaphoreWait: @LinuxCloneSemaphoreWait; ); procedure InitThreads(); begin SetThreadManager(LinuxCloneThreadManager); end; var ReadyEvent: PRTLEvent; threadvar DummyThreadVar: AnsiString; function Thread1(Parameter: Pointer): Int64; begin Writeln('Thread1 sleeping...'); Sleep(5000); DummyThreadVar := '1'; Writeln('Thread1 setting event...'); RTLEventSetEvent(ReadyEvent); Result := PtrUInt(Parameter) + Length(DummyThreadVar);; end; function Thread2(Parameter: Pointer): Int64; begin DummyThreadVar := '22'; Writeln('Thread2 sleeping...'); Sleep(20000); Writeln('Thread2 setting event...'); RTLEventSetEvent(ReadyEvent); Result := PtrUInt(Parameter) + Length(DummyThreadVar); end; var A, B: TThreadID; begin InitThreads(); Writeln('Create event...'); ReadyEvent := RTLEventCreate(); Writeln('Begin threads...'); RTLEventResetEvent(ReadyEvent); A := BeginThread(@Thread1, Pointer(1000)); B := BeginThread(@Thread2, Pointer(2000)); Writeln('Wait for event...'); RTLEventWaitFor(ReadyEvent, 100000); Writeln('Wait for threads...'); Writeln(WaitForThreadTerminate(A, 0)); Writeln(WaitForThreadTerminate(B, 0)); Writeln('Close threads...'); CloseThread(A); CloseThread(B); Writeln('Destroy event...'); RTLEventDestroy(ReadyEvent); end. *)