|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include "nspr.h" |
|
7 #include "plgetopt.h" |
|
8 |
|
9 #include <stdio.h> |
|
10 |
|
11 #define SEM_NAME1 "/tmp/foo.sem" |
|
12 #define SEM_NAME2 "/tmp/bar.sem" |
|
13 #define SEM_MODE 0666 |
|
14 #define ITERATIONS 1000 |
|
15 |
|
16 static PRBool debug_mode = PR_FALSE; |
|
17 static PRIntn iterations = ITERATIONS; |
|
18 static PRIntn counter; |
|
19 static PRSem *sem1, *sem2; |
|
20 |
|
21 /* |
|
22 * Thread 2 waits on semaphore 2 and posts to semaphore 1. |
|
23 */ |
|
24 void ThreadFunc(void *arg) |
|
25 { |
|
26 PRIntn i; |
|
27 |
|
28 for (i = 0; i < iterations; i++) { |
|
29 if (PR_WaitSemaphore(sem2) == PR_FAILURE) { |
|
30 fprintf(stderr, "PR_WaitSemaphore failed\n"); |
|
31 exit(1); |
|
32 } |
|
33 if (counter == 2*i+1) { |
|
34 if (debug_mode) printf("thread 2: counter = %d\n", counter); |
|
35 } else { |
|
36 fprintf(stderr, "thread 2: counter should be %d but is %d\n", |
|
37 2*i+1, counter); |
|
38 exit(1); |
|
39 } |
|
40 counter++; |
|
41 if (PR_PostSemaphore(sem1) == PR_FAILURE) { |
|
42 fprintf(stderr, "PR_PostSemaphore failed\n"); |
|
43 exit(1); |
|
44 } |
|
45 } |
|
46 } |
|
47 |
|
48 static void Help(void) |
|
49 { |
|
50 fprintf(stderr, "sema test program usage:\n"); |
|
51 fprintf(stderr, "\t-d debug mode (FALSE)\n"); |
|
52 fprintf(stderr, "\t-c <count> loop count (%d)\n", ITERATIONS); |
|
53 fprintf(stderr, "\t-h this message\n"); |
|
54 } /* Help */ |
|
55 |
|
56 int main(int argc, char **argv) |
|
57 { |
|
58 PRThread *thred; |
|
59 PRIntn i; |
|
60 PLOptStatus os; |
|
61 PLOptState *opt = PL_CreateOptState(argc, argv, "dc:h"); |
|
62 |
|
63 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { |
|
64 if (PL_OPT_BAD == os) continue; |
|
65 switch (opt->option) { |
|
66 case 'd': /* debug mode */ |
|
67 debug_mode = PR_TRUE; |
|
68 break; |
|
69 case 'c': /* loop count */ |
|
70 iterations = atoi(opt->value); |
|
71 break; |
|
72 case 'h': |
|
73 default: |
|
74 Help(); |
|
75 return 2; |
|
76 } |
|
77 } |
|
78 PL_DestroyOptState(opt); |
|
79 |
|
80 if (PR_DeleteSemaphore(SEM_NAME1) == PR_SUCCESS) { |
|
81 fprintf(stderr, "warning: removed semaphore %s left over " |
|
82 "from previous run\n", SEM_NAME1); |
|
83 } |
|
84 if (PR_DeleteSemaphore(SEM_NAME2) == PR_SUCCESS) { |
|
85 fprintf(stderr, "warning: removed semaphore %s left over " |
|
86 "from previous run\n", SEM_NAME2); |
|
87 } |
|
88 |
|
89 sem1 = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 1); |
|
90 if (NULL == sem1) { |
|
91 fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n", |
|
92 PR_GetError(), PR_GetOSError()); |
|
93 exit(1); |
|
94 } |
|
95 sem2 = PR_OpenSemaphore(SEM_NAME2, PR_SEM_CREATE, SEM_MODE, 0); |
|
96 if (NULL == sem2) { |
|
97 fprintf(stderr, "PR_OpenSemaphore failed\n"); |
|
98 exit(1); |
|
99 } |
|
100 thred = PR_CreateThread(PR_USER_THREAD, ThreadFunc, NULL, |
|
101 PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, PR_JOINABLE_THREAD, 0); |
|
102 if (NULL == thred) { |
|
103 fprintf(stderr, "PR_CreateThread failed\n"); |
|
104 exit(1); |
|
105 } |
|
106 |
|
107 /* |
|
108 * Thread 1 waits on semaphore 1 and posts to semaphore 2. |
|
109 */ |
|
110 for (i = 0; i < iterations; i++) { |
|
111 if (PR_WaitSemaphore(sem1) == PR_FAILURE) { |
|
112 fprintf(stderr, "PR_WaitSemaphore failed\n"); |
|
113 exit(1); |
|
114 } |
|
115 if (counter == 2*i) { |
|
116 if (debug_mode) printf("thread 1: counter = %d\n", counter); |
|
117 } else { |
|
118 fprintf(stderr, "thread 1: counter should be %d but is %d\n", |
|
119 2*i, counter); |
|
120 exit(1); |
|
121 } |
|
122 counter++; |
|
123 if (PR_PostSemaphore(sem2) == PR_FAILURE) { |
|
124 fprintf(stderr, "PR_PostSemaphore failed\n"); |
|
125 exit(1); |
|
126 } |
|
127 } |
|
128 |
|
129 if (PR_JoinThread(thred) == PR_FAILURE) { |
|
130 fprintf(stderr, "PR_JoinThread failed\n"); |
|
131 exit(1); |
|
132 } |
|
133 |
|
134 if (PR_CloseSemaphore(sem1) == PR_FAILURE) { |
|
135 fprintf(stderr, "PR_CloseSemaphore failed\n"); |
|
136 } |
|
137 if (PR_CloseSemaphore(sem2) == PR_FAILURE) { |
|
138 fprintf(stderr, "PR_CloseSemaphore failed\n"); |
|
139 } |
|
140 if (PR_DeleteSemaphore(SEM_NAME1) == PR_FAILURE) { |
|
141 fprintf(stderr, "PR_DeleteSemaphore failed\n"); |
|
142 } |
|
143 if (PR_DeleteSemaphore(SEM_NAME2) == PR_FAILURE) { |
|
144 fprintf(stderr, "PR_DeleteSemaphore failed\n"); |
|
145 } |
|
146 printf("PASS\n"); |
|
147 return 0; |
|
148 } |