Back to index

lightning-sunbird  0.9+nobinonly
sem.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /***********************************************************************
00039 **
00040 ** Name: sem.c
00041 **
00042 ** Description: Tests Semaphonre functions.
00043 **
00044 ** Modification History:
00045 ** 20-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
00046 **              The debug mode will print all of the printfs associated with this test.
00047 **                    The regress mode will be the default mode. Since the regress tool limits
00048 **           the output to a one line status:PASS or FAIL,all of the printf statements
00049 **                    have been handled with an if (debug_mode) statement.
00050 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
00051 **                   recognize the return code from tha main program.
00052 ***********************************************************************/
00053 
00054 /***********************************************************************
00055 ** Includes
00056 ***********************************************************************/
00057 /* Used to get the command line option */
00058 #include "plgetopt.h"
00059 
00060 #include "nspr.h"
00061 #include "prpriv.h"
00062 
00063 #include <stdio.h>
00064 #include <stdlib.h>
00065 #include <string.h>
00066 
00067 PRIntn failed_already=0;
00068 PRIntn debug_mode;
00069 
00070 /* 
00071        Since we don't have stdin, stdout everywhere, we will fake 
00072        it with our in-memory buffers called stdin and stdout.
00073 */
00074 
00075 #define SBSIZE 1024
00076 
00077 #ifdef XP_MAC
00078 #include "prlog.h"
00079 #include "prsem.h"
00080 #define printf PR_LogPrint
00081 extern void SetupMacPrintfLog(char *logFile);
00082 #else
00083 #include "obsolete/prsem.h"
00084 #endif
00085 
00086 static char stdinBuf[SBSIZE];
00087 static char stdoutBuf[SBSIZE];
00088 
00089 static PRUintn stdinBufIdx = 0;
00090 static PRUintn stdoutBufIdx = 0;
00091 static PRStatus finalResult = PR_SUCCESS;
00092 
00093 
00094 static size_t dread (PRUintn device, char *buf, size_t bufSize)
00095 {
00096        PRUintn       i;
00097        
00098        /* during first read call, initialize the stdinBuf buffer*/
00099        if (stdinBufIdx == 0) {
00100               for (i=0; i<SBSIZE; i++)
00101                      stdinBuf[i] = i;
00102        }
00103 
00104        /* now copy data from stdinBuf to the given buffer upto bufSize */
00105        for (i=0; i<bufSize; i++) {
00106               if (stdinBufIdx == SBSIZE)
00107                      break;
00108               buf[i] = stdinBuf[stdinBufIdx++];
00109        }
00110 
00111        return i;
00112 }
00113 
00114 static size_t dwrite (PRUintn device, char *buf, size_t bufSize)
00115 {
00116        PRUintn       i, j;
00117        
00118        /* copy data from the given buffer upto bufSize to stdoutBuf */
00119        for (i=0; i<bufSize; i++) {
00120               if (stdoutBufIdx == SBSIZE)
00121                      break;
00122               stdoutBuf[stdoutBufIdx++] = buf[i];
00123        }
00124 
00125        /* during last write call, compare the two buffers */
00126        if (stdoutBufIdx == SBSIZE)
00127               for (j=0; j<SBSIZE; j++)
00128                      if (stdinBuf[j] != stdoutBuf[j]) {
00129                             if (debug_mode) printf("data mismatch for index= %d \n", j);
00130                             finalResult = PR_FAILURE;
00131                      }
00132 
00133        return i;
00134 }
00135 
00136 /*------------------ Following is the real test program ---------*/
00137 /*
00138        Program to copy standard input to standard output.  The program
00139        uses two threads.  One reads the input and puts the data in a 
00140        double buffer.  The other reads the buffer contents and writes 
00141        it to standard output.
00142 */
00143 
00144 PRSemaphore   *emptyBufs;   /* number of empty buffers */
00145 PRSemaphore *fullBufs;      /* number of buffers that are full */
00146 
00147 #define BSIZE 100
00148 
00149 struct {
00150        char data[BSIZE];
00151        PRUintn nbytes;             /* number of bytes in this buffer */
00152 } buf[2];
00153 
00154 static void PR_CALLBACK reader(void *arg)
00155 {
00156        PRUintn       i = 0;
00157        size_t nbytes;
00158        
00159        do {
00160               (void) PR_WaitSem(emptyBufs);
00161               nbytes = dread(0, buf[i].data, BSIZE);
00162               buf[i].nbytes = nbytes;
00163               PR_PostSem(fullBufs);
00164               i = (i + 1) % 2;
00165        } while (nbytes > 0);
00166 }
00167 
00168 static void writer(void)
00169 {
00170        PRUintn       i = 0;
00171        size_t nbytes;
00172        
00173        do {
00174               (void) PR_WaitSem(fullBufs);
00175               nbytes = buf[i].nbytes;
00176               if (nbytes > 0) {
00177                      nbytes = dwrite(1, buf[i].data, nbytes);
00178                      PR_PostSem(emptyBufs);
00179                      i = (i + 1) % 2;
00180               }
00181        } while (nbytes > 0);
00182 }
00183 
00184 int main(int argc, char **argv)
00185 {
00186        PRThread *r;
00187 
00188     PR_STDIO_INIT();
00189     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
00190 
00191     {
00192        /* The command line argument: -d is used to determine if the test is being run
00193        in debug mode. The regress tool requires only one line output:PASS or FAIL.
00194        All of the printfs associated with this test has been handled with a if (debug_mode)
00195        test.
00196        Usage: test_name -d
00197        */
00198        PLOptStatus os;
00199        PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
00200        while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
00201         {
00202               if (PL_OPT_BAD == os) continue;
00203             switch (opt->option)
00204             {
00205             case 'd':  /* debug mode */
00206                      debug_mode = 1;
00207                 break;
00208              default:
00209                 break;
00210             }
00211         }
00212        PL_DestroyOptState(opt);
00213     }        
00214 
00215  /* main test */
00216 
00217 #ifdef XP_MAC
00218        SetupMacPrintfLog("sem.log");
00219        debug_mode = 1;
00220 #endif
00221 
00222     emptyBufs = PR_NewSem(2);      /* two empty buffers */
00223 
00224     fullBufs = PR_NewSem(0);       /* zero full buffers */
00225 
00226        /* create the reader thread */
00227        
00228        r = PR_CreateThread(PR_USER_THREAD,
00229                                   reader, 0, 
00230                                   PR_PRIORITY_NORMAL,
00231                                   PR_LOCAL_THREAD,
00232                               PR_UNJOINABLE_THREAD,
00233                                   0);
00234 
00235        /* Do the writer operation in this thread */
00236        writer();
00237 
00238        PR_DestroySem(emptyBufs);
00239        PR_DestroySem(fullBufs);
00240 
00241        if (finalResult == PR_SUCCESS) {
00242               if (debug_mode) printf("sem Test Passed.\n");
00243        }
00244        else{
00245               if (debug_mode) printf("sem Test Failed.\n");
00246               failed_already=1;
00247        }
00248     PR_Cleanup();
00249        if(failed_already)   
00250               return 1;
00251        else
00252               return 0;
00253 }