TOC PREV NEXT INDEX

POSIX 1.b Migration Guide

0

Semaphores

Introduction

Most of the old functionality of semaphores has an equivalent under the new standard. The most important change is that Draft 9 provides binary semaphores, whereas POSIX.1b provides counting semaphores. Also, Draft 9 provides only named semaphores, whereas POSIX.1b provides named as well as unnamed semaphores. Two new functions, sem_init() and sem_destroy(), were introduced for unnamed semaphores.

Draft 9 semaphores were special files and relied on the underlying file system. POSIX.1b semaphores are independent of the file system. Names for POSIX.1b named semaphores are implemented as simple strings without file system involvement. These strings are processed with a new, efficient name service. This difference between Draft 9 and POSIX.1b may be experienced in other ways. For example, the ls and rm utilities could access the Draft 9 semaphores. This cannot be done for POSIX.1b named semaphores.

LynxOS provides two new utilities, lipcs and lipcrm, to list and remove named IPC objects - semaphores, shared memory objects, and message queues. Refer to the lipcs and lipcrm man pages for more information.

Also, there are persistence-related differences between the Draft 9 and POSIX.1b semaphores. Draft 9 provides persistent and non-persistent semaphores. Persistent semaphores were requested explicitly with the SEM_PERSIST flag. POSIX.1b, on the other hand, only provides persistent semaphores.

Persistence of an object implies that the object and its state (e.g., value of a semaphore, data in a message queue, data for a shared memory object) are preserved once the object is no longer referenced by a process. If the user absolutely needs to migrate non-persistent behavior from Draft 9 to POSIX.1b, here is an alternative method: After all the processes that wish to use a non-persistent semaphore have opened the semaphore, sem_unlink the semaphore. The semaphore is deleted when all references to it are removed, simulating a non-persistent semaphore.

Unnamed Semaphores

The following example illustrates the use of POSIX.1b unnamed semaphores. Notice that for two processes to use an unnamed semaphore, it must reside in shared memory.

#include <sys/mman.h>
#include <semaphore.h>

main()
{
struct shared_info *sp;
:
fd = shm_open(shmname, oflags, mode);
:
sp = mmap(0, SHMSIZE, PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0);
close(fd);
shm_unlink(shmname);
:
sem_init(&sp->sem, TRUE, 0);
:
pid = fork();

if (pid) {
/* Parent */
:
sem_post(&sp->sem);
:
}
else {
/* Child */
:
sem_wait(&sp->sem);
:
}
}

Creating a Named Semaphore

Named semaphores for POSIX.1b are created using the function sem_open() with the O_CREAT flag, instead of the mksem() function from Draft 9.

The following example compares the creation of a named semaphore. Note the use of the SEM_PERSIST flag in Draft 9 code to request creation of a persistent semaphore. For POSIX.1b, no special flag is necessary, because POSIX.1b only provides persistent semaphores.

Draft 9 Code

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sem.h>

main()
{
int sem;
:
mksem("semaphore", SEM_PERSIST | 0666,
STATE_LOCKED);
sem = open("semaphore", O_RDWR, SEM_PERSIST | 0666);
:
close(sem);
unlink("semaphore");
:
}

Equivalent POSIX.1b Code

#include <semaphore.h>

main()
{
sem_t *sem;
:
sem = sem_open("semaphore", O_CREAT, 0666, 0);
:
sem_close(sem);
sem_unlink("semaphore");
:
}

Posting and Waiting on Semaphores

Refer to "Changes from Draft 9 to POSIX.1b" later in this chapter, for equivalence of function names to post to and wait on semaphores. The following example compares Draft 9 and POSIX.1b for this functionality.

Draft 9 Code

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sem.h>

main()
{
int sem;
:
mksem("semaphore",.....);
sem = open("semaphore",....);
:
/* this could also be semwait() */
semifwait(sem);
:
sempost(sem);
:
}

Equivalent POSIX.1b Code

