io_timeoutk.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. /*
  6. ** name io_timeoutk.c
  7. ** Description:Test socket IO timeouts (kernel level)
  8. **
  9. ** Modification History:
  10. ** 19-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
  11. ** The debug mode will print all of the printfs associated with this test.
  12. ** The regress mode will be the default mode. Since the regress tool limits
  13. ** the output to a one line status:PASS or FAIL,all of the printf statements
  14. ** have been handled with an if (debug_mode) statement.
  15. ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
  16. ** recognize the return code from tha main program.
  17. ***********************************************************************/
  18. /***********************************************************************
  19. ** Includes
  20. ***********************************************************************/
  21. /* Used to get the command line option */
  22. #include "plgetopt.h"
  23. #include <stdio.h>
  24. #include "nspr.h"
  25. #define NUM_THREADS 1
  26. #define BASE_PORT 8000
  27. #define DEFAULT_ACCEPT_TIMEOUT 2
  28. typedef struct threadInfo {
  29. PRInt16 id;
  30. PRInt16 accept_timeout;
  31. PRLock *dead_lock;
  32. PRCondVar *dead_cv;
  33. PRInt32 *alive;
  34. } threadInfo;
  35. PRIntn failed_already=0;
  36. PRIntn debug_mode;
  37. void
  38. thread_main(void *_info)
  39. {
  40. threadInfo *info = (threadInfo *)_info;
  41. PRNetAddr listenAddr;
  42. PRNetAddr clientAddr;
  43. PRFileDesc *listenSock = NULL;
  44. PRFileDesc *clientSock;
  45. PRStatus rv;
  46. if (debug_mode) {
  47. printf("thread %d is alive\n", info->id);
  48. }
  49. listenSock = PR_NewTCPSocket();
  50. if (!listenSock) {
  51. if (debug_mode) {
  52. printf("unable to create listen socket\n");
  53. }
  54. goto dead;
  55. }
  56. listenAddr.inet.family = AF_INET;
  57. listenAddr.inet.port = PR_htons(BASE_PORT + info->id);
  58. listenAddr.inet.ip = PR_htonl(INADDR_ANY);
  59. rv = PR_Bind(listenSock, &listenAddr);
  60. if (rv == PR_FAILURE) {
  61. if (debug_mode) {
  62. printf("unable to bind\n");
  63. }
  64. goto dead;
  65. }
  66. rv = PR_Listen(listenSock, 4);
  67. if (rv == PR_FAILURE) {
  68. if (debug_mode) {
  69. printf("unable to listen\n");
  70. }
  71. goto dead;
  72. }
  73. if (debug_mode) printf("thread %d going into accept for %d seconds\n",
  74. info->id, info->accept_timeout + info->id);
  75. clientSock = PR_Accept(listenSock, &clientAddr, PR_SecondsToInterval(info->accept_timeout +info->id));
  76. if (clientSock == NULL) {
  77. if (PR_GetError() == PR_IO_TIMEOUT_ERROR)
  78. if (debug_mode) {
  79. printf("PR_Accept() timeout worked!\n");
  80. printf("TEST FAILED! PR_Accept() returned error %d\n",
  81. PR_GetError());
  82. }
  83. else {
  84. failed_already=1;
  85. }
  86. } else {
  87. if (debug_mode) {
  88. printf ("TEST FAILED! PR_Accept() succeeded?\n");
  89. }
  90. else {
  91. failed_already=1;
  92. }
  93. PR_Close(clientSock);
  94. }
  95. dead:
  96. if (listenSock) {
  97. PR_Close(listenSock);
  98. }
  99. PR_Lock(info->dead_lock);
  100. (*info->alive)--;
  101. PR_NotifyCondVar(info->dead_cv);
  102. PR_Unlock(info->dead_lock);
  103. if (debug_mode) {
  104. printf("thread %d is dead\n", info->id);
  105. }
  106. }
  107. void
  108. thread_test(PRInt32 scope, PRInt32 num_threads)
  109. {
  110. PRInt32 index;
  111. PRThread *thr;
  112. PRLock *dead_lock;
  113. PRCondVar *dead_cv;
  114. PRInt32 alive;
  115. if (debug_mode) {
  116. printf("IO Timeout test started with %d threads\n", num_threads);
  117. }
  118. dead_lock = PR_NewLock();
  119. dead_cv = PR_NewCondVar(dead_lock);
  120. alive = num_threads;
  121. for (index = 0; index < num_threads; index++) {
  122. threadInfo *info = (threadInfo *)malloc(sizeof(threadInfo));
  123. info->id = index;
  124. info->dead_lock = dead_lock;
  125. info->dead_cv = dead_cv;
  126. info->alive = &alive;
  127. info->accept_timeout = DEFAULT_ACCEPT_TIMEOUT;
  128. thr = PR_CreateThread( PR_USER_THREAD,
  129. thread_main,
  130. (void *)info,
  131. PR_PRIORITY_NORMAL,
  132. scope,
  133. PR_UNJOINABLE_THREAD,
  134. 0);
  135. if (!thr) {
  136. PR_Lock(dead_lock);
  137. alive--;
  138. PR_Unlock(dead_lock);
  139. }
  140. }
  141. PR_Lock(dead_lock);
  142. while(alive) {
  143. if (debug_mode) {
  144. printf("main loop awake; alive = %d\n", alive);
  145. }
  146. PR_WaitCondVar(dead_cv, PR_INTERVAL_NO_TIMEOUT);
  147. }
  148. PR_Unlock(dead_lock);
  149. }
  150. int main(int argc, char **argv)
  151. {
  152. PRInt32 num_threads;
  153. /* The command line argument: -d is used to determine if the test is being run
  154. in debug mode. The regress tool requires only one line output:PASS or FAIL.
  155. All of the printfs associated with this test has been handled with a if (debug_mode)
  156. test.
  157. Usage: test_name -d
  158. */
  159. PLOptStatus os;
  160. PLOptState *opt = PL_CreateOptState(argc, argv, "d:");
  161. while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
  162. {
  163. if (PL_OPT_BAD == os) {
  164. continue;
  165. }
  166. switch (opt->option)
  167. {
  168. case 'd': /* debug mode */
  169. debug_mode = 1;
  170. break;
  171. default:
  172. break;
  173. }
  174. }
  175. PL_DestroyOptState(opt);
  176. /* main test */
  177. if (argc > 2) {
  178. num_threads = atoi(argv[2]);
  179. }
  180. else {
  181. num_threads = NUM_THREADS;
  182. }
  183. PR_Init(PR_USER_THREAD, PR_PRIORITY_LOW, 0);
  184. PR_STDIO_INIT();
  185. if (debug_mode) {
  186. printf("kernel level test\n");
  187. }
  188. thread_test(PR_GLOBAL_THREAD, num_threads);
  189. PR_Cleanup();
  190. if(failed_already) {
  191. return 1;
  192. }
  193. else {
  194. return 0;
  195. }
  196. }