From d59bbaad4ea7160c67562d328ded608b9535b96e Mon Sep 17 00:00:00 2001
From: Pavel <68122101+red-prig@users.noreply.github.com>
Date: Tue, 27 Jun 2023 14:29:33 +0300
Subject: [PATCH] +
---
sys/kern/kern_callout.pas | 14 +++-
sys/kern/kern_thr.pas | 21 ++++--
sys/kern/kern_thread.pas | 64 +++++++++++++---
sys/kern/kern_timeout.pas | 139 ++++------------------------------
sys/md/md_context.pas | 8 +-
sys/md/md_timeout.pas | 152 ++++++++++++++++++++++++++++++++++++++
sys/sys_sysinit.pas | 4 +-
sys/test/project1.lpi | 4 +
8 files changed, 265 insertions(+), 141 deletions(-)
create mode 100644 sys/md/md_timeout.pas
diff --git a/sys/kern/kern_callout.pas b/sys/kern/kern_callout.pas
index 362ed457..520773a9 100644
--- a/sys/kern/kern_callout.pas
+++ b/sys/kern/kern_callout.pas
@@ -7,7 +7,8 @@ interface
uses
mqueue,
- LFQueue;
+ LFQueue,
+ kern_mtx;
type
t_callout_func=procedure(arg:Pointer);
@@ -33,6 +34,17 @@ const
CALLOUT_SHAREDLOCK =$0020; // callout lock held in shared mode
CALLOUT_RWLOCK =$0040; // callout used rw lock
+type
+ p_callout_cpu=^t_callout_cpu;
+ t_callout_cpu=record
+ cc_lock :mtx;
+ cc_curr :p_callout;
+ cc_calllist:TAILQ_HEAD;
+ cc_callfree:TAILQ_HEAD;
+ cc_cancel :Integer;
+ cc_waiting :Integer;
+ end;
+
implementation
end.
diff --git a/sys/kern/kern_thr.pas b/sys/kern/kern_thr.pas
index d1808c9a..1f001172 100644
--- a/sys/kern/kern_thr.pas
+++ b/sys/kern/kern_thr.pas
@@ -129,14 +129,25 @@ const
type
p_teb=^teb;
teb=packed record
- _align1:array[0..23] of QWORD;
- wow64 :Pointer; //0xC0
+ SEH :Pointer;
+ stack :Pointer;
+ sttop :Pointer;
+ _align1:array[0..20] of QWORD;
+ wow64 :Pointer; //0xC0
_align2:array[0..198] of QWORD;
- thread:Pointer; //0x700
- tcb :Pointer; //0x708
- iflag :Integer; //0x710
+ thread :Pointer; //0x700
+ tcb :Pointer; //0x708
+ iflag :Integer; //0x710
end;
+const
+ teb_wow64 =ptruint(@teb(nil^).wow64);
+ teb_thread=ptruint(@teb(nil^).thread);
+
+ {$IF teb_wow64 <>$0C0}{$STOP teb_wow64 <>$0C0}{$ENDIF}
+ {$IF teb_thread<>$700}{$STOP teb_thread<>$700}{$ENDIF}
+
+type
t_td_name=array[0..31] of AnsiChar;
pp_kthread=^p_kthread;
diff --git a/sys/kern/kern_thread.pas b/sys/kern/kern_thread.pas
index 0d9ba431..00e0b592 100644
--- a/sys/kern/kern_thread.pas
+++ b/sys/kern/kern_thread.pas
@@ -117,9 +117,16 @@ end;
//
+function _thread_null(parameter:pointer):ptrint; register;
+begin
+ Result:=0;
+end;
+
procedure threadinit;
begin
FillChar(tidhashtbl,SizeOf(tidhashtbl),0);
+ //init internals
+ BeginThread(@_thread_null);
end;
{
@@ -312,6 +319,44 @@ begin
HAMT_get_value32(i,@Result);
end;
+procedure KernSetThreadDebugName(newtd:p_kthread;prefix:PChar);
+var
+ td:p_kthread;
+ sttop:Pointer;
+ stack:Pointer;
+ name:shortstring;
+begin
+ //check stack limits
+ td:=curkthread;
+ if (td<>nil) then
+ begin
+ //in kstack?
+ if (SPtr>td^.td_ksttop) and (SPtr<=td^.td_kstack) then
+ begin
+ //save
+ sttop:=td^.td_teb^.sttop;
+ stack:=td^.td_teb^.stack;
+ //set kstack
+ td^.td_teb^.sttop:=td^.td_ksttop;
+ td^.td_teb^.stack:=td^.td_kstack;
+ end else
+ begin
+ //dont change
+ td:=nil;
+ end;
+ end;
+
+ name:=shortstring(prefix)+shortstring(newtd^.td_name);
+ SetThreadDebugName(newtd^.td_tid,name);
+
+ if (td<>nil) then
+ begin
+ //restore
+ td^.td_teb^.sttop:=sttop;
+ td^.td_teb^.stack:=stack;
+ end;
+end;
+
procedure before_start(td:p_kthread);
begin
//init this
@@ -461,7 +506,7 @@ begin
begin
Move(name^,newtd^.td_name,SizeOf(t_td_name));
end;
- SetThreadDebugName(newtd^.td_handle,'ps4:'+newtd^.td_name);
+ KernSetThreadDebugName(newtd,'ps4:');
sched_fork_thread(td,newtd);
@@ -494,8 +539,7 @@ function kthread_add(func,arg:Pointer;newtdp:pp_kthread;name:PChar):Integer;
var
td:p_kthread;
newtd:p_kthread;
- stack_base:Pointer;
- stack_size:QWORD;
+ stack:stack_t;
n:Integer;
begin
@@ -514,12 +558,12 @@ begin
newtd:=thread_alloc;
if (newtd=nil) then Exit(ENOMEM);
- stack_base:=newtd^.td_kstack;
- stack_size:=(ptruint(newtd^.td_kstack)-ptruint(newtd^.td_ksttop));
+ stack.ss_sp :=newtd^.td_ksttop;
+ stack.ss_size:=(ptruint(newtd^.td_kstack)-ptruint(newtd^.td_ksttop));
n:=cpu_thread_create(newtd,
- stack_base,
- stack_size,
+ stack.ss_sp,
+ stack.ss_size,
func,
arg);
@@ -529,6 +573,8 @@ begin
Exit(EINVAL);
end;
+ cpu_set_upcall_kse(newtd,func,arg,@stack);
+
if (td<>nil) then
begin
newtd^.td_sigmask:=td^.td_sigmask;
@@ -542,7 +588,7 @@ begin
begin
Move(name^,newtd^.td_name,SizeOf(t_td_name));
end;
- SetThreadDebugName(newtd^.td_handle,newtd^.td_name);
+ KernSetThreadDebugName(newtd,'kern:');
sched_fork_thread(td,newtd);
@@ -910,7 +956,7 @@ begin
thread_lock(td);
td^.td_name:=name;
- SetThreadDebugName(td^.td_handle,'ps4:'+name);
+ KernSetThreadDebugName(td,'ps4:');
thread_unlock(td);
diff --git a/sys/kern/kern_timeout.pas b/sys/kern/kern_timeout.pas
index cb3a292a..8b45e791 100644
--- a/sys/kern/kern_timeout.pas
+++ b/sys/kern/kern_timeout.pas
@@ -6,11 +6,7 @@ unit kern_timeout;
interface
uses
- windows,
-
mqueue,
- LFQueue,
- md_sleep,
kern_synch,
subr_sleepqueue,
kern_thr,
@@ -18,20 +14,18 @@ uses
kern_rwlock,
kern_callout;
-type
- p_callout_cpu=^t_callout_cpu;
- t_callout_cpu=record
- cc_lock :mtx;
- cc_curr :p_callout;
- cc_calllist:TAILQ_HEAD;
- cc_callfree:TAILQ_HEAD;
- cc_cancel :Integer;
- cc_waiting :Integer;
- end;
+procedure kern_timeout_init();
+
+procedure CC_LOCK(cc:p_callout_cpu);
+procedure CC_UNLOCK(cc:p_callout_cpu);
+procedure CC_LOCK_ASSERT(cc:p_callout_cpu);
+function callout_lock():p_callout_cpu;
+procedure callout_cc_del(c:p_callout;cc:p_callout_cpu);
procedure callout_init (c:p_callout;mpsafe:Integer);
procedure _callout_init_lock(c:p_callout;lock:Pointer;flags:Integer);
-procedure callout_done(c:p_callout);
+
+procedure softclock_call_cc(c:p_callout;cc:p_callout_cpu);
function _callout_stop_safe(c:p_callout;safe:Integer):Integer;
function callout_reset_on(c:p_callout;to_ticks:Int64;ftn:t_callout_func;arg:Pointer):Integer;
@@ -46,14 +40,11 @@ function callout_reset_curcpu(c:p_callout;on_tick:Int64;fn:t_callout_func;arg:P
implementation
uses
- kern_thread;
+ md_timeout;
var
timeout_cpu:t_callout_cpu;
- timeout_thr:p_kthread=nil;
- timeout_new:TIntrusiveMPSCQueue;
-
rw_giant:Pointer=nil;
procedure callout_cpu_init(cc:p_callout_cpu);
@@ -63,21 +54,10 @@ begin
TAILQ_INIT(@cc^.cc_callfree);
end;
-procedure kern_timeout_callwheel_init();
+procedure kern_timeout_init();
begin
callout_cpu_init(@timeout_cpu);
-end;
-
-procedure softclock(arg:Pointer); forward;
-
-procedure start_softclock();
-var
- r:Integer;
-begin
- timeout_new.Create;
-
- r:=kthread_add(@softclock,nil,@timeout_thr,'softclock');
- Assert(r=0,'softclock');
+ md_start_softclock();
end;
procedure callout_init(c:p_callout;mpsafe:Integer);
@@ -91,8 +71,6 @@ begin
c^.c_lock :=@rw_giant;
c^.c_flags:=CALLOUT_RWLOCK;
end;
- //
- c^.c_timer:=CreateWaitableTimer(nil,true,nil);
end;
procedure _callout_init_lock(c:p_callout;lock:Pointer;flags:Integer);
@@ -103,13 +81,6 @@ begin
Assert((lock<>nil) or ((flags and CALLOUT_RETURNUNLOCKED)=0),'callout_init_lock: CALLOUT_RETURNUNLOCKED with no lock');
Assert(lock=nil,'invalid lock');
c^.c_flags:=flags and (CALLOUT_RETURNUNLOCKED or CALLOUT_SHAREDLOCK);
- //
- c^.c_timer:=CreateWaitableTimer(nil,true,nil);
-end;
-
-procedure callout_done(c:p_callout);
-begin
- CloseHandle(c^.c_timer);
end;
procedure CC_LOCK(cc:p_callout_cpu); inline;
@@ -133,20 +104,6 @@ begin
CC_LOCK(Result);
end;
-Procedure wt_timer_add(c:p_callout;cc:p_callout_cpu); forward;
-
-procedure callout_new_inserted(c:p_callout;cc:p_callout_cpu);
-begin
- if (timeout_thr=curkthread) then
- begin
- wt_timer_add(c,cc);
- end else
- begin
- timeout_new.Push(c);
- wakeup_td(timeout_thr);
- end;
-end;
-
procedure callout_cc_add(c:p_callout;cc:p_callout_cpu;to_ticks:Int64;func:t_callout_func;arg:Pointer);
begin
CC_LOCK_ASSERT(cc);
@@ -163,11 +120,12 @@ begin
TAILQ_INSERT_TAIL(@cc^.cc_calllist,c,@c^.c_links);
- callout_new_inserted(c,cc);
+ md_callout_new_inserted(c,cc);
end;
procedure callout_cc_del(c:p_callout;cc:p_callout_cpu);
begin
+ md_callout_done(c);
if ((c^.c_flags and CALLOUT_LOCAL_ALLOC)=0) then Exit;
c^.c_func:=nil;
TAILQ_INSERT_TAIL(@cc^.cc_callfree,c,@c^.c_links);
@@ -295,71 +253,6 @@ begin
end;
end;
-procedure wt_event(arg:Pointer;dwTimerLowValue,dwTimerHighValue:DWORD); stdcall;
-var
- c:p_callout;
- cc:p_callout_cpu;
-begin
- if (arg=nil) then Exit;
- c:=arg;
- cc:=callout_lock();
- softclock_call_cc(c,cc);
- CC_UNLOCK(cc);
-end;
-
-Procedure wt_timer_add(c:p_callout;cc:p_callout_cpu);
-var
- f:Int64;
- b:Boolean;
-begin
- f:=-c^.c_time;
- b:=false;
-
- if ((c^.c_flags and CALLOUT_PENDING)<>0) then
- begin
- b:=SetWaitableTimer(c^.c_timer,f,0,@wt_event,c,false);
- end;
-
- if not b then
- begin
- if (cc^.cc_waiting<>0) then
- begin
- cc^.cc_waiting:=0;
- CC_UNLOCK(cc);
- wakeup(@cc^.cc_waiting);
- CC_LOCK(cc);
- end;
-
- Assert(((c^.c_flags and CALLOUT_LOCAL_ALLOC)=0) or (c^.c_flags=CALLOUT_LOCAL_ALLOC),'corrupted callout');
-
- if ((c^.c_flags and CALLOUT_LOCAL_ALLOC)<>0) then
- begin
- callout_cc_del(c, cc);
- end;
- end;
-end;
-
-procedure softclock(arg:Pointer);
-var
- c:p_callout;
- cc:p_callout_cpu;
-begin
- repeat
- cc:=nil;
- c:=nil;
-
- while timeout_new.Pop(c) do
- begin
- CC_LOCK(cc);
- wt_timer_add(c,cc);
- CC_UNLOCK(cc);
- end;
-
- msleep_td(0);
- until false;
- kthread_exit();
-end;
-
{
* New interface; clients allocate their own callout structures.
*
@@ -385,7 +278,7 @@ begin
cc:=callout_lock();
- CancelWaitableTimer(c^.c_timer);
+ md_callout_reset(c);
if (cc^.cc_curr=c) then
begin
@@ -441,7 +334,7 @@ begin
again:
cc:=callout_lock();
- CancelWaitableTimer(c^.c_timer);
+ md_callout_stop(c);
if ((c^.c_flags and CALLOUT_PENDING)=0) then
begin
diff --git a/sys/md/md_context.pas b/sys/md/md_context.pas
index f71a47d6..39e82efa 100644
--- a/sys/md/md_context.pas
+++ b/sys/md/md_context.pas
@@ -344,7 +344,7 @@ end;
function IS_SYSTEM_STACK(td:p_kthread;rsp:qword):Boolean; inline;
begin
- Result:=(rsp<=QWORD(td^.td_kstack)) and (rsp>(QWORD(td^.td_kstack)-SYS_STACK_SIZE));
+ Result:=(rsp<=QWORD(td^.td_kstack)) and (rsp>(QWORD(td^.td_ksttop)));
end;
function IS_SYSCALL(rip:qword):Boolean;
@@ -363,7 +363,11 @@ end;
function get_top_mem_td(td:p_kthread;size,align:qword):Pointer;
begin
Result:=System.Align(td^.td_ksttop,align);
- if ((Result+size)>=SPtr) then Exit(nil);
+
+ if (SPtr>td^.td_ksttop) and (SPtr<=td^.td_kstack) then
+ begin
+ if ((Result+size)>=SPtr) then Exit(nil);
+ end;
end;
procedure _apc_null(dwParam:PTRUINT); stdcall;
diff --git a/sys/md/md_timeout.pas b/sys/md/md_timeout.pas
new file mode 100644
index 00000000..69125bf6
--- /dev/null
+++ b/sys/md/md_timeout.pas
@@ -0,0 +1,152 @@
+unit md_timeout;
+
+{$mode ObjFPC}{$H+}
+{$CALLING SysV_ABI_CDecl}
+
+interface
+
+uses
+ windows,
+
+ LFQueue,
+ md_sleep,
+ kern_synch,
+ kern_thr,
+ kern_callout;
+
+procedure md_start_softclock();
+procedure md_callout_new_inserted(c:p_callout;cc:p_callout_cpu);
+procedure md_callout_reset(c:p_callout);
+procedure md_callout_stop(c:p_callout);
+procedure md_callout_done(c:p_callout);
+
+implementation
+
+uses
+ kern_thread,
+ kern_timeout;
+
+var
+ timeout_thr:p_kthread=nil;
+ timeout_new:TIntrusiveMPSCQueue;
+
+procedure softclock(arg:Pointer); forward;
+
+procedure md_start_softclock();
+var
+ r:Integer;
+begin
+ timeout_new.Create;
+
+ r:=kthread_add(@softclock,nil,@timeout_thr,'softclock');
+ Assert(r=0,'softclock');
+end;
+
+procedure wt_event(arg:Pointer;dwTimerLowValue,dwTimerHighValue:DWORD); stdcall;
+var
+ c:p_callout;
+ cc:p_callout_cpu;
+begin
+ if (arg=nil) then Exit;
+ c:=arg;
+ cc:=callout_lock();
+ softclock_call_cc(c,cc);
+ CC_UNLOCK(cc);
+end;
+
+Procedure wt_timer_add(c:p_callout;cc:p_callout_cpu);
+var
+ f:Int64;
+ b:Boolean;
+begin
+ f:=-c^.c_time;
+ b:=false;
+
+ if ((c^.c_flags and CALLOUT_PENDING)<>0) then
+ begin
+ b:=SetWaitableTimer(c^.c_timer,f,0,@wt_event,c,false);
+ end;
+
+ if not b then
+ begin
+ if (cc^.cc_waiting<>0) then
+ begin
+ cc^.cc_waiting:=0;
+ CC_UNLOCK(cc);
+ wakeup(@cc^.cc_waiting);
+ CC_LOCK(cc);
+ end;
+
+ Assert(((c^.c_flags and CALLOUT_LOCAL_ALLOC)=0) or (c^.c_flags=CALLOUT_LOCAL_ALLOC),'corrupted callout');
+
+ if ((c^.c_flags and CALLOUT_LOCAL_ALLOC)<>0) then
+ begin
+ callout_cc_del(c, cc);
+ end;
+ end;
+end;
+
+procedure md_callout_new_inserted(c:p_callout;cc:p_callout_cpu);
+begin
+ if (timeout_thr=curkthread) then
+ begin
+ wt_timer_add(c,cc);
+ end else
+ begin
+ timeout_new.Push(c);
+ wakeup_td(timeout_thr);
+ end;
+end;
+
+procedure softclock(arg:Pointer);
+var
+ c:p_callout;
+ cc:p_callout_cpu;
+begin
+ repeat
+ cc:=nil;
+ c:=nil;
+
+ while timeout_new.Pop(c) do
+ begin
+ CC_LOCK(cc);
+ wt_timer_add(c,cc);
+ CC_UNLOCK(cc);
+ end;
+
+ msleep_td(0);
+ until false;
+ kthread_exit();
+end;
+
+procedure md_callout_reset(c:p_callout);
+begin
+ if (c^.c_timer=0) then
+ begin
+ c^.c_timer:=CreateWaitableTimer(nil,true,nil);
+ end else
+ begin
+ CancelWaitableTimer(c^.c_timer);
+ end;
+end;
+
+procedure md_callout_stop(c:p_callout);
+begin
+ if (c^.c_timer<>0) then
+ begin
+ CancelWaitableTimer(c^.c_timer);
+ end;
+end;
+
+procedure md_callout_done(c:p_callout);
+begin
+ if (c^.c_timer<>0) then
+ begin
+ CloseHandle(c^.c_timer);
+ c^.c_timer:=0;
+ end;
+end;
+
+
+end.
+
diff --git a/sys/sys_sysinit.pas b/sys/sys_sysinit.pas
index 1cfccb61..581b12cf 100644
--- a/sys/sys_sysinit.pas
+++ b/sys/sys_sysinit.pas
@@ -16,6 +16,7 @@ uses
kern_thr,
kern_thread,
kern_sig,
+ kern_timeout,
kern_umtx,
kern_namedobj,
vmount,
@@ -61,6 +62,7 @@ begin
threadinit;
siginit;
umtxq_sysinit;
+ kern_timeout_init;
named_table_init;
vmountinit;
fd_table_init;
@@ -69,7 +71,7 @@ begin
selectinit;
vntblinit;
nameiinit;
- knote_init();
+ knote_init;
vfs_event_init;
devfs_mtx_init;
devfs_devs_init;
diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi
index 9f123343..0b2e13f8 100644
--- a/sys/test/project1.lpi
+++ b/sys/test/project1.lpi
@@ -561,6 +561,10 @@
+
+
+
+