This commit is contained in:
Pavel 2023-03-06 16:53:20 +03:00
parent 24e6c9a6e8
commit f258b7e8c5
9 changed files with 513 additions and 44 deletions

215
sys/kern/kern_id.pas Normal file
View File

@ -0,0 +1,215 @@
unit kern_id;
{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}
interface
uses
hamt,
kern_rwlock;
Const
def_max_key=$7FFFFFFF;
type
p_id_desc=^t_id_desc;
t_id_desc=packed record
refs:QWORD;
free:procedure(data:pointer);
end;
p_id_desc_table=^t_id_desc_table;
t_id_desc_table=packed record
FLock :Pointer;
FHAMT :TSTUB_HAMT32;
FCount :Integer;
FPos :Integer;
min_key:Integer;
max_key:Integer;
end;
Procedure id_acqure (d:p_id_desc);
Procedure id_release(d:p_id_desc);
procedure id_table_init(t:p_id_desc_table;min:Integer);
procedure id_table_fini(t:p_id_desc_table);
function id_new(t:p_id_desc_table;d:p_id_desc;pKey:PInteger):Boolean;
function id_set(t:p_id_desc_table;d:p_id_desc;Key:Integer):Boolean;
function id_get(t:p_id_desc_table;Key:Integer):p_id_desc;
function id_del(t:p_id_desc_table;Key:Integer):Boolean;
implementation
Procedure id_acqure(d:p_id_desc);
begin
System.InterlockedIncrement64(d^.refs);
end;
Procedure id_release(d:p_id_desc);
begin
if (System.InterlockedDecrement64(d^.refs)=0) then
if (d^.free<>nil) then
begin
d^.free(d);
end;
end;
procedure _free_data_cb(data,userdata:Pointer); register;
begin
if (data<>nil) then
begin
id_release(data);
end;
end;
procedure id_table_init(t:p_id_desc_table;min:Integer);
begin
if (t=nil) then Exit;
FillChar(t^,SizeOf(t_id_desc_table),0);
t^.min_key:=min;
t^.max_key:=def_max_key;
t^.FPos :=min;
end;
procedure id_table_fini(t:p_id_desc_table);
begin
if (t=nil) then Exit;
HAMT_clear32(@t^.FHAMT,@_free_data_cb,nil);
end;
function id_new(t:p_id_desc_table;d:p_id_desc;pKey:PInteger):Boolean;
Label
_data,_exit;
Var
i,m:Integer;
data:PPointer;
begin
Result:=False;
if (t=nil) or (d=nil) or (pKey=nil) then Exit;
rw_wlock(t^.FLock);
m:=(t^.max_key-t^.min_key);
if (t^.FCount>=m+1) then goto _exit;
if (t^.FPos<t^.min_key) or
(t^.FPos>t^.max_key) then
begin
t^.FPos:=t^.min_key;
end;
if (t^.FCount=0) then
begin
pKey^:=t^.FPos;
Inc(t^.FPos);
data:=HAMT_insert32(@t^.FHAMT,pKey^,Pointer(d));
if (data=nil) then goto _exit;
if (data^<>Pointer(d)) then goto _exit;
end else
begin
For i:=0 to m do
begin
pKey^:=t^.FPos;
Inc(t^.FPos);
if (t^.FPos>t^.max_key) then
begin
t^.FPos:=t^.min_key;
end;
data:=HAMT_insert32(@t^.FHAMT,pKey^,Pointer(d));
if (data=nil) then goto _exit;
if (data^=Pointer(d)) then goto _data;
end;
goto _exit;
end;
_data:
Inc(t^.FCount);
id_acqure(d);
id_acqure(d);
Result:=True;
_exit:
rw_wunlock(t^.FLock);
end;
function id_set(t:p_id_desc_table;d:p_id_desc;Key:Integer):Boolean;
Label
_exit;
Var
data:PPointer;
begin
Result:=False;
if (t=nil) or (d=nil) or (Key<t^.min_key) or (Key>t^.max_key) then Exit;
rw_wlock(t^.FLock);
data:=HAMT_insert32(@t^.FHAMT,Key,Pointer(d));
if (data=nil) then goto _exit;
if (data^<>Pointer(d)) then goto _exit;
Inc(t^.FCount);
id_acqure(d);
id_acqure(d);
Result:=True;
_exit:
rw_wunlock(t^.FLock);
end;
function id_get(t:p_id_desc_table;Key:Integer):p_id_desc;
Var
data:PPointer;
Label
_exit;
begin
Result:=nil;
if (t=nil) or (Key<t^.min_key) or (Key>t^.max_key) then Exit;
rw_rlock(t^.FLock);
data:=HAMT_search32(@t^.FHAMT,Key);
if (data=nil) then Goto _exit;
Pointer(Result):=data^;
if (Result<>nil) then
begin
id_acqure(Result);
end;
_exit:
rw_runlock(t^.FLock);
end;
function id_del(t:p_id_desc_table;Key:Integer):Boolean;
Var
d:p_id_desc;
begin
Result:=False;
if (t=nil) or (Key<t^.min_key) or (Key>t^.max_key) then Exit;
rw_wlock(t^.FLock);
Pointer(d):=HAMT_delete32(@t^.FHAMT,Key);
if (d<>nil) then
begin
id_release(d);
Dec(t^.FCount);
Result:=True;
end;
rw_wunlock(t^.FLock);
end;
end.

