threads_scenarii.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. /*
  2. * Copyright (c) 2004, Bull S.A.. All rights reserved.
  3. * Created by: Sebastien Decugis
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it would be useful, but
  10. * WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. *
  13. * You should have received a copy of the GNU General Public License along
  14. * with this program; if not, write the Free Software Foundation, Inc.,
  15. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. *
  17. * This file is a helper file for the pthread_create tests
  18. * It defines the following objects:
  19. * scenarii: array of struct __scenario type.
  20. * NSCENAR : macro giving the total # of scenarii
  21. * scenar_init(): function to call before use the scenarii array.
  22. * scenar_fini(): function to call after end of use of the scenarii array.
  23. */
  24. static struct __scenario {
  25. /*
  26. * Object to hold the given configuration,
  27. * and which will be used to create the threads
  28. */
  29. pthread_attr_t ta;
  30. /* General parameters */
  31. /* 0 => joinable; 1 => detached */
  32. int detached;
  33. /* Scheduling parameters */
  34. /*
  35. * 0 => sched policy is inherited;
  36. * 1 => sched policy from the attr param
  37. */
  38. int explicitsched;
  39. /* 0 => default; 1=> SCHED_FIFO; 2=> SCHED_RR */
  40. int schedpolicy;
  41. /*
  42. * 0 => default sched param;
  43. * 1 => max value for sched param;
  44. * -1 => min value for sched param
  45. */
  46. int schedparam;
  47. /*
  48. * 0 => default contension scope;
  49. * 1 => alternative contension scope
  50. */
  51. int altscope;
  52. /* Stack parameters */
  53. /* 0 => system manages the stack; 1 => stack is provided */
  54. int altstack;
  55. /*
  56. * 0 => default guardsize;
  57. * 1=> guardsize is 0;
  58. * 2=> guard is 1 page
  59. * -- this setting only affect system stacks (not user's).
  60. */
  61. int guard;
  62. /*
  63. * 0 => default stack size;
  64. * 1 => stack size specified (min value)
  65. * -- ignored when stack is provided
  66. */
  67. int altsize;
  68. /* Additionnal information */
  69. /* object description */
  70. char *descr;
  71. /* Stores the stack start when an alternate stack is required */
  72. void *bottom;
  73. /*
  74. * This thread creation is expected to:
  75. * 0 => succeed; 1 => fail; 2 => unknown
  76. */
  77. int result;
  78. /*
  79. * This semaphore is used to signal the end of
  80. * the detached threads execution
  81. */
  82. sem_t sem;
  83. } scenarii[] =
  84. #define CASE(det, expl, scp, spa, sco, sta, gua, ssi, desc, res) \
  85. { \
  86. .detached = det, \
  87. .explicitsched = expl, \
  88. .schedpolicy = scp, \
  89. .schedparam = spa, \
  90. .altscope = sco, \
  91. .altstack = sta, \
  92. .guard = gua, \
  93. .altsize = ssi, \
  94. .descr = desc, \
  95. .bottom = NULL, \
  96. .result = res \
  97. }
  98. #define CASE_POS(det, expl, scp, spa, sco, sta, gua, ssi, desc) \
  99. CASE(det, expl, scp, spa, sco, sta, gua, ssi, desc, 0)
  100. #define CASE_NEG(det, expl, scp, spa, sco, sta, gua, ssi, desc) \
  101. CASE(det, expl, scp, spa, sco, sta, gua, ssi, desc, 1)
  102. #define CASE_UNK(det, expl, scp, spa, sco, sta, gua, ssi, desc) \
  103. CASE(det, expl, scp, spa, sco, sta, gua, ssi, desc, 2)
  104. /*
  105. * This array gives the different combinations of threads
  106. * attributes for the testcases.
  107. *
  108. * Some combinations must be avoided.
  109. * -> Do not have a detached thread use an alternative stack;
  110. * as we don't know when the thread terminates to free the stack memory
  111. * -> ... (to be completed)
  112. */
  113. {
  114. /* Unary tests */
  115. CASE_POS(0, 0, 0, 0, 0, 0, 0, 0, "default"),
  116. CASE_POS(1, 0, 0, 0, 0, 0, 0, 0, "detached"),
  117. CASE_POS(0, 1, 0, 0, 0, 0, 0, 0, "Explicit sched"),
  118. CASE_UNK(0, 0, 1, 0, 0, 0, 0, 0, "FIFO Policy"),
  119. CASE_UNK(0, 0, 2, 0, 0, 0, 0, 0, "RR Policy"),
  120. CASE_UNK(0, 0, 0, 1, 0, 0, 0, 0, "Max sched param"),
  121. CASE_UNK(0, 0, 0, -1, 0, 0, 0, 0, "Min sched param"),
  122. CASE_POS(0, 0, 0, 0, 1, 0, 0, 0, "Alternative contension scope"),
  123. CASE_POS(0, 0, 0, 0, 0, 1, 0, 0, "Alternative stack"),
  124. CASE_POS(0, 0, 0, 0, 0, 0, 1, 0, "No guard size"),
  125. CASE_UNK(0, 0, 0, 0, 0, 0, 2, 0, "1p guard size"),
  126. CASE_POS(0, 0, 0, 0, 0, 0, 0, 1, "Min stack size"),
  127. /* Stack play */
  128. CASE_POS(0, 0, 0, 0, 0, 0, 1, 1, "Min stack size, no guard"),
  129. CASE_UNK(0, 0, 0, 0, 0, 0, 2, 1, "Min stack size, 1p guard"),
  130. CASE_POS(1, 0, 0, 0, 0, 1, 0, 0, "Detached, Alternative stack"),
  131. CASE_POS(1, 0, 0, 0, 0, 0, 1, 1,
  132. "Detached, Min stack size, no guard"), CASE_UNK(1, 0, 0, 0,
  133. 0, 0, 2, 1,
  134. "Detached, Min stack size, 1p guard"),
  135. /*
  136. * Scheduling play
  137. * -- all results are unknown since it might depend on
  138. * the user priviledges
  139. */
  140. CASE_UNK(0, 1, 1, 1, 0, 0, 0, 0, "Explicit FIFO max param"),
  141. CASE_UNK(0, 1, 2, 1, 0, 0, 0, 0,
  142. "Explicit RR max param"),
  143. CASE_UNK(0, 1, 1, -1, 0, 0, 0, 0,
  144. "Explicit FIFO min param"),
  145. CASE_UNK(0, 1, 2, -1, 0, 0, 0, 0,
  146. "Explicit RR min param"),
  147. CASE_UNK(0, 1, 1, 1, 1, 0, 0, 0,
  148. "Explicit FIFO max param, alt scope"),
  149. CASE_UNK(0, 1, 2, 1, 1, 0, 0, 0,
  150. "Explicit RR max param, alt scope"),
  151. CASE_UNK(0, 1, 1, -1, 1, 0, 0, 0,
  152. "Explicit FIFO min param, alt scope"),
  153. CASE_UNK(0, 1, 2, -1, 1, 0, 0, 0,
  154. "Explicit RR min param, alt scope"),
  155. CASE_UNK(1, 1, 1, 1, 0, 0, 0, 0,
  156. "Detached, explicit FIFO max param"),
  157. CASE_UNK(1, 1, 2, 1, 0, 0, 0, 0,
  158. "Detached, explicit RR max param"),
  159. CASE_UNK(1, 1, 1, -1, 0, 0, 0, 0,
  160. "Detached, explicit FIFO min param"),
  161. CASE_UNK(1, 1, 2, -1, 0, 0, 0, 0,
  162. "Detached, explicit RR min param"),
  163. CASE_UNK(1, 1, 1, 1, 1, 0, 0, 0,
  164. "Detached, explicit FIFO max param,"
  165. " alt scope"), CASE_UNK(1, 1, 2, 1,
  166. 1,
  167. 0,
  168. 0,
  169. 0,
  170. "Detached, explicit RR max param,"
  171. " alt scope"),
  172. CASE_UNK(1, 1, 1, -1, 1, 0, 0, 0,
  173. "Detached, explicit FIFO min param,"
  174. " alt scope"), CASE_UNK(1, 1, 2,
  175. -1,
  176. 1,
  177. 0,
  178. 0,
  179. 0,
  180. "Detached, explicit RR min param,"
  181. " alt scope"),};
  182. #define NSCENAR (sizeof(scenarii) / sizeof(scenarii[0]))
  183. /*
  184. * This function will initialize every pthread_attr_t object
  185. * in the scenarii array
  186. */
  187. static void scenar_init(void)
  188. {
  189. int ret = 0;
  190. unsigned int i;
  191. int old;
  192. long pagesize, minstacksize;
  193. long tsa, tss, tps;
  194. pagesize = sysconf(_SC_PAGESIZE);
  195. minstacksize = sysconf(_SC_THREAD_STACK_MIN);
  196. tsa = sysconf(_SC_THREAD_ATTR_STACKADDR);
  197. tss = sysconf(_SC_THREAD_ATTR_STACKSIZE);
  198. tps = sysconf(_SC_THREAD_PRIORITY_SCHEDULING);
  199. #if VERBOSE > 0
  200. output("System abilities:\n");
  201. output(" TSA: %li\n", tsa);
  202. output(" TSS: %li\n", tss);
  203. output(" TPS: %li\n", tps);
  204. output(" pagesize: %li\n", pagesize);
  205. output(" min stack size: %li\n", minstacksize);
  206. #endif
  207. if (minstacksize % pagesize)
  208. UNTESTED("The min stack size is not a multiple"
  209. " of the page size");
  210. for (i = 0; i < NSCENAR; i++) {
  211. #if VERBOSE > 2
  212. output("Initializing attribute for scenario %i: %s\n",
  213. i, scenarii[i].descr);
  214. #endif
  215. ret = pthread_attr_init(&scenarii[i].ta);
  216. if (ret != 0)
  217. UNRESOLVED(ret, "Failed to initialize a"
  218. " thread attribute object");
  219. /* Set the attributes according to the scenario */
  220. if (scenarii[i].detached == 1) {
  221. ret = pthread_attr_setdetachstate(&scenarii[i].ta,
  222. PTHREAD_CREATE_DETACHED);
  223. if (ret != 0)
  224. UNRESOLVED(ret, "Unable to set detachstate");
  225. } else {
  226. ret =
  227. pthread_attr_getdetachstate(&scenarii[i].ta, &old);
  228. if (ret != 0)
  229. UNRESOLVED(ret, "Unable to get detachstate"
  230. " from initialized attribute");
  231. if (old != PTHREAD_CREATE_JOINABLE)
  232. FAILED("The default attribute is not"
  233. " PTHREAD_CREATE_JOINABLE");
  234. }
  235. #if VERBOSE > 4
  236. output("Detach state was set successfully\n");
  237. #endif
  238. /* Sched related attributes */
  239. /*
  240. * This routine is dependent on the Thread Execution
  241. * Scheduling option
  242. */
  243. if (tps > 0) {
  244. if (scenarii[i].explicitsched == 1)
  245. ret =
  246. pthread_attr_setinheritsched(&scenarii
  247. [i].ta,
  248. PTHREAD_EXPLICIT_SCHED);
  249. else
  250. ret =
  251. pthread_attr_setinheritsched(&scenarii
  252. [i].ta,
  253. PTHREAD_INHERIT_SCHED);
  254. if (ret != 0)
  255. UNRESOLVED(ret, "Unable to set inheritsched"
  256. " attribute");
  257. #if VERBOSE > 4
  258. output("inheritsched state was set successfully\n");
  259. #endif
  260. }
  261. #if VERBOSE > 4
  262. else
  263. output("TPS unsupported => inheritsched parameter"
  264. " untouched\n");
  265. #endif
  266. if (tps > 0) {
  267. if (scenarii[i].schedpolicy == 1)
  268. ret =
  269. pthread_attr_setschedpolicy(&scenarii[i].ta,
  270. SCHED_FIFO);
  271. if (scenarii[i].schedpolicy == 2)
  272. ret =
  273. pthread_attr_setschedpolicy(&scenarii[i].ta,
  274. SCHED_RR);
  275. if (ret != 0)
  276. UNRESOLVED(ret, "Unable to set the"
  277. " sched policy");
  278. #if VERBOSE > 4
  279. if (scenarii[i].schedpolicy)
  280. output("Sched policy was set successfully\n");
  281. else
  282. output("Sched policy untouched\n");
  283. #endif
  284. }
  285. #if VERBOSE > 4
  286. else
  287. output("TPS unsupported => sched policy parameter"
  288. " untouched\n");
  289. #endif
  290. if (scenarii[i].schedparam != 0) {
  291. struct sched_param sp;
  292. ret =
  293. pthread_attr_getschedpolicy(&scenarii[i].ta, &old);
  294. if (ret != 0)
  295. UNRESOLVED(ret, "Unable to get sched policy"
  296. " from attribute");
  297. if (scenarii[i].schedparam == 1)
  298. sp.sched_priority = sched_get_priority_max(old);
  299. if (scenarii[i].schedparam == -1)
  300. sp.sched_priority = sched_get_priority_min(old);
  301. ret = pthread_attr_setschedparam(&scenarii[i].ta, &sp);
  302. if (ret != 0)
  303. UNRESOLVED(ret,
  304. "Failed to set the sched param");
  305. #if VERBOSE > 4
  306. output("Sched param was set successfully to %i\n",
  307. sp.sched_priority);
  308. } else {
  309. output("Sched param untouched\n");
  310. #endif
  311. }
  312. if (tps > 0) {
  313. ret = pthread_attr_getscope(&scenarii[i].ta, &old);
  314. if (ret != 0)
  315. UNRESOLVED(ret, "Failed to get contension"
  316. " scope from thread attribute");
  317. if (scenarii[i].altscope != 0) {
  318. if (old == PTHREAD_SCOPE_PROCESS)
  319. old = PTHREAD_SCOPE_SYSTEM;
  320. else
  321. old = PTHREAD_SCOPE_PROCESS;
  322. ret =
  323. pthread_attr_setscope(&scenarii[i].ta, old);
  324. #if VERBOSE > 0
  325. if (ret != 0)
  326. output("WARNING: The TPS option is"
  327. " claimed to be supported but"
  328. " setscope fails\n");
  329. #endif
  330. #if VERBOSE > 4
  331. output("Contension scope set to %s\n",
  332. old == PTHREAD_SCOPE_PROCESS ?
  333. "PTHREAD_SCOPE_PROCESS" :
  334. "PTHREAD_SCOPE_SYSTEM");
  335. } else {
  336. output("Contension scope untouched (%s)\n",
  337. old == PTHREAD_SCOPE_PROCESS ?
  338. "PTHREAD_SCOPE_PROCESS" :
  339. "PTHREAD_SCOPE_SYSTEM");
  340. #endif
  341. }
  342. }
  343. #if VERBOSE > 4
  344. else
  345. output("TPS unsupported => sched contension scope"
  346. " parameter untouched\n");
  347. #endif
  348. /* Stack related attributes */
  349. /*
  350. * This routine is dependent on the Thread Stack Address
  351. * Attribute and Thread Stack Size Attribute options
  352. */
  353. if ((tss > 0) && (tsa > 0)) {
  354. if (scenarii[i].altstack != 0) {
  355. /*
  356. * This is slightly more complicated.
  357. * We need to alloc a new stackand free
  358. * it upon test termination.
  359. * We will alloc with a simulated guardsize
  360. * of 1 pagesize */
  361. scenarii[i].bottom = malloc(minstacksize + pagesize);
  362. if (scenarii[i].bottom == NULL)
  363. UNRESOLVED(errno, "Unable to alloc"
  364. " enough memory for"
  365. " alternative stack");
  366. ret = pthread_attr_setstack(&scenarii[i].ta,
  367. scenarii[i].bottom,
  368. minstacksize);
  369. if (ret != 0)
  370. UNRESOLVED(ret, "Failed to specify"
  371. " alternate stack");
  372. #if VERBOSE > 1
  373. output("Alternate stack created successfully."
  374. " Bottom=%p, Size=%i\n",
  375. scenarii[i].bottom, minstacksize);
  376. #endif
  377. }
  378. }
  379. #if VERBOSE > 4
  380. else
  381. output("TSA or TSS unsupported => "
  382. "No alternative stack\n");
  383. #endif
  384. #ifndef WITHOUT_XOPEN
  385. if (scenarii[i].guard != 0) {
  386. if (scenarii[i].guard == 1)
  387. ret =
  388. pthread_attr_setguardsize(&scenarii[i].ta,
  389. 0);
  390. if (scenarii[i].guard == 2)
  391. ret =
  392. pthread_attr_setguardsize(&scenarii[i].ta,
  393. pagesize);
  394. if (ret != 0)
  395. UNRESOLVED(ret, "Unable to set guard area"
  396. " size in thread stack");
  397. #if VERBOSE > 4
  398. output("Guard size set to %i\n",
  399. scenarii[i].guard == 1 ? 1 : pagesize);
  400. #endif
  401. }
  402. #endif
  403. if (tss > 0) {
  404. if (scenarii[i].altsize != 0) {
  405. ret = pthread_attr_setstacksize(&scenarii[i].ta,
  406. minstacksize);
  407. if (ret != 0)
  408. UNRESOLVED(ret, "Unable to change"
  409. " stack size");
  410. #if VERBOSE > 4
  411. output("Stack size set to %i (this is the "
  412. "min)\n", minstacksize);
  413. #endif
  414. }
  415. }
  416. #if VERBOSE > 4
  417. else
  418. output("TSS unsupported => stack size unchanged\n");
  419. #endif
  420. ret = sem_init(&scenarii[i].sem, 0, 0);
  421. if (ret == -1)
  422. UNRESOLVED(errno, "Unable to init a semaphore");
  423. }
  424. #if VERBOSE > 0
  425. output("All %i thread attribute objects were initialized\n\n", NSCENAR);
  426. #endif
  427. }
  428. /*
  429. * This function will free all resources consumed
  430. * in the scenar_init() routine
  431. */
  432. static void scenar_fini(void)
  433. {
  434. int ret = 0;
  435. unsigned int i;
  436. for (i = 0; i < NSCENAR; i++) {
  437. if (scenarii[i].bottom != NULL)
  438. free(scenarii[i].bottom);
  439. ret = sem_destroy(&scenarii[i].sem);
  440. if (ret == -1)
  441. UNRESOLVED(errno, "Unable to destroy a semaphore");
  442. ret = pthread_attr_destroy(&scenarii[i].ta);
  443. if (ret != 0)
  444. UNRESOLVED(ret, "Failed to destroy a thread"
  445. " attribute object");
  446. }
  447. }
  448. static unsigned int sc;
  449. #ifdef STD_MAIN
  450. static void *threaded(void *arg);
  451. int main(void)
  452. {
  453. int ret = 0;
  454. pthread_t child;
  455. output_init();
  456. scenar_init();
  457. for (sc = 0; sc < NSCENAR; sc++) {
  458. #if VERBOSE > 0
  459. output("-----\n");
  460. output("Starting test with scenario (%i): %s\n",
  461. sc, scenarii[sc].descr);
  462. #endif
  463. ret = pthread_create(&child, &scenarii[sc].ta, threaded, NULL);
  464. switch (scenarii[sc].result) {
  465. case 0: /* Operation was expected to succeed */
  466. if (ret != 0)
  467. UNRESOLVED(ret, "Failed to create this thread");
  468. break;
  469. case 1: /* Operation was expected to fail */
  470. if (ret == 0)
  471. UNRESOLVED(-1, "An error was expected but the"
  472. " thread creation succeeded");
  473. break;
  474. case 2: /* We did not know the expected result */
  475. default:
  476. #if VERBOSE > 0
  477. if (ret == 0)
  478. output("Thread has been created successfully"
  479. " for this scenario\n");
  480. else
  481. output("Thread creation failed with the error:"
  482. " %s\n", strerror(ret));
  483. #endif
  484. }
  485. if (ret == 0) {
  486. if (scenarii[sc].detached == 0) {
  487. ret = pthread_join(child, NULL);
  488. if (ret != 0)
  489. UNRESOLVED(ret, "Unable to join a"
  490. " thread");
  491. } else {
  492. /* Just wait for the thread to terminate */
  493. do {
  494. ret = sem_wait(&scenarii[sc].sem);
  495. } while ((ret == -1) && (errno == EINTR));
  496. if (ret == -1)
  497. UNRESOLVED(errno, "Failed to wait for"
  498. " the semaphore");
  499. }
  500. }
  501. }
  502. scenar_fini();
  503. #if VERBOSE > 0
  504. output("-----\n");
  505. output("All test data destroyed\n");
  506. output("Test PASSED\n");
  507. #endif
  508. PASSED;
  509. }
  510. #endif