Листинг 10.37. Функция sem_open: первая часть
//my_pxsem_svsem/sem_open. с
1 #include "unpipc.h"
2 #include "semaphore.h"
3 #include
4 #define MAX_TRIES 10 /* количество попыток инициализации */
5 mysem_t *
6 mysem_open(const char *pathname, int oflag, … )
7 {
8 int i, fd, semflag, semid, save_errno;
9 key_t key;
10 mode_t mode;
11 va_list ap;
12 mysem_t *sem;
13 union semun arg;
14 unsigned int value;
15 struct semid_ds seminfo;
16 struct sembuf initop;
17 /* режим доступа для sem_open() без O_CREAT не указывается; угадываем */
18 semflag = SVSEM_MODE;
19 semid = –1;
20 if (oflag & O_CREAT) {
21 va_start(ap, oflag); /* инициализируем ар последним явно указанным аргументом */
22 mode = va_arg(ap, va_mode_t);
23 value = va_arg(ap, unsigned int);
24 va_end(ap);
25 /* преобразуем в ключ, который будет идентифицировать семафор System V */
26 if ((fd = open(pathname, oflag, mode)) == –1)
27 return(SEM_FAILED);
28 close(fd);
29 if ((key = ftok(pathname, 0)) == (key_t) –1)
30 return(SEM_FAILED);
31 semflag = IPC_CREAT | (mode & 0777);
32 if (oflag & O_EXCL)
33 semflag |= IPC_EXCL;
34 /* создаем семафор System V с флагом IPC_EXCL */
35 if ((semid = semget(key, 1, semflag | IPC_EXCD) >= 0) {
36 /* OK, мы успели первыми, поэтому инициализируем нулем */
37 arg.val = 0;
38 if (semctl(semid, 0, SETVAL, arg) == –1)
39 goto err;
40 /* увеличиваем значение, чтобы sem_otime стало ненулевым */
41 if (value > SEMVMX) {
42 errno = EINVAL;
43 goto err;
44 }
45 initop.sem_num = 0;
46 initop.sem_op = value;
47 initop.sem_flg = 0;
48 if (semop(semid, &initop, 1) == –1)
49 goto err;
50 goto finish;
51 } else if (errno != EEXIST || (semflag & IPC_EXCL) != 0)
52 goto err:
53 /* иначе продолжаем выполнение */
54 }