This commit is contained in:
red-prig 2022-06-04 01:21:55 +03:00
parent 8e45297e69
commit 40ff63760a
1 changed files with 105 additions and 30 deletions

View File

@ -153,12 +153,13 @@ Const
LIFE_COND=$C0BAB1FD;
DEAD_COND=$C0DEADBF;
{type
sCondWaitHelper=record
type
psCondWaitHelper=^sCondWaitHelper;
sCondWaitHelper=packed record
c:pthread_cond;
external_mutex:pthread_mutex;
external_mutex:p_pthread_mutex;
r:Pinteger;
end;}
end;
var
cond_locked:Pointer=nil;
@ -299,27 +300,29 @@ begin
if not safe_test(_c^.valid,LIFE_COND) then
Exit(EINVAL);
//Writeln('pthread_cond_signal:',_c^.name);
SwEnterCriticalSection(_c^.waiters_count_lock_);
//mingw implement is wrong
if true {(_c^.waiters_count_unblock_<>0)} then
if {true} (_c^.waiters_count_unblock_<>0) then
begin
if (_c^.waiters_count_=0) then
begin
System.LeaveCriticalSection(_c^.waiters_count_lock_);
Exit(0);
end;
Dec(_c^.waiters_count_);
Inc(_c^.waiters_count_unblock_);
end else
if false {(_c^.waiters_count_>_c^.waiters_count_gone_)} then
if {false} (_c^.waiters_count_>_c^.waiters_count_gone_) then
begin
r:=do_sema_b_wait(_c^.sema_b,nil,_c^.waiters_b_lock_,_c^.value_b);
if (r<>0) then
begin
//r:=do_sema_b_release (_c^.sema_b,1,_c^.waiters_b_lock_,_c^.value_b);
System.LeaveCriticalSection (_c^.waiters_count_lock_);
Exit(r);
end;
@ -329,12 +332,10 @@ begin
Dec(_c^.waiters_count_,_c^.waiters_count_gone_);
_c^.waiters_count_gone_:=0;
end;
Dec(_c^.waiters_count_);
_c^.waiters_count_unblock_:=1;
//System.LeaveCriticalSection(_c^.waiters_count_lock_);
//r:=do_sema_b_release (_c^.sema_b,1,_c^.waiters_b_lock_,_c^.value_b);
end else
begin
System.LeaveCriticalSection(_c^.waiters_count_lock_);
@ -361,10 +362,12 @@ begin
if not safe_test(_c^.valid,LIFE_COND) then
Exit(EINVAL);
//Writeln('pthread_cond_broadcast:',_c^.name);
SwEnterCriticalSection(_c^.waiters_count_lock_);
//mingw implement is wrong
if true {(_c^.waiters_count_unblock_<>0)} then
if {true} (_c^.waiters_count_unblock_<>0) then
begin
if (_c^.waiters_count_=0) then
begin
@ -375,29 +378,27 @@ begin
_c^.waiters_count_:=0;
Inc(_c^.waiters_count_unblock_,relCnt);
end else
if false {(_c^.waiters_count_>_c^.waiters_count_gone_)} then
if {false} (_c^.waiters_count_>_c^.waiters_count_gone_) then
begin
r:=do_sema_b_wait(_c^.sema_b,nil,_c^.waiters_b_lock_,_c^.value_b);
if (r<>0) then
begin
//r:=do_sema_b_release (_c^.sema_b,1,_c^.waiters_b_lock_,_c^.value_b);
System.LeaveCriticalSection(_c^.waiters_count_lock_);
Exit(r);
end;
if (_c^.waiters_count_gone_<>0) then
begin
Dec(_c^.waiters_count_,_c^.waiters_count_gone_);
_c^.waiters_count_gone_:=0;
end;
relCnt:=_c^.waiters_count_;
_c^.waiters_count_:=0;
_c^.waiters_count_unblock_:=relCnt;
//System.LeaveCriticalSection(_c^.waiters_count_lock_);
//r:=do_sema_b_release (_c^.sema_b,1,_c^.waiters_b_lock_,_c^.value_b);
end else
begin
System.LeaveCriticalSection(_c^.waiters_count_lock_);
@ -409,9 +410,81 @@ begin
Result:=do_sema_b_release(_c^.sema_q,relCnt,_c^.waiters_q_lock_,_c^.value_q);
end;
procedure cleanup_wait(arg:Pointer); SysV_ABI_CDecl;
const
INT_MAX=High(Integer);
var
n,r:Integer;
ch:psCondWaitHelper;
_c:pthread_cond;
begin
if (arg=nil) then Exit;
ch:=psCondWaitHelper(arg);
_c:=ch^.c;
System.EnterCriticalSection(_c^.waiters_count_lock_);
n:=_c^.waiters_count_unblock_;
if (n<>0) then
begin
Dec(_c^.waiters_count_unblock_);
end else
if (((INT_MAX/2)-1)=_c^.waiters_count_gone_) then
begin
Inc(_c^.waiters_count_gone_);
r:=do_sema_b_wait(_c^.sema_b,nil,_c^.waiters_b_lock_,_c^.value_b);
if (r<>0) then
begin
System.LeaveCriticalSection(_c^.waiters_count_lock_);
ch^.r^:=r;
Exit;
end;
Dec(_c^.waiters_count_,_c^.waiters_count_gone_);
r:=do_sema_b_release(_c^.sema_b,1,_c^.waiters_b_lock_,_c^.value_b);
if (r<>0) then
begin
System.LeaveCriticalSection(_c^.waiters_count_lock_);
ch^.r^:=r;
Exit;
end;
_c^.waiters_count_gone_:=0;
end else
begin
Inc(_c^.waiters_count_gone_);
end;
System.LeaveCriticalSection(_c^.waiters_count_lock_);
if (n=1) then
begin
r:=do_sema_b_release(_c^.sema_b,1,_c^.waiters_b_lock_,_c^.value_b);
if (r<>0) then
begin
ch^.r^:=r;
Exit;
end;
end;
r:=ps4_pthread_mutex_lock(ch^.external_mutex);
if (r<>0) then
begin
ch^.r^:=r;
end;
end;
function pthread_cond_wait(pCond:p_pthread_cond;pMutex:p_pthread_mutex):Integer; SysV_ABI_CDecl;
var
//ch:sCondWaitHelper;
ch:sCondWaitHelper;
r:Integer;
_c:pthread_cond;
Label
@ -429,6 +502,8 @@ begin
if not safe_test(_c^.valid,LIFE_COND) then
Exit(EINVAL);
//Writeln('pthread_cond_wait:',_c^.name);
tryagain:
r:=do_sema_b_wait(_c^.sema_b,nil,_c^.waiters_b_lock_,_c^.value_b);
if (r<>0) then Exit(r);
@ -448,27 +523,26 @@ begin
r:=do_sema_b_release (_c^.sema_b,1,_c^.waiters_b_lock_,_c^.value_b);
if (r<>0) then Exit(r);
//ch.c = _c;
//ch.r = &r;
//ch.external_mutex = external_mutex;
ch.c:=_c;
ch.r:=@r;
ch.external_mutex:=pMutex;
//pthread_cleanup_push(cleanup_wait, (void *) &ch);
r:=ps4_pthread_mutex_unlock(pMutex);
//Writeln('ps4_pthread_mutex_unlock:',HexStr(pMutex),':',HexStr(r,8));
if (r=0) then
begin
r:=do_sema_b_wait(_c^.sema_q,nil,_c^.waiters_q_lock_,_c^.value_q);
end;
ps4_pthread_mutex_lock(pMutex); //WHY IT NO IN MINGW
cleanup_wait(@ch);
//pthread_cleanup_pop(1);
Result:=r;
end;
function pthread_cond_timedwait_impl(c:p_pthread_cond;m:p_pthread_mutex;pTimeout:PQWORD):Integer;
var
//ch:sCondWaitHelper;
ch:sCondWaitHelper;
r:Integer;
_c:pthread_cond;
Label
@ -486,6 +560,8 @@ begin
if not safe_test(_c^.valid,LIFE_COND) then
Exit(EINVAL);
//Writeln('pthread_cond_timedwait_impl:',_c^.name);
tryagain:
r:=do_sema_b_wait(_c^.sema_b,nil,_c^.waiters_b_lock_,_c^.value_b);
if (r<>0) then Exit(r);
@ -505,20 +581,19 @@ begin
r:=do_sema_b_release(_c^.sema_b,1,_c^.waiters_b_lock_,_c^.value_b);
if (r<>0) then Exit(r);
//ch.c = _c;
//ch.r = &r;
//ch.external_mutex = external_mutex;
ch.c:=_c;
ch.r:=@r;
ch.external_mutex:=m;
//pthread_cleanup_push(cleanup_wait, (void *) &ch);
r:=ps4_pthread_mutex_unlock(m);
//Writeln('ps4_pthread_mutex_unlock:',HexStr(m),':',HexStr(r,8));
if (r=0) then
begin
r:=do_sema_b_wait(_c^.sema_q,pTimeout,_c^.waiters_q_lock_,_c^.value_q);
end;
ps4_pthread_mutex_lock(m); //WHY IT NO IN MINGW
cleanup_wait(@ch);
//pthread_cleanup_pop(1);
Result:=r;