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