added pthread_once() implementation and tests

there is still a TODO on an init race condition 


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23076 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Jérôme Duval
2007-12-07 21:02:59 +00:00
parent 4ff6af6d52
commit d2d6724788
16 changed files with 1192 additions and 1 deletions
+2
View File
@@ -456,6 +456,8 @@ if $(HAIKU_ADD_POSIX_TEST_SUITE_TO_IMAGE) {
pthread_key_create_3-1 ;
AddFilesToHaikuImage home posixtestsuite conformance interfaces pthread_key_delete
: pthread_key_delete_1-1 pthread_key_delete_1-2 pthread_key_delete_2-1 ;
AddFilesToHaikuImage home posixtestsuite conformance interfaces pthread_once
: pthread_once_1-1 pthread_once_1-2 pthread_once_1-3 pthread_once_2-1 ;
AddFilesToHaikuImage home posixtestsuite conformance interfaces pthread_setspecific
: pthread_setspecific_1-1 pthread_setspecific_1-2 ;
}
+1
View File
@@ -125,6 +125,7 @@ extern int pthread_condattr_setpshared(pthread_condattr_t *condAttr, int process
/* misc. functions */
extern int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));
extern int pthread_once(pthread_once_t *once_control, void (*init_routine)());
/* thread attributes functions */
extern int pthread_attr_destroy(pthread_attr_t *attr);
+1
View File
@@ -11,5 +11,6 @@ MergeObject posix_pthread.o :
pthread_key.c
pthread_mutex.c
pthread_mutexattr.c
pthread_once.c
;
@@ -0,0 +1,31 @@
/*
** Copyright 2007, Jérôme Duval. All rights reserved.
** Distributed under the terms of the MIT License.
*/
#include <pthread.h>
#include "pthread_private.h"
int
pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{
if (once_control->state == PTHREAD_NEEDS_INIT) {
// TODO race condition ?
if (once_control->mutex == NULL) {
if (pthread_mutex_init(&once_control->mutex, NULL) != 0)
return -1;
}
pthread_mutex_lock(&once_control->mutex);
if (once_control->state == PTHREAD_NEEDS_INIT) {
init_routine();
once_control->state = PTHREAD_DONE_INIT;
}
pthread_mutex_unlock(&once_control->mutex);
}
return 0;
}
@@ -6,6 +6,7 @@ SubInclude HAIKU_TOP src tests system libroot posix posixtestsuite conformance i
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 ;
@@ -0,0 +1,62 @@
/*
* 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_once()
*
* Dynamic package installation. Tihe first call to pthread_once() by any
* thread in a process, with a given 'once_control', shall call the
* 'init_routine' with no arguments. Subsequent calls of pthread_once()
* with the same once_control shall not call the 'init_routine'. The
* 'once_control' paramter shall determine whether the associated
* initialization routine has been called.
*
* STEPS:
* 1.Initialize a pthread_once object
* 2.Call pthread_once passing it this object
* 3.Call pthread_once again, this time, it shouldn't execute the function
* passed to it. If it does, the test fails.
*/
#include <pthread.h>
#include <stdio.h>
#include "posixtest.h"
/* Keeps track of how many times the init function has been called. */
int init_flag;
/* The init function that pthread_once calls */
void *an_init_func()
{
init_flag++;
return NULL;
}
int main()
{
pthread_once_t once_control = PTHREAD_ONCE_INIT;
init_flag=0;
/* Call pthread_once, passing it the once_control */
pthread_once(&once_control, (void*)an_init_func);
/* Call pthread_once again. The init function should not be
* called. */
pthread_once(&once_control, (void*)an_init_func);
if(init_flag != 1)
{
printf("Test FAILED\n");
return PTS_FAIL;
}
printf("Test PASSED\n");
return PTS_PASS;
}
@@ -0,0 +1,118 @@
/*
* 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:
*
* In a process, the first call to pthread_once with a given once_control
* calls the init routine.
* The steps are:
* -> call pthread_once
* -> check the init_routine executed
* The test fails if the init_routine has not been called after pthread_once
* has returned.
*/
/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
#define _POSIX_C_SOURCE 200112L
/********************************************************************************************/
/****************************** standard includes *****************************************/
/********************************************************************************************/
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.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 case *****************************************/
/********************************************************************************************/
int control;
void my_init( void )
{
control = 1;
return ;
}
/* The main test function. */
int main( int argc, char * argv[] )
{
int ret;
pthread_once_t myctl = PTHREAD_ONCE_INIT;
/* Initialize output */
output_init();
control = 0;
/* Call the initializer */
ret = pthread_once( &myctl, my_init );
if ( ret != 0 )
{
UNRESOLVED( ret, "pthread_once failed" );
}
if ( control != 1 )
{
FAILED( "The initializer function did not execute" );
}
PASSED;
}
@@ -0,0 +1,183 @@
/*
* 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:
*
* Subsequent calls with the same once_control do not call init routine.
* The steps are:
* -> Create several threads
* -> each call pthread_once
* -> check the init_routine executed once
* The test fails if the init_routine has not been called or has
* been called several times.
*/
/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
#define _POSIX_C_SOURCE 200112L
/********************************************************************************************/
/****************************** standard includes *****************************************/
/********************************************************************************************/
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.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 NTHREADS 30
/********************************************************************************************/
/*********************************** Test case *****************************************/
/********************************************************************************************/
int control;
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
void my_init( void )
{
int ret = 0;
ret = pthread_mutex_lock( &mtx );
if ( ret != 0 )
{
UNRESOLVED( ret, "Failed to lock mutex in initializer" );
}
control++;
ret = pthread_mutex_unlock( &mtx );
if ( ret != 0 )
{
UNRESOLVED( ret, "Failed to unlock mutex in initializer" );
}
return ;
}
/* Thread function */
void * threaded ( void * arg )
{
int ret;
ret = pthread_once( arg, my_init );
if ( ret != 0 )
{
UNRESOLVED( ret, "pthread_once failed" );
}
return NULL;
}
/* The main test function. */
int main( int argc, char * argv[] )
{
int ret, i;
pthread_once_t myctl = PTHREAD_ONCE_INIT;
pthread_t th[ NTHREADS ];
/* Initialize output */
output_init();
control = 0;
/* Create the children */
for ( i = 0; i < NTHREADS; i++ )
{
ret = pthread_create( &th[ i ], NULL, threaded, &myctl );
if ( ret != 0 )
{
UNRESOLVED( ret, "Failed to create a thread" );
}
}
/* Then join */
for ( i = 0; i < NTHREADS; i++ )
{
ret = pthread_join( th[ i ], NULL );
if ( ret != 0 )
{
UNRESOLVED( ret, "Failed to join a thread" );
}
}
/* Fetch the memory */
ret = pthread_mutex_lock( &mtx );
if ( ret != 0 )
{
UNRESOLVED( ret, "Failed to lock mutex in initializer" );
}
if ( control != 1 )
{
output( "Control: %d\n", control );
FAILED( "The initializer function did not execute once" );
}
ret = pthread_mutex_unlock( &mtx );
if ( ret != 0 )
{
UNRESOLVED( ret, "Failed to unlock mutex in initializer" );
}
PASSED;
}
@@ -0,0 +1,118 @@
/*
* 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_once returns only when init routine has completed.
* The steps are:
* -> call pthread_once (the init routine lasts for 1 second)
* -> check the init_routine executed
* The test fails if the init_routine has not been completed when pthread_once
* returns.
*/
/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
#define _POSIX_C_SOURCE 200112L
/********************************************************************************************/
/****************************** standard includes *****************************************/
/********************************************************************************************/
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.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 case *****************************************/
/********************************************************************************************/
int control;
void my_init( void )
{
sleep( 1 );
control = 1;
return ;
}
/* The main test function. */
int main( int argc, char * argv[] )
{
int ret;
pthread_once_t myctl = PTHREAD_ONCE_INIT;
/* Initialize output */
output_init();
control = 0;
/* Call the initializer */
ret = pthread_once( &myctl, my_init );
if ( ret != 0 )
{
UNRESOLVED( ret, "pthread_once failed" );
}
if ( control != 1 )
{
FAILED( "The initializer function did not execute" );
}
PASSED;
}
@@ -0,0 +1,121 @@
/*
* 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_once()
*
* The pthread_once() function is not a cancelation point. However if
* 'init_routine'is a cancelation point and is canceled, the effect on
* 'once_control' shall be as if pthread_once() was never called.
*
* STEPS:
* 1. Create a cancelable thread.
* 2. In the thread routine, call pthread_once using a global pthread_once_t
* object.
* 3. Cancel the thread during the pthread_once init function
* 4. Call pthread_once again with the same pthread once_t object
* 5. This should call the pthread_once init function. If not, the test fails.
*/
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include "posixtest.h"
/* Global pthread_once_t object */
pthread_once_t once_control;
/* Keeps track of how many times the init function has been called. */
int init_flag;
/* The init function that pthread_once calls */
void *an_init_func()
{
/* Indicate to main() that the init function has been reached */
init_flag=1;
/* Stay in a continuous loop until the thread that called
* this function gets canceled */
sleep(10);
/* The thread could not be canceled, timeout after 10 secs */
perror("Init function timed out (10 secs), thread could not be canceled\n");
init_flag=-1;
return NULL;
}
/* Thread function */
void *a_thread_func()
{
/* Make the thread cancelable immediately */
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
pthread_once(&once_control, (void*)an_init_func);
return NULL;
}
/* 2nd init function used by the 2nd call of pthread_once */
void *an_init_func2()
{
/* Indicate to main() that this init function has been reached */
init_flag=1;
return NULL;
}
int main()
{
pthread_t new_th;
once_control = PTHREAD_ONCE_INIT;
init_flag=0;
/* Create a thread that will execute the first call to pthread_once() */
if(pthread_create(&new_th, NULL, a_thread_func, NULL) != 0)
{
perror("Error creating thread\n");
return PTS_UNRESOLVED;
}
/* Wait until the init function is reached to cancel the thread */
while(init_flag==0)
sleep(1);
/* Send cancel request to the thread*/
if(pthread_cancel(new_th) != 0)
{
perror("Could send cancel request to thread\n");
return PTS_UNRESOLVED;
}
/* Wait until the thread is canceled */
pthread_join(new_th, NULL);
/* If the thread could not be canceled and timed out, send
* an error */
if (init_flag == -1)
{
perror("Error: could not cancel thread\n");
return PTS_UNRESOLVED;
}
init_flag=0;
/* Should be able to call pthread_once() again with the same
* pthread_once_t object. */
pthread_once(&once_control, (void*)an_init_func2);
/* If the init function from the 2nd call to pthread_once() was not
* reached, the test fails. */
if(init_flag != 1)
{
printf("Test FAILED\n: %d", init_flag);
return PTS_FAIL;
}
printf("Test PASSED\n");
return PTS_PASS;
}
@@ -0,0 +1,17 @@
/*
* 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_once()
*The constant PTHREAD_ONCE_INIT is defined in the pthread.h header.
*/
#include <pthread.h>
pthread_once_t dummy = PTHREAD_ONCE_INIT;
@@ -0,0 +1,365 @@
/*
* 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:
* -> kill a thread which calls pthread_once
* -> check that EINTR is never returned
*/
/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
#define _POSIX_C_SOURCE 200112L
/********************************************************************************************/
/****************************** standard includes *****************************************/
/********************************************************************************************/
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <semaphore.h>
#include <errno.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 *****************************************/
/********************************************************************************************/
char do_it = 1;
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
}
int init_ctl;
/* Init function */
void initializer( void )
{
init_ctl++;
return ;
}
/* Test function -- calls pthread_equal() and checks that EINTR is never returned. */
void * test( void * arg )
{
int ret = 0;
pthread_once_t once_ctl;
/* 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" );
}
while ( do_it )
{
count_ope++;
once_ctl = PTHREAD_ONCE_INIT;
init_ctl = 0;
ret = pthread_once( &once_ctl, initializer );
if ( ret == EINTR )
{
FAILED( "pthread_once returned EINTR" );
}
if ( ret != 0 )
{
UNRESOLVED( ret, "pthread_once failed" );
}
ret = pthread_once( &once_ctl, initializer );
if ( ret == EINTR )
{
FAILED( "pthread_once returned EINTR" );
}
if ( ret != 0 )
{
UNRESOLVED( ret, "pthread_once failed" );
}
if ( init_ctl != 1 )
{
output( "init_ctl:%d\n", init_ctl );
FAILED( "The initializer did not execute as expected" );
}
}
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();
/* 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" );
}
#if VERBOSE > 0
output( "Test executed successfully.\n" );
output( " %d initializations.\n", count_ope );
#ifdef WITH_SYNCHRO
output( " %d signals were sent meanwhile.\n", count_sig );
#endif
#endif
PASSED;
}
@@ -0,0 +1,11 @@
SubDir HAIKU_TOP src tests system libroot posix posixtestsuite conformance interfaces pthread_once ;
SubDirHdrs [ FDirName $(SUBDIR) $(DOTDOT) $(DOTDOT) $(DOTDOT) include ] ;
SimpleTest pthread_once_1-1 : 1-1.c ;
SimpleTest pthread_once_1-2 : 1-2.c ;
SimpleTest pthread_once_1-3 : 1-3.c ;
SimpleTest pthread_once_2-1 : 2-1.c ;
#SimpleTest pthread_once_3-1 : 3-1.c ;
#SimpleTest pthread_once_4-1 : 4-1.c ;
#SimpleTest pthread_once_6-1 : 6-1.c ;
@@ -0,0 +1,70 @@
/*
* 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 file is a wrapper to use the tests from the NPTL Test & Trace Project
* with either the Linux Test Project or the Open POSIX Test Suite.
* The following function are defined:
* void output_init()
* void output_fini()
* void output(char * string, ...)
*
* The are used to output informative text (as a printf).
*/
#include <time.h>
#include <sys/types.h>
/* We use a mutex to avoid conflicts in traces */
static pthread_mutex_t m_trace = PTHREAD_MUTEX_INITIALIZER;
/*****************************************************************************************/
/******************************* stdout module *****************************************/
/*****************************************************************************************/
/* The following functions will output to stdout */
#if (1)
static void output_init()
{
/* do nothing */
return;
}
static void output( char * string, ... )
{
va_list ap;
char *ts="[??:??:??]";
struct tm * now;
time_t nw;
pthread_mutex_lock(&m_trace);
nw = time(NULL);
now = localtime(&nw);
if (now == NULL)
printf(ts);
else
printf("[%2.2d:%2.2d:%2.2d]", now->tm_hour, now->tm_min, now->tm_sec);
va_start( ap, string);
vprintf(string, ap);
va_end(ap);
pthread_mutex_unlock(&m_trace);
}
static void output_fini()
{
/*do nothing */
return;
}
#endif
@@ -0,0 +1,84 @@
/*
* 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 file is a wrapper to use the tests from the NPTL Test & Trace Project
* with either the Linux Test Project or the Open POSIX Test Suite.
* The following macros are defined here:
* 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 without calling one of those macros.
*
*
*/
#include "posixtest.h"
#include <string.h> /* for the strerror() routine */
#ifdef __GNUC__ /* We are using GCC */
#define UNRESOLVED(x, s) \
{ output("Test %s unresolved: got %i (%s) on line %i (%s)\n", __FILE__, x, strerror(x), __LINE__, s); \
output_fini(); \
exit(PTS_UNRESOLVED); }
#define FAILED(s) \
{ output("Test %s FAILED: %s\n", __FILE__, s); \
output_fini(); \
exit(PTS_FAIL); }
#define PASSED \
output_fini(); \
exit(PTS_PASS);
#define UNTESTED(s) \
{ output("File %s cannot test: %s\n", __FILE__, s); \
output_fini(); \
exit(PTS_UNTESTED); \
}
#else /* not using GCC */
#define UNRESOLVED(x, s) \
{ output("Test unresolved: got %i (%s) on line %i (%s)\n", x, strerror(x), __LINE__, s); \
output_fini(); \
exit(PTS_UNRESOLVED); }
#define FAILED(s) \
{ output("Test FAILED: %s\n", s); \
output_fini(); \
exit(PTS_FAIL); }
#define PASSED \
output_fini(); \
exit(PTS_PASS);
#define UNTESTED(s) \
{ output("Unable to test: %s\n", s); \
output_fini(); \
exit(PTS_UNTESTED); \
}
#endif
@@ -64,7 +64,13 @@ threads_tests()
conformance/interfaces/pthread_key_delete/pthread_key_delete_1-2
# conformance/interfaces/pthread_key_delete/pthread_key_delete_2-1
echo "pthread_key_delete_2-1: FIXME: test blocks, see bug #1642"
echo ""
echo
echo "pthread_once()"
conformance/interfaces/pthread_once/pthread_once_1-1
conformance/interfaces/pthread_once/pthread_once_1-2
conformance/interfaces/pthread_once/pthread_once_1-3
conformance/interfaces/pthread_once/pthread_once_2-1
echo
echo "pthread_setspecific()"
conformance/interfaces/pthread_setspecific/pthread_setspecific_1-1
conformance/interfaces/pthread_setspecific/pthread_setspecific_1-2