sem.c (5386B)
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 /*********************************************************************** 7 ** 8 ** Name: sem.c 9 ** 10 ** Description: Tests Semaphonre functions. 11 ** 12 ** Modification History: 13 ** 20-May-97 AGarcia- Converted the test to accomodate the debug_mode flag. 14 ** The debug mode will print all of the printfs associated with this 15 *test. 16 ** The regress mode will be the default mode. Since the regress tool 17 *limits 18 ** the output to a one line status:PASS or FAIL,all of the printf 19 *statements 20 ** have been handled with an if (debug_mode) statement. 21 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been 22 *updated to 23 ** recognize the return code from tha main program. 24 ***********************************************************************/ 25 26 /*********************************************************************** 27 ** Includes 28 ***********************************************************************/ 29 /* Used to get the command line option */ 30 #include "plgetopt.h" 31 32 #include "nspr.h" 33 #include "prpriv.h" 34 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 39 PRIntn failed_already = 0; 40 PRIntn debug_mode; 41 42 /* 43 Since we don't have stdin, stdout everywhere, we will fake 44 it with our in-memory buffers called stdin and stdout. 45 */ 46 47 #define SBSIZE 1024 48 49 #include "obsolete/prsem.h" 50 51 static char stdinBuf[SBSIZE]; 52 static char stdoutBuf[SBSIZE]; 53 54 static PRUintn stdinBufIdx = 0; 55 static PRUintn stdoutBufIdx = 0; 56 static PRStatus finalResult = PR_SUCCESS; 57 58 static size_t dread(PRUintn device, char* buf, size_t bufSize) { 59 PRUintn i; 60 61 /* during first read call, initialize the stdinBuf buffer*/ 62 if (stdinBufIdx == 0) { 63 for (i = 0; i < SBSIZE; i++) { 64 stdinBuf[i] = i; 65 } 66 } 67 68 /* now copy data from stdinBuf to the given buffer upto bufSize */ 69 for (i = 0; i < bufSize; i++) { 70 if (stdinBufIdx == SBSIZE) { 71 break; 72 } 73 buf[i] = stdinBuf[stdinBufIdx++]; 74 } 75 76 return i; 77 } 78 79 static size_t dwrite(PRUintn device, char* buf, size_t bufSize) { 80 PRUintn i, j; 81 82 /* copy data from the given buffer upto bufSize to stdoutBuf */ 83 for (i = 0; i < bufSize; i++) { 84 if (stdoutBufIdx == SBSIZE) { 85 break; 86 } 87 stdoutBuf[stdoutBufIdx++] = buf[i]; 88 } 89 90 /* during last write call, compare the two buffers */ 91 if (stdoutBufIdx == SBSIZE) 92 for (j = 0; j < SBSIZE; j++) 93 if (stdinBuf[j] != stdoutBuf[j]) { 94 if (debug_mode) { 95 printf("data mismatch for index= %d \n", j); 96 } 97 finalResult = PR_FAILURE; 98 } 99 100 return i; 101 } 102 103 /*------------------ Following is the real test program ---------*/ 104 /* 105 Program to copy standard input to standard output. The program 106 uses two threads. One reads the input and puts the data in a 107 double buffer. The other reads the buffer contents and writes 108 it to standard output. 109 */ 110 111 PRSemaphore* emptyBufs; /* number of empty buffers */ 112 PRSemaphore* fullBufs; /* number of buffers that are full */ 113 114 #define BSIZE 100 115 116 struct { 117 char data[BSIZE]; 118 PRUintn nbytes; /* number of bytes in this buffer */ 119 } buf[2]; 120 121 static void PR_CALLBACK reader(void* arg) { 122 PRUintn i = 0; 123 size_t nbytes; 124 125 do { 126 (void)PR_WaitSem(emptyBufs); 127 nbytes = dread(0, buf[i].data, BSIZE); 128 buf[i].nbytes = nbytes; 129 PR_PostSem(fullBufs); 130 i = (i + 1) % 2; 131 } while (nbytes > 0); 132 } 133 134 static void writer(void) { 135 PRUintn i = 0; 136 size_t nbytes; 137 138 do { 139 (void)PR_WaitSem(fullBufs); 140 nbytes = buf[i].nbytes; 141 if (nbytes > 0) { 142 nbytes = dwrite(1, buf[i].data, nbytes); 143 PR_PostSem(emptyBufs); 144 i = (i + 1) % 2; 145 } 146 } while (nbytes > 0); 147 } 148 149 int main(int argc, char** argv) { 150 PRThread* r; 151 152 PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); 153 154 { 155 /* The command line argument: -d is used to determine if the test is being 156 run in debug mode. The regress tool requires only one line output:PASS or 157 FAIL. All of the printfs associated with this test has been handled with a 158 if (debug_mode) test. Usage: test_name -d 159 */ 160 PLOptStatus os; 161 PLOptState* opt = PL_CreateOptState(argc, argv, "d:"); 162 while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) { 163 if (PL_OPT_BAD == os) { 164 continue; 165 } 166 switch (opt->option) { 167 case 'd': /* debug mode */ 168 debug_mode = 1; 169 break; 170 default: 171 break; 172 } 173 } 174 PL_DestroyOptState(opt); 175 } 176 177 /* main test */ 178 179 emptyBufs = PR_NewSem(2); /* two empty buffers */ 180 181 fullBufs = PR_NewSem(0); /* zero full buffers */ 182 183 /* create the reader thread */ 184 185 r = PR_CreateThread(PR_USER_THREAD, reader, 0, PR_PRIORITY_NORMAL, 186 PR_LOCAL_THREAD, PR_UNJOINABLE_THREAD, 0); 187 188 /* Do the writer operation in this thread */ 189 writer(); 190 191 PR_DestroySem(emptyBufs); 192 PR_DestroySem(fullBufs); 193 194 if (finalResult == PR_SUCCESS) { 195 if (debug_mode) { 196 printf("sem Test Passed.\n"); 197 } 198 } else { 199 if (debug_mode) { 200 printf("sem Test Failed.\n"); 201 } 202 failed_already = 1; 203 } 204 PR_Cleanup(); 205 if (failed_already) { 206 return 1; 207 } else { 208 return 0; 209 } 210 }