This commit is contained in:
red-prig 2023-03-12 23:24:40 +03:00
parent d5ae7d0c5a
commit f850dff674
5 changed files with 377 additions and 51 deletions

View File

@ -91,55 +91,10 @@ var
init_once:Integer=0;
procedure THR_LIST_ADD(thrd:p_pthread);
procedure THR_LIST_REMOVE(thrd:p_pthread);
procedure THR_GCLIST_ADD(thrd:p_pthread);
procedure THR_GCLIST_REMOVE(thrd:p_pthread);
procedure _libpthread_init(curthread:p_pthread);
implementation
procedure THR_LIST_ADD(thrd:p_pthread);
begin
if ((thrd^.tlflags and TLFLAGS_IN_TDLIST)=0) then
begin
TAILQ_INSERT_HEAD(@_thread_list,@thrd,@thrd^.tle);
//_thr_hash_add(thrd);
thrd^.tlflags:=thrd^.tlflags or TLFLAGS_IN_TDLIST;
end;
end;
procedure THR_LIST_REMOVE(thrd:p_pthread);
begin
if (((thrd)^.tlflags and TLFLAGS_IN_TDLIST)<>0) then
begin
TAILQ_REMOVE(@_thread_list,@thrd,@thrd^.tle);
//_thr_hash_remove(thrd);
thrd^.tlflags:=thrd^.tlflags and (not TLFLAGS_IN_TDLIST);
end;
end;
procedure THR_GCLIST_ADD(thrd:p_pthread);
begin
if ((thrd^.tlflags and TLFLAGS_IN_GCLIST)=0) then
begin
TAILQ_INSERT_HEAD(@_thread_gc_list,@thrd,@thrd^.gcle);
thrd^.tlflags:=thrd^.tlflags or TLFLAGS_IN_GCLIST;
Inc(_gc_count);
end;
end;
procedure THR_GCLIST_REMOVE(thrd:p_pthread);
begin
if (((thrd)^.tlflags and TLFLAGS_IN_GCLIST)<>0) then
begin
TAILQ_REMOVE(@_thread_list,@thrd,@thrd^.gcle);
thrd^.tlflags:=thrd^.tlflags and (not TLFLAGS_IN_GCLIST);
Dec(_gc_count);
end;
end;
const
g_user_stacksize=$10000;

View File

