xnotify.c 11 KB

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