This commit is contained in:
Pavel 2023-06-27 14:29:33 +03:00
parent 3788427643
commit d59bbaad4e
8 changed files with 265 additions and 141 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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;

152
sys/md/md_timeout.pas Normal file
View File

@ -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.

View File

@ -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;

View File

@ -561,6 +561,10 @@
<Filename Value="..\kern\kern_timeout.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="..\md\md_timeout.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>