[libdispatch-dev] [PATCH 09/17] portability

Kevin Van Vechten kvv at apple.com
Fri Oct 30 11:14:47 PDT 2009


On Oct 28, 2009, at 11:03 AM, Joakim Johansson wrote:

> I agree, it would be a good change for robustness, on Solaris 10 it is not a scalar even - I had the following code in my local porting tree while still figuring things out for later revisiting:
> 
> -------------
> 
> static void
> _dispatch_posix_semaphore_create(sem_t *s4)
> {
> 	int ret;
> 
> /*
>   Commented this out for Solaris port, as sem_t is a structure on solaris and not a scalar.
>   This check seems unclear semantically, as it assumes that sem_t is of a certain type.
> 
>   if (*s4) {
> 		return;
> 	}
> */
> 	ret = sem_init(s4, 0, 0);
> 	dispatch_assume_zero(ret);
> }

While reviewing the semaphore implementation I noticed that _dispatch_posix_semaphore_create is not mirroring _dispatch_sempahore_create_port's semantics.

A dispatch semaphore starts life as an integer value that is incremented or decremented.  The more heavy-weight OS semaphore is allocated lazily only if a thread needs to block (or another thread believes that a thread is blocked on the semaphore and needs to be signaled).  The _dispatch_semaphore_create_port function allocates a new OS semaphore and then performs a dispatch_atomic_cmpxchg to initialize the field in the dispatch_semaphore_t.  If it loses the race (because another thread had already allocated an OS semaphore for the same dispatch_semaphore_t) then the create function destroys its speculative OS semaphore before returning and leaves the dispatch_semaphore_t unchanged.

// abridged _dispatch_semaphore_create_port and _dispatch_posix_semaphore_create

> #if HAVE_MACH
> static void
> _dispatch_semaphore_create_port(semaphore_t *s4) {
> 	if (*s4) return;
> 
> 	tmp = semaphore_create();
> 	if (!dispatch_atomic_cmpxchg(s4, 0, tmp)) {
> 		semaphore_destroy(tmp);
> 	}
> }
> #else /* !HAVE_MACH */
> static void
> _dispatch_posix_semaphore_create(sem_t *s4)
> {
> 	if (*s4) return;
> 	ret = sem_init(s4, 0, 0); // XXX race condition for assignment to s4
> }
> #endif /* HAVE_MACH */

Based on the above discussion it seems like we may need to make dispatch_semaphore_t be a thinner wrapper around OS semaphores on platforms where the semaphore's handle cannot be atomically exchanged — i.e. we may need to forgo the optimization of lazily allocating the OS semaphore.

Kevin


More information about the libdispatch-dev mailing list