@ -7,6 +7,7 @@ interface
uses
mqueue,
time,
signal,
_umtx;
@ -115,6 +116,7 @@ type
child :TProcedure;
end;
p_pthread_attr=^pthread_attr;
pthread_attr=packed record
sched_policy :Integer;
sched_inherit :Integer;
@ -289,14 +291,49 @@ type
sched_priority:Integer;
end;
function TID(thr:p_pthread):Integer; inline;
function TID(thr:p_pthread):Integer; inline;
function SHOULD_CANCEL(thr:p_pthread):Boolean; inline;
function THR_SHOULD_GC(thr:p_pthread):Boolean; inline;
function THR_IN_CRITICAL(thr:p_pthread):Boolean; inline;
function SHOULD_CANCEL(thr:p_pthread):Boolean; inline;
function THR_SHOULD_GC(thr:p_pthread):Boolean; inline;
function THR_IN_CRITICAL(thr:p_pthread):Boolean; inline;
procedure THR_CRITICAL_ENTER(thr:p_pthread); inline;
procedure THR_CRITICAL_LEAVE(thr:p_pthread); inline;
function THR_UMUTEX_TRYLOCK(thr:p_pthread;lck:p_umutex):Integer; inline;
function THR_UMUTEX_LOCK(thr:p_pthread;lck:p_umutex):Integer; inline;
function THR_UMUTEX_TIMEDLOCK(thr:p_pthread;lck:p_umutex;timo:ptimespec):Integer; inline;
function THR_UMUTEX_UNLOCK(thr:p_pthread;lck:p_umutex):Integer; inline;
procedure THR_LOCK_ACQUIRE(thr:p_pthread;lck:p_umutex); inline;
procedure THR_LOCK_ACQUIRE_SPIN(thr:p_pthread;lck:p_umutex); inline;
procedure THR_ASSERT_LOCKLEVEL(thr:p_pthread); inline;
procedure THR_LOCK_RELEASE(thr:p_pthread;lck:p_umutex); inline;
procedure THR_LOCK(curthrd:p_pthread); inline;
procedure THR_UNLOCK(curthrd:p_pthread); inline;
procedure THR_THREAD_LOCK(curthrd,thr:p_pthread); inline;
procedure THR_THREAD_UNLOCK(curthrd,thr:p_pthread); inline;
procedure THREAD_LIST_RDLOCK(curthrd:p_pthread); inline;
procedure THREAD_LIST_WRLOCK(curthrd:p_pthread); inline;
procedure THREAD_LIST_UNLOCK(curthrd:p_pthread); inline;
procedure THR_LIST_ADD(thrd:p_pthread);
procedure THR_LIST_REMOVE(thrd:p_pthread);
procedure THR_GCLIST_ADD(thrd:p_pthread);
procedure THR_GCLIST_REMOVE(thrd:p_pthread);
procedure THR_REF_ADD(curthrd,thrd:p_pthread); inline;
procedure THR_REF_DEL(curthrd,thrd:p_pthread); inline;
function GC_NEEDED:Boolean; inline;
implementation
uses
thr_init,
thr_umtx;
function TID(thr:p_pthread):Integer; inline;
begin
Result:=thr^.tid;
@ -322,5 +359,161 @@ begin
(thr^.critical_count>0);
end;
procedure THR_CRITICAL_ENTER(thr:p_pthread); inline;
begin
Inc(thr^.critical_count);
end;
procedure THR_CRITICAL_LEAVE(thr:p_pthread); inline;
begin
Dec(thr^.critical_count);
//_thr_ast(thr);
end;
function THR_UMUTEX_TRYLOCK(thr:p_pthread;lck:p_umutex):Integer; inline;
begin
Result:=_thr_umutex_trylock(lck,TID(thr));
end;
function THR_UMUTEX_LOCK(thr:p_pthread;lck:p_umutex):Integer; inline;
begin
Result:=_thr_umutex_lock(lck,TID(thr));
end;
function THR_UMUTEX_TIMEDLOCK(thr:p_pthread;lck:p_umutex;timo:ptimespec):Integer; inline;
begin
Result:=_thr_umutex_timedlock(lck,TID(thr),timo);
end;
function THR_UMUTEX_UNLOCK(thr:p_pthread;lck:p_umutex):Integer; inline;
begin
Result:=_thr_umutex_unlock(lck,TID(thr));
end;
procedure THR_LOCK_ACQUIRE(thr:p_pthread;lck:p_umutex); inline;
begin
Inc(thr^.locklevel);
_thr_umutex_lock(lck,TID(thr));
end;
procedure THR_LOCK_ACQUIRE_SPIN(thr:p_pthread;lck:p_umutex); inline;
begin
Inc(thr^.locklevel);
_thr_umutex_lock_spin(lck,TID(thr));
end;
procedure THR_ASSERT_LOCKLEVEL(thr:p_pthread); inline;
begin
if (thr^.locklevel<=0) then
begin
//_thr_assert_lock_level();
end;
end;
procedure THR_LOCK_RELEASE(thr:p_pthread;lck:p_umutex); inline;
begin
THR_ASSERT_LOCKLEVEL(thr);
_thr_umutex_unlock(lck,TID(thr));
Dec(thr^.locklevel);
//_thr_ast(thr);
end;
procedure THR_LOCK(curthrd:p_pthread); inline;
begin
THR_LOCK_ACQUIRE(curthrd,@curthrd^.lock);
end;
procedure THR_UNLOCK(curthrd:p_pthread); inline;
begin
THR_LOCK_RELEASE(curthrd,@curthrd^.lock);
end;
procedure THR_THREAD_LOCK(curthrd,thr:p_pthread); inline;
begin
THR_LOCK_ACQUIRE(curthrd,@thr^.lock);
end;
procedure THR_THREAD_UNLOCK(curthrd,thr:p_pthread); inline;
begin
THR_LOCK_RELEASE(curthrd,@thr^.lock);
end;
procedure THREAD_LIST_RDLOCK(curthrd:p_pthread); inline;
begin
Inc(curthrd^.locklevel);
_thr_rwl_rdlock(@_thr_list_lock);
end;
procedure THREAD_LIST_WRLOCK(curthrd:p_pthread); inline;
begin
Inc(curthrd^.locklevel);
_thr_rwl_wrlock(@_thr_list_lock)
end;
procedure THREAD_LIST_UNLOCK(curthrd:p_pthread); inline;
begin
_thr_rwl_unlock(@_thr_list_lock);
Dec(curthrd^.locklevel);
//_thr_ast(curthrd);
end;
procedure THR_LIST_ADD(thrd:p_pthread);
begin
if ((thrd^.tlflags and TLFLAGS_IN_TDLIST)=0) then
begin
TAILQ_INSERT_HEAD(@_thread_list,@thrd,@thrd^.tle);
//_thr_hash_add(thrd);
thrd^.tlflags:=thrd^.tlflags or TLFLAGS_IN_TDLIST;
end;
end;
procedure THR_LIST_REMOVE(thrd:p_pthread);
begin
if (((thrd)^.tlflags and TLFLAGS_IN_TDLIST)<>0) then
begin
TAILQ_REMOVE(@_thread_list,@thrd,@thrd^.tle);
//_thr_hash_remove(thrd);
thrd^.tlflags:=thrd^.tlflags and (not TLFLAGS_IN_TDLIST);
end;
end;
procedure THR_GCLIST_ADD(thrd:p_pthread);
begin
if ((thrd^.tlflags and TLFLAGS_IN_GCLIST)=0) then
begin
TAILQ_INSERT_HEAD(@_thread_gc_list,@thrd,@thrd^.gcle);
thrd^.tlflags:=thrd^.tlflags or TLFLAGS_IN_GCLIST;
Inc(_gc_count);
end;
end;
procedure THR_GCLIST_REMOVE(thrd:p_pthread);
begin
if (((thrd)^.tlflags and TLFLAGS_IN_GCLIST)<>0) then
begin
TAILQ_REMOVE(@_thread_list,@thrd,@thrd^.gcle);
thrd^.tlflags:=thrd^.tlflags and (not TLFLAGS_IN_GCLIST);
Dec(_gc_count);
end;
end;
procedure THR_REF_ADD(curthrd,thrd:p_pthread); inline;
begin
THR_CRITICAL_ENTER(curthrd);
Inc(thrd^.refcount);
end;
procedure THR_REF_DEL(curthrd,thrd:p_pthread); inline;
begin
Dec(thrd^.refcount);
THR_CRITICAL_LEAVE(curthrd);
end;
function GC_NEEDED:Boolean; inline;
begin
Result:=(_gc_count>=5);
end;
end.

