123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555 |
- /*
- * Copyright (c) 2004, Bull S.A.. All rights reserved.
- * Created by: Sebastien Decugis
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * This file is a helper file for the pthread_create tests
- * It defines the following objects:
- * scenarii: array of struct __scenario type.
- * NSCENAR : macro giving the total # of scenarii
- * scenar_init(): function to call before use the scenarii array.
- * scenar_fini(): function to call after end of use of the scenarii array.
- */
- static struct __scenario {
- /*
- * Object to hold the given configuration,
- * and which will be used to create the threads
- */
- pthread_attr_t ta;
- /* General parameters */
- /* 0 => joinable; 1 => detached */
- int detached;
- /* Scheduling parameters */
- /*
- * 0 => sched policy is inherited;
- * 1 => sched policy from the attr param
- */
- int explicitsched;
- /* 0 => default; 1=> SCHED_FIFO; 2=> SCHED_RR */
- int schedpolicy;
- /*
- * 0 => default sched param;
- * 1 => max value for sched param;
- * -1 => min value for sched param
- */
- int schedparam;
- /*
- * 0 => default contension scope;
- * 1 => alternative contension scope
- */
- int altscope;
- /* Stack parameters */
- /* 0 => system manages the stack; 1 => stack is provided */
- int altstack;
- /*
- * 0 => default guardsize;
- * 1=> guardsize is 0;
- * 2=> guard is 1 page
- * -- this setting only affect system stacks (not user's).
- */
- int guard;
- /*
- * 0 => default stack size;
- * 1 => stack size specified (min value)
- * -- ignored when stack is provided
- */
- int altsize;
- /* Additionnal information */
- /* object description */
- char *descr;
- /* Stores the stack start when an alternate stack is required */
- void *bottom;
- /*
- * This thread creation is expected to:
- * 0 => succeed; 1 => fail; 2 => unknown
- */
- int result;
- /*
- * This semaphore is used to signal the end of
- * the detached threads execution
- */
- sem_t sem;
- } scenarii[] =
- #define CASE(det, expl, scp, spa, sco, sta, gua, ssi, desc, res) \
- { \
- .detached = det, \
- .explicitsched = expl, \
- .schedpolicy = scp, \
- .schedparam = spa, \
- .altscope = sco, \
- .altstack = sta, \
- .guard = gua, \
- .altsize = ssi, \
- .descr = desc, \
- .bottom = NULL, \
- .result = res \
- }
- #define CASE_POS(det, expl, scp, spa, sco, sta, gua, ssi, desc) \
- CASE(det, expl, scp, spa, sco, sta, gua, ssi, desc, 0)
- #define CASE_NEG(det, expl, scp, spa, sco, sta, gua, ssi, desc) \
- CASE(det, expl, scp, spa, sco, sta, gua, ssi, desc, 1)
- #define CASE_UNK(det, expl, scp, spa, sco, sta, gua, ssi, desc) \
- CASE(det, expl, scp, spa, sco, sta, gua, ssi, desc, 2)
- /*
- * This array gives the different combinations of threads
- * attributes for the testcases.
- *
- * Some combinations must be avoided.
- * -> Do not have a detached thread use an alternative stack;
- * as we don't know when the thread terminates to free the stack memory
- * -> ... (to be completed)
- */
- {
- /* Unary tests */
- CASE_POS(0, 0, 0, 0, 0, 0, 0, 0, "default"),
- CASE_POS(1, 0, 0, 0, 0, 0, 0, 0, "detached"),
- CASE_POS(0, 1, 0, 0, 0, 0, 0, 0, "Explicit sched"),
- CASE_UNK(0, 0, 1, 0, 0, 0, 0, 0, "FIFO Policy"),
- CASE_UNK(0, 0, 2, 0, 0, 0, 0, 0, "RR Policy"),
- CASE_UNK(0, 0, 0, 1, 0, 0, 0, 0, "Max sched param"),
- CASE_UNK(0, 0, 0, -1, 0, 0, 0, 0, "Min sched param"),
- CASE_POS(0, 0, 0, 0, 1, 0, 0, 0, "Alternative contension scope"),
- CASE_POS(0, 0, 0, 0, 0, 1, 0, 0, "Alternative stack"),
- CASE_POS(0, 0, 0, 0, 0, 0, 1, 0, "No guard size"),
- CASE_UNK(0, 0, 0, 0, 0, 0, 2, 0, "1p guard size"),
- CASE_POS(0, 0, 0, 0, 0, 0, 0, 1, "Min stack size"),
- /* Stack play */
- CASE_POS(0, 0, 0, 0, 0, 0, 1, 1, "Min stack size, no guard"),
- CASE_UNK(0, 0, 0, 0, 0, 0, 2, 1, "Min stack size, 1p guard"),
- CASE_POS(1, 0, 0, 0, 0, 1, 0, 0, "Detached, Alternative stack"),
- CASE_POS(1, 0, 0, 0, 0, 0, 1, 1,
- "Detached, Min stack size, no guard"), CASE_UNK(1, 0, 0, 0,
- 0, 0, 2, 1,
- "Detached, Min stack size, 1p guard"),
- /*
- * Scheduling play
- * -- all results are unknown since it might depend on
- * the user priviledges
- */
- CASE_UNK(0, 1, 1, 1, 0, 0, 0, 0, "Explicit FIFO max param"),
- CASE_UNK(0, 1, 2, 1, 0, 0, 0, 0,
- "Explicit RR max param"),
- CASE_UNK(0, 1, 1, -1, 0, 0, 0, 0,
- "Explicit FIFO min param"),
- CASE_UNK(0, 1, 2, -1, 0, 0, 0, 0,
- "Explicit RR min param"),
- CASE_UNK(0, 1, 1, 1, 1, 0, 0, 0,
- "Explicit FIFO max param, alt scope"),
- CASE_UNK(0, 1, 2, 1, 1, 0, 0, 0,
- "Explicit RR max param, alt scope"),
- CASE_UNK(0, 1, 1, -1, 1, 0, 0, 0,
- "Explicit FIFO min param, alt scope"),
- CASE_UNK(0, 1, 2, -1, 1, 0, 0, 0,
- "Explicit RR min param, alt scope"),
- CASE_UNK(1, 1, 1, 1, 0, 0, 0, 0,
- "Detached, explicit FIFO max param"),
- CASE_UNK(1, 1, 2, 1, 0, 0, 0, 0,
- "Detached, explicit RR max param"),
- CASE_UNK(1, 1, 1, -1, 0, 0, 0, 0,
- "Detached, explicit FIFO min param"),
- CASE_UNK(1, 1, 2, -1, 0, 0, 0, 0,
- "Detached, explicit RR min param"),
- CASE_UNK(1, 1, 1, 1, 1, 0, 0, 0,
- "Detached, explicit FIFO max param,"
- " alt scope"), CASE_UNK(1, 1, 2, 1,
- 1,
- 0,
- 0,
- 0,
- "Detached, explicit RR max param,"
- " alt scope"),
- CASE_UNK(1, 1, 1, -1, 1, 0, 0, 0,
- "Detached, explicit FIFO min param,"
- " alt scope"), CASE_UNK(1, 1, 2,
- -1,
- 1,
- 0,
- 0,
- 0,
- "Detached, explicit RR min param,"
- " alt scope"),};
- #define NSCENAR (sizeof(scenarii) / sizeof(scenarii[0]))
- /*
- * This function will initialize every pthread_attr_t object
- * in the scenarii array
- */
- static void scenar_init(void)
- {
- int ret = 0;
- unsigned int i;
- int old;
- long pagesize, minstacksize;
- long tsa, tss, tps;
- pagesize = sysconf(_SC_PAGESIZE);
- minstacksize = sysconf(_SC_THREAD_STACK_MIN);
- tsa = sysconf(_SC_THREAD_ATTR_STACKADDR);
- tss = sysconf(_SC_THREAD_ATTR_STACKSIZE);
- tps = sysconf(_SC_THREAD_PRIORITY_SCHEDULING);
- #if VERBOSE > 0
- output("System abilities:\n");
- output(" TSA: %li\n", tsa);
- output(" TSS: %li\n", tss);
- output(" TPS: %li\n", tps);
- output(" pagesize: %li\n", pagesize);
- output(" min stack size: %li\n", minstacksize);
- #endif
- if (minstacksize % pagesize)
- UNTESTED("The min stack size is not a multiple"
- " of the page size");
- for (i = 0; i < NSCENAR; i++) {
- #if VERBOSE > 2
- output("Initializing attribute for scenario %i: %s\n",
- i, scenarii[i].descr);
- #endif
- ret = pthread_attr_init(&scenarii[i].ta);
- if (ret != 0)
- UNRESOLVED(ret, "Failed to initialize a"
- " thread attribute object");
- /* Set the attributes according to the scenario */
- if (scenarii[i].detached == 1) {
- ret = pthread_attr_setdetachstate(&scenarii[i].ta,
- PTHREAD_CREATE_DETACHED);
- if (ret != 0)
- UNRESOLVED(ret, "Unable to set detachstate");
- } else {
- ret =
- pthread_attr_getdetachstate(&scenarii[i].ta, &old);
- if (ret != 0)
- UNRESOLVED(ret, "Unable to get detachstate"
- " from initialized attribute");
- if (old != PTHREAD_CREATE_JOINABLE)
- FAILED("The default attribute is not"
- " PTHREAD_CREATE_JOINABLE");
- }
- #if VERBOSE > 4
- output("Detach state was set successfully\n");
- #endif
- /* Sched related attributes */
- /*
- * This routine is dependent on the Thread Execution
- * Scheduling option
- */
- if (tps > 0) {
- if (scenarii[i].explicitsched == 1)
- ret =
- pthread_attr_setinheritsched(&scenarii
- [i].ta,
- PTHREAD_EXPLICIT_SCHED);
- else
- ret =
- pthread_attr_setinheritsched(&scenarii
- [i].ta,
- PTHREAD_INHERIT_SCHED);
- if (ret != 0)
- UNRESOLVED(ret, "Unable to set inheritsched"
- " attribute");
- #if VERBOSE > 4
- output("inheritsched state was set successfully\n");
- #endif
- }
- #if VERBOSE > 4
- else
- output("TPS unsupported => inheritsched parameter"
- " untouched\n");
- #endif
- if (tps > 0) {
- if (scenarii[i].schedpolicy == 1)
- ret =
- pthread_attr_setschedpolicy(&scenarii[i].ta,
- SCHED_FIFO);
- if (scenarii[i].schedpolicy == 2)
- ret =
- pthread_attr_setschedpolicy(&scenarii[i].ta,
- SCHED_RR);
- if (ret != 0)
- UNRESOLVED(ret, "Unable to set the"
- " sched policy");
- #if VERBOSE > 4
- if (scenarii[i].schedpolicy)
- output("Sched policy was set successfully\n");
- else
- output("Sched policy untouched\n");
- #endif
- }
- #if VERBOSE > 4
- else
- output("TPS unsupported => sched policy parameter"
- " untouched\n");
- #endif
- if (scenarii[i].schedparam != 0) {
- struct sched_param sp;
- ret =
- pthread_attr_getschedpolicy(&scenarii[i].ta, &old);
- if (ret != 0)
- UNRESOLVED(ret, "Unable to get sched policy"
- " from attribute");
- if (scenarii[i].schedparam == 1)
- sp.sched_priority = sched_get_priority_max(old);
- if (scenarii[i].schedparam == -1)
- sp.sched_priority = sched_get_priority_min(old);
- ret = pthread_attr_setschedparam(&scenarii[i].ta, &sp);
- if (ret != 0)
- UNRESOLVED(ret,
- "Failed to set the sched param");
- #if VERBOSE > 4
- output("Sched param was set successfully to %i\n",
- sp.sched_priority);
- } else {
- output("Sched param untouched\n");
- #endif
- }
- if (tps > 0) {
- ret = pthread_attr_getscope(&scenarii[i].ta, &old);
- if (ret != 0)
- UNRESOLVED(ret, "Failed to get contension"
- " scope from thread attribute");
- if (scenarii[i].altscope != 0) {
- if (old == PTHREAD_SCOPE_PROCESS)
- old = PTHREAD_SCOPE_SYSTEM;
- else
- old = PTHREAD_SCOPE_PROCESS;
- ret =
- pthread_attr_setscope(&scenarii[i].ta, old);
- #if VERBOSE > 0
- if (ret != 0)
- output("WARNING: The TPS option is"
- " claimed to be supported but"
- " setscope fails\n");
- #endif
- #if VERBOSE > 4
- output("Contension scope set to %s\n",
- old == PTHREAD_SCOPE_PROCESS ?
- "PTHREAD_SCOPE_PROCESS" :
- "PTHREAD_SCOPE_SYSTEM");
- } else {
- output("Contension scope untouched (%s)\n",
- old == PTHREAD_SCOPE_PROCESS ?
- "PTHREAD_SCOPE_PROCESS" :
- "PTHREAD_SCOPE_SYSTEM");
- #endif
- }
- }
- #if VERBOSE > 4
- else
- output("TPS unsupported => sched contension scope"
- " parameter untouched\n");
- #endif
- /* Stack related attributes */
- /*
- * This routine is dependent on the Thread Stack Address
- * Attribute and Thread Stack Size Attribute options
- */
- if ((tss > 0) && (tsa > 0)) {
- if (scenarii[i].altstack != 0) {
- /*
- * This is slightly more complicated.
- * We need to alloc a new stackand free
- * it upon test termination.
- * We will alloc with a simulated guardsize
- * of 1 pagesize */
- scenarii[i].bottom = malloc(minstacksize + pagesize);
- if (scenarii[i].bottom == NULL)
- UNRESOLVED(errno, "Unable to alloc"
- " enough memory for"
- " alternative stack");
- ret = pthread_attr_setstack(&scenarii[i].ta,
- scenarii[i].bottom,
- minstacksize);
- if (ret != 0)
- UNRESOLVED(ret, "Failed to specify"
- " alternate stack");
- #if VERBOSE > 1
- output("Alternate stack created successfully."
- " Bottom=%p, Size=%i\n",
- scenarii[i].bottom, minstacksize);
- #endif
- }
- }
- #if VERBOSE > 4
- else
- output("TSA or TSS unsupported => "
- "No alternative stack\n");
- #endif
- #ifndef WITHOUT_XOPEN
- if (scenarii[i].guard != 0) {
- if (scenarii[i].guard == 1)
- ret =
- pthread_attr_setguardsize(&scenarii[i].ta,
- 0);
- if (scenarii[i].guard == 2)
- ret =
- pthread_attr_setguardsize(&scenarii[i].ta,
- pagesize);
- if (ret != 0)
- UNRESOLVED(ret, "Unable to set guard area"
- " size in thread stack");
- #if VERBOSE > 4
- output("Guard size set to %i\n",
- scenarii[i].guard == 1 ? 1 : pagesize);
- #endif
- }
- #endif
- if (tss > 0) {
- if (scenarii[i].altsize != 0) {
- ret = pthread_attr_setstacksize(&scenarii[i].ta,
- minstacksize);
- if (ret != 0)
- UNRESOLVED(ret, "Unable to change"
- " stack size");
- #if VERBOSE > 4
- output("Stack size set to %i (this is the "
- "min)\n", minstacksize);
- #endif
- }
- }
- #if VERBOSE > 4
- else
- output("TSS unsupported => stack size unchanged\n");
- #endif
- ret = sem_init(&scenarii[i].sem, 0, 0);
- if (ret == -1)
- UNRESOLVED(errno, "Unable to init a semaphore");
- }
- #if VERBOSE > 0
- output("All %i thread attribute objects were initialized\n\n", NSCENAR);
- #endif
- }
- /*
- * This function will free all resources consumed
- * in the scenar_init() routine
- */
- static void scenar_fini(void)
- {
- int ret = 0;
- unsigned int i;
- for (i = 0; i < NSCENAR; i++) {
- if (scenarii[i].bottom != NULL)
- free(scenarii[i].bottom);
- ret = sem_destroy(&scenarii[i].sem);
- if (ret == -1)
- UNRESOLVED(errno, "Unable to destroy a semaphore");
- ret = pthread_attr_destroy(&scenarii[i].ta);
- if (ret != 0)
- UNRESOLVED(ret, "Failed to destroy a thread"
- " attribute object");
- }
- }
- static unsigned int sc;
- #ifdef STD_MAIN
- static void *threaded(void *arg);
- int main(void)
- {
- int ret = 0;
- pthread_t child;
- output_init();
- scenar_init();
- for (sc = 0; sc < NSCENAR; sc++) {
- #if VERBOSE > 0
- output("-----\n");
- output("Starting test with scenario (%i): %s\n",
- sc, scenarii[sc].descr);
- #endif
- ret = pthread_create(&child, &scenarii[sc].ta, threaded, NULL);
- switch (scenarii[sc].result) {
- case 0: /* Operation was expected to succeed */
- if (ret != 0)
- UNRESOLVED(ret, "Failed to create this thread");
- break;
- case 1: /* Operation was expected to fail */
- if (ret == 0)
- UNRESOLVED(-1, "An error was expected but the"
- " thread creation succeeded");
- break;
- case 2: /* We did not know the expected result */
- default:
- #if VERBOSE > 0
- if (ret == 0)
- output("Thread has been created successfully"
- " for this scenario\n");
- else
- output("Thread creation failed with the error:"
- " %s\n", strerror(ret));
- #endif
- }
- if (ret == 0) {
- if (scenarii[sc].detached == 0) {
- ret = pthread_join(child, NULL);
- if (ret != 0)
- UNRESOLVED(ret, "Unable to join a"
- " thread");
- } else {
- /* Just wait for the thread to terminate */
- do {
- ret = sem_wait(&scenarii[sc].sem);
- } while ((ret == -1) && (errno == EINTR));
- if (ret == -1)
- UNRESOLVED(errno, "Failed to wait for"
- " the semaphore");
- }
- }
- }
- scenar_fini();
- #if VERBOSE > 0
- output("-----\n");
- output("All test data destroyed\n");
- output("Test PASSED\n");
- #endif
- PASSED;
- }
- #endif
|