diff options
author | mcorino <mcorino@users.noreply.github.com> | 2005-06-24 10:34:26 +0000 |
---|---|---|
committer | mcorino <mcorino@users.noreply.github.com> | 2005-06-24 10:34:26 +0000 |
commit | 7c6148dca9d50acae7e9b66146bcfcb8f4efee13 (patch) | |
tree | 7b661b078ece25e4ddf38ce3c4d64d71e28f3880 | |
parent | d3b8c4aa5c54d0d014210f4c4fa3ac525a352c6a (diff) | |
download | ATCD-7c6148dca9d50acae7e9b66146bcfcb8f4efee13.tar.gz |
ChangeLogTag: Fri Jun 23 10:20:12 UTC 2005 Martin Corino <mcorino@remedy.nl>
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | ace/OS_NS_Thread.inl | 11 | ||||
-rw-r--r-- | tests/Auto_Event_Test.cpp | 226 | ||||
-rw-r--r-- | tests/Manual_Event_Test.cpp | 205 | ||||
-rw-r--r-- | tests/Process_Manual_Event_Test.cpp | 209 | ||||
-rw-r--r-- | tests/Process_Semaphore_Test.cpp | 219 | ||||
-rw-r--r-- | tests/Semaphore_Test.cpp | 8 | ||||
-rw-r--r-- | tests/run_test.lst | 3 | ||||
-rw-r--r-- | tests/tests.mpc | 28 |
9 files changed, 919 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog index b52de365092..485f47bf452 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +Fri Jun 23 10:20:12 UTC 2005 Martin Corino <mcorino@remedy.nl> + + * ace/OS_NS_Thread.inl: + Made sure ETIME is always returned on timeouts of + ACE_OS::sema_timedwait and not ETIMEDOUT. + + * tests/Semaphore_Test.cpp: + Extended platform coverage of timeout tests. + + * tests/Auto_Event_Test.cpp: + * tests/Manual_Event_Test.cpp: + * tests/Process_Manual_Event_Test.cpp: + * tests/Process_Semaphore_Test.cpp: + * tests/run_test.lst: + * tests/tests.mpc: + Added new tests. + Fri Jun 23 09:17:12 UTC 2005 Martin Corino <mcorino@remedy.nl> * tests/INET_Addr_Test_IPV6.cpp: diff --git a/ace/OS_NS_Thread.inl b/ace/OS_NS_Thread.inl index ed9a00e1f6f..27080c9a2d5 100644 --- a/ace/OS_NS_Thread.inl +++ b/ace/OS_NS_Thread.inl @@ -2121,9 +2121,13 @@ ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value &tv) ACE_OS_TRACE ("ACE_OS::sema_wait"); # if defined (ACE_HAS_POSIX_SEM) # if defined (ACE_HAS_POSIX_SEM_TIMEOUT) + int rc; timespec_t ts; ts = tv; // Calls ACE_Time_Value::operator timespec_t(). - ACE_OSCALL_RETURN (::sem_timedwait (s->sema_, &ts), int, -1); + ACE_OSCALL (::sem_timedwait (s->sema_, &ts), int, -1, rc); + if (rc == -1 && errno == ETIMEDOUT) + errno = ETIME; /* POSIX returns ETIMEDOUT but we need ETIME */ + return rc; # else ACE_UNUSED_ARG (s); ACE_UNUSED_ARG (tv); @@ -2144,8 +2148,9 @@ ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value &tv) if ((rc = ACE_OS::select (ACE_Handle_Set::MAXSIZE, fds_, 0, 0, timeout)) != 1) { if (rc == 0) - // make sure errno is set right (select() sets ETIME) - errno = ETIMEDOUT; + errno = ETIME; + else if (rc == -1 && errno == EINTR) + errno = ETIME; return (-1); } diff --git a/tests/Auto_Event_Test.cpp b/tests/Auto_Event_Test.cpp new file mode 100644 index 00000000000..a31b8a9f6a1 --- /dev/null +++ b/tests/Auto_Event_Test.cpp @@ -0,0 +1,226 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Auto_Event Test +// +// = DESCRIPTION +// This test verifies the functionality of the <ACE_Auto_Event> +// implementation. +// +// = AUTHOR +// Martin Corino <mcorino@remedy.nl> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Auto_Event.h" +#include "ace/Thread.h" +#include "ace/Thread_Manager.h" +#include "ace/Get_Opt.h" +#include "ace/OS_NS_sys_time.h" +#include "ace/OS_NS_time.h" +#include "ace/OS_NS_unistd.h" + +ACE_RCSID(tests, Auto_Event_Test, "$Id$") + +// msec that times are allowed to differ before test fails. +#if defined (ACE_HAS_HI_RES_TIMER) || defined (ACE_HAS_AIX_HI_RES_TIMER) || \ + defined (ACE_HAS_PENTIUM) || defined (ACE_HAS_ALPHA_TIMER) || \ + defined (ACE_HAS_POWERPC_TIMER) +# define ACE_ALLOWED_SLACK 100 +#else /* don't have a high-res timer */ +# define ACE_ALLOWED_SLACK 1100 +#endif /* don't have a high-res timer */ + +// Test results, 'success' is 0 +static int test_result = 0; + +#if defined (ACE_HAS_THREADS) + +// Event used in the tests. Start it "unsignalled" (i.e., its initial +// state is 0). +static ACE_Auto_Event evt ((unsigned int) 0); + +// Default number of iterations. +static int n_iterations = 10; + +// Number of worker threads. +static size_t n_workers = 10; + +// Number of timeouts. +static size_t timeouts = 0; + +// Number of times to call test_timeout (). +static size_t test_timeout_count = 3; + +// Tests the amount of time spent in a timed wait. +static int +test_timeout (void) +{ + int status = 0; + + // milliseconds... + long msecs_expected; + long msecs_waited; + long msecs_diff; + + // Wait a little longer each time + static long wait_secs = 3; + + ACE_Time_Value wait = ACE_OS::gettimeofday (); + + ACE_Time_Value begin = wait; + + wait.sec (wait.sec () + wait_secs); + + if (evt.wait (&wait) == -1) + ACE_ASSERT (errno == ETIME); + + ACE_Time_Value wait_diff = ACE_OS::gettimeofday () - begin; + + msecs_waited = wait_diff.msec (); + msecs_expected = wait_secs * 1000; + msecs_diff = labs (msecs_expected - msecs_waited); + + if (msecs_diff > ACE_ALLOWED_SLACK) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Timed wait fails length test\n"))); + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Value: %d ms, actual %d ms\n"), + msecs_expected, + msecs_waited)); + status = -1; + } + + ++wait_secs; + return status; +} + +// Explain usage and exit. +static void +print_usage_and_die (void) +{ + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("usage: %n [-w n_workers] [-n iteration_count]\n"))); + ACE_OS::exit (1); +} + +static void +parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("w:n:")); + + int c; + + while ((c = get_opt ()) != -1) + switch (c) + { + case 'w': + n_workers = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'n': + n_iterations = ACE_OS::atoi (get_opt.opt_arg ()); + break; + default: + print_usage_and_die (); + break; + } +} + +// Worker tries to acquire the semaphore, hold it for a while, and +// then releases it. + +static void * +worker (void *) +{ + for (int iterations = 1; + iterations <= n_iterations; + iterations++) + { + ACE_Time_Value wait (0, + iterations * 1000 * 100); // Wait 'iter' msec + ACE_Time_Value tv = ACE_OS::gettimeofday () + wait; + if (evt.wait (&tv) == -1) + { + // verify that we have ETIME + ACE_ASSERT(ACE_OS::last_error() == ETIME); + ++timeouts; + ACE_Time_Value diff = ACE_OS::gettimeofday (); + diff = diff - tv; // tv should have been reset to time acquired + long diff_msec = diff.msec (); + + if (diff_msec > ACE_ALLOWED_SLACK) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Acquire fails time reset test\n"))); + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Diff btw now and returned time: %d ms\n"), + diff.msec ())); + test_result = 1; + } + // Hold the lock for a while. + ACE_OS::sleep (ACE_Time_Value (0, + (ACE_OS::rand () % 1000) * 1000)); + evt.signal (); + } + + ACE_Thread::yield (); + } + + return 0; +} + +#endif /* ACE_HAS_THREADS */ + +// Test event functionality. + +int run_main (int argc, ACE_TCHAR *argv[]) +{ + ACE_START_TEST (ACE_TEXT ("Auto_Event_Test")); + +#if defined (ACE_HAS_THREADS) + parse_args (argc, argv); + ACE_OS::srand (ACE_OS::time (0L)); + + //Test timed waits. + for (size_t i = 0; i < test_timeout_count; i++) + if (test_timeout () != 0) + test_result = 1; + + if (ACE_Thread_Manager::instance ()->spawn_n + (static_cast<size_t> (n_workers), + ACE_THR_FUNC (worker), + 0, + THR_NEW_LWP) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("spawn_n")), + 1); + + // Release the first worker. + evt.signal (); + + ACE_Thread_Manager::instance ()->wait (); + + size_t percent = (timeouts * 100) / (n_workers * n_iterations); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Worker threads timed out %d percent of the time\n"), + percent)); + + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Auto_Event Test successful\n"))); +#else + ACE_UNUSED_ARG (argc); + ACE_UNUSED_ARG (argv); + ACE_ERROR ((LM_INFO, + ACE_TEXT ("Threads not supported on this platform\n"))); +#endif /* ACE_HAS_THREADS */ + ACE_END_TEST; + return test_result; +} diff --git a/tests/Manual_Event_Test.cpp b/tests/Manual_Event_Test.cpp new file mode 100644 index 00000000000..1b28d846a71 --- /dev/null +++ b/tests/Manual_Event_Test.cpp @@ -0,0 +1,205 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Manual_Event Test +// +// = DESCRIPTION +// This test verifies the functionality of the <ACE_Manual_Event> +// implementation. +// +// = AUTHOR +// Martin Corino <mcorino@remedy.nl> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Manual_Event.h" +#include "ace/Thread.h" +#include "ace/Thread_Manager.h" +#include "ace/Get_Opt.h" +#include "ace/OS_NS_sys_time.h" +#include "ace/OS_NS_time.h" +#include "ace/OS_NS_unistd.h" +#include "ace/Atomic_Op.h" + +ACE_RCSID(tests, Manual_Event_Test, "$Id$") + +// msec that times are allowed to differ before test fails. +#if defined (ACE_HAS_HI_RES_TIMER) || defined (ACE_HAS_AIX_HI_RES_TIMER) || \ + defined (ACE_HAS_PENTIUM) || defined (ACE_HAS_ALPHA_TIMER) || \ + defined (ACE_HAS_POWERPC_TIMER) +# define ACE_ALLOWED_SLACK 100 +#else /* don't have a high-res timer */ +# define ACE_ALLOWED_SLACK 1100 +#endif /* don't have a high-res timer */ + +// Test results, 'success' is 0 +static int test_result = 0; + +#if defined (ACE_HAS_THREADS) + +// Event used in the tests. Start it "unsignalled" (i.e., its initial +// state is 0). +static ACE_Manual_Event evt ((unsigned int) 0); + +// Default number of iterations. +static int n_iterations = 10; + +// Number of worker threads. +static long n_workers = 10; + +// Number of wakeups. +#if defined (ACE_HAS_BUILTIN_ATOMIC_OP) +static ACE_Atomic_Op<ACE_Thread_Mutex, long> n_awoken; +static ACE_Atomic_Op<ACE_Thread_Mutex, long> n_awoken2; +#else +static long n_awoken; +static long n_awoken2; +#endif + +// Explain usage and exit. +static void +print_usage_and_die (void) +{ + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("usage: %n [-w n_workers] [-n iteration_count]\n"))); + ACE_OS::exit (1); +} + +static void +parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("w:n:")); + + int c; + + while ((c = get_opt ()) != -1) + switch (c) + { + case 'w': + n_workers = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'n': + n_iterations = ACE_OS::atoi (get_opt.opt_arg ()); + break; + default: + print_usage_and_die (); + break; + } +} + +// Worker tries to acquire the semaphore, hold it for a while, and +// then manually releases it. + +static void * +worker (void *) +{ + if (evt.wait() == -1) + { + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%P|%t) Failed waiting for pulse()\n"))); + return 0; + } + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) awake\n"))); + + if (++n_awoken < n_workers) + { + ACE_Time_Value wait (1, 0); // Wait 10 sec + ACE_Time_Value tv = ACE_OS::gettimeofday () + wait; + + if (evt.wait (&tv) == -1) + { + // verify that we have ETIME + ACE_ASSERT(ACE_OS::last_error() == ETIME); + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) timeout\n"))); + } + else + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) awake in time\n"))); + + if (++n_awoken2 >= (n_workers/2)) + evt.reset(); // reset signal (rest times out) + } + } + else + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) last awake; send signal\n"))); + // last one wakes others + evt.signal(); + + ACE_OS::sleep (ACE_Time_Value(0, 200 * 1000 * 100)); // 200 msec + } + + if (evt.wait() == -1) + { + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%P|%t) Failed waiting for signal()\n"))); + } + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P|%t) worker finished\n"))); + + return 0; +} + +#endif /* ACE_HAS_THREADS */ + +// Test event functionality. + +int run_main (int argc, ACE_TCHAR *argv[]) +{ + ACE_START_TEST (ACE_TEXT ("Manual_Event_Test")); + +#if defined (ACE_HAS_THREADS) + parse_args (argc, argv); + + if (ACE_Thread_Manager::instance ()->spawn_n + (static_cast<size_t> (n_workers), + ACE_THR_FUNC (worker), + 0, + THR_NEW_LWP) == -1) + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("spawn_n")), + 1); + + // gives all workers chance to start + ACE_OS::sleep (5); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("sending pulse()\n"))); + + // Release the all workers. + evt.pulse (); + + // Wait 2 sec + ACE_OS::sleep (2); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("sending signal()\n"))); + + // Signal + evt.signal(); + + ACE_Thread_Manager::instance ()->wait (); + + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Manual_Event Test successful\n"))); +#else + ACE_UNUSED_ARG (argc); + ACE_UNUSED_ARG (argv); + ACE_ERROR ((LM_INFO, + ACE_TEXT ("Threads not supported on this platform\n"))); +#endif /* ACE_HAS_THREADS */ + ACE_END_TEST; + return test_result; +} diff --git a/tests/Process_Manual_Event_Test.cpp b/tests/Process_Manual_Event_Test.cpp new file mode 100644 index 00000000000..a4bf69ea288 --- /dev/null +++ b/tests/Process_Manual_Event_Test.cpp @@ -0,0 +1,209 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Process_Manual_Event_Test.cpp +// +// = DESCRIPTION +// This test verifies the functionality of the <ACE_Manual_Event> +// processshared implementation. +// +// = AUTHOR +// Martin Corino <mcorino@remedy.nl> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Process.h" +#include "ace/Manual_Event.h" +#include "ace/Get_Opt.h" +#include "ace/ACE.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_string.h" +#include "ace/os_include/os_dirent.h" + +#if !defined (ACE_LACKS_FORK) +static int iterations = 10; +static int child_process = 0; +static const char *event_ping_name = "ACE_Ping_Event"; +static const char *event_pong_name = "ACE_Pong_Event"; + +// Explain usage and exit. +static void +print_usage_and_die (void) +{ + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("usage: %n [-i #iterations] [-c (child process)]\n"))); + ACE_OS::exit (1); +} + +// Parse the command-line arguments and set options. +static void +parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("i:c")); + + int c; + + while ((c = get_opt ()) != -1) + switch (c) + { + case 'i': + iterations = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'c': + child_process = 1; + break; + default: + print_usage_and_die (); + break; + } +} + +static void +acquire_release (void) +{ + ACE_Manual_Event event_ping (0, USYNC_PROCESS, ACE_TEXT_CHAR_TO_TCHAR (event_ping_name)); + ACE_Manual_Event event_pong (0, USYNC_PROCESS, ACE_TEXT_CHAR_TO_TCHAR (event_pong_name)); + + // Make sure the constructor succeeded + ACE_ASSERT (ACE_LOG_MSG->op_status () == 0); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Begin ping-pong\n"))); + + if (child_process) + { + for (int i=0; i<iterations ;++i) + { + event_ping.signal (); + + if (event_pong.wait ()) + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%P) Failed acquiring pong (%p)\n"))); + else + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Pong\n"))); + event_pong.reset (); + } + } + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Testing timeouts\n"))); + + // test timed wait + ACE_Time_Value wait = ACE_OS::gettimeofday (); + wait.sec (wait.sec () + 3); // timeout in 3 secs + + if (event_pong.wait (&wait)) + ACE_ASSERT(errno == ETIME); + else + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%P) Acquired pong without release()\n"))); + + event_ping.signal (); // release waiting parent before timeout + } + else + { + for (int i=0; i<iterations ;++i) + { + if (event_ping.wait ()) + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%P) Failed acquiring ping (%p)\n"))); + else + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Ping\n"))); + event_ping.reset (); + } + + event_pong.signal (); + } + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Testing timeouts\n"))); + + // test timed wait + ACE_Time_Value wait = ACE_OS::gettimeofday (); + wait.sec (wait.sec () + 10); // timeout in 10 secs + + if (event_ping.wait (&wait)) + { + ACE_ASSERT(errno == ETIME); + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%P) Acquiring pong timed out\n"))); + } + } +} +#endif /* ! ACE_LACKS_FORK */ + +int +run_main (int argc, ACE_TCHAR *argv[]) +{ +#if defined (ACE_LACKS_FORK) + ACE_UNUSED_ARG (argc); + ACE_UNUSED_ARG (argv); + + ACE_START_TEST (ACE_TEXT ("Process_Manual_Event_Test")); + ACE_ERROR ((LM_INFO, + ACE_TEXT ("fork is not supported on this platform\n"))); + ACE_END_TEST; +#else /* ! ACE_LACKS_FORK */ + + parse_args (argc, argv); + + // Child process code. + if (child_process) + { + ACE_START_TEST (ACE_TEXT ("Process_Manual_Event_Test-child")); + acquire_release (); + ACE_END_LOG; + } + else + { + ACE_START_TEST (ACE_TEXT ("Process_Manual_Event_Test")); + + ACE_Process_Options options; + options.command_line (ACE_TEXT (".") ACE_DIRECTORY_SEPARATOR_STR + ACE_TEXT ("Process_Manual_Event_Test") + ACE_PLATFORM_EXE_SUFFIX + ACE_TEXT (" -c -i %d"), + iterations); + + // Spawn a child process that will contend for the + // lock. + ACE_Process child; + + // Spawn the child process. + int result = child.spawn (options); + ACE_ASSERT (result != -1); + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Parent spawned child process with pid = %d.\n"), + child.getpid ())); + + // start test + acquire_release (); + + ACE_exitcode child_status; + // Wait for the child processes we created to exit. + ACE_ASSERT (child.wait (&child_status) != -1); + if (child_status == 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Child %d finished ok\n"), + child.getpid ())); + else + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Child %d finished with status %d\n"), + child.getpid (), child_status)); + + ACE_END_TEST; + } +#endif /* ! ACE_LACKS_FORK */ + + return 0; +} diff --git a/tests/Process_Semaphore_Test.cpp b/tests/Process_Semaphore_Test.cpp new file mode 100644 index 00000000000..16add44af3c --- /dev/null +++ b/tests/Process_Semaphore_Test.cpp @@ -0,0 +1,219 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Process_Semaphore_Test.cpp +// +// = DESCRIPTION +// Tests an ACE Semaphore shared between multiple child processes. +// +// = AUTHOR +// Martin Corino <mcorino@remedy.nl> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Mutex.h" +#include "ace/Process.h" +#if defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_USES_FIFO_SEM) || defined (ACE_HAS_WTHREADS) +# include "ace/Time_Value.h" +# include "ace/Semaphore.h" +#else +# include "ace/Process_Semaphore.h" +#endif +#include "ace/Get_Opt.h" +#include "ace/ACE.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_string.h" +#include "ace/os_include/os_dirent.h" + +ACE_RCSID(tests, Process_Semaphore_Test, "Process_Semaphore_Test.cpp,v 4.42 2003/12/26 21:59:35 shuston Exp") + +#if !defined (ACE_LACKS_FORK) +static int iterations = 10; +static int child_process = 0; +static const char *sema_ping_name = "ACE_Ping_Semaphore"; +static const char *sema_pong_name = "ACE_Pong_Semaphore"; + +// Explain usage and exit. +static void +print_usage_and_die (void) +{ + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("usage: %n [-i #iterations] [-c (child process)]\n"))); + ACE_OS::exit (1); +} + +// Parse the command-line arguments and set options. +static void +parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("i:c")); + + int c; + + while ((c = get_opt ()) != -1) + switch (c) + { + case 'i': + iterations = ACE_OS::atoi (get_opt.opt_arg ()); + break; + case 'c': + child_process = 1; + break; + default: + print_usage_and_die (); + break; + } +} + +static void +acquire_release (void) +{ +#if defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_USES_FIFO_SEM) || defined (ACE_HAS_WTHREADS) + ACE_Semaphore sema_ping (0, USYNC_PROCESS, ACE_TEXT_CHAR_TO_TCHAR (sema_ping_name)); + ACE_Semaphore sema_pong (0, USYNC_PROCESS, ACE_TEXT_CHAR_TO_TCHAR (sema_pong_name)); +#else + ACE_Process_Semaphore sema_ping (0, ACE_TEXT_CHAR_TO_TCHAR (sema_ping_name)); + ACE_Process_Semaphore sema_pong (0, ACE_TEXT_CHAR_TO_TCHAR (sema_pong_name)); +#endif + + // Make sure the constructor succeeded + ACE_ASSERT (ACE_LOG_MSG->op_status () == 0); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Begin ping-pong\n"))); + + if (child_process) + { + for (int i=0; i<iterations ;++i) + { + sema_ping.release (); + + if (sema_pong.acquire ()) + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%P) Failed acquiring pong\n"))); + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Pong\n"))); + } + +#if defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_USES_FIFO_SEM) || defined (ACE_HAS_WTHREADS) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Testing timeouts\n"))); + + // test timed wait + ACE_Time_Value wait = ACE_OS::gettimeofday (); + wait.sec (wait.sec () + 3); // timeout in 3 secs + + if (sema_pong.acquire (wait)) + ACE_ASSERT(errno == ETIME); + else + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%P) Acquired pong without release()\n"))); + + sema_ping.release (); // release waiting parent before timeout +#endif + } + else + { + for (int i=0; i<iterations ;++i) + { + if (sema_ping.acquire ()) + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%P) Failed acquiring ping\n"))); + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Ping\n"))); + + sema_pong.release (); + } + +#if defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_USES_FIFO_SEM) || defined (ACE_HAS_WTHREADS) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Testing timeouts\n"))); + + // test timed wait + ACE_Time_Value wait = ACE_OS::gettimeofday (); + wait.sec (wait.sec () + 10); // timeout in 10 secs + + if (sema_ping.acquire (wait)) + { + ACE_ASSERT(errno == ETIME); + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%P) Acquiring pong timed out\n"))); + } +#endif + } +} +#endif /* ! ACE_LACKS_FORK */ + +int +run_main (int argc, ACE_TCHAR *argv[]) +{ +#if defined (ACE_LACKS_FORK) + ACE_UNUSED_ARG (argc); + ACE_UNUSED_ARG (argv); + + ACE_START_TEST (ACE_TEXT ("Process_Semaphore_Test")); + ACE_ERROR ((LM_INFO, + ACE_TEXT ("fork is not supported on this platform\n"))); + ACE_END_TEST; +#else /* ! ACE_LACKS_FORK */ + + parse_args (argc, argv); + + // Child process code. + if (child_process) + { + ACE_START_TEST (ACE_TEXT ("Process_Semaphore_Test-child")); + acquire_release (); + ACE_END_LOG; + } + else + { + ACE_START_TEST (ACE_TEXT ("Process_Semaphore_Test")); + + ACE_Process_Options options; + options.command_line (ACE_TEXT (".") ACE_DIRECTORY_SEPARATOR_STR + ACE_TEXT ("Process_Semaphore_Test") + ACE_PLATFORM_EXE_SUFFIX + ACE_TEXT (" -c -i %d"), + iterations); + + // Spawn a child process that will contend for the + // lock. + ACE_Process child; + + // Spawn the child process. + int result = child.spawn (options); + ACE_ASSERT (result != -1); + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Parent spawned child process with pid = %d.\n"), + child.getpid ())); + + // start test + acquire_release (); + + ACE_exitcode child_status; + // Wait for the child processes we created to exit. + ACE_ASSERT (child.wait (&child_status) != -1); + if (child_status == 0) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Child %d finished ok\n"), + child.getpid ())); + else + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Child %d finished with status %d\n"), + child.getpid (), child_status)); + + ACE_END_TEST; + } +#endif /* ! ACE_LACKS_FORK */ + + return 0; +} diff --git a/tests/Semaphore_Test.cpp b/tests/Semaphore_Test.cpp index 7232666ff10..e2b82042559 100644 --- a/tests/Semaphore_Test.cpp +++ b/tests/Semaphore_Test.cpp @@ -55,7 +55,7 @@ static size_t n_workers = 10; // Amount to release the semaphore. static u_int n_release_count = 3; -#if !defined (ACE_HAS_STHREADS) && !defined (ACE_HAS_POSIX_SEM) +#if !defined (ACE_HAS_STHREADS) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_HAS_POSIX_SEM_TIMEOUT)) // Number of timeouts. static size_t timeouts = 0; @@ -151,7 +151,7 @@ worker (void *) iterations <= n_iterations; iterations++) { -#if !defined (ACE_HAS_STHREADS) && !defined (ACE_HAS_POSIX_SEM) +#if !defined (ACE_HAS_STHREADS) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_HAS_POSIX_SEM_TIMEOUT)) ACE_Time_Value wait (0, iterations * 1000 * 100); // Wait 'iter' msec ACE_Time_Value tv = ACE_OS::gettimeofday () + wait; @@ -203,7 +203,7 @@ int run_main (int argc, ACE_TCHAR *argv[]) parse_args (argc, argv); ACE_OS::srand (ACE_OS::time (0L)); -# if !defined (ACE_HAS_STHREADS) && !defined (ACE_HAS_POSIX_SEM) +# if !defined (ACE_HAS_STHREADS) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_HAS_POSIX_SEM_TIMEOUT)) //Test timed waits. for (size_t i = 0; i < test_timeout_count; i++) if (test_timeout () != 0) @@ -225,7 +225,7 @@ int run_main (int argc, ACE_TCHAR *argv[]) ACE_Thread_Manager::instance ()->wait (); -# if !defined (ACE_HAS_STHREADS) && !defined (ACE_HAS_POSIX_SEM) +# if !defined (ACE_HAS_STHREADS) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_HAS_POSIX_SEM_TIMEOUT)) size_t percent = (timeouts * 100) / (n_workers * n_iterations); ACE_DEBUG ((LM_DEBUG, diff --git a/tests/run_test.lst b/tests/run_test.lst index 0562f3b9f1c..b79d885edcd 100644 --- a/tests/run_test.lst +++ b/tests/run_test.lst @@ -20,6 +20,7 @@ ACE_Test Arg_Shifter_Test Array_Map_Test Atomic_Op_Test +Auto_Event_Test Auto_IncDec_Test Barrier_Test Basic_Types_Test @@ -96,7 +97,9 @@ Proactor_Scatter_Gather_Test: !chorus !VxWorks !LynxOS Proactor_Test: !chorus !VxWorks !LynxOS Proactor_Timer_Test: !chorus !VxWorks !LynxOS Process_Manager_Test: !chorus !VxWorks +Process_Manual_Event_Test: !chorus !VxWorks !LynxOS Process_Mutex_Test: !chorus !VxWorks !LynxOS +Process_Semaphore_Test: !chorus !VxWorks !LynxOS RB_Tree_Test Reactor_Dispatch_Order_Test Reactor_Exceptions_Test diff --git a/tests/tests.mpc b/tests/tests.mpc index ce499beb7cc..1a5ac07da83 100644 --- a/tests/tests.mpc +++ b/tests/tests.mpc @@ -112,6 +112,13 @@ project(Atomic Op Test) : acetest { } } +project(Auto Event Test) : acetest { + exename = Auto_Event_Test + Source_Files { + Auto_Event_Test.cpp + } +} + project(Auto IncDec Test) : acetest { exename = Auto_IncDec_Test Source_Files { @@ -376,6 +383,13 @@ project(Malloc Test) : acetest { } } +project(Manual_Event Test) : acetest { + exename = Manual_Event_Test + Source_Files { + Manual_Event_Test.cpp + } +} + project(Map Test) : acetest { exename = Map_Test Source_Files { @@ -551,6 +565,13 @@ project(Proactor Timer Test) : acetest { } } +project(Process Manual Event Test) : acetest { + exename = Process_Manual_Event_Test + Source_Files { + Process_Manual_Event_Test.cpp + } +} + project(Process Mutex Test) : acetest { exename = Process_Mutex_Test Source_Files { @@ -558,6 +579,13 @@ project(Process Mutex Test) : acetest { } } +project(Process Semaphore Test) : acetest { + exename = Process_Semaphore_Test + Source_Files { + Process_Semaphore_Test.cpp + } +} + project(Process Strategy Test) : acetest { exename = Process_Strategy_Test Source_Files { |