Back to index

lightning-sunbird  0.9+nobinonly
xnotify.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 #include "plerror.h"
00039 #include "plgetopt.h"
00040 
00041 #include "prinit.h"
00042 #include "prprf.h"
00043 #include "prio.h"
00044 #include "prcvar.h"
00045 #include "prmon.h"
00046 #include "prcmon.h"
00047 #include "prlock.h"
00048 #include "prerror.h"
00049 #include "prinit.h"
00050 #include "prinrval.h"
00051 #include "prthread.h"
00052 
00053 static PRLock *ml = NULL;
00054 static PRIntervalTime base;
00055 static PRFileDesc *err = NULL;
00056 
00057 typedef struct CMonShared
00058 {
00059     PRInt32 o1, o2;
00060 } CMonShared;
00061 
00062 typedef struct MonShared
00063 {
00064     PRMonitor *o1, *o2;
00065 } MonShared;
00066 
00067 typedef struct LockShared
00068 {
00069     PRLock *o1, *o2;
00070     PRCondVar *cv1, *cv2;
00071 } LockShared;
00072 
00073 static void LogNow(const char *msg, PRStatus rv)
00074 {
00075     PRIntervalTime now = PR_IntervalNow();
00076     PR_Lock(ml);
00077     PR_fprintf(err, "%6ld: %s", (now - base), msg);
00078     if (PR_FAILURE == rv) PL_FPrintError(err, " ");
00079     else PR_fprintf(err, "\n");
00080     PR_Unlock(ml);
00081 }  /* LogNow */
00082 
00083 static void Help(void)
00084 {
00085     PR_fprintf(err, "Usage: [-[d][l][m][c]] [-h]\n");
00086     PR_fprintf(err, "\t-d   debug mode                  (default: FALSE)\n");
00087     PR_fprintf(err, "\t-l   test with locks             (default: FALSE)\n");
00088     PR_fprintf(err, "\t-m   tests with monitors         (default: FALSE)\n");
00089     PR_fprintf(err, "\t-c   tests with cmonitors        (default: FALSE)\n");
00090     PR_fprintf(err, "\t-h   help\n");
00091 }  /* Help */
00092 
00093 static void PR_CALLBACK T2CMon(void *arg)
00094 {
00095     PRStatus rv;
00096     CMonShared *shared = (CMonShared*)arg;
00097 
00098     PR_CEnterMonitor(&shared->o1);
00099     LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS);
00100     rv = PR_CWait(&shared->o1, PR_SecondsToInterval(5));
00101     if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv);
00102     else LogNow("T2 wait failed on o1", rv);
00103 
00104     rv = PR_CNotify(&shared->o1);
00105     if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv);
00106     else LogNow("T2 notify on o1 failed", rv);
00107 
00108     PR_CExitMonitor(&shared->o1);
00109 }  /* T2CMon */
00110 
00111 static void PR_CALLBACK T3CMon(void *arg)
00112 {
00113     PRStatus rv;
00114     CMonShared *shared = (CMonShared*)arg;
00115 
00116     PR_CEnterMonitor(&shared->o2);
00117     LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS);
00118     rv = PR_CWait(&shared->o2, PR_SecondsToInterval(5));
00119     if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv);
00120     else LogNow("T3 wait failed on o2", rv);
00121     rv = PR_CNotify(&shared->o2);
00122     LogNow("T3 notify on o2", rv);
00123     PR_CExitMonitor(&shared->o2);
00124 
00125 }  /* T3CMon */
00126 
00127 static CMonShared sharedCM;
00128 
00129 static void T1CMon(void)
00130 {
00131     PRStatus rv;
00132     PRThread *t2, *t3;
00133 
00134     PR_fprintf(err, "\n**********************************\n");
00135     PR_fprintf(err, "         CACHED MONITORS\n");
00136     PR_fprintf(err, "**********************************\n");
00137 
00138     base =  PR_IntervalNow();
00139 
00140     PR_CEnterMonitor(&sharedCM.o1);
00141     LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS);
00142     rv = PR_CWait(&sharedCM.o1, PR_SecondsToInterval(3));
00143     if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv);
00144     else LogNow("T1 wait on o1 failed", rv);
00145     PR_CExitMonitor(&sharedCM.o1);
00146 
00147     LogNow("T1 creating T2", PR_SUCCESS);
00148     t2 = PR_CreateThread(
00149         PR_USER_THREAD, T2CMon, &sharedCM, PR_PRIORITY_NORMAL,
00150         PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
00151 
00152     LogNow("T1 creating T3", PR_SUCCESS);
00153     t3 = PR_CreateThread(
00154         PR_USER_THREAD, T3CMon, &sharedCM, PR_PRIORITY_NORMAL,
00155         PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
00156 
00157     PR_CEnterMonitor(&sharedCM.o2);
00158     LogNow("T1 waiting forever on o2", PR_SUCCESS);
00159     rv = PR_CWait(&sharedCM.o2, PR_INTERVAL_NO_TIMEOUT);
00160     if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv);
00161     else LogNow("T1 wait on o2 failed", rv);
00162     PR_CExitMonitor(&sharedCM.o2);
00163 
00164     (void)PR_JoinThread(t2);
00165     (void)PR_JoinThread(t3);
00166 
00167 }  /* T1CMon */
00168 
00169 static void PR_CALLBACK T2Mon(void *arg)
00170 {
00171     PRStatus rv;
00172     MonShared *shared = (MonShared*)arg;
00173 
00174     PR_EnterMonitor(shared->o1);
00175     LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS);
00176     rv = PR_Wait(shared->o1, PR_SecondsToInterval(5));
00177     if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv);
00178     else LogNow("T2 wait failed on o1", rv);
00179 
00180     rv = PR_Notify(shared->o1);
00181     if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv);
00182     else LogNow("T2 notify on o1 failed", rv);
00183 
00184     PR_ExitMonitor(shared->o1);
00185 }  /* T2Mon */
00186 
00187 static void PR_CALLBACK T3Mon(void *arg)
00188 {
00189     PRStatus rv;
00190     MonShared *shared = (MonShared*)arg;
00191 
00192     PR_EnterMonitor(shared->o2);
00193     LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS);
00194     rv = PR_Wait(shared->o2, PR_SecondsToInterval(5));
00195     if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv);
00196     else LogNow("T3 wait failed on o2", rv);
00197     rv = PR_Notify(shared->o2);
00198     LogNow("T3 notify on o2", rv);
00199     PR_ExitMonitor(shared->o2);
00200 
00201 }  /* T3Mon */
00202 
00203 static MonShared sharedM;
00204 static void T1Mon(void)
00205 {
00206     PRStatus rv;
00207     PRThread *t2, *t3;
00208 
00209     PR_fprintf(err, "\n**********************************\n");
00210     PR_fprintf(err, "            MONITORS\n");
00211     PR_fprintf(err, "**********************************\n");
00212 
00213     sharedM.o1 = PR_NewMonitor();
00214     sharedM.o2 = PR_NewMonitor();
00215 
00216     base =  PR_IntervalNow();
00217 
00218     PR_EnterMonitor(sharedM.o1);
00219     LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS);
00220     rv = PR_Wait(sharedM.o1, PR_SecondsToInterval(3));
00221     if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv);
00222     else LogNow("T1 wait on o1 failed", rv);
00223     PR_ExitMonitor(sharedM.o1);
00224 
00225     LogNow("T1 creating T2", PR_SUCCESS);
00226     t2 = PR_CreateThread(
00227         PR_USER_THREAD, T2Mon, &sharedM, PR_PRIORITY_NORMAL,
00228         PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
00229 
00230     LogNow("T1 creating T3", PR_SUCCESS);
00231     t3 = PR_CreateThread(
00232         PR_USER_THREAD, T3Mon, &sharedM, PR_PRIORITY_NORMAL,
00233         PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
00234 
00235     PR_EnterMonitor(sharedM.o2);
00236     LogNow("T1 waiting forever on o2", PR_SUCCESS);
00237     rv = PR_Wait(sharedM.o2, PR_INTERVAL_NO_TIMEOUT);
00238     if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv);
00239     else LogNow("T1 wait on o2 failed", rv);
00240     PR_ExitMonitor(sharedM.o2);
00241 
00242     (void)PR_JoinThread(t2);
00243     (void)PR_JoinThread(t3);
00244 
00245     PR_DestroyMonitor(sharedM.o1);
00246     PR_DestroyMonitor(sharedM.o2);
00247 
00248 }  /* T1Mon */
00249 
00250 static void PR_CALLBACK T2Lock(void *arg)
00251 {
00252     PRStatus rv;
00253     LockShared *shared = (LockShared*)arg;
00254 
00255     PR_Lock(shared->o1);
00256     LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS);
00257     rv = PR_WaitCondVar(shared->cv1, PR_SecondsToInterval(5));
00258     if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv);
00259     else LogNow("T2 wait failed on o1", rv);
00260 
00261     rv = PR_NotifyCondVar(shared->cv1);
00262     if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv);
00263     else LogNow("T2 notify on o1 failed", rv);
00264 
00265     PR_Unlock(shared->o1);
00266 }  /* T2Lock */
00267 
00268 static void PR_CALLBACK T3Lock(void *arg)
00269 {
00270     PRStatus rv;
00271     LockShared *shared = (LockShared*)arg;
00272 
00273     PR_Lock(shared->o2);
00274     LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS);
00275     rv = PR_WaitCondVar(shared->cv2, PR_SecondsToInterval(5));
00276     if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv);
00277     else LogNow("T3 wait failed on o2", rv);
00278     rv = PR_NotifyCondVar(shared->cv2);
00279     LogNow("T3 notify on o2", rv);
00280     PR_Unlock(shared->o2);
00281 
00282 }  /* T3Lock */
00283 
00284 /*
00285 ** Make shared' a static variable for Win16
00286 */
00287 static LockShared sharedL;
00288 
00289 static void T1Lock(void)
00290 {
00291     PRStatus rv;
00292     PRThread *t2, *t3;
00293     sharedL.o1 = PR_NewLock();
00294     sharedL.o2 = PR_NewLock();
00295     sharedL.cv1 = PR_NewCondVar(sharedL.o1);
00296     sharedL.cv2 = PR_NewCondVar(sharedL.o2);
00297 
00298     PR_fprintf(err, "\n**********************************\n");
00299     PR_fprintf(err, "             LOCKS\n");
00300     PR_fprintf(err, "**********************************\n");
00301 
00302     base =  PR_IntervalNow();
00303 
00304     PR_Lock(sharedL.o1);
00305     LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS);
00306     rv = PR_WaitCondVar(sharedL.cv1, PR_SecondsToInterval(3));
00307     if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv);
00308     else LogNow("T1 wait on o1 failed", rv);
00309     PR_Unlock(sharedL.o1);
00310 
00311     LogNow("T1 creating T2", PR_SUCCESS);
00312     t2 = PR_CreateThread(
00313         PR_USER_THREAD, T2Lock, &sharedL, PR_PRIORITY_NORMAL,
00314         PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
00315 
00316     LogNow("T1 creating T3", PR_SUCCESS);
00317     t3 = PR_CreateThread(
00318         PR_USER_THREAD, T3Lock, &sharedL, PR_PRIORITY_NORMAL,
00319         PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0);
00320 
00321     PR_Lock(sharedL.o2);
00322     LogNow("T1 waiting forever on o2", PR_SUCCESS);
00323     rv = PR_WaitCondVar(sharedL.cv2, PR_INTERVAL_NO_TIMEOUT);
00324     if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv);
00325     else LogNow("T1 wait on o2 failed", rv);
00326     PR_Unlock(sharedL.o2);
00327 
00328     (void)PR_JoinThread(t2);
00329     (void)PR_JoinThread(t3);
00330 
00331     PR_DestroyLock(sharedL.o1);
00332     PR_DestroyLock(sharedL.o2);
00333     PR_DestroyCondVar(sharedL.cv1);
00334     PR_DestroyCondVar(sharedL.cv2);
00335 }  /* T1Lock */
00336 
00337 static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv )
00338 {
00339        PLOptStatus os;
00340        PLOptState *opt = PL_CreateOptState(argc, argv, "dhlmc");
00341        PRBool locks = PR_FALSE, monitors = PR_FALSE, cmonitors = PR_FALSE;
00342 
00343     err = PR_GetSpecialFD(PR_StandardError);
00344 
00345        while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
00346     {
00347               if (PL_OPT_BAD == os) continue;
00348         switch (opt->option)
00349         {
00350         case 'd':  /* debug mode (noop) */
00351             break;
00352         case 'l':  /* locks */
00353                      locks = PR_TRUE;
00354             break;
00355         case 'm':  /* monitors */
00356                      monitors = PR_TRUE;
00357             break;
00358         case 'c':  /* cached monitors */
00359                      cmonitors = PR_TRUE;
00360             break;
00361         case 'h':  /* needs guidance */
00362          default:
00363             Help();
00364             return 2;
00365         }
00366     }
00367        PL_DestroyOptState(opt);
00368 
00369     ml = PR_NewLock();
00370     if (locks) T1Lock();
00371     if (monitors) T1Mon();
00372     if (cmonitors) T1CMon();
00373 
00374     PR_DestroyLock(ml);
00375 
00376     PR_fprintf(err, "Done!\n");    
00377     return 0;
00378 }  /* main */
00379 
00380 
00381 PRIntn main(PRIntn argc, char **argv)
00382 {
00383     PRIntn rv;
00384     
00385     PR_STDIO_INIT();
00386     rv = PR_Initialize(RealMain, argc, argv, 0);
00387     return rv;
00388 }  /* main */
00389 /* xnotify.c */