View File

@ -5,20 +5,36 @@ unit kern_osem;
interface
uses
mqueue,
kern_mtx,
kern_thr,
kern_condvar;
const
SEMA_ATTR_FIFO=$1;
SEMA_ATTR_PRIO=$2;
SEMA_ATTR_DELF=$1000;
SEMA_ATTR_SHRD=$1000;
function sys_osem_create(name:PChar;attr:DWORD;initCount,maxCount:Integer):Integer;
function sys_osem_delete(key:Integer):Integer;
function sys_osem_cancel(key,setCount:Integer;pNumWait:PInteger):Integer;
function sys_osem_post(key,signalCount:Integer):Integer;
function sys_osem_trywait(key,needCount:Integer):Integer;
function sys_osem_wait(key,needCount:Integer;pTimeout:PDWORD):Integer;
implementation
uses
mqueue,
errno,
systm,
time,
kern_time,
kern_mtx,
kern_thr,
kern_condvar,
kern_id;
type
p_osem=^t_osem;
t_osem=packed record
desc :t_id_desc;
mtx :mtx;
cv :t_cv;
list :TAILQ_HEAD;
@ -27,6 +43,7 @@ type
init_count:Integer;
max_count :Integer;
wait_count:Integer;
name :array[0..31] of Char;
end;
p_osem_node=^t_osem_node;
@ -37,15 +54,22 @@ type
retval:Integer;
end;
implementation
var
osem_table:t_id_desc_table;
uses
errno,
time,
kern_time;
function osem_alloc:p_osem; inline;
begin
Result:=AllocMem(SizeOf(t_osem));
end;
procedure osem_free(data:pointer);
begin
FreeMem(data);
end;
function osem_init(sem:p_osem;attr:DWORD;initCount,max_count:Integer):Integer;
begin
sem^.desc.free :=@osem_free;
sem^.count :=initCount;
sem^.init_count:=initCount;
sem^.max_count :=max_count;
@ -237,7 +261,9 @@ begin
begin
if (needCount<=sem^.max_count) then
begin
node.retval:=0;
node:=Default(t_osem_node);
node.td :=td;
node.count:=needCount;
if ((sem^.attr and SEMA_ATTR_FIFO)=0) then
begin
//_PRIO
@ -262,8 +288,6 @@ begin
sem^.list.tqh_last:=@node.entry.tqe_next;
end;
sem^.wait_count:=sem^.wait_count+1;
node.td:=td;
node.count:=needCount;
if (timeout=nil) then
begin
Result:=_cv_wait_sig(@sem^.cv,@sem^.mtx);
@ -348,7 +372,164 @@ begin
end;
end;
//
function sys_osem_create(name:PChar;attr:DWORD;initCount,maxCount:Integer):Integer;
var
td:p_kthread;
_name:array[0..31] of Char;
sem:p_osem;
key:Integer;
begin
Result:=EINVAL;
td:=curkthread;
if ((attr and $fffffefc)<>0) or ((attr and 3)=3) then Exit;
//process shared osem not support
if ((attr and SEMA_ATTR_SHRD)<>0) then Exit(EPERM);
if (initCount<0) or
(maxCount<=0) or
(initCount>maxCount) or
(name=nil) then Exit;
if ((attr and 3)=0) then
begin
attr:=attr or 1;
end;
FillChar(_name,32,0);
if (copyinstr(name,@_name,32,nil)<>0) then Exit;
sem:=osem_alloc;
if (sem=nil) then Exit(ENOMEM); //EAGAIN
osem_init(sem,attr,initCount,maxCount);
sem^.name:=_name;
if not id_new(@osem_table,@sem^.desc,@key) then
begin
osem_free(sem);
Exit(EAGAIN);
end;
id_release(@sem^.desc);
td^.td_retval[0]:=key;
Result:=0;
end;
function sys_osem_delete(key:Integer):Integer;
var
sem:p_osem;
begin
Result:=ESRCH;
sem:=p_osem(id_get(@osem_table,key));
if (sem=nil) then Exit;
osem_delete(sem);
id_release(@sem^.desc);
if not id_del(@osem_table,key) then Exit;
Result:=0;
end;
function sys_osem_cancel(key,setCount:Integer;pNumWait:PInteger):Integer;
var
sem:p_osem;
num:Integer;
begin
Result:=ESRCH;
num:=0;
sem:=p_osem(id_get(@osem_table,key));
if (sem=nil) then Exit;
Result:=osem_cancel(sem,setCount,@num);
id_release(@sem^.desc);
if (Result=0) then
begin
if (pNumWait<>nil) then
begin
Result:=copyout(@num,pNumWait,SizeOf(Integer));
end;
end;
end;
function sys_osem_post(key,signalCount:Integer):Integer;
var
sem:p_osem;
begin
Result:=EINVAL;
if (signalCount<=0) then Exit;
Result:=ESRCH;
sem:=p_osem(id_get(@osem_table,key));
if (sem=nil) then Exit;
Result:=osem_post(sem,signalCount);
id_release(@sem^.desc);
end;
function sys_osem_trywait(key,needCount:Integer):Integer;
var
sem:p_osem;
begin
Result:=EINVAL;
if (needCount<=0) then Exit;
Result:=ESRCH;
sem:=p_osem(id_get(@osem_table,key));
if (sem=nil) then Exit;
Result:=osem_trywait(sem,needCount);
id_release(@sem^.desc);
end;
function sys_osem_wait(key,needCount:Integer;pTimeout:PDWORD):Integer;
var
sem:p_osem;
timeout:PDWORD;
time:DWORD;
begin
Result:=EINVAL;
if (needCount<=0) then Exit;
time:=0;
timeout:=nil;
if (pTimeout<>nil) then
begin
Result:=copyin(pTimeout,@time,SizeOf(DWORD));
if (Result<>0) then Exit;
timeout:=@time;
end;
Result:=ESRCH;
sem:=p_osem(id_get(@osem_table,key));
if (sem=nil) then Exit;
Result:=osem_wait(sem,needCount,timeout);
id_release(@sem^.desc);
if (pTimeout<>nil) then
begin
Result:=copyout(@time,pTimeout,SizeOf(DWORD));
end;
end;
initialization
id_table_init(@osem_table,1);
finalization
id_table_fini(@osem_table);
end.

