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