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 DEBUG
12 #define SEM_D "D"
13 #else
14 #define SEM_D
15 #endif
16 #ifdef IS_64
17 #define SEM_64 "64"
18 #else
19 #define SEM_64
20 #endif
21 
22 #define SHM_NAME "/tmp/counter" SEM_D SEM_64
23 #define SEM_NAME1 "/tmp/foo.sem" SEM_D SEM_64
24 #define SEM_NAME2 "/tmp/bar.sem" SEM_D SEM_64
25 #define ITERATIONS 1000
26 
27 static PRBool debug_mode = PR_FALSE;
28 static PRIntn iterations = ITERATIONS;
29 static PRSem *sem1, *sem2;
30 
Help(void)31 static void Help(void)
32 {
33     fprintf(stderr, "semapong test program usage:\n");
34     fprintf(stderr, "\t-d           debug mode         (FALSE)\n");
35     fprintf(stderr, "\t-c <count>   loop count         (%d)\n", ITERATIONS);
36     fprintf(stderr, "\t-h           this message\n");
37 }  /* Help */
38 
main(int argc,char ** argv)39 int main(int argc, char **argv)
40 {
41     PRIntn i;
42     PRSharedMemory *shm;
43     PRIntn *counter_addr;
44     PLOptStatus os;
45     PLOptState *opt = PL_CreateOptState(argc, argv, "dc:h");
46 
47     while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) {
48         if (PL_OPT_BAD == os) {
49             continue;
50         }
51         switch (opt->option) {
52             case 'd':  /* debug mode */
53                 debug_mode = PR_TRUE;
54                 break;
55             case 'c':  /* loop count */
56                 iterations = atoi(opt->value);
57                 break;
58             case 'h':
59             default:
60                 Help();
61                 return 2;
62         }
63     }
64     PL_DestroyOptState(opt);
65 
66     shm = PR_OpenSharedMemory(SHM_NAME, sizeof(*counter_addr), 0, 0666);
67     if (NULL == shm) {
68         fprintf(stderr, "PR_OpenSharedMemory failed (%d, %d)\n",
69                 PR_GetError(), PR_GetOSError());
70         exit(1);
71     }
72     sem1 = PR_OpenSemaphore(SEM_NAME1, 0, 0, 0);
73     if (NULL == sem1) {
74         fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n",
75                 PR_GetError(), PR_GetOSError());
76         exit(1);
77     }
78     sem2 = PR_OpenSemaphore(SEM_NAME2, 0, 0, 0);
79     if (NULL == sem2) {
80         fprintf(stderr, "PR_OpenSemaphore failed (%d, %d)\n",
81                 PR_GetError(), PR_GetOSError());
82         exit(1);
83     }
84 
85     counter_addr = PR_AttachSharedMemory(shm, 0);
86     if (NULL == counter_addr) {
87         fprintf(stderr, "PR_AttachSharedMemory failed\n");
88         exit(1);
89     }
90 
91     /*
92      * Process 2 waits on semaphore 2 and posts to semaphore 1.
93      */
94     for (i = 0; i < iterations; i++) {
95         if (PR_WaitSemaphore(sem2) == PR_FAILURE) {
96             fprintf(stderr, "PR_WaitSemaphore failed\n");
97             exit(1);
98         }
99         if (*counter_addr == 2*i+1) {
100             if (debug_mode) {
101                 printf("process 2: counter = %d\n", *counter_addr);
102             }
103         } else {
104             fprintf(stderr, "process 2: counter should be %d but is %d\n",
105                     2*i+1, *counter_addr);
106             exit(1);
107         }
108         (*counter_addr)++;
109         if (PR_PostSemaphore(sem1) == PR_FAILURE) {
110             fprintf(stderr, "PR_PostSemaphore failed\n");
111             exit(1);
112         }
113     }
114     if (PR_DetachSharedMemory(shm, counter_addr) == PR_FAILURE) {
115         fprintf(stderr, "PR_DetachSharedMemory failed\n");
116         exit(1);
117     }
118     if (PR_CloseSharedMemory(shm) == PR_FAILURE) {
119         fprintf(stderr, "PR_CloseSharedMemory failed\n");
120         exit(1);
121     }
122     if (PR_CloseSemaphore(sem1) == PR_FAILURE) {
123         fprintf(stderr, "PR_CloseSemaphore failed\n");
124     }
125     if (PR_CloseSemaphore(sem2) == PR_FAILURE) {
126         fprintf(stderr, "PR_CloseSemaphore failed\n");
127     }
128     printf("PASS\n");
129     return 0;
130 }
131