172
kernel/libthr/thr_stack.pas Normal file
View File

@ -0,0 +1,172 @@
unit thr_stack;
{$mode ObjFPC}{$H+}
interface
uses
mqueue,
pthread_md,
thr_private,
thr_init;
procedure _thr_stack_fix_protection(td:p_pthread);
function _thr_stack_alloc(attr:p_pthread_attr):Integer;
procedure _thr_stack_free(attr:p_pthread_attr);
implementation
type
//Spare thread stack.
p_stack=^t_stack;
t_stack=packed record
qe :LIST_ENTRY; //Stack queue linkage.
stacksize:QWORD; //Stack size (rounded up).
guardsize:QWORD; //Guard size.
stackaddr:Pointer; //Stack address.
end;
var
dstackq :p_stack=nil;
mstackq :p_stack=nil;
last_stack:Pointer=nil;
function round_up(size:QWORD):QWORD; inline;
begin
if ((size mod _thr_page_size)<>0) then
begin
size:=((size div _thr_page_size)+1)*_thr_page_size;
end;
Result:=size;
end;
procedure _thr_stack_fix_protection(td:p_pthread);
begin
//mprotect(td^.attr.stackaddr_attr+
// round_up(td^.attr.guardsize_attr),
// round_up(td^.attr.stacksize_attr),
// _rtld_get_stack_prot);
end;
function _thr_stack_alloc(attr:p_pthread_attr):Integer;
var
curthread:p_pthread;
spare_stack,next:p_stack;
stacksize:QWORD;
guardsize:QWORD;
stackaddr:Pointer;
r:Integer;
begin
curthread:=_get_curthread;
stacksize:=round_up(attr^.stacksize_attr);
guardsize:=round_up(attr^.guardsize_attr);
attr^.stackaddr_attr:=nil;
attr^.flags:=attr^.flags and (not THR_STACK_USER);
THREAD_LIST_WRLOCK(curthread);
if ((stacksize=THR_STACK_DEFAULT) and
(guardsize=_thr_guard_default)) then
begin
spare_stack:=LIST_FIRST(@dstackq);
if (spare_stack<>nil) then
begin
LIST_REMOVE(spare_stack,@spare_stack^.qe);
attr^.stackaddr_attr:=spare_stack^.stackaddr;
end;
end else
begin
spare_stack:=LIST_FIRST(@mstackq);
While (spare_stack<>nil) do
begin
next:=LIST_NEXT(spare_stack,@spare_stack^.qe);
if (spare_stack^.stacksize=stacksize) and
(spare_stack^.guardsize=guardsize) then
begin
LIST_REMOVE(spare_stack,@spare_stack^.qe);
attr^.stackaddr_attr:=spare_stack^.stackaddr;
break;
end;
spare_stack:=next;
end;
end;
if (attr^.stackaddr_attr<>nil) then
begin
THREAD_LIST_UNLOCK(curthread);
end else
begin
if (last_stack=nil) then
begin
last_stack:=_usrstack-_thr_stack_initial-_thr_guard_default;
end;
stackaddr:=last_stack-stacksize-guardsize;
last_stack:=last_stack-(stacksize+guardsize);
THREAD_LIST_UNLOCK(curthread);
//stackaddr:=mmap(stackaddr,
// stacksize+guardsize,
// _rtld_get_stack_prot,
// MAP_STACK,-1,0
// );
r:=0;
if (stackaddr<>Pointer(-1)) then //MAP_FAILED
begin
//r:=mprotect(stackaddr,guardsize,PROT_NONE);
end;
if (stackaddr<>Pointer(-1)) and //MAP_FAILED
((guardsize=0) or (r=0)) then
begin
//sceKernelSetVirtualRangeName(addr,guardsize,'stack guard');
stackaddr:=stackaddr+guardsize;
end else
begin
if (stackaddr<>Pointer(-1)) then //MAP_FAILED
begin
//munmap(stackaddr,stacksize+guardsize);
end;
stackaddr:=nil;
end;
attr^.stackaddr_attr:=stackaddr;
end;
if (attr^.stackaddr_attr<>nil) then
Result:=0
else
Result:=-1;
end;
procedure _thr_stack_free(attr:p_pthread_attr);
var
spare_stack:p_stack;
begin
if (attr<>nil) and
((attr^.flags and THR_STACK_USER)=0) and
(attr^.stackaddr_attr<>nil) then
begin
spare_stack:=attr^.stackaddr_attr+attr^.stacksize_attr-sizeof(t_stack);
spare_stack^.stacksize:=round_up(attr^.stacksize_attr);
spare_stack^.guardsize:=round_up(attr^.guardsize_attr);
spare_stack^.stackaddr:=attr^.stackaddr_attr;
if (spare_stack^.stacksize=THR_STACK_DEFAULT) and
(spare_stack^.guardsize=_thr_guard_default) then
begin
LIST_INSERT_HEAD(@dstackq,spare_stack,@spare_stack^.qe);
end else
begin
LIST_INSERT_HEAD(@mstackq,spare_stack,@spare_stack^.qe);
end;
attr^.stackaddr_attr:=nil;
end;
end;
end.

View File

@ -213,6 +213,10 @@
<Filename Value="..\rtprio.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="..\..\kernel\libthr\thr_stack.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>

View File

@ -31,8 +31,10 @@ uses
kern_id,
sys_osem,
kern_evf,
sys_evf, rtprio,
pthread;
sys_evf,
rtprio,
pthread,
thr_stack;
var
mtx:umutex;