11 #define SEM_FAILED ((mysem_t *)(-1)) /* чтобы избежать предупреждений компилятора */
12 #endif
Функция sem_open
В листинге 10.28 приведен текст первой части функции sem_open, которая может использоваться для создания нового семафора или открытия существующего.
//my_pxsem_mmap/sem_open.с
1 #include "unpipc.h"
2 #include "semaphore.h"
3 #include stdarg.h /* для списков аргументов переменной длины */
4 #define MAX_TRIES 10 /* количество попыток инициализации */
5 mysem_t *
6 mysem_open(const char *pathname, int oflag, …)
7 {
8 int fd, i, created, save_errno;
9 mode_t mode;
10 va_list ap;
11 mysem_t *sem, seminit;
12 struct stat statbuff;
13 unsigned int value;
14 pthread_mutexattr_t mattr;
15 pthread_condattr_t cattr;
16 created = 0;
17 sem = MAP_FAILED; /* [sic] */
18 again:
19 if (oflag O_CREAT) {
20 va_start(ap, oflag); /* ар инициализируется последним явно указанным аргументом */
21 mode = va_arg(ap, va_mode_t) ~S_IXUSR;
22 value = va_arg(ap, unsigned int);
23 va_end(ap);
24 /* открываем с указанием флага O_EXCL и установкой бита user-execute */
25 fd = open(pathname, oflag | O_EXCL | O_RDWR, mode | S_IXUSR);
26 if (fd 0) {
27 if (errno == EEXIST (oflag O_EXCL) == 0)
28 goto exists; /* уже существует. OK */
29 else
30 return(SEM_FAILED);
31 }
32 created = 1;
33 /* кто создает файл, тот его и инициализирует */
34 /* установка размера файла */
35 bzero(seminit, sizeof(seminit));
36 if (write(fd, seminit, sizeof(seminit)) != sizeof(seminit))
37 goto err;
38 /* отображение файла в память */
39 sem = mmap(NULL, sizeof(mysem_t), PROT_READ | PROT_WRITE,
40 MAP_SHARED, fd, 0);
41 if (sem == MAP_FAILED)
42 goto err;
43 /* инициализация взаимного исключения, условной переменной, значения семафора */
44 if ((i = pthread_mutexattr_init(mattr)) != 0)
45 goto pthreaderr;
46 pthread_mutexattr_setpshared(mattr, PTHREAD_PROCESS_SHARED);
47 i = pthread_mutex_init(sem-sem_mutex, mattr);
48 pthread_mutexattr_destroy(mattr); /* не забыть удалить */
49 if (i != 0)
50 goto pthreaderr;
51 if ((i = pthread_condattr_init(cattr)) != 0)
52 goto pthreaderr;
53 pthread_condattr_setpshared(cattr, PTHREAD_PROCESS_SHARED);
54 i = pthread_cond_init(sem-sem_cond, cattr);
55 pthread_condattr_destroy(cattr); /* не забыть удалить */
56 if (i != 0)
57 goto pthreaderr;
58 if ((sem-sem_count = value) sysconf(_SC_SEM_VALUE_MAX)) {
59 errno = EINVAL;
60 goto err;
61 }
62 /* инициализация завершена, снимаем бит user-execute */
63 if (fchmod(fd, mode) == –1)
64 goto err;