@@ -659,13 +659,15 @@ private List<Event> inlinePthreadCondWait(FunctionCall call) {
659659 final Register errorRegister = getResultRegisterAndCheckArguments (2 , call );
660660 //final Expression condAddress = call.getArguments().get(0);
661661 final Expression lockAddress = call .getArguments ().get (1 );
662- // TODO: implement this without lock/unlock events and get rid of them
663- return List .of (
662+ final IntegerType type = getPthreadMutexType ();
663+ final Register oldValueRegister = call .getFunction ().newUniqueRegister ("__pthread_cond_wait" , type );
664+ final Register successRegister = call .getFunction ().newUniqueRegister ("__pthread_cond_wait" , types .getBooleanType ());
665+ return eventSequence (
664666 // Allow other threads to access the condition variable.
665- EventFactory . Pthread . newUnlock ( lockAddress . toString () , lockAddress ),
667+ newPthreadUnlock ( oldValueRegister , lockAddress ),
666668 // This thread would sleep here. Explicit or spurious signals may wake it.
667669 // Re-lock.
668- EventFactory . Pthread . newLock ( lockAddress . toString () , lockAddress ),
670+ newPthreadLock ( oldValueRegister , successRegister , lockAddress ),
669671 assignSuccess (errorRegister )
670672 );
671673 }
@@ -677,12 +679,15 @@ private List<Event> inlinePthreadCondTimedwait(FunctionCall call) {
677679 //final Expression condAddress = call.getArguments().get(0);
678680 final Expression lockAddress = call .getArguments ().get (1 );
679681 //final Expression timespec = call.getArguments().get(2);
680- return List .of (
682+ final IntegerType type = getPthreadMutexType ();
683+ final Register oldValueRegister = call .getFunction ().newUniqueRegister ("__pthread_cond_timedwait" , type );
684+ final Register successRegister = call .getFunction ().newUniqueRegister ("__pthread_cond_timedwait" , types .getBooleanType ());
685+ return eventSequence (
681686 // Allow other threads to access the condition variable.
682- EventFactory . Pthread . newUnlock ( lockAddress . toString () , lockAddress ),
687+ newPthreadUnlock ( oldValueRegister , lockAddress ),
683688 // This thread would sleep here. Explicit or spurious signals may wake it.
684689 // Re-lock.
685- EventFactory . Pthread . newLock ( lockAddress . toString () , lockAddress ),
690+ newPthreadLock ( oldValueRegister , successRegister , lockAddress ),
686691 newLocal (errorRegister , expressions .makeValue (PosixErrorCode .ETIMEDOUT .getValue (), errorType ))
687692 );
688693 }
@@ -758,17 +763,15 @@ private List<Event> inlinePthreadSetSpecific(FunctionCall call) {
758763 private static final List <String > P_THREAD_MUTEXATTR = List .of (
759764 "prioceiling" ,
760765 "protocol" ,
761- "type" ,
762- "policy_np"
766+ "type"
763767 );
764768
765769 private List <Event > inlinePthreadMutexInit (FunctionCall call ) {
766770 //see https://linux.die.net/man/3/pthread_mutex_init
767771 //TODO use attributes
768772 final Register errorRegister = getResultRegisterAndCheckArguments (2 , call );
769773 final Expression lockAddress = call .getArguments ().get (0 );
770- // FIXME: We currently use bv32 in InitLock, Lock and Unlock.
771- final IntegerType type = types .getIntegerType (32 );
774+ final IntegerType type = getPthreadMutexType ();
772775 final Expression unlocked = expressions .makeZero (type );
773776 return List .of (
774777 EventFactory .Llvm .newStore (lockAddress , unlocked , Tag .C11 .MO_RELEASE ),
@@ -789,58 +792,39 @@ private List<Event> inlinePthreadMutexLock(FunctionCall call) {
789792 //see https://linux.die.net/man/3/pthread_mutex_lock
790793 final Register errorRegister = getResultRegisterAndCheckArguments (1 , call );
791794 checkArgument (errorRegister .getType () instanceof IntegerType , "Wrong return type for \" %s\" " , call );
792- // FIXME: We currently use bv32 in InitLock, Lock and Unlock.
793- final IntegerType type = types .getIntegerType (32 );
794- final Register oldValueRegister = call .getFunction ().newRegister (type );
795- final Register successRegister = call .getFunction ().newRegister (types .getBooleanType ());
795+ final IntegerType type = getPthreadMutexType ();
796+ final Register oldValueRegister = call .getFunction ().newUniqueRegister ("__pthread_mutex_lock" , type );
797+ final Register successRegister = call .getFunction ().newUniqueRegister ("__pthread_mutex_lock" , types .getBooleanType ());
796798 final Expression lockAddress = call .getArguments ().get (0 );
797- final Expression locked = expressions .makeOne (type );
798- final Expression unlocked = expressions .makeZero (type );
799- final Expression fail = expressions .makeNot (successRegister );
800- final Label spinLoopHead = EventFactory .newLabel ("__spinloop_head" );
801- final Label spinLoopEnd = EventFactory .newLabel ("__spinloop_end" );
802- // We implement this as a caslocks
803- return List .of (
804- spinLoopHead ,
805- EventFactory .Llvm .newCompareExchange (oldValueRegister , successRegister , lockAddress , unlocked , locked , Tag .C11 .MO_ACQUIRE , true ),
806- EventFactory .newJump (successRegister , spinLoopEnd ),
807- EventFactory .newGoto (spinLoopHead ),
808- spinLoopEnd ,
809- EventFactory .newLocal (errorRegister , expressions .makeCast (fail , errorRegister .getType ()))
799+ return eventSequence (
800+ newPthreadLock (oldValueRegister , successRegister , lockAddress ),
801+ assignSuccess (errorRegister )
810802 );
811803 }
812804
813805 private List <Event > inlinePthreadMutexTryLock (FunctionCall call ) {
814806 //see https://linux.die.net/man/3/pthread_mutex_trylock
815807 final Register errorRegister = getResultRegisterAndCheckArguments (1 , call );
816808 checkArgument (errorRegister .getType () instanceof IntegerType , "Wrong return type for \" %s\" " , call );
817- // FIXME: We currently use bv32 in InitLock, Lock and Unlock.
818- final IntegerType type = types .getIntegerType (32 );
819- final Register oldValueRegister = call .getFunction ().newRegister (type );
820- final Register successRegister = call .getFunction ().newRegister (types .getBooleanType ());
809+ final IntegerType type = getPthreadMutexType ();
810+ final Register oldValueRegister = call .getFunction ().newUniqueRegister ("__pthread_mutex_try_lock" , type );
811+ final Register successRegister = call .getFunction ().newUniqueRegister ("__pthread_mutex_try_lock" , types .getBooleanType ());
821812 final Expression lockAddress = call .getArguments ().get (0 );
822- final Expression locked = expressions .makeOne (type );
823- final Expression unlocked = expressions .makeZero (type );
824813 final Expression fail = expressions .makeNot (successRegister );
825814 return List .of (
826- EventFactory . Llvm . newCompareExchange (oldValueRegister , successRegister , lockAddress , unlocked , locked , Tag . C11 . MO_ACQUIRE ),
815+ newPthreadTryLock (oldValueRegister , successRegister , lockAddress , false ),
827816 EventFactory .newLocal (errorRegister , expressions .makeCast (fail , errorRegister .getType ()))
828817 );
829818 }
830819
831820 private List <Event > inlinePthreadMutexUnlock (FunctionCall call ) {
832821 //see https://linux.die.net/man/3/pthread_mutex_unlock
833822 final Register errorRegister = getResultRegisterAndCheckArguments (1 , call );
834- // FIXME: We currently use bv32 in InitLock, Lock and Unlock.
835- final IntegerType type = types .getIntegerType (32 );
836- final Register oldValueRegister = call .getFunction ().newRegister (type );
823+ final IntegerType type = getPthreadMutexType ();
824+ final Register oldValueRegister = call .getFunction ().newUniqueRegister ("__pthread_mutex_unlock" , type );
837825 final Expression lockAddress = call .getArguments ().get (0 );
838- final Expression locked = expressions .makeOne (type );
839- final Expression unlocked = expressions .makeZero (type );
840826 return eventSequence (
841- EventFactory .Llvm .newLoad (oldValueRegister , lockAddress , Tag .C11 .MO_RELAXED ),
842- notToInline .contains (AssertionType .USER ) ? null : EventFactory .newAssert (expressions .makeEQ (oldValueRegister , locked ), "Unlocking an already unlocked mutex" ),
843- EventFactory .Llvm .newStore (lockAddress , unlocked , Tag .C11 .MO_RELEASE ),
827+ newPthreadUnlock (oldValueRegister , lockAddress ),
844828 assignSuccess (errorRegister )
845829 );
846830 }
@@ -869,6 +853,39 @@ private List<Event> inlinePthreadMutexAttr(FunctionCall call) {
869853 );
870854 }
871855
856+ private List <Event > newPthreadUnlock (Register oldValueRegister , Expression address ) {
857+ final Expression unlocked = expressions .makeGeneralZero (oldValueRegister .getType ());
858+ final boolean skipCheck = notToInline .contains (AssertionType .USER );
859+ final Event load = skipCheck ? null : EventFactory .Llvm .newLoad (oldValueRegister , address , Tag .C11 .MO_RELAXED );
860+ final Expression isLocked = skipCheck ? null : expressions .makeNEQ (oldValueRegister , unlocked );
861+ final Event check = skipCheck ? null : EventFactory .newAssert (isLocked , "Unlocking an already unlocked mutex" );
862+ final Event store = EventFactory .Llvm .newStore (address , unlocked , Tag .C11 .MO_RELEASE );
863+ return Arrays .asList (load , check , store );
864+ }
865+
866+ private Event newPthreadTryLock (Register oldValueRegister , Register successRegister , Expression address , boolean strong ) {
867+ final Expression unlocked = expressions .makeGeneralZero (oldValueRegister .getType ());
868+ final Expression locked = expressions .makeOne ((IntegerType ) oldValueRegister .getType ());
869+ return EventFactory .Llvm .newCompareExchange (oldValueRegister , successRegister , address , unlocked , locked , Tag .C11 .MO_ACQUIRE , strong );
870+ }
871+
872+ private List <Event > newPthreadLock (Register oldValueRegister , Register successRegister , Expression address ) {
873+ // We implement this as a CAS-spinlock
874+ final Label spinLoopHead = EventFactory .newLabel ("__spinloop_head" );
875+ final Label spinLoopEnd = EventFactory .newLabel ("__spinloop_end" );
876+ return List .of (
877+ spinLoopHead ,
878+ newPthreadTryLock (oldValueRegister , successRegister , address , true ),
879+ EventFactory .newJump (successRegister , spinLoopEnd ),
880+ EventFactory .newGoto (spinLoopHead ),
881+ spinLoopEnd
882+ );
883+ }
884+
885+ private IntegerType getPthreadMutexType () {
886+ return types .getIntegerType (1 );
887+ }
888+
872889 private static final List <String > P_THREAD_RWLOCK_ATTR = List .of (
873890 "pshared"
874891 );
0 commit comments