View File

@ -17,6 +17,7 @@ const
_ufssel =(2 shl 3) or 3;
_ugssel =(3 shl 3) or 3;
procedure cpu_set_syscall_retval(td:p_kthread;error:Integer);
procedure sendsig(catcher:sig_t;ksi:p_ksiginfo;mask:p_sigset_t);
function sys_sigreturn(sigcntxp:p_ucontext_t):Integer;
@ -29,6 +30,33 @@ uses
kern_sig,
trap;
procedure cpu_set_syscall_retval(td:p_kthread;error:Integer);
begin
Case error of
0:With td^.td_frame^ do
begin
tf_rax:=td^.td_retval[0];
tf_rdx:=td^.td_retval[1];
tf_rflags:=tf_rflags and (not PSL_C);
end;
ERESTART:
With td^.td_frame^ do
begin
//tf_err = size of syscall cmd
tf_rip:=tf_rip-td^.td_frame^.tf_err;
tf_r10:=tf_rcx;
set_pcb_flags(td,PCB_FULL_IRET);
end;
EJUSTRETURN:; //nothing
else
With td^.td_frame^ do
begin
tf_rax:=error;
tf_rflags:=tf_rflags or PSL_C;
end;
end;
end;
function get_fpcontext(td:p_kthread;mcp:p_mcontext_t;xstate:Pointer):Integer;
begin
Result:=0;

