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