diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/Jamfile b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/Jamfile index 052d8e9006..58451bef4a 100644 --- a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/Jamfile +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/Jamfile @@ -1,17 +1,19 @@ SubDir HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces difftime ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces fork ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces kill ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces pthread_key_create ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces pthread_key_delete ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces pthread_getspecific ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces pthread_once ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces pthread_setspecific ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces sighold ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces sigignore ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces sigprocmask ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces sigrelse ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces signal ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces sigset ; -SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces sigsuspend ; +HaikuSubInclude difftime ; +HaikuSubInclude fork ; +HaikuSubInclude kill ; +HaikuSubInclude pthread_attr_destroy ; +HaikuSubInclude pthread_create ; +HaikuSubInclude pthread_key_create ; +HaikuSubInclude pthread_key_delete ; +HaikuSubInclude pthread_getspecific ; +HaikuSubInclude pthread_once ; +HaikuSubInclude pthread_setspecific ; +HaikuSubInclude sighold ; +HaikuSubInclude sigignore ; +HaikuSubInclude sigprocmask ; +HaikuSubInclude sigrelse ; +HaikuSubInclude signal ; +HaikuSubInclude sigset ; +HaikuSubInclude sigsuspend ; diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_attr_destroy/1-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_attr_destroy/1-1.c new file mode 100644 index 0000000000..49e7ea50f3 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_attr_destroy/1-1.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2002, Intel Corporation. All rights reserved. + * Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + + * Test that pthread_attr_destroy() + * shall destory a thread attributes object. An implementation may cause + * pthread_attr_destroy() to set 'attr' to an implementation-defined invalid + * value. + * + * Steps: + * 1. Initialize a pthread_attr_t object using pthread_attr_init() + * 2. Destroy that initialized attribute using pthread_attr_destroy() + * 3. Using pthread_attr_create(), pass to it the destroyed attribute. It + * should return the error EINVAL, the value specified by 'attr' is + * is invalid. + * + */ + +#include +#include +#include +#include "posixtest.h" + + +void *a_thread_func() +{ + + pthread_exit(0); + return NULL; +} + +int main() +{ + pthread_t new_th; + pthread_attr_t new_attr; + int ret; + + /* Initialize attribute */ + if(pthread_attr_init(&new_attr) != 0) + { + perror("Cannot initialize attribute object\n"); + return PTS_UNRESOLVED; + } + + /* Destroy attribute */ + if(pthread_attr_destroy(&new_attr) != 0) + { + perror("Cannot destroy the attribute object\n"); + return PTS_UNRESOLVED; + } + + /* Creating a thread, passing to it the destroyed attribute, should + * result in an error value of EINVAL (invalid 'attr' value). */ + ret=pthread_create(&new_th, &new_attr, a_thread_func, NULL); + + if(ret==EINVAL) + { + printf("Test PASSED\n"); + return PTS_PASS; + } + else if((ret != 0) && ((ret == EPERM) || (ret == EAGAIN))) + { + perror("Error created a new thread\n"); + return PTS_UNRESOLVED; + } + else if(ret==0) + { + printf("Test PASSED: NOTE*: Though returned 0 when creating a thread with a destroyed attribute, this behavior is compliant with garbage-in-garbage-out. \n"); + return PTS_PASS; + } else + { + printf("Test FAILED: (1) Incorrect return code from pthread_create(); %d not EINVAL or (2) Error in pthread_create()'s behavior in returning error codes \n", ret); + return PTS_FAIL; + } + +} + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_attr_destroy/2-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_attr_destroy/2-1.c new file mode 100644 index 0000000000..5731020d7d --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_attr_destroy/2-1.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2002, Intel Corporation. All rights reserved. + * Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + + * A destroyed 'attr' attributes object can be reinitialized using + * pthread_attr_init(); the results of otherwise referencing the object + * after it has been destroyed are undefined. + * + * Steps: + * 1. Initialize a pthread_attr_t object using pthread_attr_init() + * 2. Destroy that initialized attribute using pthread_attr_destroy() + * 3. Initialize the pthread_attr_t object again. This should not result + * in an error. + * + */ + +#include +#include +#include +#include "posixtest.h" + + +int main() +{ + pthread_attr_t new_attr; + + /* Initialize attribute */ + if(pthread_attr_init(&new_attr) != 0) + { + perror("Cannot initialize attribute object\n"); + return PTS_UNRESOLVED; + } + + /* Destroy attribute */ + if(pthread_attr_destroy(&new_attr) != 0) + { + perror("Cannot destroy the attribute object\n"); + return PTS_UNRESOLVED; + } + + /* Initialize attribute. This shouldn't result in an error. */ + if(pthread_attr_init(&new_attr) != 0) + { + printf("Test FAILED\n"); + return PTS_FAIL; + } + else + { + printf("Test PASSED\n"); + return PTS_PASS; + } + +} + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_attr_destroy/3-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_attr_destroy/3-1.c new file mode 100644 index 0000000000..794ab2d8c8 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_attr_destroy/3-1.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002, Intel Corporation. All rights reserved. + * Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + + * Upon successful completion, pthread_attr_destroy() shall return a value of 0. + * + * Steps: + * 1. Initialize a pthread_attr_t object using pthread_attr_init() + * 2. Destroy that initialized attribute using pthread_attr_destroy(). + * This should return 0; + * + */ + +#include +#include +#include +#include "posixtest.h" + + +int main() +{ + pthread_attr_t new_attr; + + /* Initialize attribute */ + if(pthread_attr_init(&new_attr) != 0) + { + perror("Cannot initialize attribute object\n"); + return PTS_UNRESOLVED; + } + + /* Destroy attribute */ + if(pthread_attr_destroy(&new_attr) != 0) + { + printf("Test FAILED\n"); + return PTS_FAIL; + } + else + { + printf("Test PASSED\n"); + return PTS_PASS; + } +} + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_attr_destroy/Jamfile b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_attr_destroy/Jamfile new file mode 100644 index 0000000000..1a67e2edc1 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_attr_destroy/Jamfile @@ -0,0 +1,7 @@ +SubDir HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces pthread_attr_destroy ; + +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) include ] ; + +SimpleTest pthread_attr_destroy_1-1 : 1-1.c ; +SimpleTest pthread_attr_destroy_2-1 : 2-1.c ; +SimpleTest pthread_attr_destroy_3-1 : 3-1.c ; diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-1.c new file mode 100644 index 0000000000..cfbfcae9cc --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-1.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2002, Intel Corporation. All rights reserved. + * Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + + * Test that pthread_create() creates a new thread with attributes specified + * by 'attr', within a process. + * + * Steps: + * 1. Create a thread using pthread_create() + * 2. Compare the thread ID of 'main' to the thread ID of the newly created + * thread. They should be different. + */ + +#include +#include +#include "posixtest.h" + +void *a_thread_func() +{ + + pthread_exit(0); + return NULL; +} + +int main() +{ + pthread_t main_th, new_th; + + if(pthread_create(&new_th, NULL, a_thread_func, NULL) != 0) + { + perror("Error creating thread\n"); + return PTS_UNRESOLVED; + } + + /* Obtain the thread ID of this main function */ + main_th=pthread_self(); + + /* Compare the thread ID of the new thread to the main thread. + * They should be different. If not, the test fails. */ + if(pthread_equal(new_th, main_th) != 0) + { + printf("Test FAILED: A new thread wasn't created\n"); + return PTS_FAIL; + } + + printf("Test PASSED\n"); + return PTS_PASS; +} + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-2.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-2.c new file mode 100644 index 0000000000..723e2b5555 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-2.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2002, Intel Corporation. All rights reserved. + * Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + + * Test that pthread_create() creates a new thread with attributes specified + * by 'attr', within a process. + * + * Steps: + * 1. Create a thread using pthread_create() + * 2. Cancel that thread with pthread_cancel() + * 3. If that thread doesn't exist, then it pthread_cancel() will return + * an error code. This would mean that pthread_create() did not create + * a thread successfully. + */ + +#include +#include +#include +#include "posixtest.h" + +void *a_thread_func() +{ + sleep(10); + + /* Shouldn't reach here. If we do, then the pthread_cancel() + * function did not succeed. */ + perror("Could not send cancel request correctly\n"); + pthread_exit(0); + return NULL; +} + +int main() +{ + pthread_t new_th; + + if(pthread_create(&new_th, NULL, a_thread_func, NULL) < 0) + { + perror("Error creating thread\n"); + return PTS_UNRESOLVED; + } + + /* Try to cancel the newly created thread. If an error is returned, + * then the thread wasn't created successfully. */ + if(pthread_cancel(new_th) != 0) + { + printf("Test FAILED: A new thread wasn't created\n"); + return PTS_FAIL; + } + + printf("Test PASSED\n"); + return PTS_PASS; +} + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-3.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-3.c new file mode 100644 index 0000000000..017babfe52 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-3.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2002, Intel Corporation. All rights reserved. + * Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + + * Test that pthread_create() creates a new thread with attributes specified + * by 'attr', within a process. + * + * Steps: + * 1. Create a new thread that will go into a never-ending while loop. + * 2. If the thread is truly asynchronise, then the main function will + * continue instead of waiting for the thread to return (which in never + * does in this test case). + * 3. An alarm is set to go off (i.e. send the SIGARLM signal) after 3 + * seconds. This is done for 'timeing-out' reasons, in case main DOES + * wait for the thread to return. This would also mean that the test + * failed. + */ + +#include +#include +#include +#include +#include +#include "posixtest.h" + +void *a_thread_function(); +void alarm_handler(); + +pthread_t a; + +int main() +{ + + /* Set the action for SIGALRM to generate an error if it is + * reached. This is because if SIGALRM was sent, then the + * test timed out. */ + if (signal(SIGALRM, alarm_handler) == SIG_ERR) + { + printf("Error in signal()\n"); + return PTS_UNRESOLVED; + } + + /* SIGALRM will be sent in 5 seconds. */ + alarm(5); + + /* Create a new thread. */ + if(pthread_create(&a, NULL, a_thread_function, NULL) != 0) + { + perror("Error creating thread\n"); + return PTS_UNRESOLVED; + } + + pthread_cancel(a); + /* If 'main' has reached here, then the test passed because it means + * that the thread is truly asynchronise, and main isn't waiting for + * it to return in order to move on. */ + printf("Test PASSED\n"); + return PTS_PASS; +} + +/* A never-ending thread function */ +void *a_thread_function() +{ + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + + while(1) + sleep(1); + + pthread_exit(0); + return NULL; +} + +/* If this handler is called, that means that the test has failed. */ +void alarm_handler() +{ + printf("Test FAILED\n"); + exit(PTS_FAIL); +} + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-4.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-4.c new file mode 100644 index 0000000000..053f46df5b --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-4.c @@ -0,0 +1,234 @@ +/* + * 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., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + + + * This sample test aims to check the following assertion: + * + * pthread_create creates a new thread within the process + + * The steps are: + * + * -> get the thread ID and the process ID of the main thread. + * -> create a new thread, get the thread & process ID. + * -> check that the thread IDs are different but process IDs are the same + + * The test fails if the thread IDs are the same or the proces IDs are different. + + */ + + + /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ + #define _POSIX_C_SOURCE 200112L + + /* Some routines are part of the XSI Extensions */ +#ifndef WITHOUT_XOPEN + #define _XOPEN_SOURCE 600 +#endif +/********************************************************************************************/ +/****************************** standard includes *****************************************/ +/********************************************************************************************/ + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include +/********************************************************************************************/ +/****************************** Test framework *****************************************/ +/********************************************************************************************/ + #include "testfrmw.h" + #include "testfrmw.c" + /* This header is responsible for defining the following macros: + * UNRESOLVED(ret, descr); + * where descr is a description of the error and ret is an int (error code for example) + * FAILED(descr); + * where descr is a short text saying why the test has failed. + * PASSED(); + * No parameter. + * + * Both three macros shall terminate the calling process. + * The testcase shall not terminate in any other maneer. + * + * The other file defines the functions + * void output_init() + * void output(char * string, ...) + * + * Those may be used to output information. + */ + +/********************************************************************************************/ +/********************************** Configuration ******************************************/ +/********************************************************************************************/ +#ifndef VERBOSE +#define VERBOSE 1 +#endif + +/********************************************************************************************/ +/*********************************** Test cases *****************************************/ +/********************************************************************************************/ + +#include "threads_scenarii.c" + +/* This file will define 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. + */ + +/********************************************************************************************/ +/*********************************** Real Test *****************************************/ +/********************************************************************************************/ + +struct testdata +{ + pthread_t tid; + pid_t pid; + sem_t * sem; +}; + +int global; /* This value is used to check both threads share the same process memory (and not a copy) */ + +void * threaded (void * arg) +{ + struct testdata * td=(struct testdata *) arg; + pthread_t mytid; + pid_t mypid; + int ret = 0; + + /* Compare the process IDs */ + mypid=getpid(); + #if VERBOSE > 0 + output(" Main pid: %i thread pid: %i\n", td->pid, mypid); + #endif + + if (mypid != td->pid) + { + FAILED("New thread does not belong to the same process as its parent thread"); + } + + /* Compare the threads IDs */ + mytid = pthread_self(); + #if VERBOSE > 0 + /* pthread_t is a pointer with Linux/nptl. This output can be erroneous for other arcs */ + output(" Main tid: %p thread tid: %p\n", td->tid, mytid); + #endif + + if (pthread_equal(mytid, td->tid) != 0) + { + FAILED("The created thread has the same thread ID as its parent"); + } + + /* Change the global value */ + global++; + + /* Post the semaphore to unlock the main thread in case of a detached thread */ + do { ret = sem_post(td->sem); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } + + return arg; +} + +int main (int argc, char *argv[]) +{ + int ret=0; + struct testdata td; + void * rval; + pthread_t child; + int i; + + output_init(); + + td.tid=pthread_self(); + td.pid=getpid(); + + scenar_init(); + + for (i=0; i < NSCENAR; i++) + { + #if VERBOSE > 0 + output("-----\n"); + output("Starting test with scenario (%i): %s\n", i, scenarii[i].descr); + #endif + + td.sem = &scenarii[i].sem; + + global = 2*i; + + ret = pthread_create(&child, &scenarii[i].ta, threaded, &td); + switch (scenarii[i].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) /* The new thread is running */ + { + if (scenarii[i].detached == 0) + { + ret = pthread_join(child, &rval); + if (ret != 0) { UNRESOLVED(ret, "Unable to join a thread"); } + + if (rval != &td) + { + FAILED("Could not get the thread return value. Did it execute?"); + } + } + else + { + /* Just wait for the thread terminate */ + do { ret = sem_wait(td.sem); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } + } + + if (global != (2*i + 1)) + { + /* Maybe a possible issue with CPU memory-caching here? */ + FAILED("The threads do not share the same process memory."); + } + } + } + + scenar_fini(); + #if VERBOSE > 0 + output("-----\n"); + output("All test data destroyed\n"); + output("Test PASSED\n"); + #endif + + PASSED; +} + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-5.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-5.c new file mode 100644 index 0000000000..72902abbf0 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-5.c @@ -0,0 +1,263 @@ +/* + * 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., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + + + * This sample test aims to check the following assertion: + * + * pthread_create creates a thread with attributes as specified in the attr parameter. + + * The steps are: + * + * -> Create a new thread with known parameters. + * -> Check the thread behavior conforms to these parameters. + * This checking consists in: + * -> If an alternative stack has been specified, check that the new thread stack is within this specified area. + * -> If stack size and guard size are known, check that accessing the guard size fails. (new process) + * -> If we are able to run threads with high priority and known sched policy, check that a high priority thread executes before a low priority thread. + (This will be done in another test has it fails with Linux kernel (2.6.8 at least) + * -> The previous test could be extended to cross-process threads to check the scope attribute behavior (postponned for now). + * (*) The detachstate attribute is not tested cause this would mean a speculative test. Moreover, it is already tested elsewhere. + + * The test fails if one of those tests fails. + + */ + + + /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ + #define _POSIX_C_SOURCE 200112L + + /* Some routines are part of the XSI Extensions */ +#ifndef WITHOUT_XOPEN + #define _XOPEN_SOURCE 600 +#endif +/********************************************************************************************/ +/****************************** standard includes *****************************************/ +/********************************************************************************************/ + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include +/********************************************************************************************/ +/****************************** Test framework *****************************************/ +/********************************************************************************************/ + #include "testfrmw.h" + #include "testfrmw.c" + /* This header is responsible for defining the following macros: + * UNRESOLVED(ret, descr); + * where descr is a description of the error and ret is an int (error code for example) + * FAILED(descr); + * where descr is a short text saying why the test has failed. + * PASSED(); + * No parameter. + * + * Both three macros shall terminate the calling process. + * The testcase shall not terminate in any other maneer. + * + * The other file defines the functions + * void output_init() + * void output(char * string, ...) + * + * Those may be used to output information. + */ + +/********************************************************************************************/ +/********************************** Configuration ******************************************/ +/********************************************************************************************/ +#ifndef VERBOSE +#define VERBOSE 1 +#endif + +/********************************************************************************************/ +/*********************************** Test cases *****************************************/ +/********************************************************************************************/ +#define STD_MAIN /* This allows main() to be defined in the included file */ +#include "threads_scenarii.c" + +/* This file will define 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. + */ + +/********************************************************************************************/ +/*********************************** Real Test *****************************************/ +/********************************************************************************************/ + +/* The overflow function is used to test the stack overflow */ +void * overflow(void * arg) +{ + void * current; + void * pad[50]; /* We want to consume the stack quickly */ + long stacksize = sysconf(_SC_THREAD_STACK_MIN); /* make sure we touch the current stack memory */ + int ret=0; + + pad[1]=NULL; /* so compiler stops complaining about unused variables */ + + if (arg == NULL) + { + /* first call */ + current = overflow(¤t); + + /* Terminate the overflow thread */ + /* Post the semaphore to unlock the main thread in case of a detached thread */ + do { ret = sem_post(&scenarii[sc].sem); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } + return NULL; + } + + + /* we cast the pointers into long, which might be a problem on some architectures... */ + if ( ((long)arg) < ((long)¤t)) + { + /* the stack is growing up */ + if ( ((long)¤t) - ((long)arg) >= stacksize) + { + output("Growing up stack started below %p and we are currently up to %p\n", arg, ¤t); + return (void *)0; + } + } + else + { + /* the stack is growing down */ + if ( ((long)arg) - ((long)¤t) >= stacksize) + { + output("Growing down stack started upon %p and we are currently down to %p\n", arg, ¤t); + return (void *)0; + } + } + + /* We are not yet overflowing, so we loop */ + { + return overflow(arg); + } +} + + +void * threaded (void * arg) +{ + int ret = 0; + + #if VERBOSE > 4 + output("Thread %i starting...\n", sc); + #endif + + /* Alternate stack test */ + if (scenarii[sc].bottom != NULL) + { + #ifdef WITHOUT_XOPEN + output("Unable to test the alternate stack feature; need an integer pointer cast\n"); + #else + intptr_t stack_start, stack_end, current_pos; + + stack_start = (intptr_t) scenarii[sc].bottom; + stack_end = stack_start + (intptr_t)sysconf(_SC_THREAD_STACK_MIN); + current_pos = (intptr_t)&ret; + + #if VERBOSE > 2 + output("Stack bottom: %p\n", scenarii[sc].bottom); + output("Stack end : %p (stack is 0x%lx bytes)\n", (void *)stack_end, stack_end - stack_start); + output("Current pos : %p\n", &ret); + #endif + if ((stack_start > current_pos) || (current_pos > stack_end)) + { FAILED("The specified stack was not used.\n"); } + + #endif // WITHOUT_XOPEN + } + + + /* Guard size test */ + if ((scenarii[sc].bottom == NULL) /* no alternative stack was specified */ + && (scenarii[sc].guard == 2) /* guard area size is 1 memory page */ + && (scenarii[sc].altsize == 1))/* We know the stack size */ + { + pid_t child, ctrl; + int status; + + child=fork(); /* We'll test the feature in another process as this test may segfault */ + + if (child == -1) { UNRESOLVED(errno, "Failed to fork()"); } + + if (child != 0) /* father */ + { + /* Just wait for the child and check its return value */ + ctrl = waitpid(child, &status, 0); + if (ctrl != child) { UNRESOLVED(errno, "Failed to wait for process termination"); } + + if (WIFEXITED(status)) /* The process exited */ + { + if (WEXITSTATUS(status) == 0) + { FAILED("Overflow into the guard area did not fail"); } + if (WEXITSTATUS(status) == PTS_UNRESOLVED) + { UNRESOLVED(-1, "The child process returned unresolved status"); } + #if VERBOSE > 4 + else + { output("The child process returned: %i\n", WEXITSTATUS(status)); } + } + else + { + output("The child process did not returned\n"); + if (WIFSIGNALED(status)) + output("It was killed with signal %i\n", WTERMSIG(status)); + else + output("neither was it killed. (status = %i)\n", status); + #endif + } + } + + if (child == 0) /* this is the new process */ + { + pthread_t th; + + ret = pthread_create(&th, &scenarii[sc].ta, overflow, NULL); /* Create a new thread with the same attributes */ + if (ret != 0) { UNRESOLVED(ret, "Unable to create another thread with the same attributes in the new process"); } + + if (scenarii[sc].detached == 0) + { + ret = pthread_join(th, 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"); } + } + + /* Terminate the child process here */ + exit(0); + } + } + + + /* Post the semaphore to unlock the main thread in case of a detached thread */ + do { ret = sem_post(&scenarii[sc].sem); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } + + return arg; +} + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-6.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-6.c new file mode 100644 index 0000000000..8793db0751 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/1-6.c @@ -0,0 +1,282 @@ +/* + * 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., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + + + * This sample test aims to check the following assertion: + * + * pthread_create creates a thread with attributes as specified in the attr parameter. + + * The steps are: + * + * -> See test 1-5.c for details + * -> This one will test the scheduling behavior is correct. + + */ + + + /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ + #define _POSIX_C_SOURCE 200112L + + /* Some routines are part of the XSI Extensions */ +#ifndef WITHOUT_XOPEN + #define _XOPEN_SOURCE 600 +#endif +/********************************************************************************************/ +/****************************** standard includes *****************************************/ +/********************************************************************************************/ + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include +/********************************************************************************************/ +/****************************** Test framework *****************************************/ +/********************************************************************************************/ + #include "testfrmw.h" + #include "testfrmw.c" + /* This header is responsible for defining the following macros: + * UNRESOLVED(ret, descr); + * where descr is a description of the error and ret is an int (error code for example) + * FAILED(descr); + * where descr is a short text saying why the test has failed. + * PASSED(); + * No parameter. + * + * Both three macros shall terminate the calling process. + * The testcase shall not terminate in any other maneer. + * + * The other file defines the functions + * void output_init() + * void output(char * string, ...) + * + * Those may be used to output information. + */ + +/********************************************************************************************/ +/********************************** Configuration ******************************************/ +/********************************************************************************************/ +#ifndef VERBOSE +#define VERBOSE 1 +#endif + +/* The value below shall be >= to the # of CPU on the test architecture */ +#define NCPU (4) + +/********************************************************************************************/ +/*********************************** Test cases *****************************************/ +/********************************************************************************************/ +#define STD_MAIN /* This allows main() to be defined in the included file */ + +#include "threads_scenarii.c" + +/* This file will define 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. + */ + +/********************************************************************************************/ +/*********************************** Real Test *****************************************/ +/********************************************************************************************/ + + +/* The 2 following functions are used for the scheduling tests */ +void * lp_func(void * arg) +{ + int * ctrl = (int *) arg; + *ctrl=2; + return NULL; +} + +void * hp_func(void * arg) +{ + int *ctrl = (int *) arg; + int dummy=0, i; + do + { + /* some dummy task */ + dummy += 3; + dummy %= 17; + dummy *= 47; + for (i=0; i<1000000000; i++); + #if VERBOSE > 6 + output("%p\n", pthread_self()); + #endif + } + while (*ctrl == 0); + return NULL; +} + + +void * threaded (void * arg) +{ + int ret = 0; + + #if VERBOSE > 4 + output("Thread %i starting...\n", sc); + #endif + + /* Scheduling (priority) tests */ + if ((sysconf(_SC_THREAD_PRIORITY_SCHEDULING) > 0) + && (scenarii[sc].explicitsched != 0) + && (scenarii[sc].schedpolicy != 0) + && (scenarii[sc].schedparam == 1)) + { + /* We will create NCPU threads running with a high priority with the same sched policy policy + and one with a low-priority. + The low-priority thread should not run until the other threads stop running, + unless the machine has more than NCPU processors... */ + + pthread_t hpth[NCPU]; /* High priority threads */ + pthread_t lpth; /* Low Priority thread */ + int ctrl; /* Check value */ + pthread_attr_t ta; + struct sched_param sp; + int policy; + int i=0; + struct timespec now, timeout; + + /* Start with checking we are executing with the required parameters */ + ret = pthread_getschedparam(pthread_self(), &policy, &sp); + if (ret != 0) { UNRESOLVED(ret , "Failed to get current thread policy"); } + + if (((scenarii[sc].schedpolicy == 1) && (policy != SCHED_FIFO)) + || ((scenarii[sc].schedpolicy == 2) && (policy != SCHED_RR))) + { + FAILED("The thread is not using the scheduling policy that was required"); + } + if (((scenarii[sc].schedparam == 1) && (sp.sched_priority != sched_get_priority_max(policy))) + || ((scenarii[sc].schedparam ==-1) && (sp.sched_priority != sched_get_priority_min(policy)))) + { + + FAILED("The thread is not using the scheduling parameter that was required"); + } + + ctrl = 0; /* Initial state */ + + /* Get the policy information */ + ret = pthread_attr_getschedpolicy(&scenarii[sc].ta, &policy); + if (ret != 0) { UNRESOLVED(ret, "Failed to read sched policy"); } + + /* We put a timeout cause the test might lock the machine when it runs */ + alarm(60); + + /* Create the high priority threads */ + ret = pthread_attr_init(&ta); + if (ret != 0) { UNRESOLVED(ret, "Failed to initialize a thread attribute object"); } + + ret = pthread_attr_setinheritsched(&ta, PTHREAD_EXPLICIT_SCHED); + if (ret != 0) { UNRESOLVED(ret, "Unable to set inheritsched attribute"); } + + ret = pthread_attr_setschedpolicy(&ta, policy); + if (ret != 0) { UNRESOLVED(ret, "Unable to set the sched policy"); } + + sp.sched_priority = sched_get_priority_max(policy) - 1; + + ret = pthread_attr_setschedparam(&ta, &sp); + if (ret != 0) { UNRESOLVED(ret, "Failed to set the sched param"); } + + #if VERBOSE > 1 + output("Starting %i high- and 1 low-priority threads.\n", NCPU); + #endif + for (i=0; i 5 + output("The %i high-priority threads are running\n", NCPU); + #endif + + /* Create the low-priority thread */ + sp.sched_priority = sched_get_priority_min(policy); + + ret = pthread_attr_setschedparam(&ta, &sp); + if (ret != 0) { UNRESOLVED(ret, "Failed to set the sched param"); } + + ret = pthread_create(&lpth, &ta, lp_func, &ctrl); + if (ret != 0) { UNRESOLVED(ret, "Failed to create enough threads"); } + + /* Keep going */ + ret = clock_gettime(CLOCK_REALTIME, &now); + if (ret != 0) { UNRESOLVED(errno, "Failed to read current time"); } + + timeout.tv_sec = now.tv_sec; + timeout.tv_nsec = now.tv_nsec + 500000000; + while (timeout.tv_nsec >= 1000000000) + { + timeout.tv_sec++; + timeout.tv_nsec -= 1000000000; + } + + do + { + if (ctrl != 0) + { + output("The low priority thread executed. This might be normal if you have more than %i CPU.\n", NCPU + 1); + FAILED("Low priority thread executed -- the sched parameters are ignored?"); + } + ret = clock_gettime(CLOCK_REALTIME, &now); + if (ret != 0) { UNRESOLVED(errno, "Failed to read current time"); } + #if VERBOSE > 5 + output("Time: %d.%09d (to: %d.%09d)\n", now.tv_sec, now.tv_nsec, timeout.tv_sec, timeout.tv_nsec); + #endif + } + while ((now.tv_sec <= timeout.tv_sec) && (now.tv_nsec <= timeout.tv_nsec)); + + /* Ok the low priority thread did not execute :) */ + + /* tell the other high priority to terminate */ + ctrl = 1; + + for (i=0; i 1 + output("The scheduling parameter was set accordingly to the thread attribute.\n"); + #endif + + /* We're done. */ + ret = pthread_attr_destroy(&ta); + if (ret != 0) { UNRESOLVED(ret, "Failed to destroy a thread attribute object"); } + } + + /* Post the semaphore to unlock the main thread in case of a detached thread */ + do { ret = sem_post(&scenarii[sc].sem); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } + + return arg; +} + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/10-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/10-1.c new file mode 100644 index 0000000000..5d5a6afce0 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/10-1.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2002, Intel Corporation. All rights reserved. + * Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + + * Test pthread_create(). + * + * If pthread_create() fails, no new thread is created and the contents of the + * location referenced by 'thread' is undefined. + * + * EXPLANATION: 3 ways that pthread_create can fail is if (1) The system lacked memory + * resources. (2) The caller did not have the appropriate permissions. (3) An invalid + * attributes object was passed. Since the last situation is the easiest to implement, that + * is the one I chose to use in order to make pthread_create fail. + * + * The problem with that is that accessing an uninitialized attributes object will cause a + * segmentation fault (since it usually points to garbage). So the idea here is to catch + * the SIGSEGV signal (segmentation faults), and to see if the thread was ever created, by + * setting a flag in the thread's starting routine. + * + * I recognize that causing pthread_create() to fail gracefully is a very difficult task, + * especially taking into consideration that a lot of it is implementation-specific. I did + * try to manually set the members of a pthread_attr_t object to invalid values, but that didn't + * seem to make pthread_create() fail at all, in any of the implementations I tested on. So for + * now, this is what we have. + * + * + * Steps: + * 1. Create a thread using pthread_create() with an invalid attributes object (uninitialized). + * 2. Catch the SIGSEGV (seg fault) signal. In the signal handler, check to make sure that + * the start routine for the thread was never reached, meaning the thread was never created. + * 3. If SIGSEGV was not caught in 10 seconds, the test times out and fails. If the signal + * was caught, but the thread start routine was called at some point, the test also fails. + * + * + * - adam.li@intel.com: 2004-04-30 + * This case will end with segmentation fault. + * I happened to find on NPTL pthread_create() can fail is + * pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_INHERIT), while + * does not call pthread_attr_setschedparam() to set the prority. (since + * by default the priority will be 0. But this is implementation specific. + */ + +#include +#include +#include +#include +#include +#include "posixtest.h" + +int created_thread; /* Flag indicating that the thread start routine was reached, and + therefore, the thread was created. */ +int segfault_flag; /* Flag indicating that a segmentation fault occured. */ + +/* Thread's start routine. */ +void *a_thread_func() +{ + /* Indicate that the thread start routine was reached. If it was reached, the test + * fails, as the thread should have not been created in the first place. */ + created_thread = 1; + pthread_exit(0); + return NULL; +} + +/* Signal handler for SIGSEGV (segmentation fault signal) */ +void sig_handler(int sig) +{ + /* If a segmentation fault occured when it was supposed to (i.e. when pthread_create() + * was called with the invalid attributes object). */ + if(segfault_flag == 1) + { + /* check if the thread start routine was called. If yes, then the thread was + * created, meaning the test fails. */ + if(created_thread == 1) + { + printf("Test FAILED: Created thread though an invalid attribute was passed to pthread_create().\n"); + pthread_exit((void*)PTS_FAIL); + } + + printf("Test PASSED\n"); + pthread_exit((void*)PTS_PASS); + return; + } + + printf("Test FAILED: Did not receive segmentation fault signal, waited 10 seconds.\n"); + pthread_exit((void*)PTS_FAIL); + return; +} + +/* MAIN */ +int main() +{ + pthread_t new_th; + pthread_attr_t inv_attr; + struct sigaction act; + + /* Inializing flags. */ + segfault_flag = 1; + created_thread = 0; + + /* Set signal handler for SIGSEGV (seg fault) */ + act.sa_handler = sig_handler; + act.sa_flags = 0; + sigaction(SIGSEGV, &act, NULL); + + /* Create the thread with the invalid, uninitialized attributes object. */ + pthread_create(&new_th, &inv_attr, a_thread_func, NULL); + + /* Should not reach here if process correctly seg-faulted. */ + segfault_flag = 0; + + /* Timeout after 10 seconds if a segfault was not encountered. The test then fails. */ + sleep(10); + + /* Manually send the SIGSEGV signal to the signal handler. If this point is reached, + * the test fails. */ + if(raise(SIGSEGV) != 0) + { + perror("Error in raise()\n"); + return PTS_UNRESOLVED; + } + + printf("Test FAILED.\n"); + return PTS_FAIL; +} + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/11-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/11-1.c new file mode 100644 index 0000000000..9b62db0066 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/11-1.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2004, Intel Corporation. All rights reserved. + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + * + * adam.li@intel.com + * + * if _POSIX_THREAD_CPUTIME is defined, the new thread shall have a CPU-time + * clock accessible, and the initial value of this clock shall be set to 0. + */ + /* Create a new thread and get the time of the thread CUP-time clock + * using clock_gettime(). + * Note, the tv_nsec cannot be exactly 0 at the time of calling + * clock_gettime() since the thread has executed some time. */ + +#define _XOPEN_SOURCE 600 +#include +#include +#include +#include +#include +#include "posixtest.h" + +void *a_thread_func() +{ + clockid_t cpuclock; + struct timespec ts = {.tv_sec = 1, .tv_nsec = 1}; + pthread_getcpuclockid(pthread_self(), &cpuclock); + clock_gettime(cpuclock, &ts); + /* Just test the tv_sec field here. */ + if (ts.tv_sec != 0) + { + printf("ts.tv_sec: %ld, ts.tv_nsec: %ld\n", + ts.tv_sec, ts.tv_nsec); + exit(PTS_FAIL); + } + pthread_exit(0); + return NULL; +} + +int main() +{ +#if _POSIX_THREAD_CPUTIME == -1 + printf("_POSIX_THREAD_CPUTIME not supported\n"); + return PTS_UNSUPPORTED; +#endif + pthread_t new_th; + + if (sysconf(_SC_THREAD_CPUTIME) == -1) { + printf("_POSIX_THREAD_CPUTIME not supported\n"); + return PTS_UNSUPPORTED; + } + + if(pthread_create(&new_th, NULL, a_thread_func, NULL) != 0) + { + perror("Error creating thread\n"); + return PTS_UNRESOLVED; + } + + pthread_join(new_th, NULL); + printf("Test PASSED\n"); + return PTS_PASS; +} + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/12-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/12-1.c new file mode 100644 index 0000000000..e6b7662494 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/12-1.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2002, Intel Corporation. All rights reserved. + * Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + + * Test pthread_create() + * + * If success, pthread_create() returns zero. + * + * Steps: + * 1. Create a thread using pthread_create(), passing to it all valid values. + * 2. If the return code was not EGAIN, EPERM or EINVAL, it should return 0. + */ + +#include +#include +#include +#include "posixtest.h" + +/* Thread starting routine that really does nothing. */ +void *a_thread_func() +{ + pthread_exit(0); + return NULL; +} + +int main() +{ + pthread_t new_th; + int ret; + + /* Create new thread and check the return value. */ + ret = pthread_create(&new_th, NULL, a_thread_func, NULL); + if(ret != 0) + { + if((ret != EINVAL) && (ret != EAGAIN) && (ret != EPERM)) + + printf("Test FAILED: Wrong return code: %d\n", ret); + return PTS_FAIL; + } + + printf("Test PASSED\n"); + return PTS_PASS; +} + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/14-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/14-1.c new file mode 100644 index 0000000000..5448b359fc --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/14-1.c @@ -0,0 +1,333 @@ +/* + * 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., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + + + * This sample test aims to check the following assertion: + * + * The function does not return EINTR + + * The steps are: + * -> pthread_kill a thread which creates threads + * -> check that EINTR is never returned + + */ + + + /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ + #define _POSIX_C_SOURCE 200112L + + /* Some routines are part of the XSI Extensions */ +#ifndef WITHOUT_XOPEN + #define _XOPEN_SOURCE 600 +#endif +/********************************************************************************************/ +/****************************** standard includes *****************************************/ +/********************************************************************************************/ + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + #include + +/********************************************************************************************/ +/****************************** Test framework *****************************************/ +/********************************************************************************************/ + #include "testfrmw.h" + #include "testfrmw.c" + /* This header is responsible for defining the following macros: + * UNRESOLVED(ret, descr); + * where descr is a description of the error and ret is an int (error code for example) + * FAILED(descr); + * where descr is a short text saying why the test has failed. + * PASSED(); + * No parameter. + * + * Both three macros shall terminate the calling process. + * The testcase shall not terminate in any other maneer. + * + * The other file defines the functions + * void output_init() + * void output(char * string, ...) + * + * Those may be used to output information. + */ + +/********************************************************************************************/ +/********************************** Configuration ******************************************/ +/********************************************************************************************/ +#ifndef VERBOSE +#define VERBOSE 1 +#endif + +#define WITH_SYNCHRO + + +/********************************************************************************************/ +/*********************************** Test cases *****************************************/ +/********************************************************************************************/ + +#include "threads_scenarii.c" + +/* This file will define 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. + */ + + +/********************************************************************************************/ +/*********************************** Real Test *****************************************/ +/********************************************************************************************/ + +char do_it=1; +char woken=0; +unsigned long count_ope=0; +#ifdef WITH_SYNCHRO +sem_t semsig1; +sem_t semsig2; +unsigned long count_sig=0; +#endif + +sigset_t usersigs; + +typedef struct +{ + int sig; +#ifdef WITH_SYNCHRO + sem_t *sem; +#endif +} thestruct; + +/* the following function keeps on sending the signal to the process */ +void * sendsig (void * arg) +{ + thestruct *thearg = (thestruct *) arg; + int ret; + pid_t process; + + process=getpid(); + + /* We block the signals SIGUSR1 and SIGUSR2 for this THREAD */ + ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL); + if (ret != 0) { UNRESOLVED(ret, "Unable to block SIGUSR1 and SIGUSR2 in signal thread"); } + + while (do_it) + { + #ifdef WITH_SYNCHRO + if ((ret = sem_wait(thearg->sem))) + { UNRESOLVED(errno, "Sem_wait in sendsig"); } + count_sig++; + #endif + + ret = kill(process, thearg->sig); + if (ret != 0) { UNRESOLVED(errno, "Kill in sendsig"); } + + } + + return NULL; +} + +/* Next are the signal handlers. */ +/* This one is registered for signal SIGUSR1 */ +void sighdl1(int sig) +{ +#ifdef WITH_SYNCHRO + if (sem_post(&semsig1)) + { UNRESOLVED(errno, "Sem_post in signal handler 1"); } +#endif +} +/* This one is registered for signal SIGUSR2 */ +void sighdl2(int sig) +{ +#ifdef WITH_SYNCHRO + if (sem_post(&semsig2)) + { UNRESOLVED(errno, "Sem_post in signal handler 2"); } +#endif +} + +/* Thread function -- almost does nothing */ +void * threaded(void * arg) +{ + int ret; + + /* Signal we're done (especially in case of a detached thread) */ + do { ret = sem_post(&scenarii[sc].sem); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } + + /* return */ + return arg; +} + +/* Test function -- creates the threads and check that EINTR is never returned. */ +void * test(void * arg) +{ + int ret=0; + pthread_t child; + + /* We don't block the signals SIGUSR1 and SIGUSR2 for this THREAD */ + ret = pthread_sigmask(SIG_UNBLOCK, &usersigs, NULL); + if (ret != 0) { UNRESOLVED(ret, "Unable to unblock SIGUSR1 and SIGUSR2 in worker thread"); } + + sc = 0; + + while (do_it) + { + #if VERBOSE > 5 + output("-----\n"); + output("Starting test with scenario (%i): %s\n", sc, scenarii[sc].descr); + #endif + + count_ope++; + + ret = pthread_create(&child, &scenarii[sc].ta, threaded, NULL); + if (ret == EINTR) { FAILED("pthread_create returned EINTR"); } + 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 > 5 + 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) /* The new thread is running */ + { + 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"); } + } + } + + /* Change thread attribute for the next loop */ + sc++; + sc %= NSCENAR; + } + return NULL; +} + +/* Main function */ +int main (int argc, char * argv[]) +{ + int ret; + pthread_t th_work, th_sig1, th_sig2; + thestruct arg1, arg2; + struct sigaction sa; + + /* Initialize output routine */ + output_init(); + + /* Initialize thread attribute objects */ + scenar_init(); + + /* We need to register the signal handlers for the PROCESS */ + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = sighdl1; + if ((ret = sigaction (SIGUSR1, &sa, NULL))) + { UNRESOLVED(ret, "Unable to register signal handler1"); } + sa.sa_handler = sighdl2; + if ((ret = sigaction (SIGUSR2, &sa, NULL))) + { UNRESOLVED(ret, "Unable to register signal handler2"); } + + /* We prepare a signal set which includes SIGUSR1 and SIGUSR2 */ + sigemptyset(&usersigs); + ret = sigaddset(&usersigs, SIGUSR1); + ret |= sigaddset(&usersigs, SIGUSR2); + if (ret != 0) { UNRESOLVED(ret, "Unable to add SIGUSR1 or 2 to a signal set"); } + + /* We now block the signals SIGUSR1 and SIGUSR2 for this THREAD */ + ret = pthread_sigmask(SIG_BLOCK, &usersigs, NULL); + if (ret != 0) { UNRESOLVED(ret, "Unable to block SIGUSR1 and SIGUSR2 in main thread"); } + + #ifdef WITH_SYNCHRO + if (sem_init(&semsig1, 0, 1)) + { UNRESOLVED(errno, "Semsig1 init"); } + if (sem_init(&semsig2, 0, 1)) + { UNRESOLVED(errno, "Semsig2 init"); } + #endif + + if ((ret = pthread_create(&th_work, NULL, test, NULL))) + { UNRESOLVED(ret, "Worker thread creation failed"); } + + arg1.sig = SIGUSR1; + arg2.sig = SIGUSR2; +#ifdef WITH_SYNCHRO + arg1.sem = &semsig1; + arg2.sem = &semsig2; +#endif + + if ((ret = pthread_create(&th_sig1, NULL, sendsig, (void *)&arg1))) + { UNRESOLVED(ret, "Signal 1 sender thread creation failed"); } + if ((ret = pthread_create(&th_sig2, NULL, sendsig, (void *)&arg2))) + { UNRESOLVED(ret, "Signal 2 sender thread creation failed"); } + + /* Let's wait for a while now */ + sleep(1); + + /* Now stop the threads and join them */ + do { do_it=0; } + while (do_it); + + if ((ret = pthread_join(th_sig1, NULL))) + { UNRESOLVED(ret, "Signal 1 sender thread join failed"); } + if ((ret = pthread_join(th_sig2, NULL))) + { UNRESOLVED(ret, "Signal 2 sender thread join failed"); } + + if ((ret = pthread_join(th_work, NULL))) + { UNRESOLVED(ret, "Worker thread join failed"); } + + scenar_fini(); + + #if VERBOSE > 0 + output("Test executed successfully.\n"); + output(" %d thread creations.\n", count_ope); + #ifdef WITH_SYNCHRO + output(" %d signals were sent meanwhile.\n", count_sig); + #endif + #endif + PASSED; +} + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/15-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/15-1.c new file mode 100644 index 0000000000..2dcd59c542 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/15-1.c @@ -0,0 +1,156 @@ +/* + * 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., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + + + * This sample test aims to check the following assertion: + * + * If the current thread has an alternate stack, the new thread does not inherit + * this stack + + * The steps are: + * -> Create a thread with an alternate stack. + * -> From this thread, create another thread. + * -> Check that the new thread does not use the same stack. + + */ + + + /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ + #define _POSIX_C_SOURCE 200112L + + /* Some routines are part of the XSI Extensions */ +#ifndef WITHOUT_XOPEN + #define _XOPEN_SOURCE 600 +#endif +/********************************************************************************************/ +/****************************** standard includes *****************************************/ +/********************************************************************************************/ + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + + +/********************************************************************************************/ +/****************************** Test framework *****************************************/ +/********************************************************************************************/ + #include "testfrmw.h" + #include "testfrmw.c" + /* This header is responsible for defining the following macros: + * UNRESOLVED(ret, descr); + * where descr is a description of the error and ret is an int (error code for example) + * FAILED(descr); + * where descr is a short text saying why the test has failed. + * PASSED(); + * No parameter. + * + * Both three macros shall terminate the calling process. + * The testcase shall not terminate in any other maneer. + * + * The other file defines the functions + * void output_init() + * void output(char * string, ...) + * + * Those may be used to output information. + */ + +/********************************************************************************************/ +/********************************** Configuration ******************************************/ +/********************************************************************************************/ +#ifndef VERBOSE +#define VERBOSE 1 +#endif + +/********************************************************************************************/ +/*********************************** Test cases *****************************************/ +/********************************************************************************************/ + +#define STD_MAIN +#include "threads_scenarii.c" + +/* This file will define 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. + */ + + +/********************************************************************************************/ +/*********************************** Real Test *****************************************/ +/********************************************************************************************/ + +void * teststack(void * arg) +{ + int ret=0; + *(int **)arg = &ret; + return NULL; +} + +/* Thread function */ +void * threaded(void * arg) +{ + int ret; + int * child_stack; + pthread_t gchild; + + int sz = sysconf(_SC_THREAD_STACK_MIN); + + if (scenarii[sc].bottom != NULL) + { + #if VERBOSE > 1 + output("Processing test\n"); + #endif + + /* Create a new thread and get a location inside its stack */ + ret = pthread_create(&gchild, NULL, teststack, &child_stack); + if (ret != 0) { UNRESOLVED(ret, "Failed to create a thread with default attribute"); } + + ret = pthread_join(gchild, NULL); + if (ret != 0) { UNRESOLVED(ret, "Failed to join the test thread"); } + + /* Check the new thread stack location was outside of the current thread location */ + /* We convert all the @ to longs */ + #if VERBOSE > 4 + output("Current stack : %p -> %p\n", scenarii[sc].bottom, sz + (long)scenarii[sc].bottom); + output("Child location: %p\n", child_stack); + #endif + + if ( (((long)scenarii[sc].bottom) < ((long)child_stack)) + && (((long)child_stack) < (((long)scenarii[sc].bottom) + sz))) + { + FAILED("The new thread inherited th alternate stack from its parent"); + } + } + + /* Signal we're done (especially in case of a detached thread) */ + do { ret = sem_post(&scenarii[sc].sem); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } + + /* return */ + return arg; +} + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/2-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/2-1.c new file mode 100644 index 0000000000..f2075f3eb0 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/2-1.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2002, Intel Corporation. All rights reserved. + * Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + + * Test If 'attr' is NULL, the default attributes shall be used. + * The attribute that will be tested is the detached state, because that is + * the only state that has a default listed in the specification. + * + * default: PTHREAD_CREATE_JOINABLE + * Other valid values: PTHREAD_CREATE_DETACHED + + * + * Steps: + * 1. Create a thread using pthread_create() and passing 'NULL' for 'attr'. + * 2. Check to see if the thread is joinable, since that is the default. + * 3. We do this by calling pthread_join() and pthread_detach(). If + * they fail, then the thread is not joinable, and the test fails. + */ + +#include +#include +#include +#include "posixtest.h" + +void *a_thread_func() +{ + + pthread_exit(0); + return NULL; +} + +int main() +{ + pthread_t new_th; + + /* Create a new thread. The default attribute should be that + * it is joinable. */ + if(pthread_create(&new_th, NULL, a_thread_func, NULL) != 0) + { + perror("Error creating thread\n"); + return PTS_UNRESOLVED; + } + + /* The new thread should be able to be joined. */ + if(pthread_join(new_th, NULL) == EINVAL) + { + printf("Test FAILED\n"); + return PTS_FAIL; + } + + /* The new thread should be able to be detached. */ + if(pthread_detach(new_th) == EINVAL) + { + printf("Test FAILED\n"); + return PTS_FAIL; + } + + printf("Test PASSED\n"); + return PTS_PASS; +} + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/3-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/3-1.c new file mode 100644 index 0000000000..0e03f0d8d2 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/3-1.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2002, Intel Corporation. All rights reserved. + * Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + + * Test if the attributes specified by 'attr' are modified later, the thread's + * attributes shall not be affected. + * The attribute that will be tested is the detached state. + * + * + * Steps: + * 1. Set a pthread_attr_t object to be PTHREAD_CREATE_JOINABLE. + * 2. Create a new thread using pthread_create() and passing this attribute + * object. + * 3. Change the attribute object to be in a detached state rather than + * joinable. + * 4. Doing this should not effect the fact that the thread that was created + * is joinable, and so calling the functions pthread_detach() should not fail. + */ + +#include +#include +#include +#include +#include "posixtest.h" + +# define TIMEOUT 10 /* Timeout value of 10 seconds. */ +# define INTHREAD 0 /* Control going to or is already for Thread */ +# define INMAIN 1 /* Control going to or is already for Main */ + +int sem1; /* Manual semaphore */ + +void *a_thread_func() +{ + /* Indicate to main() that the thread was created. */ + sem1=INTHREAD; + + /* Wait for main to detach change the attribute object and try and detach this thread. + * Wait for a timeout value of 10 seconds before timing out if the thread was not able + * to be detached. */ + sleep(TIMEOUT); + + printf("Test FAILED: Did not detach the thread, main still waiting for it to end execution.\n"); + pthread_exit((void*)PTS_FAIL); + return NULL; +} + +int main() +{ + pthread_t new_th; + pthread_attr_t new_attr; + int ret; + + /* Initializing */ + sem1 = INMAIN; + if(pthread_attr_init(&new_attr) != 0) + { + perror("Error intializing attribute object\n"); + return PTS_UNRESOLVED; + + } + + /* Make the new attribute object joinable */ + if(pthread_attr_setdetachstate(&new_attr, PTHREAD_CREATE_JOINABLE) != 0) + { + perror("Error setting the detached state of the attribute\n"); + return PTS_UNRESOLVED; + } + + /* Create a new thread and pass it the attribute object that will + * make it joinable. */ + if(pthread_create(&new_th, &new_attr, a_thread_func, NULL) != 0) + { + perror("Error creating thread\n"); + return PTS_UNRESOLVED; + } + + while(sem1==INMAIN) + sleep(1); + + /* Now change the attribute object to be in a detached state */ + if(pthread_attr_setdetachstate(&new_attr, PTHREAD_CREATE_DETACHED) != 0) + { + perror("Error setting the detached state of the attribute\n"); + return PTS_UNRESOLVED; + } + + /* The new thread should still be able to be detached. */ + if((ret=pthread_detach(new_th)) == EINVAL) + { + printf("Test FAILED: pthread_detach failed on joinable thread. Return value is %d\n", ret); + return PTS_FAIL; + } + + printf("Test PASSED\n"); + return PTS_PASS; +} + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/3-2.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/3-2.c new file mode 100644 index 0000000000..3c3d8768dd --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/3-2.c @@ -0,0 +1,649 @@ +/* + * 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., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + + + * This sample test aims to check the following assertion: + * + * Once the thread has been created, subsequent changes to the + * thread attribute object don't affect the running thread. + + * The steps are: + * -> stack grow + * -> create a thread with minimal stack size + * -> change the stack size to a bigger value + * -> check that the thread stack size did not change. + * -> stack decrease + * -> create a thread with a known stack size (> minimum) + * -> change the stack size to the min value + * -> check that the thread stack size did not change. + * -> sched policy/param change + * -> create a new thread with a known policy + * -> change the policy in the thread attribute and check the thread policy did not change + * -> change the schedparam in the thread attribute and check the thread priority did not change + * -> change the policy in the running thread and check the thread attribute did not change. + * -> change the priority in the running thread and check the thread attribute did not change. + + * The test fails if one of the checking fails + + */ + + + /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ + #define _POSIX_C_SOURCE 200112L + + /* Some routines are part of the XSI Extensions */ +#ifndef WITHOUT_XOPEN + #define _XOPEN_SOURCE 600 +#endif +/********************************************************************************************/ +/****************************** standard includes *****************************************/ +/********************************************************************************************/ + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + + +/********************************************************************************************/ +/****************************** Test framework *****************************************/ +/********************************************************************************************/ + #include "testfrmw.h" + #include "testfrmw.c" + /* This header is responsible for defining the following macros: + * UNRESOLVED(ret, descr); + * where descr is a description of the error and ret is an int (error code for example) + * FAILED(descr); + * where descr is a short text saying why the test has failed. + * PASSED(); + * No parameter. + * + * Both three macros shall terminate the calling process. + * The testcase shall not terminate in any other maneer. + * + * The other file defines the functions + * void output_init() + * void output(char * string, ...) + * + * Those may be used to output information. + */ + +/********************************************************************************************/ +/********************************** Configuration ******************************************/ +/********************************************************************************************/ +#ifndef VERBOSE +#define VERBOSE 1 +#endif + +/********************************************************************************************/ +/*********************************** Test cases *****************************************/ +/********************************************************************************************/ + +#include "threads_scenarii.c" + +/* This file will define 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. + */ + + +/********************************************************************************************/ +/*********************************** Real Test *****************************************/ +/********************************************************************************************/ + +sem_t semsync[2]; /* These semaphores will only be used in child process! */ + +/* The overflow function is used to test the stack overflow */ +void * overflow(void * arg) +{ + void * current; + void * pad[50]; /* We want to consume the stack quickly */ + long stacksize = sysconf(_SC_THREAD_STACK_MIN); /* make sure we touch the current stack memory */ + + pad[1]=NULL; /* so compiler stops complaining about unused variables */ + int ret = 0; + + if (arg == NULL) + { + /* first call */ + + /* Synchronize with the parent */ + do { ret = sem_wait(&semsync[0]); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } + + + /* Go to recursion */ + current = overflow(¤t); + + /* Terminated */ + do { ret = sem_post(&semsync[1]); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } + + /* Terminate the overflow thread */ + return current; + } + + /* we cast the pointers into long, which might be a problem on some architectures... */ + if ( ((long)arg) < ((long)¤t)) + { + /* the stack is growing up */ + if ( ((long)¤t) - ((long)arg) >= stacksize) + { + output("Growing up stack started below %p and we are currently up to %p\n", arg, ¤t); + return (void *)0; + } + } + else + { + /* the stack is growing down */ + if ( ((long)arg) - ((long)¤t) >= stacksize) + { + output("Growing down stack started upon %p and we are currently down to %p\n", arg, ¤t); + return (void *)0; + } + } + + /* We are not yet overflowing, so we loop */ + return overflow(arg); +} + +/* The following function will return + 0 if a thread created with the attribute ta is able to fill the stack up to {minstacksize}. + 1 if the operation failed. + 2 if an error prevented the test to complete + + If newsize is not 0, the stack size in ta will be set to this value once the thread is created. + +*/ +int test_stack(pthread_attr_t * ta, size_t newsize) +{ + pid_t child, ctrl; + int status; + int ret; + + child=fork(); /* We'll test the feature in another process as this test may segfault */ + + if (child == -1) + { + output("Failed to fork (%s)\n", strerror(errno)); + return 2; + } + + if (child != 0) /* father */ + { + /* Just wait for the child and check its return value */ + ctrl = waitpid(child, &status, 0); + if (ctrl != child) + { + output("Failed to wait for process termination (%s)\n", strerror(errno)); + return 2; + } + + if (WIFEXITED(status)) /* The process exited */ + { + if (WEXITSTATUS(status) == 0) + { return 0; } /* We were able to fill the stack */ + if (WEXITSTATUS(status) == PTS_UNRESOLVED) + { + output("The child process returned unresolved status\n"); + return 2; + } + else + { + output("The child process returned: %i\n", WEXITSTATUS(status)); + return 2; + } + } + else + { + #if VERBOSE > 4 + output("The child process did not return\n"); + if (WIFSIGNALED(status)) + output("It was killed with signal %i\n", WTERMSIG(status)); + else + output("neither was it killed. (status = %i)\n", status); + #endif + } + + return 1; + } + + /* else */ + /* this is the new process */ + { + pthread_t th; + void * rc; + int detach; + + /* Semaphore to force the child to wait */ + ret = sem_init(&semsync[0], 0,0); + if (ret == -1) { UNRESOLVED(errno, "Unable to init a semaphore"); } + /* Semaphore to detect thread ending */ + ret = sem_init(&semsync[1], 0,0); + if (ret == -1) { UNRESOLVED(errno, "Unable to init a semaphore"); } + + ret = pthread_create(&th, ta, overflow, NULL); /* Create a new thread with the same attributes */ + if (ret != 0) { UNRESOLVED(ret, "Unable to create a thread in the new process"); } + + /* If we were asked to perform a change on ta, do it now. */ + if (newsize) + { + ret = pthread_attr_setstacksize(ta, newsize); + if (ret != 0) { UNRESOLVED(ret, "Failed to set the new stack size"); } + } + + /* Ok the child can run now */ + do { ret = sem_post(&semsync[0]); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } + + + /* Wait for its termination */ + do { ret = sem_wait(&semsync[1]); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } + + if (ta != NULL) + { + ret = pthread_attr_getdetachstate(ta, &detach); + if (ret != 0) { UNRESOLVED(ret, "Failed to get detach state from the thread attribute"); } + } + else + { + detach = PTHREAD_CREATE_JOINABLE; /* default */ + } + + if (detach == PTHREAD_CREATE_JOINABLE) + { + ret = pthread_join(th, &rc); + if (ret != 0) { UNRESOLVED(ret, "Unable to join a thread"); } + if (rc != (void *)0) + { UNRESOLVED((int)(long)rc, "The overflow function returned an unexpected value"); } + } + + + /* Terminate the child process here */ + exit(0); + } +} + + +typedef struct +{ + pthread_barrier_t bar; + int policy; + struct sched_param param; +} testdata_t; + +void * schedtest(void * arg) +{ + testdata_t * td = (testdata_t *)arg; + int newpol, ret=0; + struct sched_param newparam; + + /* Read the current sched policy & param */ + ret = pthread_getschedparam(pthread_self(), &(td->policy), &(td->param)); + if (ret != 0) { UNRESOLVED(ret, "Failed to read current thread policy / param"); } + + /* sync 1 */ + ret = pthread_barrier_wait(&(td->bar)); + if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { UNRESOLVED(ret, "Failed to synchronize on the barrier"); } + + /* sync 2 */ + ret = pthread_barrier_wait(&(td->bar)); + if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { UNRESOLVED(ret, "Failed to synchronize on the barrier"); } + + /* Read the current sched policy & param */ + ret = pthread_getschedparam(pthread_self(), &(td->policy), &(td->param)); + if (ret != 0) { UNRESOLVED(ret, "Failed to read current thread policy / param"); } + + /* sync 3 */ + ret = pthread_barrier_wait(&(td->bar)); + if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { UNRESOLVED(ret, "Failed to synchronize on the barrier"); } + + /* sync 4 */ + ret = pthread_barrier_wait(&(td->bar)); + if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { UNRESOLVED(ret, "Failed to synchronize on the barrier"); } + + /* Change the current sched policy & param */ + if (td->policy == SCHED_RR) + newpol = SCHED_FIFO; + else + newpol = SCHED_RR; + + newparam.sched_priority = sched_get_priority_max(newpol); + + if (newparam.sched_priority == td->param.sched_priority) + newparam.sched_priority--; + + ret = pthread_setschedparam(pthread_self(), newpol, &newparam); + #if VERBOSE > 0 + if (ret != 0) + output("Changing the current thread sched policy failed with error: %s\n", strerror(ret)); + #endif + #if VERBOSE > 2 + else + output("Executing thread scheduling policy changed\n"); + #endif + + /* sync 5 */ + ret = pthread_barrier_wait(&(td->bar)); + if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { UNRESOLVED(ret, "Failed to synchronize on the barrier"); } + + /* Post the sem in case of a detached thread */ + do { ret = sem_post(&scenarii[sc].sem); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to post the semaphore"); } + + return NULL; +} + + + +int main (int argc, char *argv[]) +{ + int ret=0; + int do_stack_tests; + int do_sched_tests; + + /* Initialize output routine */ + output_init(); + + /* Test abilities */ + do_sched_tests = (sysconf(_SC_THREAD_PRIORITY_SCHEDULING)>0?1:0); + do_stack_tests = (test_stack(NULL,0)==0?1:0); + #if VERBOSE > 0 + output("Test starting\n Stack tests %s be executed.\n Sched tests %s be executed.\n", + do_stack_tests?"will":"won't", + do_sched_tests?"will":"won't"); + #endif + + /* Initialize thread attribute objects */ + 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 + + if (do_stack_tests) + { + /* stack grow test */ + /* We need the thread attribute to specify a minimal stack */ + if ((scenarii[sc].altstack == 0) && (scenarii[sc].altsize == 1)) + { + #if VERBOSE > 2 + output("Processing stack grow test\n"); + #endif + + ret = test_stack(&scenarii[sc].ta, 2*sysconf(_SC_THREAD_STACK_MIN)); + + if (ret == 0) + { + if (scenarii[sc].guard == 2) + { + FAILED("Changing the stacksize after the thread was created changed the running thread stack size"); + } + #if VERBOSE > 2 + else + output("We were able to overflow the stack, but the guard area is unknow or null\n"); + #endif + + } + + if ((ret != 2) && (scenarii[sc].result == 1)) + { + UNRESOLVED(-1, "An error was expected but the thread creation succeeded"); + } + + #if VERBOSE > 2 + if ((ret == 1)) + { + output("Stack grow test passed\n"); + } + + if ((ret == 2) && (scenarii[sc].result == 2)) + { + output("Something went wrong -- we don't care in this case\n"); + } + #endif + + if ((ret == 2) && (scenarii[sc].result == 0)) + { + UNRESOLVED(-1, "An unexpected error occured\n"); + } + + /* Ok, set back the thread attribute object to a correct value */ + ret = pthread_attr_setstacksize(&scenarii[sc].ta, sysconf(_SC_THREAD_STACK_MIN)); + if (ret != 0) { UNRESOLVED(ret, "Failed to set stacksize back"); } + } + + + /* stack decrease test */ + if ((scenarii[sc].altstack == 0) && (scenarii[sc].altsize == 0)) + { + #if VERBOSE > 2 + output("Processing stack decrease test\n"); + #endif + + ret = test_stack(&scenarii[sc].ta, sysconf(_SC_THREAD_STACK_MIN)); + + if (ret == 1) { FAILED("Decreasing the stack size after thread is created had an influence on the thread"); } + + if ((ret == 0) && (scenarii[sc].result == 1)) + { + UNRESOLVED(-1, "An error was expected but the thread creation succeeded"); + } + + if ((ret == 2) && (scenarii[sc].result == 0)) + { + UNRESOLVED(-1, "An unexpected error occured\n"); + } + + #if VERBOSE > 2 + if (ret == 0) + output("Stack decrease test passed.\n"); + else + output("Something failed but we don't care here.\n"); + #endif + } + + + } /* if do_stack_tests */ + + if (do_sched_tests) + { + /* Sched policy/param change test */ + if (scenarii[sc].explicitsched != 0) /* We need a specified policy */ + { + pthread_t child; + int policy_ori, newpol_max; + struct sched_param param_ori, tmp; + + testdata_t td; + + #if VERBOSE > 2 + output("Processing sched policy/param change test\n"); + #endif + + /* Backup the scenario object */ + ret = pthread_attr_getschedpolicy(&(scenarii[sc].ta), &policy_ori); + if (ret != 0) { UNRESOLVED(ret, "Unable to read sched policy from thread attribute"); } + ret = pthread_attr_getschedparam(&(scenarii[sc].ta), ¶m_ori); + if (ret != 0) { UNRESOLVED(ret, "Unable to read sched param from thread attribute"); } + + /* Initialize the barrier */ + ret = pthread_barrier_init(&(td.bar), NULL, 2); + if (ret != 0) { UNRESOLVED(ret, "Unable to initialize the barrier"); } + + /* Create a new thread with this scenario attribute */ + ret = pthread_create(&child, &(scenarii[sc].ta), schedtest, &td); + if (ret != 0) + { + if (scenarii[sc].result == 0) + { UNRESOLVED(ret , "Failed to create a thread"); } + + #if VERBOSE > 2 + if (scenarii[sc].result == 2) + { + output("The thread creation failed -- we don't care\n"); + } + if (scenarii[sc].result == 1) + { + output("The thread creation failed as expected\n"); + } + #endif + } + else /* Thread created */ + { + if (scenarii[sc].result == 1) + { UNRESOLVED(-1, "The thread was created where an error was expected"); } + + #if VERBOSE > 2 + if (scenarii[sc].result == 2) + output("Thread is created\n"); + #endif + + /* sync 1 */ + ret = pthread_barrier_wait(&(td.bar)); + if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { UNRESOLVED(ret, "Failed to synchronize on the barrier"); } + + /* Check the new thread reports the attributes */ + if (td.policy != policy_ori) + { FAILED("The new thread does not report the scheluling policy that was specified"); } + + if (td.param.sched_priority != param_ori.sched_priority) + { FAILED("The new thread does not report the scheduling priority that was specified at creation"); } + + /* Change the thread attribute object policy & param */ + if (policy_ori == SCHED_RR) + { + ret = pthread_attr_setschedpolicy(&(scenarii[sc].ta), SCHED_FIFO); + newpol_max = sched_get_priority_max(SCHED_FIFO); + } + else + { + ret = pthread_attr_setschedpolicy(&(scenarii[sc].ta), SCHED_RR); + newpol_max = sched_get_priority_max(SCHED_RR); + } + if (ret != 0) { UNRESOLVED(ret, "Failed to change the attribute object"); } + + if (newpol_max == param_ori.sched_priority) + newpol_max--; + + tmp.sched_priority = newpol_max; + + ret = pthread_attr_setschedparam(&(scenarii[sc].ta), &tmp); + if (ret != 0) { UNRESOLVED(ret, "Failed to set the attribute sched param"); } + + /* sync 2 */ + ret = pthread_barrier_wait(&(td.bar)); + if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { UNRESOLVED(ret, "Failed to synchronize on the barrier"); } + + /* sync 3 */ + ret = pthread_barrier_wait(&(td.bar)); + if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { UNRESOLVED(ret, "Failed to synchronize on the barrier"); } + + /* Check if the thread saw the change (should not) */ + if (td.policy != policy_ori) + { FAILED("The new thread does not report the scheluling policy that was specified"); } + + if (td.param.sched_priority != param_ori.sched_priority) + { FAILED("The new thread does not report the scheduling priority that was specified at creation"); } + + /* Check what we can see for the child thread from here */ + ret = pthread_getschedparam(child, &(td.policy), &(td.param)); + if (ret != 0) { UNRESOLVED(ret, "Failed to read child thread policy / param"); } + + if (td.policy != policy_ori) + { FAILED("The child thread does not report the scheduling policy that was specified at creation"); } + + if (td.param.sched_priority != param_ori.sched_priority) + { FAILED("The child thread does not report the scheduling priority that was specified at creation"); } + + /* Restore the thread attribute */ + ret = pthread_attr_setschedpolicy(&(scenarii[sc].ta), policy_ori); + if (ret != 0) { UNRESOLVED(ret, "Unable to read sched policy from thread attribute"); } + ret = pthread_attr_setschedparam(&(scenarii[sc].ta), ¶m_ori); + if (ret != 0) { UNRESOLVED(ret, "Unable to read sched param from thread attribute"); } + + /* sync 4*/ + ret = pthread_barrier_wait(&(td.bar)); + if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { UNRESOLVED(ret, "Failed to synchronize on the barrier"); } + + /* sync 5*/ + ret = pthread_barrier_wait(&(td.bar)); + if ((ret != 0) && (ret != PTHREAD_BARRIER_SERIAL_THREAD)) { UNRESOLVED(ret, "Failed to synchronize on the barrier"); } + + /* check if the thread attribute reports a change (should not) */ + ret = pthread_attr_getschedpolicy(&(scenarii[sc].ta), &(td.policy)); + if (ret != 0) { UNRESOLVED(ret, "Unable to read sched policy from thread attribute"); } + ret = pthread_attr_getschedparam(&(scenarii[sc].ta), &(td.param)); + if (ret != 0) { UNRESOLVED(ret, "Unable to read sched param from thread attribute"); } + + if (td.policy != policy_ori) + { FAILED("The child thread does not report the scheduling policy that was specified at creation"); } + + if (td.param.sched_priority != param_ori.sched_priority) + { FAILED("The child thread does not report the scheduling priority that was specified at creation"); } + + /* Wait for the sem and join eventually the thread */ + do { ret = sem_wait(&scenarii[sc].sem); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } + + if (scenarii[sc].detached == 0) + { + ret = pthread_join(child, NULL); + if (ret != 0) { UNRESOLVED(ret, "Unable to join a thread"); } + } + + #if VERBOSE > 2 + output("Sched policy/param change test passed\n"); + #endif + } /* thread created */ + } + + /* We could also test if the inheritsched does not influence the new thread */ + + } /* if do_sched_tests */ + } + + scenar_fini(); + #if VERBOSE > 0 + output("-----\n"); + output("All test data destroyed\n"); + output("Test PASSED\n"); + #endif + + PASSED; +} + + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/4-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/4-1.c new file mode 100644 index 0000000000..cdd6601f3b --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/4-1.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2002, Intel Corporation. All rights reserved. + * Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + * + * Test upon successful completion, pthread_create() shall store the ID of the + * the created thread in the location referenced by 'thread'. + * + * Steps: + * 1. Create a thread using pthread_create() + * 2. Save the thread ID resulting from pthread_create() + * 3. Get the thread ID from the new thread by calling + * pthread_self(). + * 4. These 2 values should be equal. (i.e. the one from pthread_create() + * and the one from pthread_self()). + */ + +#include +#include +#include "posixtest.h" + +void *a_thread_func(); + +pthread_t self_th; /* Save the value of the function call pthread_self() + within the thread. Keeping it global so 'main' can + see it too. */ + +int main() +{ + pthread_t new_th; + + /* Create a new thread */ + if(pthread_create(&new_th, NULL, a_thread_func, NULL) != 0) + { + perror("Error creating thread\n"); + return PTS_UNRESOLVED; + } + + /* Wait for the thread function to return to make sure we got + * the thread ID value from pthread_self(). */ + if(pthread_join(new_th, NULL) != 0) + { + perror("Error calling pthread_join()\n"); + return PTS_UNRESOLVED; + } + + /* If the value of pthread_self() and the return value from + * pthread_create() is equal, then the test passes. */ + if(pthread_equal(new_th, self_th) == 0) + { + printf("Test FAILED\n"); + return PTS_FAIL; + } + + printf("Test PASSED\n"); + return PTS_PASS; +} + +/* The thread function that calls pthread_self() to obtain its thread ID */ +void *a_thread_func() +{ + self_th=pthread_self(); + pthread_exit(0); + return NULL; +} diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/5-1.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/5-1.c new file mode 100644 index 0000000000..087faa4dc9 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/5-1.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2002, Intel Corporation. All rights reserved. + * Created by: rolla.n.selbak REMOVE-THIS AT intel DOT com + * This file is licensed under the GPL license. For the full content + * of this license, see the COPYING file at the top level of this + * source tree. + + * Test pthread_create() + * The thread is created executing 'start_routine' with 'arg' as its only + * argument. + * + * Steps: + * 1. Create 5 separete threads using pthread_create() passing to it a single int 'arg'. + * 2. Use that passed int argument in the thread function start routine and make sure no + * errors occur. + */ + +#include +#include +#include +#include "posixtest.h" + +#define NUM_THREADS 5 + +/* The thread start routine. */ +void *a_thread_func(void* num) +{ + intptr_t i = (intptr_t) num; + printf("Passed argument for thread: %d\n", (int)i); + + pthread_exit(0); + return NULL; +} + +int main() +{ + pthread_t new_th; + long i; + + for(i=1;i +#include +#include "posixtest.h" + +#define NUM_THREADS 5 + +/* The thread start routine. */ +void *a_thread_func(void* num) +{ + int *i, j; + + i = (int *)num; + + for(j=0;j +#include +#include +#include "posixtest.h" + +sigset_t th_pendingset, th_sigmask; + +void *a_thread_func() +{ + /* Obtain the signal mask of this thread. */ + pthread_sigmask(SIG_SETMASK, NULL, &th_sigmask); + + /* Obtain the pending signals of this thread. It should be empty. */ + if (sigpending(&th_pendingset) != 0) { + printf("Error calling sigpending()\n"); + return (void *)PTS_UNRESOLVED; + } + + pthread_exit(0); + return NULL; +} + +int main() +{ + pthread_t new_th; + sigset_t main_sigmask, main_pendingset; + int ret; + + /* Empty set of signal mask and blocked signals */ + if ( (sigemptyset(&main_sigmask) != 0) || + (sigemptyset(&main_pendingset) != 0) ) + { + perror("Error in sigemptyset()\n"); + return PTS_UNRESOLVED; + } + + /* Add SIGCONT, SIGUSR1 and SIGUSR2 to the set of blocked signals */ + if (sigaddset(&main_sigmask, SIGUSR1) != 0) + { + perror("Error in sigaddset()\n"); + return PTS_UNRESOLVED; + } + + if (sigaddset(&main_sigmask, SIGUSR2) != 0) + { + perror("Error in sigaddset()\n"); + return PTS_UNRESOLVED; + } + + /* Block those signals. */ + if (pthread_sigmask(SIG_SETMASK, &main_sigmask, NULL) != 0) + { + printf("Error in pthread_sigmask()\n"); + return PTS_UNRESOLVED; + } + + /* Raise those signals so they are now pending. */ + if (raise(SIGUSR1) != 0) { + printf("Could not raise SIGALRM\n"); + return -1; + } + if (raise(SIGUSR2) != 0) { + printf("Could not raise SIGALRM\n"); + return -1; + } + + /* Create a new thread. */ + if(pthread_create(&new_th, NULL, a_thread_func, NULL) != 0) + { + perror("Error creating thread\n"); + return PTS_UNRESOLVED; + } + + /* Wait until the thread has finished execution. */ + if(pthread_join(new_th, NULL) != 0) + { + perror("Error in pthread_join()\n"); + return PTS_UNRESOLVED; + } + + /* Check to make sure that the sigmask of the thread is the same as the main thread */ + ret = sigismember(&th_sigmask, SIGUSR1); + if(ret != 1) + { + if(ret == 0) + { + printf("Error: Thread did not inherit main()s signal mask. SIGUSR1 not a member of the signal set.\n"); + return PTS_FAIL; + } + + perror("Error is sigismember()\n"); + return PTS_UNRESOLVED; + } + + ret = sigismember(&th_sigmask, SIGUSR2); + if(ret != 1) + { + if(ret == 0) + { + printf("Test FAILED: Thread did not inherit main()s signal mask. SIGUSR2 not a member of the signal set.\n"); + return PTS_FAIL; + } + + perror("Error is sigismember()\n"); + return PTS_UNRESOLVED; + } + + /* Check to make sure that the pending set of the thread does not contain SIGUSR1 or + * SIGUSR2. */ + + ret = sigismember(&th_pendingset, SIGUSR1); + if(ret != 0) + { + if(ret == 1) + { + printf("Error: Thread did not inherit main()s signal mask. SIGUSR1 not a member of the signal set.\n"); + return PTS_FAIL; + } + + perror("Error is sigismember()\n"); + return PTS_UNRESOLVED; + } + + ret = sigismember(&th_pendingset, SIGUSR2); + if(ret != 0) + { + if(ret == 1) + { + printf("Test FAILED: Thread did not inherit main()s signal mask. SIGUSR2 not a member of the signal set.\n"); + return PTS_FAIL; + } + + perror("Error is sigismember()\n"); + return PTS_UNRESOLVED; + } + + printf("Test PASSED\n"); + return PTS_PASS; +} + + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/8-2.c b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/8-2.c new file mode 100644 index 0000000000..c23a8e2bfd --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/8-2.c @@ -0,0 +1,270 @@ +/* + * 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., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + + + * This sample test aims to check the following assertion: + * + * The new thread inherits is signal mask from the calling thread, + * and has no pending signal at creation time. + + * The steps are: + * 1. In main(), create a signal mask with a few signals in the set (SIGUSR1 and SIGUSR2). + * 2. Raise those signals in main. These signals now should be pending. + * 3. Create a thread using pthread_create(). + * 4. The thread should have the same signal mask, but no signals should be pending. + + * Parts of this test are copied from 8-1.c (author: rolla.n.selbak REMOVE-THIS AT intel DOT com) + */ + + + /* We are testing conformance to IEEE Std 1003.1, 2003 Edition */ + #define _POSIX_C_SOURCE 200112L + + /* Some routines are part of the XSI Extensions */ +#ifndef WITHOUT_XOPEN + #define _XOPEN_SOURCE 600 +#endif +/********************************************************************************************/ +/****************************** standard includes *****************************************/ +/********************************************************************************************/ + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + #include + #include + + +/********************************************************************************************/ +/****************************** Test framework *****************************************/ +/********************************************************************************************/ + #include "testfrmw.h" + #include "testfrmw.c" + /* This header is responsible for defining the following macros: + * UNRESOLVED(ret, descr); + * where descr is a description of the error and ret is an int (error code for example) + * FAILED(descr); + * where descr is a short text saying why the test has failed. + * PASSED(); + * No parameter. + * + * Both three macros shall terminate the calling process. + * The testcase shall not terminate in any other maneer. + * + * The other file defines the functions + * void output_init() + * void output(char * string, ...) + * + * Those may be used to output information. + */ + +/********************************************************************************************/ +/********************************** Configuration ******************************************/ +/********************************************************************************************/ +#ifndef VERBOSE +#define VERBOSE 1 +#endif + +/********************************************************************************************/ +/*********************************** Test cases *****************************************/ +/********************************************************************************************/ + +#include "threads_scenarii.c" + +/* This file will define 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. + */ + + +/********************************************************************************************/ +/*********************************** Real Test *****************************************/ +/********************************************************************************************/ + +typedef struct +{ + sigset_t mask; + sigset_t pending; +} testdata_t; + + +/* Thread function; which will check the signal mask and pending signals */ +void * threaded(void * arg) +{ + int ret; + testdata_t * td=(testdata_t *)arg; + + /* Obtain the signal mask of this thread. */ + ret = pthread_sigmask(SIG_SETMASK, NULL, &(td->mask)); + if (ret != 0) { UNRESOLVED(ret, "Failed to get the signal mask of the thread"); } + + /* Obtain the pending signals of this thread. It should be empty. */ + ret = sigpending(&(td->pending)); + if (ret != 0) { UNRESOLVED(errno, "Failed to get pending signals from the thread"); } + + /* Signal we're done (especially in case of a detached thread) */ + do { ret = sem_post(&scenarii[sc].sem); } + while ((ret == -1) && (errno == EINTR)); + if (ret == -1) { UNRESOLVED(errno, "Failed to wait for the semaphore"); } + + /* return */ + return arg; +} + +int main (int argc, char *argv[]) +{ + int ret=0; + pthread_t child; + + testdata_t td_parent, td_thread; + + /* Initialize output routine */ + output_init(); + + /* Initialize thread attribute objects */ + scenar_init(); + + /* Initialize the signal state */ + ret = sigemptyset(&(td_parent.mask)); + if (ret != 0) { UNRESOLVED(ret, "Failed to initialize a signal set"); } + + ret = sigemptyset(&(td_parent.pending)); + if (ret != 0) { UNRESOLVED(ret, "Failed to initialize a signal set"); } + + /* Add SIGCONT, SIGUSR1 and SIGUSR2 to the set of blocked signals */ + ret = sigaddset(&(td_parent.mask), SIGUSR1); + if (ret != 0) { UNRESOLVED(ret, "Failed to add SIGUSR1 to the signal set"); } + + ret = sigaddset(&(td_parent.mask), SIGUSR2); + if (ret != 0) { UNRESOLVED(ret, "Failed to add SIGUSR2 to the signal set"); } + + /* Block those signals. */ + ret = pthread_sigmask(SIG_SETMASK, &(td_parent.mask), NULL); + if (ret != 0) { UNRESOLVED(ret, "Failed to mask the singals in main"); } + + /* Raise those signals so they are now pending. */ + ret = raise(SIGUSR1); + if (ret != 0) { UNRESOLVED(errno, "Failed to raise SIGUSR1"); } + ret = raise(SIGUSR2); + if (ret != 0) { UNRESOLVED(errno, "Failed to raise SIGUSR2"); } + + /* Do the testing for each thread */ + for (sc=0; sc < NSCENAR; sc++) + { + #if VERBOSE > 0 + output("-----\n"); + output("Starting test with scenario (%i): %s\n", sc, scenarii[sc].descr); + #endif + + /* (re)initialize thread signal sets */ + ret = sigemptyset(&(td_thread.mask)); + if (ret != 0) { UNRESOLVED(ret, "Failed to initialize a signal set"); } + + ret = sigemptyset(&(td_thread.pending)); + if (ret != 0) { UNRESOLVED(ret, "Failed to initialize a signal set"); } + + + ret = pthread_create(&child, &scenarii[sc].ta, threaded, &td_thread); + 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) /* The new thread is running */ + { + 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"); } + } + + /* The thread has terminated its work, so we can now control */ + ret = sigismember(&(td_thread.mask), SIGUSR1); + if (ret != 1) + { + if (ret == 0) { FAILED("The thread did not inherit the signal mask"); } + /* else */ + UNRESOLVED(ret, "sigismember() failed"); + } + + ret = sigismember(&(td_thread.mask), SIGUSR2); + if (ret != 1) + { + if (ret == 0) { FAILED("The thread did not inherit the signal mask"); } + /* else */ + UNRESOLVED(ret, "sigismember() failed"); + } + + ret = sigismember(&(td_thread.pending), SIGUSR1); + if (ret != 0) + { + if (ret == 1) { FAILED("The thread inherited the pending signal SIGUSR1"); } + /* else */ + UNRESOLVED(ret, "sigismember() failed"); + } + + ret = sigismember(&(td_thread.pending), SIGUSR2); + if (ret != 0) + { + if (ret == 1) { FAILED("The thread inherited the pending signal SIGUSR2"); } + /* else */ + UNRESOLVED(ret, "sigismember() failed"); + } + + + } + } + + scenar_fini(); + #if VERBOSE > 0 + output("-----\n"); + output("All test data destroyed\n"); + output("Test PASSED\n"); + #endif + + PASSED; +} + diff --git a/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/Jamfile b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/Jamfile new file mode 100644 index 0000000000..d5173beca6 --- /dev/null +++ b/src/tests/system/libroot/posix/posixtestsuite/conformance/interfaces/pthread_create/Jamfile @@ -0,0 +1,23 @@ +SubDir HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces pthread_create ; + +SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) include ] ; + +SimpleTest pthread_create_1-1 : 1-1.c ; +SimpleTest pthread_create_1-2 : 1-2.c ; +SimpleTest pthread_create_1-3 : 1-3.c ; +#SimpleTest pthread_create_1-4 : 1-4.c ; +#SimpleTest pthread_create_1-5 : 1-5.c ; +#SimpleTest pthread_create_1-6 : 1-6.c ; +SimpleTest pthread_create_2-1 : 2-1.c ; +SimpleTest pthread_create_3-1 : 3-1.c ; +#SimpleTest pthread_create_3-2 : 3-2.c ; +SimpleTest pthread_create_4-1 : 4-1.c ; +SimpleTest pthread_create_5-1 : 5-1.c ; +SimpleTest pthread_create_5-2 : 5-2.c ; +SimpleTest pthread_create_8-1 : 8-1.c ; +#SimpleTest pthread_create_8-2 : 8-2.c ; +SimpleTest pthread_create_10-1 : 10-1.c ; +#SimpleTest pthread_create_11-1 : 11-1.c ; +SimpleTest pthread_create_12-1 : 12-1.c ; +#SimpleTest pthread_create_14-1 : 14-1.c ; +#SimpleTest pthread_create_15-1 : 15-1.c ;