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