Upload Tizen:Base source
[toolchains/nspr.git] / mozilla / nsprpub / pr / tests / sem.c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4  *
5  * The contents of this file are subject to the Mozilla Public License Version
6  * 1.1 (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  * http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the
13  * License.
14  *
15  * The Original Code is the Netscape Portable Runtime (NSPR).
16  *
17  * The Initial Developer of the Original Code is
18  * Netscape Communications Corporation.
19  * Portions created by the Initial Developer are Copyright (C) 1998-2000
20  * the Initial Developer. All Rights Reserved.
21  *
22  * Contributor(s):
23  *
24  * Alternatively, the contents of this file may be used under the terms of
25  * either the GNU General Public License Version 2 or later (the "GPL"), or
26  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27  * in which case the provisions of the GPL or the LGPL are applicable instead
28  * of those above. If you wish to allow use of your version of this file only
29  * under the terms of either the GPL or the LGPL, and not to allow others to
30  * use your version of this file under the terms of the MPL, indicate your
31  * decision by deleting the provisions above and replace them with the notice
32  * and other provisions required by the GPL or the LGPL. If you do not delete
33  * the provisions above, a recipient may use your version of this file under
34  * the terms of any one of the MPL, the GPL or the LGPL.
35  *
36  * ***** END LICENSE BLOCK ***** */
37
38 /***********************************************************************
39 **
40 ** Name: sem.c
41 **
42 ** Description: Tests Semaphonre functions.
43 **
44 ** Modification History:
45 ** 20-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
46 **               The debug mode will print all of the printfs associated with this test.
47 **                       The regress mode will be the default mode. Since the regress tool limits
48 **           the output to a one line status:PASS or FAIL,all of the printf statements
49 **                       have been handled with an if (debug_mode) statement.
50 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
51 **                      recognize the return code from tha main program.
52 ***********************************************************************/
53
54 /***********************************************************************
55 ** Includes
56 ***********************************************************************/
57 /* Used to get the command line option */
58 #include "plgetopt.h"
59
60 #include "nspr.h"
61 #include "prpriv.h"
62
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <string.h>
66
67 PRIntn failed_already=0;
68 PRIntn debug_mode;
69
70 /* 
71         Since we don't have stdin, stdout everywhere, we will fake 
72         it with our in-memory buffers called stdin and stdout.
73 */
74
75 #define SBSIZE 1024
76
77 #include "obsolete/prsem.h"
78
79 static char stdinBuf[SBSIZE];
80 static char stdoutBuf[SBSIZE];
81
82 static PRUintn stdinBufIdx = 0;
83 static PRUintn stdoutBufIdx = 0;
84 static PRStatus finalResult = PR_SUCCESS;
85
86
87 static size_t dread (PRUintn device, char *buf, size_t bufSize)
88 {
89         PRUintn i;
90         
91         /* during first read call, initialize the stdinBuf buffer*/
92         if (stdinBufIdx == 0) {
93                 for (i=0; i<SBSIZE; i++)
94                         stdinBuf[i] = i;
95         }
96
97         /* now copy data from stdinBuf to the given buffer upto bufSize */
98         for (i=0; i<bufSize; i++) {
99                 if (stdinBufIdx == SBSIZE)
100                         break;
101                 buf[i] = stdinBuf[stdinBufIdx++];
102         }
103
104         return i;
105 }
106
107 static size_t dwrite (PRUintn device, char *buf, size_t bufSize)
108 {
109         PRUintn i, j;
110         
111         /* copy data from the given buffer upto bufSize to stdoutBuf */
112         for (i=0; i<bufSize; i++) {
113                 if (stdoutBufIdx == SBSIZE)
114                         break;
115                 stdoutBuf[stdoutBufIdx++] = buf[i];
116         }
117
118         /* during last write call, compare the two buffers */
119         if (stdoutBufIdx == SBSIZE)
120                 for (j=0; j<SBSIZE; j++)
121                         if (stdinBuf[j] != stdoutBuf[j]) {
122                                 if (debug_mode) printf("data mismatch for index= %d \n", j);
123                                 finalResult = PR_FAILURE;
124                         }
125
126         return i;
127 }
128
129 /*------------------ Following is the real test program ---------*/
130 /*
131         Program to copy standard input to standard output.  The program
132         uses two threads.  One reads the input and puts the data in a 
133         double buffer.  The other reads the buffer contents and writes 
134         it to standard output.
135 */
136
137 PRSemaphore     *emptyBufs;     /* number of empty buffers */
138 PRSemaphore *fullBufs;  /* number of buffers that are full */
139
140 #define BSIZE   100
141
142 struct {
143         char data[BSIZE];
144         PRUintn nbytes;         /* number of bytes in this buffer */
145 } buf[2];
146
147 static void PR_CALLBACK reader(void *arg)
148 {
149         PRUintn i = 0;
150         size_t  nbytes;
151         
152         do {
153                 (void) PR_WaitSem(emptyBufs);
154                 nbytes = dread(0, buf[i].data, BSIZE);
155                 buf[i].nbytes = nbytes;
156                 PR_PostSem(fullBufs);
157                 i = (i + 1) % 2;
158         } while (nbytes > 0);
159 }
160
161 static void writer(void)
162 {
163         PRUintn i = 0;
164         size_t  nbytes;
165         
166         do {
167                 (void) PR_WaitSem(fullBufs);
168                 nbytes = buf[i].nbytes;
169                 if (nbytes > 0) {
170                         nbytes = dwrite(1, buf[i].data, nbytes);
171                         PR_PostSem(emptyBufs);
172                         i = (i + 1) % 2;
173                 }
174         } while (nbytes > 0);
175 }
176
177 int main(int argc, char **argv)
178 {
179         PRThread *r;
180
181     PR_STDIO_INIT();
182     PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
183
184     {
185         /* The command line argument: -d is used to determine if the test is being run
186         in debug mode. The regress tool requires only one line output:PASS or FAIL.
187         All of the printfs associated with this test has been handled with a if (debug_mode)
188         test.
189         Usage: test_name -d
190         */
191         PLOptStatus os;
192         PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
193         while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
194         {
195                 if (PL_OPT_BAD == os) continue;
196             switch (opt->option)
197             {
198             case 'd':  /* debug mode */
199                         debug_mode = 1;
200                 break;
201              default:
202                 break;
203             }
204         }
205         PL_DestroyOptState(opt);
206     }        
207
208  /* main test */
209
210     emptyBufs = PR_NewSem(2);   /* two empty buffers */
211
212     fullBufs = PR_NewSem(0);    /* zero full buffers */
213
214         /* create the reader thread */
215         
216         r = PR_CreateThread(PR_USER_THREAD,
217                                       reader, 0, 
218                                       PR_PRIORITY_NORMAL,
219                                       PR_LOCAL_THREAD,
220                                   PR_UNJOINABLE_THREAD,
221                                       0);
222
223         /* Do the writer operation in this thread */
224         writer();
225
226         PR_DestroySem(emptyBufs);
227         PR_DestroySem(fullBufs);
228
229         if (finalResult == PR_SUCCESS) {
230                 if (debug_mode) printf("sem Test Passed.\n");
231         }
232         else{
233                 if (debug_mode) printf("sem Test Failed.\n");
234                 failed_already=1;
235         }
236     PR_Cleanup();
237         if(failed_already)      
238                 return 1;
239         else
240                 return 0;
241 }