View File

@ -233,6 +233,10 @@ begin
td:=curkthread;
td_frame:=td^.td_frame;
//cpu_fetch_syscall_args
td^.td_retval[0]:=0;
td^.td_retval[1]:=td_frame^.tf_rdx;
error:=0;
if (td_frame^.tf_rax<>0) then
begin

View File

@ -18,7 +18,6 @@ var
function cpu_thread_alloc(td:p_kthread):Integer;
function cpu_thread_free(td:p_kthread):Integer;
procedure cpu_set_syscall_retval(td:p_kthread;error:Integer);
function cpuset_setaffinity(td:p_kthread;new:Ptruint):Integer;
function cpuset_setproc(new:Ptruint):Integer;
function cpuset_getproc(var old:Ptruint):Integer;
@ -172,33 +171,6 @@ begin
);
end;
procedure cpu_set_syscall_retval(td:p_kthread;error:Integer);
begin
Case error of
0:With td^.td_frame^ do
begin
tf_rax:=td^.td_retval[0];
tf_rdx:=td^.td_retval[1];
tf_rflags:=tf_rflags and (not PSL_C);
end;
ERESTART:
With td^.td_frame^ do
begin
//tf_err = size of syscall cmd
tf_rip:=tf_rip-td^.td_frame^.tf_err;
tf_r10:=tf_rcx;
set_pcb_flags(td,PCB_FULL_IRET);
end;
EJUSTRETURN:; //nothing
else
With td^.td_frame^ do
begin
tf_rax:=error;
tf_rflags:=tf_rflags or PSL_C;
end;
end;
end;
function cpuset_setaffinity(td:p_kthread;new:Ptruint):Integer;
begin
td^.td_cpuset:=new;

59
sys/sys_osem.pas Normal file
View File

@ -0,0 +1,59 @@
unit sys_osem;
{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}
interface
function _osem_create_err(name:PChar;attr:DWORD;initCount,maxCount:Integer):Integer;
function _osem_delete_err(key:Integer):Integer;
function _osem_cancel_err(key,setCount:Integer;pNumWait:PInteger):Integer;
function _osem_post_err(key,signalCount:Integer):Integer;
function _osem_trywait_err(key,needCount:Integer):Integer;
function _osem_wait_err(key,needCount:Integer;pTimeout:PDWORD):Integer;
implementation
uses
kern_osem,
trap,
thr_error;
function _osem_create_err(name:PChar;attr:DWORD;initCount,maxCount:Integer):Integer; assembler; nostackframe;
asm
movq sys_osem_create,%rax
call fast_syscall
end;
function _osem_delete_err(key:Integer):Integer; assembler; nostackframe;
asm
movq sys_osem_delete,%rax
call fast_syscall
end;
function _osem_cancel_err(key,setCount:Integer;pNumWait:PInteger):Integer; assembler; nostackframe;
asm
movq sys_osem_cancel,%rax
call fast_syscall
end;
function _osem_post_err(key,signalCount:Integer):Integer; assembler; nostackframe;
asm
movq sys_osem_post,%rax
call fast_syscall
end;
function _osem_trywait_err(key,needCount:Integer):Integer; assembler; nostackframe;
asm
movq sys_osem_trywait,%rax
call fast_syscall
end;
function _osem_wait_err(key,needCount:Integer;pTimeout:PDWORD):Integer; assembler; nostackframe;
asm
movq sys_osem_wait,%rax
call fast_syscall
end;
end.

View File

@ -6,7 +6,6 @@ unit sys_umtx;
interface
uses
errno,
time,
_umtx;
@ -27,6 +26,7 @@ function _umtx_op_err(obj:Pointer;op:Integer;val:QWORD;uaddr1,uaddr2:Pointer):I
implementation
uses
errno,
kern_umtx,
trap,
thr_error;

View File

@ -185,6 +185,14 @@
<Filename Value="..\kern\kern_osem.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="..\kern\kern_id.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
<Unit>
<Filename Value="..\sys_osem.pas"/>
<IsPartOfProject Value="True"/>
</Unit>
</Units>
</ProjectOptions>
<CompilerOptions>

View File

@ -28,7 +28,9 @@ uses
kern_thr,
rtprio,
kern_condvar,
kern_osem;
kern_osem,
kern_id,
sys_osem;
var
mtx:umutex;