листинге 10.32 приведен текст функции sem_post, которая увеличивает значение семафора, возобновляя выполнение всех процессов, заблокированных в ожидании этого события.
Листинг 10.32. Функция sem_post
//my_pxsem_mmap/sem_post.с
1 #include "unpipc.h"
2 #include "semaphore.h"
3 int
4 mysem_post(mysem_t *sem)
5 {
6 int n;
7 if (sem->sem_magic != SEM_MAGIC) {
8 errno = EINVAL;
9 return(-1);
10 }
11 if ((n = pthread_mutex_lock(&sem->sem_mutex)) != 0) {
12 errno = n;
13 return(-1);
14 }
15 if (sem->sem_count == 0)
16 pthread_cond_signal(&sem->sem_cond);
17 sem->sem_count++;
18 pthread_mutex_unlock(&sem->sem_mutex);
19 return(0);
20 }
11-18 Прежде чем работать со структурой, нужно заблокировать соответствующее взаимное исключение. Если значение семафора изменяется с 0 на 1, нужно вызвать pthread_cond_signal, чтобы возобновилось выполнение одного из процессов, зарегистрированных на уведомление по данной условной переменной.
Функция sem_wait
В листинге 10.33 приведен текст функции sem_wait, которая ожидает изменения значения семафора с 0 на положительное, после чего уменьшает его на 1.
Листинг 10.33. Функция sem_wait
//my_pxsem_mmap/sem_wait.с
1 #include "unpipc.h"
2 #include "semaphore.h"
3 int
4 mysem_wait(mysem_t *sem)
5 {
6 int n;
7 if (setn->sem_magic != SEM_MAGIC) {
8 errno = EINVAL;
9 return(-1);
10 }
11 if ((n = pthread_mutex_lock(&sem->sem_mutex)) != 0) {
Прежде чем работать с семафором, нужно заблокировать соответствующее взаимное исключение. Если значение семафора 0, выполнение процесса приостанавливается в вызове pthread_cond_wait до тех пор, пока другой процесс не вызовет pthread_cond_signal для этого семафора, изменив его значение с 0 на 1. После того как значение становится ненулевым, мы уменьшаем его на 1 и разблокируем взаимное исключение.
Функция sem_trywait
В листинге 10.34 приведен текст функции sem_trywait, которая представляет собой просто неблокируемый вариант функции sem_wait.
11-22 Мы блокируем взаимное исключение и проверяем значение семафора. Если оно положительно, мы вычитаем из него 1 и возвращаем вызвавшему процессу код 0. В противном случае возвращается –1, а переменной errno присваивается код ошибки EAGAIN.
Листинг 10.34. Функция sem_trywait
//my_pxsem_nmap/sem_trywait.с
1 #include "unpipc.h"
2 #include "semaphore.h"
3 int
4 mysem_trywait(mysem_t *sem)
5 {
6 int n, rc;
7 if (sem->sem_magic != SEM_MAGIC) {
8 errno = EINVAL;
9 return(-1);
10 }
11 if ((n = pthread_mutex_lock(&sem->sem_mutex)) != 0) {
12 errno = n;
13 return(-1);
14 }
15 if (sem->sem_count > 0) {
16 sem->sem_count--;
17 rc = 0;
18 } else {
19 rc = –1;
20 errno = EAGAIN;
21 }
22 pthread_mutex_unlock(&sem->sem_mutex);
23 return(rc);
24 }
Функция sem_getvalue
В листинге 10.35 приведен текст последней функции в этой реализации — sem_getvalue. Она возвращает текущее значение семафора.
11-16 Мы блокируем соответствующее взаимное исключение и считываем значение семафора.