Ticket #10977: 10977.cpp

File 10977.cpp, 2.1 KB (added by bonefish, 10 years ago)

Test program to reproduce the issue

Line 
1#include <errno.h>
2#include <pthread.h>
3#include <stdarg.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <sys/wait.h>
8#include <time.h>
9#include <unistd.h>
10
11
12static pthread_mutex_t sMutex = PTHREAD_MUTEX_INITIALIZER;
13static volatile int* sSync;
14
15
16static void
17require_errno(bool condition, const char* message,...)
18{
19 if (condition)
20 return;
21
22 va_list args;
23 va_start(args, message);
24 vfprintf(stderr, message, args);
25 va_end(args);
26
27 fprintf(stderr, ": %s\n", strerror(errno));
28 exit(1);
29}
30
31
32static void
33require_no_error(int error, const char* message,...)
34{
35 if (error >= 0)
36 return;
37
38 va_list args;
39 va_start(args, message);
40 vfprintf(stderr, message, args);
41 va_end(args);
42
43 fprintf(stderr, ": %s\n", strerror(error));
44 exit(1);
45}
46
47
48static void
49sync_threads(volatile int* syncMe, volatile int* syncOther, int value)
50{
51 bool meFirst = syncMe < syncOther;
52 if (meFirst)
53 *syncMe = value;
54
55 while (*syncOther != value) {
56 }
57
58 if (!meFirst)
59 *syncMe = value;
60}
61
62
63static void*
64locker_thread(void* arg)
65{
66 volatile int* syncMe = (volatile int*)arg;
67 volatile int* syncOther = syncMe == sSync ? sSync + 1 : sSync;
68
69 for (;;) {
70 sync_threads(syncMe, syncOther, 1);
71
72 timespec timeout;
73 require_errno(clock_gettime(CLOCK_REALTIME, &timeout) == 0,
74 "failed to get time");
75 timeout.tv_nsec += 10000;
76 if (timeout.tv_nsec >= 1000000000) {
77 timeout.tv_nsec -= 1000000000;
78 timeout.tv_sec += 1;
79 }
80
81 pthread_mutex_timedlock(&sMutex, &timeout);
82
83 sync_threads(syncMe, syncOther, 2);
84 }
85
86 return NULL;
87}
88
89
90int
91main()
92{
93 sSync = new int[2];
94 sSync[0] = sSync[1] = 0;
95
96 require_no_error(pthread_mutex_lock(&sMutex), "failed to lock mutex");
97
98 // start the threads
99 pthread_t thread;
100 require_no_error(pthread_create(&thread, NULL, &locker_thread,
101 (void*)sSync), "failed to create thread 1");
102 require_no_error(pthread_create(&thread, NULL, &locker_thread,
103 (void*)(sSync + 1)), "failed to create thread 1");
104
105 // wait for the threads to be ready
106 while (sSync[1] != 1) {
107 }
108
109 // fork
110 pid_t pid = fork();
111 require_errno(pid >= 0, "fork() failed");
112 if (pid == 0)
113 usleep(100000);
114 else
115 waitpid(pid, NULL, 0);
116
117 return 0;
118}