* Added some pthread_attr_destroy() and pthread_create() tests from

posixtestsuite into our repository.
* A few of the latter ones actually fail on Haiku.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33776 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-10-26 17:13:11 +00:00
parent ebcd4e1ada
commit 0c2788b4ce
25 changed files with 3366 additions and 15 deletions
@@ -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 ;
@@ -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 <pthread.h>
#include <stdio.h>
#include <errno.h>
#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;
}
}
@@ -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 <pthread.h>
#include <stdio.h>
#include <errno.h>
#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;
}
}
@@ -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 <pthread.h>
#include <stdio.h>
#include <errno.h>
#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;
}
}
@@ -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 ;
@@ -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 <pthread.h>
#include <stdio.h>
#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;
}
@@ -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 <pthread.h>
#include <stdio.h>
#include <unistd.h>
#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;
}
@@ -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 <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#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);
}
@@ -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 <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
/********************************************************************************************/
/****************************** 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;
}
@@ -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 <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <sys/wait.h>
/********************************************************************************************/
/****************************** 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(&current);
/* 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)&current))
{
/* the stack is growing up */
if ( ((long)&current) - ((long)arg) >= stacksize)
{
output("Growing up stack started below %p and we are currently up to %p\n", arg, &current);
return (void *)0;
}
}
else
{
/* the stack is growing down */
if ( ((long)arg) - ((long)&current) >= stacksize)
{
output("Growing down stack started upon %p and we are currently down to %p\n", arg, &current);
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;
}
@@ -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 <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <sys/wait.h>
/********************************************************************************************/
/****************************** 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<NCPU; i++)
{
ret = pthread_create(&hpth[i], &ta, hp_func, &ctrl);
if (ret != 0) { UNRESOLVED(ret, "Failed to create enough threads"); }
}
#if VERBOSE > 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<NCPU; i++)
{
ret = pthread_join(hpth[i], NULL);
if (ret != 0) { UNRESOLVED(ret, "Failed to join a thread"); }
}
/* Ok so now the low priority should execute when we stop this one (or earlier). */
ret = pthread_join(lpth, NULL);
if (ret != 0) { UNRESOLVED(ret, "Failed to join the low priority thread"); }
/* We just check that it executed */
if (ctrl != 2) { FAILED("Joined the low-priority thread but it did not execute."); }
#if VERBOSE > 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;
}
@@ -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.
*
*
* - [email protected]: 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 <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#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;
}
@@ -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.
*
* [email protected]
*
* 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 <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#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;
}
@@ -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 <pthread.h>
#include <stdio.h>
#include <errno.h>
#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;
}
@@ -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 <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <sys/wait.h>
#include <time.h>
#include <signal.h>
/********************************************************************************************/
/****************************** 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;
}
@@ -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 <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <sys/wait.h>
/********************************************************************************************/
/****************************** 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;
}
@@ -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 <pthread.h>
#include <stdio.h>
#include <errno.h>
#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;
}
@@ -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 <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#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;
}
@@ -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 <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <sys/wait.h>
/********************************************************************************************/
/****************************** 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(&current);
/* 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)&current))
{
/* the stack is growing up */
if ( ((long)&current) - ((long)arg) >= stacksize)
{
output("Growing up stack started below %p and we are currently up to %p\n", arg, &current);
return (void *)0;
}
}
else
{
/* the stack is growing down */
if ( ((long)arg) - ((long)&current) >= stacksize)
{
output("Growing down stack started upon %p and we are currently down to %p\n", arg, &current);
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), &param_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), &param_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;
}
@@ -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 <pthread.h>
#include <stdio.h>
#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;
}
@@ -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 <stdint.h>
#include <pthread.h>
#include <stdio.h>
#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<NUM_THREADS+1;i++)
{
if(pthread_create(&new_th, NULL, a_thread_func, (void*)i) != 0)
{
printf("Error creating thread\n");
return PTS_FAIL;
}
/* Wait for thread to end execution */
pthread_join(new_th, NULL);
}
printf("Test PASSED\n");
return PTS_PASS;
}
@@ -0,0 +1,59 @@
/*
* 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 a thread using pthread_create() passing to it an array of 'int's as an argument.
* 2. Use that passed int argument in the thread function start routine and make sure no
* errors occur.
*/
#include <pthread.h>
#include <stdio.h>
#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<NUM_THREADS;j++)
printf("Passed argument %d for thread\n", i[j]);
pthread_exit(0);
return NULL;
}
int main()
{
pthread_t new_th;
int i[NUM_THREADS], j;
for(j=0;j<NUM_THREADS;j++)
i[j] = j+1;
if(pthread_create(&new_th, NULL, a_thread_func, (void*)&i) != 0)
{
printf("Error creating thread\n");
return PTS_FAIL;
}
/* Wait for thread to end execution */
pthread_join(new_th, NULL);
printf("Test PASSED\n");
return PTS_PASS;
}
@@ -0,0 +1,163 @@
/*
* 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 signal state of the new thread will be initialized as so:
*
* - The signal mask shall be inherited from the created thread
* - The set of signals pending for the new thread shall be empty.
*
* Steps:
* 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.
*
*/
#include <pthread.h>
#include <stdio.h>
#include <signal.h>
#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;
}
@@ -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 <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sched.h>
#include <semaphore.h>
#include <errno.h>
#include <assert.h>
#include <sys/wait.h>
#include <signal.h>
/********************************************************************************************/
/****************************** 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;
}
@@ -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 ;