diff --git a/sys/_umtx.pas b/sys/_umtx.pas index eebe1000..35add3ad 100644 --- a/sys/_umtx.pas +++ b/sys/_umtx.pas @@ -29,7 +29,7 @@ type p_urwlock=^urwlock; urwlock=packed record - rw_state :Integer; + rw_state :DWORD; rw_flags :DWORD; rw_blocked_readers:DWORD; rw_blocked_writers:DWORD; diff --git a/sys/kern_umtx.pas b/sys/kern_umtx.pas index 2de01466..27725311 100644 --- a/sys/kern_umtx.pas +++ b/sys/kern_umtx.pas @@ -1398,12 +1398,10 @@ begin until false; umtxq_lock(uq^.uq_key); - if (Result=0) then begin umtxq_signal(uq^.uq_key,High(Integer)); end; - umtxq_unlock(uq^.uq_key); umtx_key_release(uq^.uq_key); @@ -1585,6 +1583,7 @@ begin if ((uq^.uq_flags and UQF_UMTXQ)=0) then begin + umtxq_unlock(uq^.uq_key); Result:=0; end else begin @@ -1592,12 +1591,14 @@ begin begin oldlen:=uq^.uq_cur_queue^.length; umtxq_remove(uq); + umtxq_unlock(uq^.uq_key); if (oldlen=1) then begin - umtxq_unlock(uq^.uq_key); suword32(cv^.c_has_waiters,0); - umtxq_lock(uq^.uq_key); end; + end else + begin + umtxq_unlock(uq^.uq_key); end; if (Result=ERESTART) then begin @@ -1605,8 +1606,6 @@ begin end; end; - umtxq_unlock(uq^.uq_key); - _exit: umtx_key_release(uq^.uq_key); end; @@ -1623,21 +1622,17 @@ begin if (key=nil) then Exit(EFAULT); umtxq_lock(key); - count:=umtxq_count(key); nwake:=umtxq_signal(key,1); - if (count<=nwake) then - begin - umtxq_unlock(&key); - Result:=suword32(cv^.c_has_waiters,0); - umtxq_lock(&key); - end; - umtxq_unlock(key); - umtx_key_release(key); + if (count<=nwake) then + begin + Result:=suword32(cv^.c_has_waiters,0); + if (Result<>0) then Result:=EFAULT; + end; - if (Result<>0) then Result:=EFAULT; + umtx_key_release(key); end; function do_cv_broadcast(td:p_kthread;cv:p_ucond):Integer; @@ -1655,10 +1650,9 @@ begin umtxq_unlock(key); Result:=suword32(cv^.c_has_waiters,0); + if (Result<>0) then Result:=EFAULT; umtx_key_release(key); - - if (Result<>0) then Result:=EFAULT; end; //// @@ -1795,7 +1789,7 @@ end; function do_rw_rdlock2(td:p_kthread;rwlock:p_urwlock;fflag:QWORD;timeout:ptimespec):Integer; var - ts,ts2,ts3,tv:Int64; + ts,ts2,tv:Int64; begin Result:=0; @@ -1816,9 +1810,7 @@ begin Break; end; - ts3:=ts; - ts3:=ts3-ts2; - tv:=ts3; + tv:=ts-ts2; until false; if (Result=ERESTART) then @@ -1927,7 +1919,7 @@ begin state:=fuword32(rwlock^.rw_state); end; - blocked_writers:=fuword32(&rwlock^.rw_blocked_writers); + blocked_writers:=fuword32(rwlock^.rw_blocked_writers); suword32(rwlock^.rw_blocked_writers,blocked_writers-1); if (blocked_writers=1) then @@ -1964,7 +1956,7 @@ end; function do_rw_wrlock2(td:p_kthread;rwlock:p_urwlock;fflag:QWORD;timeout:ptimespec):Integer; var - ts,ts2,ts3,tv:Int64; + ts,ts2,tv:Int64; begin Result:=0; @@ -1985,9 +1977,7 @@ begin Break; end; - ts3:=ts; - ts3:=ts3-ts2; - tv:=ts3; + tv:=ts-ts2; until false; if (Result=ERESTART) then @@ -1996,7 +1986,6 @@ begin end; end; - function do_rw_unlock(td:p_kthread;rwlock:p_urwlock):Integer; label _exit; @@ -2114,6 +2103,108 @@ end; //// +function do_sem_wait(td:p_kthread;sem:p__usem;timeout:ptimespec):Integer; +var + uq:p_umtx_q; + count:DWORD; + cts,ets,tv:Int64; +begin + Result:=0; + + uq:=td^.td_umtxq; + + uq^.uq_key:=umtx_key_get(sem,TYPE_SEM); + if (uq^.uq_key=nil) then Exit(EFAULT); + + umtxq_lock(uq^.uq_key); + umtxq_insert(uq); + umtxq_unlock(uq^.uq_key); + + if ((fuword32(sem^._has_waiters))=0) then + begin + casuword32(sem^._has_waiters,0,1); + end; + + count:=fuword32(sem^._count); + + if (count<>0) then + begin + umtxq_lock(uq^.uq_key); + umtxq_remove(uq); + umtxq_unlock(uq^.uq_key); + umtx_key_release(uq^.uq_key); + Exit(0); + end; + + if (timeout=nil) then + begin + Result:=umtxq_sleep(uq,NT_INFINITE); + end else + begin + ets:=get_unit_uptime; + tv:=TIMESPEC_TO_UNIT(timeout); + ets:=ets+tv; + + repeat + Result:=umtxq_sleep(uq,-tv); + if (Result<>ETIMEDOUT) then Break; + + cts:=get_unit_uptime; + + if (cts>=ets) then + begin + Result:=ETIMEDOUT; + Break; + end; + + tv:=ets-cts; + until false; + end; + + if ((uq^.uq_flags and UQF_UMTXQ)=0) then + begin + Result:=0; + end else + begin + umtxq_lock(uq^.uq_key); + umtxq_remove(uq); + umtxq_unlock(uq^.uq_key); + + if (Result=ERESTART) and (timeout<>nil) then + begin + Result:=EINTR; + end; + end; + + umtx_key_release(uq^.uq_key); +end; + +function do_sem_wake(td:p_kthread;sem:p__usem):Integer; +var + key:umtx_key; + count,nwake:Integer; +begin + Result:=0; + + key:=umtx_key_get(sem,TYPE_SEM); + if (key=nil) then Exit(EFAULT); + + umtxq_lock(key); + count:=umtxq_count(key); + nwake:=umtxq_signal(key,1); + umtxq_unlock(key); + + if (count<=nwake) then + begin + Result:=suword32(sem^._has_waiters,0); + if (Result<>0) then Result:=EFAULT; + end; + + umtx_key_release(key); +end; + +//// + function umtx_copyin_timeout(addr:Pointer;tsp:ptimespec):Integer; begin Result:=copyin(addr,tsp,SizeOf(timespec)); @@ -2382,6 +2473,28 @@ begin Result:=do_unlock_umtx(td,mtx,td^.td_tid); end; +function __umtx_op_sem_wait(td:p_kthread;obj:Pointer;val:QWORD;uaddr1,uaddr2:Pointer):Integer; +var + ts:ptimespec; + timeout:timespec; +begin + if (ptrint(obj)<$1000) then Exit(EFAULT); + + ts:=nil; + if (uaddr2<>nil) then + begin + Result:=umtx_copyin_timeout(uaddr2,@timeout); + if (Result<>0) then Exit; + ts:=@timeout; + end; + Result:=do_sem_wait(td,obj,ts); +end; + +function __umtx_op_sem_wake(td:p_kthread;obj:Pointer;val:QWORD;uaddr1,uaddr2:Pointer):Integer; inline; +begin + Result:=do_sem_wake(td,obj) +end; + function _sys_umtx_op(obj:Pointer;op:Integer;val:QWORD;uaddr1,uaddr2:Pointer):Integer; var td:p_kthread; @@ -2409,8 +2522,8 @@ begin UMTX_OP_WAKE_PRIVATE :Result:=__umtx_op_wake_private (td,obj,val,uaddr1,uaddr2); UMTX_OP_MUTEX_WAIT :Result:=__umtx_op_wait_umutex (td,obj,val,uaddr1,uaddr2); UMTX_OP_MUTEX_WAKE :Result:=__umtx_op_wake_umutex (td,obj,val,uaddr1,uaddr2); - //UMTX_OP_SEM_WAIT - //UMTX_OP_SEM_WAKE + UMTX_OP_SEM_WAIT :Result:=__umtx_op_sem_wait (td,obj,val,uaddr1,uaddr2); + UMTX_OP_SEM_WAKE :Result:=__umtx_op_sem_wake (td,obj,val,uaddr1,uaddr2); UMTX_OP_NWAKE_PRIVATE :Result:=__umtx_op_nwake_private (td,obj,val,uaddr1,uaddr2); UMTX_OP_MUTEX_WAKE2 :Result:=__umtx_op_wake2_umutex (td,obj,val,uaddr1,uaddr2); else diff --git a/sys/systm.pas b/sys/systm.pas index 7813b8ac..80a733f3 100644 --- a/sys/systm.pas +++ b/sys/systm.pas @@ -12,10 +12,8 @@ function copyin(udaddr,kaddr:Pointer;len:ptruint):Integer; inline; function copyinstr(udaddr,kaddr:Pointer;len:ptruint;lencopied:pptruint):Integer; function copyout(udaddr,kaddr:Pointer;len:ptruint):Integer; inline; function fuword32(var base:DWORD):DWORD; inline; -function fuword32(var base:Integer):Integer; inline; function fuword64(var base:QWORD):QWORD; inline; function casuword32(var base:DWORD;oldval,newval:DWORD):DWORD; inline; -function casuword32(var base:Integer;oldval,newval:Integer):Integer; inline; function casuword64(var base:QWORD;oldval,newval:QWORD):QWORD; inline; function suword32(var base:DWORD;word:DWORD):DWORD; inline; @@ -74,14 +72,6 @@ begin end; end; -function fuword32(var base:Integer):Integer; inline; -begin - if (NtReadVirtualMemory(NtCurrentProcess,@base,@Result,SizeOf(DWORD),nil)<>0) then - begin - Result:=-1; - end; -end; - function fuword64(var base:QWORD):QWORD; inline; begin if (NtReadVirtualMemory(NtCurrentProcess,@base,@Result,SizeOf(QWORD),nil)<>0) then @@ -95,11 +85,6 @@ begin Result:=System.InterlockedCompareExchange(base,newval,oldval); end; -function casuword32(var base:Integer;oldval,newval:Integer):Integer; inline; -begin - Result:=System.InterlockedCompareExchange(base,newval,oldval); -end; - function casuword64(var base:QWORD;oldval,newval:QWORD):QWORD; inline; begin Result:=System.InterlockedCompareExchange64(base,newval,oldval); diff --git a/sys/test/project1.lpr b/sys/test/project1.lpr index f648f97b..4fa34303 100644 --- a/sys/test/project1.lpr +++ b/sys/test/project1.lpr @@ -20,6 +20,7 @@ uses var mtx:umutex; + rwl:urwlock; e:Integer; event:Thandle; @@ -45,7 +46,8 @@ begin repeat //e:=sys_umtx_op(@mtx,{UMTX_OP_MUTEX_LOCK} UMTX_OP_LOCK,td.td_tid,nil,nil); - e:=sys_umtx_op(@mtx,UMTX_OP_MUTEX_LOCK,td.td_tid,nil,nil); + //e:=sys_umtx_op(@mtx,UMTX_OP_MUTEX_LOCK,td.td_tid,nil,nil); + e:=sys_umtx_op(@rwl,UMTX_OP_RW_WRLOCK,0,nil,nil); Writeln(' lock[',GetCurrentThreadId,'] ',e); //e:=_do_lock_normal(GetCurrentThreadId,@mtx,0,NT_INFINITE,0); @@ -54,7 +56,8 @@ begin //sleep(100); //e:=sys_umtx_op(@mtx,{UMTX_OP_MUTEX_UNLOCK} UMTX_OP_UNLOCK,td.td_tid,nil,nil); - e:=sys_umtx_op(@mtx,UMTX_OP_MUTEX_UNLOCK,td.td_tid,nil,nil); + //e:=sys_umtx_op(@mtx,UMTX_OP_MUTEX_UNLOCK,td.td_tid,nil,nil); + e:=sys_umtx_op(@rwl,UMTX_OP_RW_UNLOCK,0,nil,nil); Writeln('unlock[',GetCurrentThreadId,'] ',e); sleep(1000)