System V Semaphores 975
if (argc < 3 || strcmp(argv[1], "--help") == 0)
usageErr("%s semid val...\n", argv[0]);
semid = getInt(argv[1], 0, "semid");
/* Obtain size of semaphore set */
arg.buf = &ds;
if (semctl(semid, 0, IPC_STAT, arg) == -1)
errExit("semctl");
if (ds.sem_nsems != argc - 2)
cmdLineErr("Set contains %ld semaphores, but %d values were supplied\n",
(long) ds.sem_nsems, argc - 2);
/* Set up array of values; perform semaphore initialization */
arg.array = calloc(ds.sem_nsems, sizeof(arg.array[0]));
if (arg.array == NULL)
errExit("calloc");
for (j = 2; j < argc; j++)
arg.array[j - 2] = getInt(argv[j], 0, "val");
if (semctl(semid, 0, SETALL, arg) == -1)
errExit("semctl-SETALL");
printf("Semaphore values changed (PID=%ld)\n", (long) getpid());
exit(EXIT_SUCCESS);
}
––––––––––––––––––––––––––––––––––––––––––––––––––––– svsem/svsem_setall.c
47.5 Semaphore Initialization
According to SUSv3, an implementation is not required to initialize the values of
the semaphores in a set created by semget(). Instead, the programmer must explicitly
initialize the semaphores using the semctl() system call. (On Linux, the semaphores
returned by semget() are in fact initialized to 0, but we can’t portably rely on this.) As
stated earlier, the fact that semaphore creation and initialization must be per-
formed by separate system calls, instead of in a single atomic step, leads to possible
race conditions when initializing a semaphore. In this section, we detail the nature
of the race and look at a method of avoiding it based on an idea described in
[Stevens, 1999].
Suppose that we have an application consisting of multiple peer processes
employing a semaphore to coordinate their actions. Since no single process is guar-
anteed to be the first to use the semaphore (this is what is meant by the term peer),
each process must be prepared to create and initialize the semaphore if it doesn’t
already exist. For this purpose, we might consider employing the code shown in
Listing 47-5.