Index: libcfa/src/concurrency/locks.cfa
===================================================================
--- libcfa/src/concurrency/locks.cfa	(revision b6de35ec789adbc02c9c90ec2de52be7f841fd58)
+++ libcfa/src/concurrency/locks.cfa	(revision b94579a749583cbd65dea52dbcbcb8a8c0fbaaca)
@@ -587,20 +587,4 @@
 // Semaphore, counting
 
-// PRIVATE
-
-thread$ * V( semaphore & sem, const bool doUnpark ) with( sem ) {
-	thread$ * thrd = 0p;
-	lock( lock$ __cfaabi_dbg_ctx2 );
-	count$ += 1;
-	if ( count$ <= 0 ) {
-		thrd = pop_head( waiting$ );						// remove task at head of waiting list
-	}
-	unlock( lock$ );
-	if ( doUnpark ) unpark( thrd );						// make new owner
-	return thrd;
-}
-
-// PUBLIC
-
 void ?{}( semaphore & sem, ssize_t count = 1 ) with( sem ) {
 	count$ = count;
@@ -613,6 +597,6 @@
 	count$ -= 1;
 	if ( count$ < 0 ) {									// in use ?
-		append( waiting$, active_thread() );				// queue current task
-		unlock( lock$ );									// atomically release spin lock and block
+		append( waiting$, active_thread() );			// queue current task
+		unlock( lock$ );								// atomically release spin lock and block
 		park();
 		return false;
@@ -629,5 +613,5 @@
 		} // if
 	} else {
-		V( sem );										// V other semaphore
+		V( lock );										// V mutex semaphore
 		count$ -= 1;
 	} // if
@@ -654,5 +638,5 @@
 }
 
-bool V( semaphore & sem ) with( sem ) {
+thread$ * V( semaphore & sem, const bool doUnpark ) with( sem ) {
 	thread$ * thrd = 0p;
 	lock( lock$ __cfaabi_dbg_ctx2 );
@@ -662,7 +646,6 @@
 	}
 	unlock( lock$ );
-	if ( true ) unpark( thrd );						// make new owner
-//	thread$ * thrd = V(sem, true);
-	return thrd != 0p;
+	if ( doUnpark ) unpark( thrd );						// make new owner
+	return thrd;
 }
 
Index: libcfa/src/concurrency/locks.hfa
===================================================================
--- libcfa/src/concurrency/locks.hfa	(revision b6de35ec789adbc02c9c90ec2de52be7f841fd58)
+++ libcfa/src/concurrency/locks.hfa	(revision b94579a749583cbd65dea52dbcbcb8a8c0fbaaca)
@@ -11,6 +11,6 @@
 // Created On       : Thu Jan 21 19:46:50 2021
 // Last Modified By : Peter A. Buhr
-// Last Modified On : Fri Oct 31 09:20:22 2025
-// Update Count     : 59
+// Last Modified On : Wed Nov  5 10:27:45 2025
+// Update Count     : 61
 //
 
@@ -91,8 +91,4 @@
 };
 
-// PRIVATE
-//thread$ * V( semaphore & sem, bool );
-
-// PUBLIC
 void ?{}( semaphore & sem, ssize_t count = 1 );
 // Return values are used for composition. Calling threads know if a thread is unblocked, which can be useful for
@@ -103,5 +99,6 @@
 bool try_P( semaphore & sem );
 static inline bool P( semaphore & sem, semaphore & lock, uintptr_t shadow ) { active_thread()->shadow$ = shadow; return P( sem, lock ); }
-bool V( semaphore & sem );
+thread$ * V( semaphore & sem, const bool doUnpark = true );
+static inline bool V( semaphore & sem ) with( sem ) { return V( sem, true ) != 0p; }
 bool V( semaphore & sem, size_t count );
 static inline uintptr_t front( semaphore & sem ) with( sem ) { // return shadow information for first waiting thread