#include <semaphore.h>

main()
{
sem_t *sem;
:
sem = sem_open("semaphore",.....);
:
/* this could also be sem_wait() */
sem_trywait(sem);
:
sem_post(sem);
:
}

Conditional Posting to Semaphores

The Draft 9 facility for conditional posting to a semaphore with the semifpost() function (only if a process is waiting for it), was removed. However, POSIX.1b offers a new function, sem_getvalue(), to allow the user to obtain the value of a semaphore at any time.

If the semaphore is locked, sem_getvalue() returns a zero or a negative number. The absolute value of this number indicates the number of processes waiting for the semaphore. This value is sampled at an unspecified time inside the sem_getvalue() call. The following example illustrates the use of sem_getvalue() and sem_post() to simulate the effect of semifpost() from Draft 9. As explained below, the equivalence in this example does not
always hold.

Draft 9 Code

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/sem.h>

main()
{
int sem;
:
mksem("semaphore",.....);
sem = open("semaphore",....);
:
semifpost(sem);
:
}

Equivalent POSIX.1b Code

#include <semaphore.h>

main()
{
sem_t *sem;
int value;
:
sem = sem_open("semaphore",......);
:
sem_getvalue(sem, &value);
if (value < 0)
sem_post(sem);
:
}

The semifpost() function from Draft 9 has an inherent race condition. If a process is about to sleep on the semaphore, semifpost() would never wake that process up. Therefore, programs that use semifpost() have a race condition upon wake-up. (For more details on why sem_ifpost() has been removed from POSIX.1b, refer to the rationales of the POSIX.1b standard.)

Also note that sem_getvalue() samples the value of the semaphore, and (because there is no locking built into semaphores) does not give a reliable value for heavily-used semaphores. POSIX.1b semaphores are not POSIX.1c
condition variables.

Changes from Draft 9 to POSIX.1b

Semaphores changed, although not in a major way. The most important change is that Draft 9 provides binary semaphores, while POSIX.1b provides counting semaphores. Also, Draft 9 provides only named semaphores and they are special files. POSIX.1b provides named and unnamed semaphores; the interface is independent of any file system.

Semaphore Interface  
Draft 9
POSIX.1b
Binary semaphores
Counting semaphores
Semaphores = Special files
Independent of file system
Only named semaphores
Named and unnamed semaphores
Persistent as well as non-persistent semaphores with the flag SEM_PERSIST
Persistent semaphores
<sys/sem.h>
<semaphore.h>
No Equivalent
sem_init()
Initializes unnamed semaphore
No Equivalent
sem_destroy()
Destroys unnamed semaphore
mksem()
Done by sem_open()
open()
sem_open()
close()
sem_close()
unlink()
sem_unlink()
semwait()
sem_wait()
semifwait()
sem_trywait()
sempost()
sem_post()
semifpost()
No Equivalent
No Equivalent
sem_getvalue()
Get semaphore value

Conditional Posting

Draft 9 provides a semifpost() function to do a conditional post to a semaphore if a process is waiting for it. This functionality is discontinued in POSIX.1b. It can be simulated with a combination of sem_getvalue() and sem_post(), but is not an atomic operation.

Permission Checking

Since Draft 9 semaphores are special files, there is the overhead of complete file permission checking. In POSIX.1b, this is replaced by an efficient name service for the named semaphores. The new service does not need to do directory traversals or complicated permission checking. User ID and standard POSIX.1 permission checking is performed on a per-object-name basis.

New Utilities

LynxOS provides two new utilities, lipcs and lipcrm, to respectively list and remove named semaphores. Refer to the lipcs and lipcrm man pages for more information.

Interoperability

There is no semaphore interoperability between Draft 9 and POSIX.1b.



LynuxWorks, Inc.
855 Branham Lane East
San Jose, CA 95138
http://www.lynuxworks.com
1.800.255.5969
TOC PREV NEXT INDEX