mirror of https://github.com/red-prig/fpPS4.git
664 lines
18 KiB
Plaintext
664 lines
18 KiB
Plaintext
unit kern_thr;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
{$CALLING SysV_ABI_CDecl}
|
|
|
|
interface
|
|
|
|
uses
|
|
mqueue,
|
|
ucontext,
|
|
signal,
|
|
signalvar,
|
|
kern_mtx;
|
|
|
|
const
|
|
TDS_INACTIVE =0;
|
|
TDS_INHIBITED=1;
|
|
TDS_CAN_RUN =2;
|
|
TDS_RUNQ =3;
|
|
TDS_RUNNING =4;
|
|
|
|
TDF_BORROWING =$00000001; // Thread is borrowing pri from another.
|
|
TDF_INPANIC =$00000002; // Caused a panic, let it drive crashdump.
|
|
TDF_INMEM =$00000004; // Thread's stack is in memory.
|
|
TDF_SINTR =$00000008; // Sleep is interruptible.
|
|
TDF_TIMEOUT =$00000010; // Timing out during sleep.
|
|
TDF_IDLETD =$00000020; // This is a per-CPU idle thread.
|
|
TDF_CANSWAP =$00000040; // Thread can be swapped.
|
|
TDF_SLEEPABORT =$00000080; // sleepq_abort was called.
|
|
TDF_KTH_SUSP =$00000100; // kthread is suspended
|
|
TDF_UNUSED09 =$00000200; // --available--
|
|
TDF_BOUNDARY =$00000400; // Thread suspended at user boundary
|
|
TDF_ASTPENDING =$00000800; // Thread has some asynchronous events.
|
|
TDF_TIMOFAIL =$00001000; // Timeout from sleep after we were awake.
|
|
TDF_SBDRY =$00002000; // Stop only on usermode boundary.
|
|
TDF_UPIBLOCKED =$00004000; // Thread blocked on user PI mutex.
|
|
TDF_NEEDSUSPCHK=$00008000; // Thread may need to suspend.
|
|
TDF_NEEDRESCHED=$00010000; // Thread needs to yield.
|
|
TDF_NEEDSIGCHK =$00020000; // Thread may need signal delivery.
|
|
TDF_NOLOAD =$00040000; // Ignore during load avg calculations.
|
|
TDF_UNUSED19 =$00080000; // --available--
|
|
TDF_THRWAKEUP =$00100000; // Libthr thread must not suspend itself.
|
|
TDF_UNUSED21 =$00200000; // --available--
|
|
TDF_SWAPINREQ =$00400000; // Swapin request due to wakeup.
|
|
TDF_UNUSED23 =$00800000; // --available--
|
|
TDF_SCHED0 =$01000000; // Reserved for scheduler private use
|
|
TDF_SCHED1 =$02000000; // Reserved for scheduler private use
|
|
TDF_SCHED2 =$04000000; // Reserved for scheduler private use
|
|
TDF_SCHED3 =$08000000; // Reserved for scheduler private use
|
|
TDF_ALRMPEND =$10000000; // Pending SIGVTALRM needs to be posted.
|
|
TDF_PROFPEND =$20000000; // Pending SIGPROF needs to be posted.
|
|
TDF_MACPEND =$40000000; // AST-based MAC event pending.
|
|
|
|
TDF_SLICEEND =TDF_SCHED2; // Thread time slice is over.
|
|
|
|
TDF_SUSP_CTX =$80000000; // Sony extension
|
|
|
|
//
|
|
|
|
TDP_OLDMASK =$00000001; // Need to restore mask after suspend.
|
|
TDP_INKTR =$00000002; // Thread is currently in KTR code.
|
|
TDP_INKTRACE =$00000004; // Thread is currently in KTRACE code.
|
|
TDP_BUFNEED =$00000008; // Do not recurse into the buf flush
|
|
TDP_COWINPROGRESS=$00000010; // Snapshot copy-on-write in progress.
|
|
TDP_ALTSTACK =$00000020; // Have alternate signal stack.
|
|
TDP_DEADLKTREAT =$00000040; // Lock aquisition - deadlock treatment.
|
|
TDP_NOFAULTING =$00000080; // Do not handle page faults.
|
|
TDP_NOSLEEPING =$00000100; // Thread is not allowed to sleep on a sq.
|
|
TDP_OWEUPC =$00000200; // Call addupc() at next AST.
|
|
TDP_ITHREAD =$00000400; // Thread is an interrupt thread.
|
|
TDP_SYNCIO =$00000800; // Local override, disable async i/o.
|
|
TDP_SCHED1 =$00001000; // Reserved for scheduler private use
|
|
TDP_SCHED2 =$00002000; // Reserved for scheduler private use
|
|
TDP_SCHED3 =$00004000; // Reserved for scheduler private use
|
|
TDP_SCHED4 =$00008000; // Reserved for scheduler private use
|
|
TDP_GEOM =$00010000; // Settle GEOM before finishing syscall
|
|
TDP_SOFTDEP =$00020000; // Stuck processing softdep worklist
|
|
TDP_NORUNNINGBUF =$00040000; // Ignore runningbufspace check
|
|
TDP_WAKEUP =$00080000; // Don't sleep in umtx cond_wait
|
|
TDP_INBDFLUSH =$00100000; // Already in BO_BDFLUSH, do not recurse
|
|
TDP_KTHREAD =$00200000; // This is an official kernel thread
|
|
TDP_CALLCHAIN =$00400000; // Capture thread's callchain
|
|
TDP_IGNSUSP =$00800000; // Permission to ignore the MNTK_SUSPEND*
|
|
TDP_AUDITREC =$01000000; // Audit record pending on thread
|
|
TDP_RFPPWAIT =$02000000; // Handle RFPPWAIT on syscall exit
|
|
TDP_RESETSPUR =$04000000; // Reset spurious page fault history.
|
|
TDP_NERRNO =$08000000; // Last errno is already in td_errno
|
|
TDP_UIOHELD =$10000000; // Current uio has pages held in td_ma
|
|
TDP_DEVMEMIO =$20000000; // Accessing memory for /dev/mem
|
|
TDP_EXECVMSPC =$40000000; // Execve destroyed old vmspace
|
|
|
|
TDI_SUSPENDED =$0001; // On suspension queue.
|
|
TDI_SLEEPING =$0002; // Actually asleep! (tricky).
|
|
TDI_SWAPPED =$0004; // Stack not in mem. Bad juju if run.
|
|
TDI_LOCK =$0008; // Stopped on a lock.
|
|
TDI_IWAIT =$0010; // Awaiting interrupt.
|
|
|
|
TDI_SUSP_CTX =$0020; // Sony extension
|
|
|
|
THR_SUSPENDED =$0001;
|
|
|
|
// These flags are kept in p_flag.
|
|
P_ADVLOCK =$00001; // Process may hold a POSIX advisory lock.
|
|
P_CONTROLT =$00002; // Has a controlling terminal.
|
|
P_WEXIT =$02000; // Working on exiting.
|
|
P_EXEC =$04000; // Process called exec.
|
|
P_INEXEC =$4000000; // Process is in execve().
|
|
|
|
// Types and flags for mi_switch().
|
|
SW_TYPE_MASK =$ff; // First 8 bits are switch type
|
|
SWT_NONE = 0; // Unspecified switch.
|
|
SWT_PREEMPT = 1; // Switching due to preemption.
|
|
SWT_OWEPREEMPT = 2; // Switching due to opepreempt.
|
|
SWT_TURNSTILE = 3; // Turnstile contention.
|
|
SWT_SLEEPQ = 4; // Sleepq wait.
|
|
SWT_SLEEPQTIMO = 5; // Sleepq timeout wait.
|
|
SWT_RELINQUISH = 6; // yield call.
|
|
SWT_NEEDRESCHED = 7; // NEEDRESCHED was set.
|
|
SWT_IDLE = 8; // Switching from the idle thread.
|
|
SWT_IWAIT = 9; // Waiting for interrupts.
|
|
SWT_SUSPEND =10; // Thread suspended.
|
|
SWT_REMOTEPREEMPT =11; // Remote processor preempted.
|
|
SWT_REMOTEWAKEIDLE=12; // Remote processor preempted idle.
|
|
SWT_COUNT =13; // Number of switch types.
|
|
|
|
// Flags
|
|
SW_VOL =$0100; // Voluntary switch.
|
|
SW_INVOL =$0200; // Involuntary switch.
|
|
SW_PREEMPT=$0400; // The invol switch is a preemption
|
|
|
|
PCB_FULL_IRET=1;
|
|
PCB_IS_JIT =2;
|
|
PCB_IS_HLE =4;
|
|
|
|
type
|
|
p_teb=^teb;
|
|
teb=packed record
|
|
SEH :Pointer;
|
|
stack :Pointer;
|
|
sttop :Pointer;
|
|
SubSystemTib :Pointer;
|
|
FiberData :Pointer;
|
|
Arbitrary :Pointer;
|
|
TIB :Pointer;
|
|
_align1 :array[0..24] of QWORD;
|
|
WOW64 :Pointer; //0x100
|
|
_align2 :array[0..18] of QWORD;
|
|
_resrv1 :array[0..3] of QWORD;
|
|
thread :Pointer; //0x1C0
|
|
fsbase :Pointer; //0x1C8
|
|
gsbase :Pointer; //0x1D0
|
|
jitcall :Pointer; //0x1D8
|
|
jit_trp :Pointer; //0x1E0
|
|
jit____ :Pointer; //0x1E8
|
|
iflag :QWORD; //0x1F0
|
|
_resrv2 :array[0..17] of QWORD;
|
|
_align3 :array[0..7] of QWORD;
|
|
actctx :Pointer; //0x2C8
|
|
_align4 :array[0..180] of QWORD;
|
|
_align5 :array[0..383] of QWORD;
|
|
DeallocationStack:Pointer; //0x1478
|
|
end;
|
|
|
|
const
|
|
teb_stack =ptruint(@teb(nil^).stack );
|
|
teb_sttop =ptruint(@teb(nil^).sttop );
|
|
teb_jitcall=ptruint(@teb(nil^).jitcall);
|
|
teb_thread =ptruint(@teb(nil^).thread );
|
|
teb_fsbase =ptruint(@teb(nil^).fsbase );
|
|
teb_gsbase =ptruint(@teb(nil^).gsbase );
|
|
teb_actctx =ptruint(@teb(nil^).actctx );
|
|
teb_jit_trp=ptruint(@teb(nil^).jit_trp);
|
|
teb_iflag =ptruint(@teb(nil^).iflag );
|
|
teb_dealloc=ptruint(@teb(nil^).DeallocationStack);
|
|
|
|
{$IF teb_jitcall<>$01D8}{$STOP teb_jitcall<>$01D8}{$ENDIF}
|
|
{$IF teb_thread <>$01C0}{$STOP teb_thread <>$01C0}{$ENDIF}
|
|
{$IF teb_actctx <>$02C8}{$STOP teb_actctx <>$02C8}{$ENDIF}
|
|
{$IF teb_dealloc<>$1478}{$STOP teb_dealloc<>$1478}{$ENDIF}
|
|
|
|
type
|
|
t_td_name=array[0..31] of AnsiChar;
|
|
|
|
t_td_stack=packed record
|
|
stack:Pointer;
|
|
sttop:Pointer;
|
|
end;
|
|
|
|
t_td_buffer=packed record
|
|
addr:Pointer;
|
|
size:QWORD;
|
|
end;
|
|
|
|
p_td_jctx=^t_td_jctx;
|
|
t_td_jctx=packed record
|
|
//block:Pointer;
|
|
rsp:Pointer;
|
|
rbp:Pointer;
|
|
local_cache:array[0..255] of Pointer;
|
|
call_ret_cache:Pointer;
|
|
end;
|
|
|
|
pp_kthread=^p_kthread;
|
|
p_kthread=^kthread;
|
|
kthread=record
|
|
td_plist :TAILQ_ENTRY;
|
|
td_umtxq :Pointer; //p_umtx_q
|
|
td_handle :THandle; //nt thread
|
|
td_teb :p_teb;
|
|
td_lock :p_mtx;
|
|
td_tid :QWORD;
|
|
td_sigstk :stack_t;
|
|
td_state :Integer;
|
|
td_pflags :Integer;
|
|
td_flags :Integer;
|
|
td_errno :Integer;
|
|
pcb_flags :Integer;
|
|
td_ref :Integer;
|
|
//
|
|
td_priority :Word;
|
|
td_pri_class :Word;
|
|
td_base_pri :Word;
|
|
td_base_user_pri:Word;
|
|
td_lend_user_pri:Word;
|
|
td_user_pri :Word;
|
|
td_name :t_td_name;
|
|
//
|
|
td_sigmask :sigset_t;
|
|
td_oldsigmask :sigset_t;
|
|
td_sigqueue :sigqueue_t;
|
|
td_frame :trapframe;
|
|
td_fpstate :t_fpstate;
|
|
td_retval :array[0..1] of QWORD;
|
|
td_jctx :t_td_jctx;
|
|
td_ustack :t_td_stack;
|
|
td_kstack :t_td_stack;
|
|
//
|
|
td_cpuset :Ptruint;
|
|
td_sleepqueue :Pointer;
|
|
td_slpq :TAILQ_ENTRY;
|
|
td_zombie :TAILQ_ENTRY;
|
|
td_wchan :Pointer;
|
|
td_wmesg :PChar;
|
|
td_sqqueue :Integer;
|
|
td_intrval :Integer;
|
|
td_inhibitors :Integer;
|
|
td_dupfd :Integer;
|
|
td_ru :packed record
|
|
ru_inblock :Int64;
|
|
ru_oublock :Int64;
|
|
ru_nsignals :Int64;
|
|
ru_nvcsw :Int64;
|
|
ru_nivcsw :Int64;
|
|
end;
|
|
//
|
|
td_slptick :Int64;
|
|
td_slpcallout :Pointer;
|
|
tdq_lock :mtx;
|
|
{$IFDEF DEBUG_MTX}
|
|
td_debug_mtx :p_mtx;
|
|
{$ENDIF}
|
|
//
|
|
td_rlqe :Pointer;
|
|
td_fpop :Pointer;
|
|
td_map_cookie :Pointer;
|
|
td_map_def_user :Pointer;
|
|
td_rmap_def_user:Pointer;
|
|
td_sel :Pointer;
|
|
td_vp_reserv :Int64;
|
|
pcb_fsbase :Pointer;
|
|
pcb_gsbase :Pointer;
|
|
pcb_onfault :Pointer;
|
|
td_guards :array[0..1] of Pointer;
|
|
td_temp :t_td_buffer;
|
|
td_padding :t_td_buffer;
|
|
end;
|
|
|
|
const
|
|
kthread_fpstate=ptruint(@kthread(nil^).td_fpstate);
|
|
|
|
{$IF (kthread_fpstate mod 64)<>0}
|
|
{$STOP kthread.td_fpstate must be 64 aligned}
|
|
{$ENDIF}
|
|
|
|
type
|
|
p_thr_param=^thr_param;
|
|
thr_param=packed record
|
|
start_func:Pointer;
|
|
arg :Pointer;
|
|
stack_base:Pointer;
|
|
stack_size:Ptruint;
|
|
tls_base :Pointer;
|
|
tls_size :Ptruint;
|
|
child_tid :PDWORD;
|
|
parent_tid:PDWORD;
|
|
flags :Integer;
|
|
align :Integer;
|
|
rtp :Pointer;
|
|
name :PChar;
|
|
spare :array[0..1] of Pointer;
|
|
end;
|
|
{$IF sizeof(thr_param)<>104}{$STOP sizeof(thr_param)<>104}{$ENDIF}
|
|
|
|
function curkthread:p_kthread;
|
|
procedure set_curkthread(td:p_kthread);
|
|
|
|
const
|
|
SIG_ALTERABLE=$80000000;
|
|
SIG_STI_LOCK =$40000000;
|
|
|
|
NOT_PCB_FULL_IRET=not PCB_FULL_IRET;
|
|
NOT_SIG_ALTERABLE=not SIG_ALTERABLE;
|
|
NOT_SIG_STI_LOCK =not SIG_STI_LOCK;
|
|
|
|
TDF_AST=TDF_ASTPENDING or TDF_NEEDRESCHED;
|
|
|
|
procedure sig_sta; assembler;
|
|
procedure sig_cla; assembler;
|
|
procedure sig_sti; assembler;
|
|
procedure sig_cli; assembler;
|
|
|
|
procedure set_pcb_flags(td:p_kthread;f:Integer);
|
|
|
|
function TD_IS_SLEEPING(td:p_kthread):Boolean;
|
|
function TD_ON_SLEEPQ(td:p_kthread):Boolean;
|
|
function TD_IS_SUSPENDED(td:p_kthread):Boolean;
|
|
function TD_IS_SWAPPED(td:p_kthread):Boolean;
|
|
function TD_ON_LOCK(td:p_kthread):Boolean;
|
|
function TD_AWAITING_INTR(td:p_kthread):Boolean;
|
|
function TD_IS_RUNNING(td:p_kthread):Boolean;
|
|
function TD_ON_RUNQ(td:p_kthread):Boolean;
|
|
function TD_CAN_RUN(td:p_kthread):Boolean;
|
|
function TD_IS_INHIBITED(td:p_kthread):Boolean;
|
|
function TD_ON_UPILOCK(td:p_kthread):Boolean;
|
|
function TD_IS_IDLETHREAD(td:p_kthread):Boolean;
|
|
|
|
procedure TD_SET_SLEEPING(td:p_kthread);
|
|
procedure TD_SET_SWAPPED(td:p_kthread);
|
|
procedure TD_SET_LOCK(td:p_kthread);
|
|
procedure TD_SET_SUSPENDED(td:p_kthread);
|
|
procedure TD_SET_IWAIT(td:p_kthread);
|
|
|
|
procedure TD_CLR_SLEEPING(td:p_kthread);
|
|
procedure TD_CLR_SWAPPED(td:p_kthread);
|
|
procedure TD_CLR_LOCK(td:p_kthread);
|
|
procedure TD_CLR_SUSPENDED(td:p_kthread);
|
|
procedure TD_CLR_IWAIT(td:p_kthread);
|
|
|
|
procedure TD_SET_RUNNING(td:p_kthread);
|
|
procedure TD_SET_RUNQ(td:p_kthread);
|
|
procedure TD_SET_CAN_RUN(td:p_kthread);
|
|
|
|
procedure THREAD_NO_SLEEPING();
|
|
procedure THREAD_SLEEPING_OK();
|
|
function THREAD_IS_NOSLEEPING:Boolean;
|
|
|
|
function SIGPENDING(td:p_kthread):Boolean; external;
|
|
|
|
function curthread_pflags_set(flags:Integer):Integer;
|
|
procedure curthread_pflags_restore(save:Integer);
|
|
procedure curthread_set_pcb_onfault(v:Pointer);
|
|
|
|
procedure threads_lock; external;
|
|
function threads_trylock:Boolean; external;
|
|
procedure threads_unlock; external;
|
|
|
|
function get_p_threads:Pointer; external;
|
|
|
|
procedure thread_inc_ref(td:p_kthread); external;
|
|
procedure thread_dec_ref(td:p_kthread); external;
|
|
|
|
procedure thread_lock_assert(td:p_kthread); external;
|
|
procedure thread_lock(td:p_kthread); external;
|
|
procedure thread_unlock(td:p_kthread); external;
|
|
|
|
function tdfind(tid:DWORD):p_kthread; external;
|
|
|
|
procedure thread_suspend_all(exclude:p_kthread); external;
|
|
procedure thread_resume_all (exclude:p_kthread); external;
|
|
|
|
function kthread_add(func,arg:Pointer;newtdp:pp_kthread;pages:Word;name:PChar):Integer; external;
|
|
procedure kthread_exit(); external;
|
|
|
|
function thread_get_local_buffer(td:p_kthread;size:QWORD):Pointer;
|
|
procedure thread_free_local_buffer(td:p_kthread);
|
|
|
|
implementation
|
|
|
|
function curkthread:p_kthread; assembler; nostackframe;
|
|
asm
|
|
movqq %gs:teb.thread,Result
|
|
end;
|
|
|
|
procedure set_curkthread(td:p_kthread); assembler; nostackframe;
|
|
asm
|
|
movqq td,%gs:teb.thread
|
|
end;
|
|
|
|
procedure sig_sta; assembler; nostackframe;
|
|
asm
|
|
lock orl SIG_ALTERABLE,%gs:teb.iflag
|
|
end;
|
|
|
|
procedure sig_cla; assembler; nostackframe;
|
|
asm
|
|
lock andl NOT_SIG_ALTERABLE,%gs:teb.iflag
|
|
end;
|
|
|
|
procedure sig_sti; assembler; nostackframe;
|
|
asm
|
|
lock orl SIG_STI_LOCK,%gs:teb.iflag
|
|
end;
|
|
|
|
procedure sig_cli; assembler; nostackframe;
|
|
asm
|
|
lock andl NOT_SIG_STI_LOCK,%gs:teb.iflag
|
|
end;
|
|
|
|
procedure set_pcb_flags(td:p_kthread;f:Integer);
|
|
begin
|
|
td^.pcb_flags:=f or (td^.pcb_flags and (PCB_IS_JIT or PCB_IS_HLE));
|
|
end;
|
|
|
|
function TD_IS_SLEEPING(td:p_kthread):Boolean;
|
|
begin
|
|
Result:=(td^.td_inhibitors and TDI_SLEEPING)<>0;
|
|
end;
|
|
|
|
function TD_ON_SLEEPQ(td:p_kthread):Boolean;
|
|
begin
|
|
Result:=(td^.td_wchan<>nil);
|
|
end;
|
|
|
|
function TD_IS_SUSPENDED(td:p_kthread):Boolean;
|
|
begin
|
|
Result:=(td^.td_inhibitors and TDI_SUSPENDED)<>0;
|
|
end;
|
|
|
|
function TD_IS_SWAPPED(td:p_kthread):Boolean;
|
|
begin
|
|
Result:=(td^.td_inhibitors and TDI_SWAPPED)<>0;
|
|
end;
|
|
|
|
function TD_ON_LOCK(td:p_kthread):Boolean;
|
|
begin
|
|
Result:=(td^.td_inhibitors and TDI_LOCK)<>0;
|
|
end;
|
|
|
|
function TD_AWAITING_INTR(td:p_kthread):Boolean;
|
|
begin
|
|
Result:=(td^.td_inhibitors and TDI_IWAIT)<>0;
|
|
end;
|
|
|
|
function TD_IS_RUNNING(td:p_kthread):Boolean;
|
|
begin
|
|
Result:=(td^.td_state=TDS_RUNNING);
|
|
end;
|
|
|
|
function TD_ON_RUNQ(td:p_kthread):Boolean;
|
|
begin
|
|
Result:=(td^.td_state=TDS_RUNQ);
|
|
end;
|
|
|
|
function TD_CAN_RUN(td:p_kthread):Boolean;
|
|
begin
|
|
Result:=(td^.td_state=TDS_CAN_RUN);
|
|
end;
|
|
|
|
function TD_IS_INHIBITED(td:p_kthread):Boolean;
|
|
begin
|
|
Result:=(td^.td_state=TDS_INHIBITED);
|
|
end;
|
|
|
|
function TD_ON_UPILOCK(td:p_kthread):Boolean;
|
|
begin
|
|
Result:=(td^.td_flags and TDF_UPIBLOCKED)<>0;
|
|
end;
|
|
|
|
function TD_IS_IDLETHREAD(td:p_kthread):Boolean;
|
|
begin
|
|
Result:=(td^.td_flags and TDF_IDLETD)<>0;
|
|
end;
|
|
|
|
procedure TD_SET_INHIB(td:p_kthread;inhib:Integer); inline;
|
|
begin
|
|
td^.td_state:=TDS_INHIBITED;
|
|
td^.td_inhibitors:=td^.td_inhibitors or inhib;
|
|
end;
|
|
|
|
procedure TD_CLR_INHIB(td:p_kthread;inhib:Integer); inline;
|
|
begin
|
|
if ((td^.td_inhibitors and inhib)<>0) then
|
|
begin
|
|
inhib:=td^.td_inhibitors and (not inhib);
|
|
td^.td_inhibitors:=inhib;
|
|
if (inhib=0) then
|
|
begin
|
|
td^.td_state:=TDS_CAN_RUN;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TD_SET_SLEEPING(td:p_kthread);
|
|
begin
|
|
TD_SET_INHIB(td,TDI_SLEEPING);
|
|
end;
|
|
|
|
procedure TD_SET_SWAPPED(td:p_kthread);
|
|
begin
|
|
TD_SET_INHIB(td,TDI_SWAPPED);
|
|
end;
|
|
|
|
procedure TD_SET_LOCK(td:p_kthread);
|
|
begin
|
|
TD_SET_INHIB(td,TDI_LOCK);
|
|
end;
|
|
|
|
procedure TD_SET_SUSPENDED(td:p_kthread);
|
|
begin
|
|
TD_SET_INHIB(td,TDI_SUSPENDED);
|
|
end;
|
|
|
|
procedure TD_SET_IWAIT(td:p_kthread);
|
|
begin
|
|
TD_SET_INHIB(td,TDI_IWAIT);
|
|
end;
|
|
|
|
|
|
procedure TD_CLR_SLEEPING(td:p_kthread);
|
|
begin
|
|
TD_CLR_INHIB(td,TDI_SLEEPING);
|
|
end;
|
|
|
|
procedure TD_CLR_SWAPPED(td:p_kthread);
|
|
begin
|
|
TD_CLR_INHIB(td,TDI_SWAPPED);
|
|
end;
|
|
|
|
procedure TD_CLR_LOCK(td:p_kthread);
|
|
begin
|
|
TD_CLR_INHIB(td,TDI_LOCK);
|
|
end;
|
|
|
|
procedure TD_CLR_SUSPENDED(td:p_kthread);
|
|
begin
|
|
TD_CLR_INHIB(td,TDI_SUSPENDED);
|
|
end;
|
|
|
|
procedure TD_CLR_IWAIT(td:p_kthread);
|
|
begin
|
|
TD_CLR_INHIB(td,TDI_IWAIT);
|
|
end;
|
|
|
|
procedure TD_SET_RUNNING(td:p_kthread);
|
|
begin
|
|
td^.td_state:=TDS_RUNNING;
|
|
end;
|
|
|
|
procedure TD_SET_RUNQ(td:p_kthread);
|
|
begin
|
|
td^.td_state:=TDS_RUNQ;
|
|
end;
|
|
|
|
procedure TD_SET_CAN_RUN(td:p_kthread);
|
|
begin
|
|
td^.td_state:=TDS_CAN_RUN;
|
|
end;
|
|
|
|
procedure THREAD_NO_SLEEPING();
|
|
var
|
|
td:p_kthread;
|
|
begin
|
|
td:=curkthread;
|
|
Assert((td^.td_pflags and TDP_NOSLEEPING)=0,'nested no sleeping');
|
|
td^.td_pflags:=td^.td_pflags or TDP_NOSLEEPING;
|
|
end;
|
|
|
|
procedure THREAD_SLEEPING_OK();
|
|
var
|
|
td:p_kthread;
|
|
begin
|
|
td:=curkthread;
|
|
Assert((td^.td_pflags and TDP_NOSLEEPING)<>0,'nested sleeping ok');
|
|
td^.td_pflags:=td^.td_pflags and (not TDP_NOSLEEPING);
|
|
end;
|
|
|
|
function THREAD_IS_NOSLEEPING:Boolean;
|
|
var
|
|
td:p_kthread;
|
|
begin
|
|
td:=curkthread;
|
|
Result:=(td^.td_pflags and TDP_NOSLEEPING)<>0;
|
|
end;
|
|
|
|
//
|
|
|
|
function curthread_pflags_set(flags:Integer):Integer;
|
|
var
|
|
td:p_kthread;
|
|
begin
|
|
td:=curkthread;
|
|
if (td=nil) then Exit(0);
|
|
Result:=(not flags) or (td^.td_pflags and flags);
|
|
td^.td_pflags:=td^.td_pflags or flags;
|
|
end;
|
|
|
|
procedure curthread_pflags_restore(save:Integer);
|
|
var
|
|
td:p_kthread;
|
|
begin
|
|
td:=curkthread;
|
|
if (td=nil) then Exit;
|
|
td^.td_pflags:=td^.td_pflags and save;
|
|
end;
|
|
|
|
procedure curthread_set_pcb_onfault(v:Pointer);
|
|
var
|
|
td:p_kthread;
|
|
begin
|
|
td:=curkthread;
|
|
if (td=nil) then Exit;
|
|
td^.pcb_onfault:=v;
|
|
end;
|
|
|
|
//
|
|
|
|
function thread_get_local_buffer(td:p_kthread;size:QWORD):Pointer;
|
|
begin
|
|
if (td=nil) then Exit(nil);
|
|
|
|
if (size<=td^.td_padding.size) then
|
|
begin
|
|
Result:=td^.td_padding.addr;
|
|
end else
|
|
if (size<=td^.td_temp.size) then
|
|
begin
|
|
Result:=td^.td_temp.addr;
|
|
end else
|
|
begin
|
|
if (td^.td_temp.addr<>nil) then
|
|
begin
|
|
FreeMem(td^.td_temp.addr);
|
|
end;
|
|
Result:=GetMem(size);
|
|
td^.td_temp.addr:=Result;
|
|
td^.td_temp.size:=MemSize(Result);
|
|
end;
|
|
|
|
end;
|
|
|
|
procedure thread_free_local_buffer(td:p_kthread);
|
|
begin
|
|
if (td=nil) then Exit;
|
|
|
|
if (td^.td_temp.addr<>nil) then
|
|
begin
|
|
FreeMem(td^.td_temp.addr);
|
|
end;
|
|
td^.td_temp:=Default(t_td_buffer);
|
|
end;
|
|
|
|
end.
|
|
|