Wed, 31 Dec 2014 07:53:36 +0100
Correct small whitespace inconsistency, lost while renaming variables.
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 | #include "plerror.h" |
michael@0 | 7 | #include "plgetopt.h" |
michael@0 | 8 | |
michael@0 | 9 | #include "prinit.h" |
michael@0 | 10 | #include "prprf.h" |
michael@0 | 11 | #include "prio.h" |
michael@0 | 12 | #include "prcvar.h" |
michael@0 | 13 | #include "prmon.h" |
michael@0 | 14 | #include "prcmon.h" |
michael@0 | 15 | #include "prlock.h" |
michael@0 | 16 | #include "prerror.h" |
michael@0 | 17 | #include "prinit.h" |
michael@0 | 18 | #include "prinrval.h" |
michael@0 | 19 | #include "prthread.h" |
michael@0 | 20 | |
michael@0 | 21 | static PRLock *ml = NULL; |
michael@0 | 22 | static PRIntervalTime base; |
michael@0 | 23 | static PRFileDesc *err = NULL; |
michael@0 | 24 | |
michael@0 | 25 | typedef struct CMonShared |
michael@0 | 26 | { |
michael@0 | 27 | PRInt32 o1, o2; |
michael@0 | 28 | } CMonShared; |
michael@0 | 29 | |
michael@0 | 30 | typedef struct MonShared |
michael@0 | 31 | { |
michael@0 | 32 | PRMonitor *o1, *o2; |
michael@0 | 33 | } MonShared; |
michael@0 | 34 | |
michael@0 | 35 | typedef struct LockShared |
michael@0 | 36 | { |
michael@0 | 37 | PRLock *o1, *o2; |
michael@0 | 38 | PRCondVar *cv1, *cv2; |
michael@0 | 39 | } LockShared; |
michael@0 | 40 | |
michael@0 | 41 | static void LogNow(const char *msg, PRStatus rv) |
michael@0 | 42 | { |
michael@0 | 43 | PRIntervalTime now = PR_IntervalNow(); |
michael@0 | 44 | PR_Lock(ml); |
michael@0 | 45 | PR_fprintf(err, "%6ld: %s", (now - base), msg); |
michael@0 | 46 | if (PR_FAILURE == rv) PL_FPrintError(err, " "); |
michael@0 | 47 | else PR_fprintf(err, "\n"); |
michael@0 | 48 | PR_Unlock(ml); |
michael@0 | 49 | } /* LogNow */ |
michael@0 | 50 | |
michael@0 | 51 | static void Help(void) |
michael@0 | 52 | { |
michael@0 | 53 | PR_fprintf(err, "Usage: [-[d][l][m][c]] [-h]\n"); |
michael@0 | 54 | PR_fprintf(err, "\t-d debug mode (default: FALSE)\n"); |
michael@0 | 55 | PR_fprintf(err, "\t-l test with locks (default: FALSE)\n"); |
michael@0 | 56 | PR_fprintf(err, "\t-m tests with monitors (default: FALSE)\n"); |
michael@0 | 57 | PR_fprintf(err, "\t-c tests with cmonitors (default: FALSE)\n"); |
michael@0 | 58 | PR_fprintf(err, "\t-h help\n"); |
michael@0 | 59 | } /* Help */ |
michael@0 | 60 | |
michael@0 | 61 | static void PR_CALLBACK T2CMon(void *arg) |
michael@0 | 62 | { |
michael@0 | 63 | PRStatus rv; |
michael@0 | 64 | CMonShared *shared = (CMonShared*)arg; |
michael@0 | 65 | |
michael@0 | 66 | PR_CEnterMonitor(&shared->o1); |
michael@0 | 67 | LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS); |
michael@0 | 68 | rv = PR_CWait(&shared->o1, PR_SecondsToInterval(5)); |
michael@0 | 69 | if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv); |
michael@0 | 70 | else LogNow("T2 wait failed on o1", rv); |
michael@0 | 71 | |
michael@0 | 72 | rv = PR_CNotify(&shared->o1); |
michael@0 | 73 | if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv); |
michael@0 | 74 | else LogNow("T2 notify on o1 failed", rv); |
michael@0 | 75 | |
michael@0 | 76 | PR_CExitMonitor(&shared->o1); |
michael@0 | 77 | } /* T2CMon */ |
michael@0 | 78 | |
michael@0 | 79 | static void PR_CALLBACK T3CMon(void *arg) |
michael@0 | 80 | { |
michael@0 | 81 | PRStatus rv; |
michael@0 | 82 | CMonShared *shared = (CMonShared*)arg; |
michael@0 | 83 | |
michael@0 | 84 | PR_CEnterMonitor(&shared->o2); |
michael@0 | 85 | LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS); |
michael@0 | 86 | rv = PR_CWait(&shared->o2, PR_SecondsToInterval(5)); |
michael@0 | 87 | if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv); |
michael@0 | 88 | else LogNow("T3 wait failed on o2", rv); |
michael@0 | 89 | rv = PR_CNotify(&shared->o2); |
michael@0 | 90 | LogNow("T3 notify on o2", rv); |
michael@0 | 91 | PR_CExitMonitor(&shared->o2); |
michael@0 | 92 | |
michael@0 | 93 | } /* T3CMon */ |
michael@0 | 94 | |
michael@0 | 95 | static CMonShared sharedCM; |
michael@0 | 96 | |
michael@0 | 97 | static void T1CMon(void) |
michael@0 | 98 | { |
michael@0 | 99 | PRStatus rv; |
michael@0 | 100 | PRThread *t2, *t3; |
michael@0 | 101 | |
michael@0 | 102 | PR_fprintf(err, "\n**********************************\n"); |
michael@0 | 103 | PR_fprintf(err, " CACHED MONITORS\n"); |
michael@0 | 104 | PR_fprintf(err, "**********************************\n"); |
michael@0 | 105 | |
michael@0 | 106 | base = PR_IntervalNow(); |
michael@0 | 107 | |
michael@0 | 108 | PR_CEnterMonitor(&sharedCM.o1); |
michael@0 | 109 | LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS); |
michael@0 | 110 | rv = PR_CWait(&sharedCM.o1, PR_SecondsToInterval(3)); |
michael@0 | 111 | if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv); |
michael@0 | 112 | else LogNow("T1 wait on o1 failed", rv); |
michael@0 | 113 | PR_CExitMonitor(&sharedCM.o1); |
michael@0 | 114 | |
michael@0 | 115 | LogNow("T1 creating T2", PR_SUCCESS); |
michael@0 | 116 | t2 = PR_CreateThread( |
michael@0 | 117 | PR_USER_THREAD, T2CMon, &sharedCM, PR_PRIORITY_NORMAL, |
michael@0 | 118 | PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); |
michael@0 | 119 | |
michael@0 | 120 | LogNow("T1 creating T3", PR_SUCCESS); |
michael@0 | 121 | t3 = PR_CreateThread( |
michael@0 | 122 | PR_USER_THREAD, T3CMon, &sharedCM, PR_PRIORITY_NORMAL, |
michael@0 | 123 | PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); |
michael@0 | 124 | |
michael@0 | 125 | PR_CEnterMonitor(&sharedCM.o2); |
michael@0 | 126 | LogNow("T1 waiting forever on o2", PR_SUCCESS); |
michael@0 | 127 | rv = PR_CWait(&sharedCM.o2, PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 128 | if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv); |
michael@0 | 129 | else LogNow("T1 wait on o2 failed", rv); |
michael@0 | 130 | PR_CExitMonitor(&sharedCM.o2); |
michael@0 | 131 | |
michael@0 | 132 | (void)PR_JoinThread(t2); |
michael@0 | 133 | (void)PR_JoinThread(t3); |
michael@0 | 134 | |
michael@0 | 135 | } /* T1CMon */ |
michael@0 | 136 | |
michael@0 | 137 | static void PR_CALLBACK T2Mon(void *arg) |
michael@0 | 138 | { |
michael@0 | 139 | PRStatus rv; |
michael@0 | 140 | MonShared *shared = (MonShared*)arg; |
michael@0 | 141 | |
michael@0 | 142 | PR_EnterMonitor(shared->o1); |
michael@0 | 143 | LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS); |
michael@0 | 144 | rv = PR_Wait(shared->o1, PR_SecondsToInterval(5)); |
michael@0 | 145 | if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv); |
michael@0 | 146 | else LogNow("T2 wait failed on o1", rv); |
michael@0 | 147 | |
michael@0 | 148 | rv = PR_Notify(shared->o1); |
michael@0 | 149 | if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv); |
michael@0 | 150 | else LogNow("T2 notify on o1 failed", rv); |
michael@0 | 151 | |
michael@0 | 152 | PR_ExitMonitor(shared->o1); |
michael@0 | 153 | } /* T2Mon */ |
michael@0 | 154 | |
michael@0 | 155 | static void PR_CALLBACK T3Mon(void *arg) |
michael@0 | 156 | { |
michael@0 | 157 | PRStatus rv; |
michael@0 | 158 | MonShared *shared = (MonShared*)arg; |
michael@0 | 159 | |
michael@0 | 160 | PR_EnterMonitor(shared->o2); |
michael@0 | 161 | LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS); |
michael@0 | 162 | rv = PR_Wait(shared->o2, PR_SecondsToInterval(5)); |
michael@0 | 163 | if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv); |
michael@0 | 164 | else LogNow("T3 wait failed on o2", rv); |
michael@0 | 165 | rv = PR_Notify(shared->o2); |
michael@0 | 166 | LogNow("T3 notify on o2", rv); |
michael@0 | 167 | PR_ExitMonitor(shared->o2); |
michael@0 | 168 | |
michael@0 | 169 | } /* T3Mon */ |
michael@0 | 170 | |
michael@0 | 171 | static MonShared sharedM; |
michael@0 | 172 | static void T1Mon(void) |
michael@0 | 173 | { |
michael@0 | 174 | PRStatus rv; |
michael@0 | 175 | PRThread *t2, *t3; |
michael@0 | 176 | |
michael@0 | 177 | PR_fprintf(err, "\n**********************************\n"); |
michael@0 | 178 | PR_fprintf(err, " MONITORS\n"); |
michael@0 | 179 | PR_fprintf(err, "**********************************\n"); |
michael@0 | 180 | |
michael@0 | 181 | sharedM.o1 = PR_NewMonitor(); |
michael@0 | 182 | sharedM.o2 = PR_NewMonitor(); |
michael@0 | 183 | |
michael@0 | 184 | base = PR_IntervalNow(); |
michael@0 | 185 | |
michael@0 | 186 | PR_EnterMonitor(sharedM.o1); |
michael@0 | 187 | LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS); |
michael@0 | 188 | rv = PR_Wait(sharedM.o1, PR_SecondsToInterval(3)); |
michael@0 | 189 | if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv); |
michael@0 | 190 | else LogNow("T1 wait on o1 failed", rv); |
michael@0 | 191 | PR_ExitMonitor(sharedM.o1); |
michael@0 | 192 | |
michael@0 | 193 | LogNow("T1 creating T2", PR_SUCCESS); |
michael@0 | 194 | t2 = PR_CreateThread( |
michael@0 | 195 | PR_USER_THREAD, T2Mon, &sharedM, PR_PRIORITY_NORMAL, |
michael@0 | 196 | PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); |
michael@0 | 197 | |
michael@0 | 198 | LogNow("T1 creating T3", PR_SUCCESS); |
michael@0 | 199 | t3 = PR_CreateThread( |
michael@0 | 200 | PR_USER_THREAD, T3Mon, &sharedM, PR_PRIORITY_NORMAL, |
michael@0 | 201 | PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); |
michael@0 | 202 | |
michael@0 | 203 | PR_EnterMonitor(sharedM.o2); |
michael@0 | 204 | LogNow("T1 waiting forever on o2", PR_SUCCESS); |
michael@0 | 205 | rv = PR_Wait(sharedM.o2, PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 206 | if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv); |
michael@0 | 207 | else LogNow("T1 wait on o2 failed", rv); |
michael@0 | 208 | PR_ExitMonitor(sharedM.o2); |
michael@0 | 209 | |
michael@0 | 210 | (void)PR_JoinThread(t2); |
michael@0 | 211 | (void)PR_JoinThread(t3); |
michael@0 | 212 | |
michael@0 | 213 | PR_DestroyMonitor(sharedM.o1); |
michael@0 | 214 | PR_DestroyMonitor(sharedM.o2); |
michael@0 | 215 | |
michael@0 | 216 | } /* T1Mon */ |
michael@0 | 217 | |
michael@0 | 218 | static void PR_CALLBACK T2Lock(void *arg) |
michael@0 | 219 | { |
michael@0 | 220 | PRStatus rv; |
michael@0 | 221 | LockShared *shared = (LockShared*)arg; |
michael@0 | 222 | |
michael@0 | 223 | PR_Lock(shared->o1); |
michael@0 | 224 | LogNow("T2 waiting 5 seconds on o1", PR_SUCCESS); |
michael@0 | 225 | rv = PR_WaitCondVar(shared->cv1, PR_SecondsToInterval(5)); |
michael@0 | 226 | if (PR_SUCCESS == rv) LogNow("T2 resuming on o1", rv); |
michael@0 | 227 | else LogNow("T2 wait failed on o1", rv); |
michael@0 | 228 | |
michael@0 | 229 | rv = PR_NotifyCondVar(shared->cv1); |
michael@0 | 230 | if (PR_SUCCESS == rv) LogNow("T2 notified o1", rv); |
michael@0 | 231 | else LogNow("T2 notify on o1 failed", rv); |
michael@0 | 232 | |
michael@0 | 233 | PR_Unlock(shared->o1); |
michael@0 | 234 | } /* T2Lock */ |
michael@0 | 235 | |
michael@0 | 236 | static void PR_CALLBACK T3Lock(void *arg) |
michael@0 | 237 | { |
michael@0 | 238 | PRStatus rv; |
michael@0 | 239 | LockShared *shared = (LockShared*)arg; |
michael@0 | 240 | |
michael@0 | 241 | PR_Lock(shared->o2); |
michael@0 | 242 | LogNow("T3 waiting 5 seconds on o2", PR_SUCCESS); |
michael@0 | 243 | rv = PR_WaitCondVar(shared->cv2, PR_SecondsToInterval(5)); |
michael@0 | 244 | if (PR_SUCCESS == rv) LogNow("T3 resuming on o2", rv); |
michael@0 | 245 | else LogNow("T3 wait failed on o2", rv); |
michael@0 | 246 | rv = PR_NotifyCondVar(shared->cv2); |
michael@0 | 247 | LogNow("T3 notify on o2", rv); |
michael@0 | 248 | PR_Unlock(shared->o2); |
michael@0 | 249 | |
michael@0 | 250 | } /* T3Lock */ |
michael@0 | 251 | |
michael@0 | 252 | /* |
michael@0 | 253 | ** Make shared' a static variable for Win16 |
michael@0 | 254 | */ |
michael@0 | 255 | static LockShared sharedL; |
michael@0 | 256 | |
michael@0 | 257 | static void T1Lock(void) |
michael@0 | 258 | { |
michael@0 | 259 | PRStatus rv; |
michael@0 | 260 | PRThread *t2, *t3; |
michael@0 | 261 | sharedL.o1 = PR_NewLock(); |
michael@0 | 262 | sharedL.o2 = PR_NewLock(); |
michael@0 | 263 | sharedL.cv1 = PR_NewCondVar(sharedL.o1); |
michael@0 | 264 | sharedL.cv2 = PR_NewCondVar(sharedL.o2); |
michael@0 | 265 | |
michael@0 | 266 | PR_fprintf(err, "\n**********************************\n"); |
michael@0 | 267 | PR_fprintf(err, " LOCKS\n"); |
michael@0 | 268 | PR_fprintf(err, "**********************************\n"); |
michael@0 | 269 | |
michael@0 | 270 | base = PR_IntervalNow(); |
michael@0 | 271 | |
michael@0 | 272 | PR_Lock(sharedL.o1); |
michael@0 | 273 | LogNow("T1 waiting 3 seconds on o1", PR_SUCCESS); |
michael@0 | 274 | rv = PR_WaitCondVar(sharedL.cv1, PR_SecondsToInterval(3)); |
michael@0 | 275 | if (PR_SUCCESS == rv) LogNow("T1 resuming on o1", rv); |
michael@0 | 276 | else LogNow("T1 wait on o1 failed", rv); |
michael@0 | 277 | PR_Unlock(sharedL.o1); |
michael@0 | 278 | |
michael@0 | 279 | LogNow("T1 creating T2", PR_SUCCESS); |
michael@0 | 280 | t2 = PR_CreateThread( |
michael@0 | 281 | PR_USER_THREAD, T2Lock, &sharedL, PR_PRIORITY_NORMAL, |
michael@0 | 282 | PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); |
michael@0 | 283 | |
michael@0 | 284 | LogNow("T1 creating T3", PR_SUCCESS); |
michael@0 | 285 | t3 = PR_CreateThread( |
michael@0 | 286 | PR_USER_THREAD, T3Lock, &sharedL, PR_PRIORITY_NORMAL, |
michael@0 | 287 | PR_LOCAL_THREAD, PR_JOINABLE_THREAD, 0); |
michael@0 | 288 | |
michael@0 | 289 | PR_Lock(sharedL.o2); |
michael@0 | 290 | LogNow("T1 waiting forever on o2", PR_SUCCESS); |
michael@0 | 291 | rv = PR_WaitCondVar(sharedL.cv2, PR_INTERVAL_NO_TIMEOUT); |
michael@0 | 292 | if (PR_SUCCESS == rv) LogNow("T1 resuming on o2", rv); |
michael@0 | 293 | else LogNow("T1 wait on o2 failed", rv); |
michael@0 | 294 | PR_Unlock(sharedL.o2); |
michael@0 | 295 | |
michael@0 | 296 | (void)PR_JoinThread(t2); |
michael@0 | 297 | (void)PR_JoinThread(t3); |
michael@0 | 298 | |
michael@0 | 299 | PR_DestroyLock(sharedL.o1); |
michael@0 | 300 | PR_DestroyLock(sharedL.o2); |
michael@0 | 301 | PR_DestroyCondVar(sharedL.cv1); |
michael@0 | 302 | PR_DestroyCondVar(sharedL.cv2); |
michael@0 | 303 | } /* T1Lock */ |
michael@0 | 304 | |
michael@0 | 305 | static PRIntn PR_CALLBACK RealMain( PRIntn argc, char **argv ) |
michael@0 | 306 | { |
michael@0 | 307 | PLOptStatus os; |
michael@0 | 308 | PLOptState *opt = PL_CreateOptState(argc, argv, "dhlmc"); |
michael@0 | 309 | PRBool locks = PR_FALSE, monitors = PR_FALSE, cmonitors = PR_FALSE; |
michael@0 | 310 | |
michael@0 | 311 | err = PR_GetSpecialFD(PR_StandardError); |
michael@0 | 312 | |
michael@0 | 313 | while (PL_OPT_EOL != (os = PL_GetNextOpt(opt))) |
michael@0 | 314 | { |
michael@0 | 315 | if (PL_OPT_BAD == os) continue; |
michael@0 | 316 | switch (opt->option) |
michael@0 | 317 | { |
michael@0 | 318 | case 'd': /* debug mode (noop) */ |
michael@0 | 319 | break; |
michael@0 | 320 | case 'l': /* locks */ |
michael@0 | 321 | locks = PR_TRUE; |
michael@0 | 322 | break; |
michael@0 | 323 | case 'm': /* monitors */ |
michael@0 | 324 | monitors = PR_TRUE; |
michael@0 | 325 | break; |
michael@0 | 326 | case 'c': /* cached monitors */ |
michael@0 | 327 | cmonitors = PR_TRUE; |
michael@0 | 328 | break; |
michael@0 | 329 | case 'h': /* needs guidance */ |
michael@0 | 330 | default: |
michael@0 | 331 | Help(); |
michael@0 | 332 | return 2; |
michael@0 | 333 | } |
michael@0 | 334 | } |
michael@0 | 335 | PL_DestroyOptState(opt); |
michael@0 | 336 | |
michael@0 | 337 | ml = PR_NewLock(); |
michael@0 | 338 | if (locks) T1Lock(); |
michael@0 | 339 | if (monitors) T1Mon(); |
michael@0 | 340 | if (cmonitors) T1CMon(); |
michael@0 | 341 | |
michael@0 | 342 | PR_DestroyLock(ml); |
michael@0 | 343 | |
michael@0 | 344 | PR_fprintf(err, "Done!\n"); |
michael@0 | 345 | return 0; |
michael@0 | 346 | } /* main */ |
michael@0 | 347 | |
michael@0 | 348 | |
michael@0 | 349 | int main(int argc, char **argv) |
michael@0 | 350 | { |
michael@0 | 351 | PRIntn rv; |
michael@0 | 352 | |
michael@0 | 353 | PR_STDIO_INIT(); |
michael@0 | 354 | rv = PR_Initialize(RealMain, argc, argv, 0); |
michael@0 | 355 | return rv; |
michael@0 | 356 | } /* main */ |
michael@0 | 357 | /* xnotify.c */ |