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  */
ThreadFunc(void * arg)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 
Help(void)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 
main(int argc,char ** argv)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 }
149