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 #ifdef SYMBIAN
12 #define SHM_NAME "c:\\data\\counter"
13 #define SEM_NAME1 "c:\\data\\foo.sem"
14 #define SEM_NAME2 "c:\\data\\bar.sem"
15 #define EXE_NAME "nspr_tests_semapong.exe"
16 #else
17 #define SHM_NAME "/tmp/counter"
18 #define SEM_NAME1 "/tmp/foo.sem"
19 #define SEM_NAME2 "/tmp/bar.sem"
20 #define EXE_NAME "semapong"
21 #endif
22 #define SEM_MODE 0666
23 #define SHM_MODE 0666
24 #define ITERATIONS 1000
25
26 static PRBool debug_mode = PR_FALSE;
27 static PRIntn iterations = ITERATIONS;
28 static PRSem *sem1, *sem2;
29
Help(void)30 static void Help(void)
31 {
32 fprintf(stderr, "semaping test program usage:\n");
33 fprintf(stderr, "\t-d debug mode (FALSE)\n");
34 fprintf(stderr, "\t-c <count> loop count (%d)\n", ITERATIONS);
35 fprintf(stderr, "\t-h this message\n");
36 } /* Help */
37
main(int argc,char ** argv)38 int main(int argc, char **argv)
39 {
40 PRProcess *proc;
41 PRIntn i;
42 char *child_argv[32];
43 char **child_arg;
44 char iterations_buf[32];
45 PRSharedMemory *shm;
46 PRIntn *counter_addr;
47 PRInt32 exit_code;
48 PLOptStatus os;
49 PLOptState *opt = PL_CreateOptState(argc, argv, "dc:h");
50
51 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
52 if (PL_OPT_BAD == os) continue;
53 switch (opt->option) {
54 case 'd': /* debug mode */
55 debug_mode = PR_TRUE;
56 break;
57 case 'c': /* loop count */
58 iterations = atoi(opt->value);
59 break;
60 case 'h':
61 default:
62 Help();
63 return 2;
64 }
65 }
66 PL_DestroyOptState(opt);
67
68 if (PR_DeleteSharedMemory(SHM_NAME) == PR_SUCCESS) {
69 fprintf(stderr, "warning: removed shared memory %s left over "
70 "from previous run\n", SHM_NAME);
71 }
72 if (PR_DeleteSemaphore(SEM_NAME1) == PR_SUCCESS) {
73 fprintf(stderr, "warning: removed semaphore %s left over "
74 "from previous run\n", SEM_NAME1);
75 }
76 if (PR_DeleteSemaphore(SEM_NAME2) == PR_SUCCESS) {
77 fprintf(stderr, "warning: removed semaphore %s left over "
78 "from previous run\n", SEM_NAME2);
79 }
80
81 shm = PR_OpenSharedMemory(SHM_NAME, sizeof(*counter_addr), PR_SHM_CREATE, SHM_MODE);
82 if (NULL == shm) {
83 fprintf(stderr, "PR_OpenSharedMemory failed (%d, %d)\n",
84 PR_GetError(), PR_GetOSError());
85 exit(1);
86 }
87 counter_addr = PR_AttachSharedMemory(shm, 0);
88 if (NULL == counter_addr) {
89 fprintf(stderr, "PR_AttachSharedMemory failed\n");
90 exit(1);
91 }
92 *counter_addr = 0;
93 sem1 = PR_OpenSemaphore(SEM_NAME1, PR_SEM_CREATE, SEM_MODE, 1);
94 if (NULL == sem1) {
95 fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n",
96 PR_GetError(), PR_GetOSError());
97 exit(1);
98 }
99 sem2 = PR_OpenSemaphore(SEM_NAME2, PR_SEM_CREATE, SEM_MODE, 0);
100 if (NULL == sem2) {
101 fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n",
102 PR_GetError(), PR_GetOSError());
103 exit(1);
104 }
105
106 child_arg = &child_argv[0];
107 *child_arg++ = EXE_NAME;
108 if (debug_mode != PR_FALSE) {
109 *child_arg++ = "-d";
110 }
111 if (iterations != ITERATIONS) {
112 *child_arg++ = "-c";
113 PR_snprintf(iterations_buf, sizeof(iterations_buf), "%d", iterations);
114 *child_arg++ = iterations_buf;
115 }
116 *child_arg = NULL;
117 proc = PR_CreateProcess(child_argv[0], child_argv, NULL, NULL);
118 if (NULL == proc) {
119 fprintf(stderr, "PR_CreateProcess failed\n");
120 exit(1);
121 }
122
123 /*
124 * Process 1 waits on semaphore 1 and posts to semaphore 2.
125 */
126 for (i = 0; i < iterations; i++) {
127 if (PR_WaitSemaphore(sem1) == PR_FAILURE) {
128 fprintf(stderr, "PR_WaitSemaphore failed\n");
129 exit(1);
130 }
131 if (*counter_addr == 2*i) {
132 if (debug_mode) printf("process 1: counter = %d\n", *counter_addr);
133 } else {
134 fprintf(stderr, "process 1: counter should be %d but is %d\n",
135 2*i, *counter_addr);
136 exit(1);
137 }
138 (*counter_addr)++;
139 if (PR_PostSemaphore(sem2) == PR_FAILURE) {
140 fprintf(stderr, "PR_PostSemaphore failed\n");
141 exit(1);
142 }
143 }
144 if (PR_DetachSharedMemory(shm, counter_addr) == PR_FAILURE) {
145 fprintf(stderr, "PR_DetachSharedMemory failed\n");
146 exit(1);
147 }
148 if (PR_CloseSharedMemory(shm) == PR_FAILURE) {
149 fprintf(stderr, "PR_CloseSharedMemory failed\n");
150 exit(1);
151 }
152 if (PR_CloseSemaphore(sem1) == PR_FAILURE) {
153 fprintf(stderr, "PR_CloseSemaphore failed\n");
154 }
155 if (PR_CloseSemaphore(sem2) == PR_FAILURE) {
156 fprintf(stderr, "PR_CloseSemaphore failed\n");
157 }
158
159 if (PR_WaitProcess(proc, &exit_code) == PR_FAILURE) {
160 fprintf(stderr, "PR_WaitProcess failed\n");
161 exit(1);
162 }
163 if (exit_code != 0) {
164 fprintf(stderr, "process 2 failed with exit code %d\n", exit_code);
165 exit(1);
166 }
167
168 if (PR_DeleteSharedMemory(SHM_NAME) == PR_FAILURE) {
169 fprintf(stderr, "PR_DeleteSharedMemory failed\n");
170 }
171 if (PR_DeleteSemaphore(SEM_NAME1) == PR_FAILURE) {
172 fprintf(stderr, "PR_DeleteSemaphore failed\n");
173 }
174 if (PR_DeleteSemaphore(SEM_NAME2) == PR_FAILURE) {
175 fprintf(stderr, "PR_DeleteSemaphore failed\n");
176 }
177 printf("PASS\n");
178 return 0;
179 }
180