Читаем Programming with POSIX® Threads полностью

32-35 Notice the code to check for EINTR return status from the sem_wait call. The POSIX timer signal in this program will always occur while one or more threads are blocked in sem_wait. When a signal occurs for a process (such as a timer signal), the system may deliver that signal within the context of any thread within the process. Likely "victims" include threads that the kernel knows to be waiting, for example, on a semaphore. So there is a fairly good chance that the sem_wait thread will be chosen, at least sometimes. If that occurs, the call to sem_wait will return with EINTR. The thread must then retry the call. Treating an EINTR return as "success" would make it appear that two threads had been awakened by each call to sem_post: the thread that was interrupted, and the thread that was awakened by the sem_post call.

■ semaphore_signal.c

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include "errors.h"

8

9 sem_t semaphore;

10

11 /*

12 * Signal-catching function.

13 */

14 void signal_catcher (int sig)

15 {

16  if (sem_post (&semaphore) == -1)

17  errno_abort ("Post semaphore");

18 }

19

20 /*

21 * Thread start routine which waits on the semaphore.

22 */

23 void *sem_waiter (void *arg)

24 {

25 int number = (int)arg;

26 int counter;

27

28 /*

29 * Each thread waits 5 times.

30 */

31 for (counter = 1; counter <= 5; counter++) {

32 while (sem_wait (&semaphore) == -1) {

33  if (errno != EINTR)

34  errno_abort ("Wait on semaphore");

35 }

36 printf ("%d waking (%d)...\n", number, counter);

37 }

38 return NULL;

39 }

40

41 int main (int argc, char *argv[])

42 {

43 int thread_count, status;

44 struct sigevent sig_event;

45 struct sigaction sig_action;

46 sigset_t sig_mask;

47 timer_t timer_id;

48 struct itimerspec timer_val;

49 pthread_t sem_waiters[5];

50

51 #if !defined(_POSIX_SEMAPHORES) || !defined(_POSIX_TIMERS)

52 #if !defined(_POSIX_SEMAPHORES)

53 printf ("This system does not support POSIX semaphores\n");

54 # endif

55 #if !defined(_POSIX_TIMERS)

56 printf ("This system does not support POSIX timers\n");

57 #endif

58 return -1;

59 #else

60 sem_init (&semaphore, 0, 0);

61

62 /*

63 * Create 5 threads to wait on a semaphore.

64 */

65 for (thread_count = 0; thread_count < 5; thread_count++) {

66  status = pthread_create (

67  &sem_waiters[thread_count], NULL,

68  sem_waiter, (void*)thread_count);

69 if (status != 0)

70  err_abort (status, "Create thread");

71 }

72

73 /*

74 * Set up a repeating timer using signal number SIGRTMIN,

75 * set to occur every 2 seconds.

76 */

77 sig_event.sigev_value.sival_int = 0;

78 sig_event.sigev_signo = SIGRTMIN;

79 sig_event.sigev_notify = SIGEV_SIGNAL;

80 if (timer_create (CLOCK_REALTIME, &sig_event, &timer_id) == -1)

81  errno_abort ("Create timer");

82 sigemptyset (&sig_mask);

83 sigaddset (&sig_mask, SIGRTMIN);

84 sig_action.sa_handler = signal_catcher;

85 sig_action.sa_mask = sig mask;

86 sig_action.sa_flags = 0;

87 if (sigaction (SIGRTMIN, &sig_action, NULL) == -1)

Перейти на страницу:

Похожие книги

C++: базовый курс
C++: базовый курс

В этой книге описаны все основные средства языка С++ - от элементарных понятий до супервозможностей. После рассмотрения основ программирования на C++ (переменных, операторов, инструкций управления, функций, классов и объектов) читатель освоит такие более сложные средства языка, как механизм обработки исключительных ситуаций (исключений), шаблоны, пространства имен, динамическая идентификация типов, стандартная библиотека шаблонов (STL), а также познакомится с расширенным набором ключевых слов, используемым в .NET-программировании. Автор справочника - общепризнанный авторитет в области программирования на языках C и C++, Java и C# - включил в текст своей книги и советы программистам, которые позволят повысить эффективность их работы. Книга рассчитана на широкий круг читателей, желающих изучить язык программирования С++.

Герберт Шилдт

Программирование, программы, базы данных