1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/nsprpub/pr/tests/xnotify.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,357 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "plerror.h" 1.10 +#include "plgetopt.h" 1.11 + 1.12 +#include "prinit.h" 1.13 +#include "prprf.h" 1.14 +#include "prio.h" 1.15 +#include "prcvar.h" 1.16 +#include "prmon.h" 1.17 +#include "prcmon.h" 1.18 +#include "prlock.h" 1.19 +#include "prerror.h" 1.20 +#include "prinit.h" 1.21 +#include "prinrval.h" 1.22 +#include "prthread.h" 1.23 + 1.24 +static PRLock *ml = NULL; 1.25 +static PRIntervalTime base; 1.26 +static PRFileDesc *err = NULL; 1.27 + 1.28 +typedef struct CMonShared 1.29 +{ 1.30 + PRInt32 o1, o2; 1.31 +} CMonShared; 1.32 + 1.33 +typedef struct MonShared 1.34 +{ 1.35 + PRMonitor *o1, *o2; 1.36 +} MonShared; 1.37 + 1.38 +typedef struct LockShared 1.39 +{ 1.40 + PRLock *o1, *o2; 1.41 + PRCondVar *cv1, *cv2; 1.42 +} LockShared; 1.43 + 1.44 +static void LogNow(const char *msg, PRStatus rv) 1.45 +{ 1.46 + PRIntervalTime now = PR_IntervalNow(); 1.47 + PR_Lock(ml); 1.48 + PR_fprintf(err, "%6ld: %s", (now - base), msg); 1.49 + if (PR_FAILURE == rv) PL_FPrintError(err, " "); 1.50 + else PR_fprintf(err, "\n"); 1.51 + PR_Unlock(ml); 1.52 +} /* LogNow */ 1.53 + 1.54 +static void Help(void) 1.55 +{ 1.56 + PR_fprintf(err, "Usage: [-[d][l][m][c]] [-h]\n"); 1.57 + PR_fprintf(err, "\t-d debug mode (default: FALSE)\n"); 1.58 + PR_fprintf(err, "\t-l test with locks (default: FALSE)\n"); 1.59 + PR_fprintf(err, "\t-m tests with monitors (default: FALSE)\n"); 1.60 + PR_fprintf(err, "\t-c tests with cmonitors (default: FALSE)\n"); 1.61 + PR_fprintf(err, "\t-h help\n"); 1.62 +} /* Help */ 1.63 + 1.64 +static void PR_CALLBACK T2CMon(void *arg) 1.65 +{ 1.66 + PRStatus rv; 1.67 + CMonShared *shared = (CMonShared*)arg; 1.68 + 1.69 + PR_CEnterMonitor(&shared->o1); 1.70 + LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS); 1.71 + rv = PR_CWait(&shared->o1, PR_SecondsToInterval(5)); 1.72 + if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv); 1.73 + else LogNow("T2 wait failed on o1", rv); 1.74 + 1.75 + rv = PR_CNotify(&shared->o1); 1.76 + if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv); 1.77 + else LogNow("T2 notify on o1 failed", rv); 1.78 + 1.79 + PR_CExitMonitor(&shared->o1); 1.80 +} /* T2CMon */ 1.81 + 1.82 +static void PR_CALLBACK T3CMon(void *arg) 1.83 +{ 1.84 + PRStatus rv; 1.85 + CMonShared *shared = (CMonShared*)arg; 1.86 + 1.87 + PR_CEnterMonitor(&shared->o2); 1.88 + LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS); 1.89 + rv = PR_CWait(&shared->o2, PR_SecondsToInterval(5)); 1.90 + if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv); 1.91 + else LogNow("T3 wait failed on o2", rv); 1.92 + rv = PR_CNotify(&shared->o2); 1.93 + LogNow("T3 notify on o2", rv); 1.94 + PR_CExitMonitor(&shared->o2); 1.95 + 1.96 +} /* T3CMon */ 1.97 + 1.98 +static CMonShared sharedCM; 1.99 + 1.100 +static void T1CMon(void) 1.101 +{ 1.102 + PRStatus rv; 1.103 + PRThread *t2, *t3; 1.104 + 1.105 + PR_fprintf(err, "\n**********************************\n"); 1.106 + PR_fprintf(err, " CACHED MONITORS\n"); 1.107 + PR_fprintf(err, "**********************************\n"); 1.108 + 1.109 + base = PR_IntervalNow(); 1.110 + 1.111 + PR_CEnterMonitor(&sharedCM.o1); 1.112 + LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS); 1.113 + rv = PR_CWait(&sharedCM.o1, PR_SecondsToInterval(3)); 1.114 + if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv); 1.115 + else LogNow("T1 wait on o1 failed", rv); 1.116 + PR_CExitMonitor(&sharedCM.o1); 1.117 + 1.118 + LogNow("T1 creating T2", PR_SUCCESS); 1.119 + t2 = PR_CreateThread( 1.120 + PR_USER_THREAD, T2CMon, &sharedCM, PR_PRIORITY_NORMAL, 1.121 + PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); 1.122 + 1.123 + LogNow("T1 creating T3", PR_SUCCESS); 1.124 + t3 = PR_CreateThread( 1.125 + PR_USER_THREAD, T3CMon, &sharedCM, PR_PRIORITY_NORMAL, 1.126 + PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); 1.127 + 1.128 + PR_CEnterMonitor(&sharedCM.o2); 1.129 + LogNow("T1 waiting forever on o2", PR_SUCCESS); 1.130 + rv = PR_CWait(&sharedCM.o2, PR_INTERVAL_NO_TIMEOUT); 1.131 + if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv); 1.132 + else LogNow("T1 wait on o2 failed", rv); 1.133 + PR_CExitMonitor(&sharedCM.o2); 1.134 + 1.135 + (void)PR_JoinThread(t2); 1.136 + (void)PR_JoinThread(t3); 1.137 + 1.138 +} /* T1CMon */ 1.139 + 1.140 +static void PR_CALLBACK T2Mon(void *arg) 1.141 +{ 1.142 + PRStatus rv; 1.143 + MonShared *shared = (MonShared*)arg; 1.144 + 1.145 + PR_EnterMonitor(shared->o1); 1.146 + LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS); 1.147 + rv = PR_Wait(shared->o1, PR_SecondsToInterval(5)); 1.148 + if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv); 1.149 + else LogNow("T2 wait failed on o1", rv); 1.150 + 1.151 + rv = PR_Notify(shared->o1); 1.152 + if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv); 1.153 + else LogNow("T2 notify on o1 failed", rv); 1.154 + 1.155 + PR_ExitMonitor(shared->o1); 1.156 +} /* T2Mon */ 1.157 + 1.158 +static void PR_CALLBACK T3Mon(void *arg) 1.159 +{ 1.160 + PRStatus rv; 1.161 + MonShared *shared = (MonShared*)arg; 1.162 + 1.163 + PR_EnterMonitor(shared->o2); 1.164 + LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS); 1.165 + rv = PR_Wait(shared->o2, PR_SecondsToInterval(5)); 1.166 + if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv); 1.167 + else LogNow("T3 wait failed on o2", rv); 1.168 + rv = PR_Notify(shared->o2); 1.169 + LogNow("T3 notify on o2", rv); 1.170 + PR_ExitMonitor(shared->o2); 1.171 + 1.172 +} /* T3Mon */ 1.173 + 1.174 +static MonShared sharedM; 1.175 +static void T1Mon(void) 1.176 +{ 1.177 + PRStatus rv; 1.178 + PRThread *t2, *t3; 1.179 + 1.180 + PR_fprintf(err, "\n**********************************\n"); 1.181 + PR_fprintf(err, " MONITORS\n"); 1.182 + PR_fprintf(err, "**********************************\n"); 1.183 + 1.184 + sharedM.o1 = PR_NewMonitor(); 1.185 + sharedM.o2 = PR_NewMonitor(); 1.186 + 1.187 + base = PR_IntervalNow(); 1.188 + 1.189 + PR_EnterMonitor(sharedM.o1); 1.190 + LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS); 1.191 + rv = PR_Wait(sharedM.o1, PR_SecondsToInterval(3)); 1.192 + if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv); 1.193 + else LogNow("T1 wait on o1 failed", rv); 1.194 + PR_ExitMonitor(sharedM.o1); 1.195 + 1.196 + LogNow("T1 creating T2", PR_SUCCESS); 1.197 + t2 = PR_CreateThread( 1.198 + PR_USER_THREAD, T2Mon, &sharedM, PR_PRIORITY_NORMAL, 1.199 + PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); 1.200 + 1.201 + LogNow("T1 creating T3", PR_SUCCESS); 1.202 + t3 = PR_CreateThread( 1.203 + PR_USER_THREAD, T3Mon, &sharedM, PR_PRIORITY_NORMAL, 1.204 + PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); 1.205 + 1.206 + PR_EnterMonitor(sharedM.o2); 1.207 + LogNow("T1 waiting forever on o2", PR_SUCCESS); 1.208 + rv = PR_Wait(sharedM.o2, PR_INTERVAL_NO_TIMEOUT); 1.209 + if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv); 1.210 + else LogNow("T1 wait on o2 failed", rv); 1.211 + PR_ExitMonitor(sharedM.o2); 1.212 + 1.213 + (void)PR_JoinThread(t2); 1.214 + (void)PR_JoinThread(t3); 1.215 + 1.216 + PR_DestroyMonitor(sharedM.o1); 1.217 + PR_DestroyMonitor(sharedM.o2); 1.218 + 1.219 +} /* T1Mon */ 1.220 + 1.221 +static void PR_CALLBACK T2Lock(void *arg) 1.222 +{ 1.223 + PRStatus rv; 1.224 + LockShared *shared = (LockShared*)arg; 1.225 + 1.226 + PR_Lock(shared->o1); 1.227 + LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS); 1.228 + rv = PR_WaitCondVar(shared->cv1, PR_SecondsToInterval(5)); 1.229 + if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv); 1.230 + else LogNow("T2 wait failed on o1", rv); 1.231 + 1.232 + rv = PR_NotifyCondVar(shared->cv1); 1.233 + if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv); 1.234 + else LogNow("T2 notify on o1 failed", rv); 1.235 + 1.236 + PR_Unlock(shared->o1); 1.237 +} /* T2Lock */ 1.238 + 1.239 +static void PR_CALLBACK T3Lock(void *arg) 1.240 +{ 1.241 + PRStatus rv; 1.242 + LockShared *shared = (LockShared*)arg; 1.243 + 1.244 + PR_Lock(shared->o2); 1.245 + LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS); 1.246 + rv = PR_WaitCondVar(shared->cv2, PR_SecondsToInterval(5)); 1.247 + if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv); 1.248 + else LogNow("T3 wait failed on o2", rv); 1.249 + rv = PR_NotifyCondVar(shared->cv2); 1.250 + LogNow("T3 notify on o2", rv); 1.251 + PR_Unlock(shared->o2); 1.252 + 1.253 +} /* T3Lock */ 1.254 + 1.255 +/* 1.256 +** Make shared' a static variable for Win16 1.257 +*/ 1.258 +static LockShared sharedL; 1.259 + 1.260 +static void T1Lock(void) 1.261 +{ 1.262 + PRStatus rv; 1.263 + PRThread *t2, *t3; 1.264 + sharedL.o1 = PR_NewLock(); 1.265 + sharedL.o2 = PR_NewLock(); 1.266 + sharedL.cv1 = PR_NewCondVar(sharedL.o1); 1.267 + sharedL.cv2 = PR_NewCondVar(sharedL.o2); 1.268 + 1.269 + PR_fprintf(err, "\n**********************************\n"); 1.270 + PR_fprintf(err, " LOCKS\n"); 1.271 + PR_fprintf(err, "**********************************\n"); 1.272 + 1.273 + base = PR_IntervalNow(); 1.274 + 1.275 + PR_Lock(sharedL.o1); 1.276 + LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS); 1.277 + rv = PR_WaitCondVar(sharedL.cv1, PR_SecondsToInterval(3)); 1.278 + if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv); 1.279 + else LogNow("T1 wait on o1 failed", rv); 1.280 + PR_Unlock(sharedL.o1); 1.281 + 1.282 + LogNow("T1 creating T2", PR_SUCCESS); 1.283 + t2 = PR_CreateThread( 1.284 + PR_USER_THREAD, T2Lock, &sharedL, PR_PRIORITY_NORMAL, 1.285 + PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); 1.286 + 1.287 + LogNow("T1 creating T3", PR_SUCCESS); 1.288 + t3 = PR_CreateThread( 1.289 + PR_USER_THREAD, T3Lock, &sharedL, PR_PRIORITY_NORMAL, 1.290 + PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); 1.291 + 1.292 + PR_Lock(sharedL.o2); 1.293 + LogNow("T1 waiting forever on o2", PR_SUCCESS); 1.294 + rv = PR_WaitCondVar(sharedL.cv2, PR_INTERVAL_NO_TIMEOUT); 1.295 + if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv); 1.296 + else LogNow("T1 wait on o2 failed", rv); 1.297 + PR_Unlock(sharedL.o2); 1.298 + 1.299 + (void)PR_JoinThread(t2); 1.300 + (void)PR_JoinThread(t3); 1.301 + 1.302 + PR_DestroyLock(sharedL.o1); 1.303 + PR_DestroyLock(sharedL.o2); 1.304 + PR_DestroyCondVar(sharedL.cv1); 1.305 + PR_DestroyCondVar(sharedL.cv2); 1.306 +} /* T1Lock */ 1.307 + 1.308 +static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) 1.309 +{ 1.310 + PLOptStatus os; 1.311 + PLOptState *opt = PL_CreateOptState(argc, argv, "dhlmc"); 1.312 + PRBool locks = PR_FALSE, monitors = PR_FALSE, cmonitors = PR_FALSE; 1.313 + 1.314 + err = PR_GetSpecialFD(PR_StandardError); 1.315 + 1.316 + while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) 1.317 + { 1.318 + if (PL_OPT_BAD == os) continue; 1.319 + switch (opt->option) 1.320 + { 1.321 + case 'd': /* debug mode (noop) */ 1.322 + break; 1.323 + case 'l': /* locks */ 1.324 + locks = PR_TRUE; 1.325 + break; 1.326 + case 'm': /* monitors */ 1.327 + monitors = PR_TRUE; 1.328 + break; 1.329 + case 'c': /* cached monitors */ 1.330 + cmonitors = PR_TRUE; 1.331 + break; 1.332 + case 'h': /* needs guidance */ 1.333 + default: 1.334 + Help(); 1.335 + return 2; 1.336 + } 1.337 + } 1.338 + PL_DestroyOptState(opt); 1.339 + 1.340 + ml = PR_NewLock(); 1.341 + if (locks) T1Lock(); 1.342 + if (monitors) T1Mon(); 1.343 + if (cmonitors) T1CMon(); 1.344 + 1.345 + PR_DestroyLock(ml); 1.346 + 1.347 + PR_fprintf(err, "Done!\n"); 1.348 + return 0; 1.349 +} /* main */ 1.350 + 1.351 + 1.352 +int main(int argc, char **argv) 1.353 +{ 1.354 + PRIntn rv; 1.355 + 1.356 + PR_STDIO_INIT(); 1.357 + rv = PR_Initialize(RealMain, argc, argv, 0); 1.358 + return rv; 1.359 +} /* main */ 1.360 +/* xnotify.c */