// This program tests out all the various ACE_Malloc combinations and // the ACE_Allocator_Adapter. #include "ace/Thread.h" #include "ace/Thread_Manager.h" #include "ace/Malloc.h" #include "ace/Signal.h" #include "ace/Truncate.h" #include "ace/OS_NS_stdio.h" #include "ace/OS_NS_string.h" #include "ace/OS_NS_sys_wait.h" #include "ace/OS_NS_unistd.h" #include "Malloc.h" #include "Options.h" static int gen_size (void) { #if defined (ACE_HAS_THREADS) unsigned int seed = static_cast (reinterpret_cast (&seed)); return ( ACE_Utils::truncate_cast ( ACE_OS::rand_r (&seed) % Options::instance ()->max_msg_size ()) + 1); #else return ( ACE_Utils::truncate_cast ( ACE_OS::rand () % Options::instance ()->max_msg_size ()) + 1); #endif /* ACE_HAS_THREADS */ } // Recursively allocate and deallocate dynamic memory. static int malloc_recurse (int count) { static char default_char = 0; if (count <= 0) { if (Options::instance ()->debug ()) { // Note that you'll need to #define ACE_HAS_MALLOC_STATS in // the main ACE config.h file and remake ACE to enable this. ACE_MALLOC_STATS (Malloc::instance ()->print_stats ()); } } else { int alloc_size = gen_size (); void *ptr = Malloc::instance ()->malloc (alloc_size); if (ptr == 0) ACE_ERROR ((LM_ERROR, "(%P|%t) *** malloc of size %d failed, %p\n%a", "malloc", alloc_size)); else { ACE_OS::memset (ptr, default_char++, alloc_size); if (Options::instance ()->debug ()) ACE_DEBUG ((LM_INFO, "(%P|%t) %u (alloc), size = %d\n", ptr, alloc_size)); // Call ourselves recursively malloc_recurse (count - 1); if (Options::instance ()->debug ()) ACE_DEBUG ((LM_INFO, "(%P|%t) %u (free), size = %d\n", ptr, alloc_size)); Malloc::instance ()->free (ptr); } } return 0; } #if defined (ACE_HAS_THREADS) static void * worker (void *arg) { // Cast the arg to a long, first, because a pointer is the same // size as a long on all current ACE platforms. malloc_recurse (static_cast (reinterpret_cast (arg))); return 0; } #endif /* ACE_HAS_THREADS */ // Create the appropriate type of process/thread. static void spawn (void) { if (Options::instance ()->spawn_threads ()) { #if defined (ACE_HAS_THREADS) if (ACE_Thread_Manager::instance ()->spawn (ACE_THR_FUNC (worker), (void *) Options::instance ()->iteration_count (), THR_BOUND) == -1) ACE_ERROR ((LM_ERROR, "%p\n%a", "thread create failed")); #else if (Options::instance ()->spawn_count () > 1) ACE_ERROR ((LM_ERROR, "only one thread may be run in a process on this platform\n%a", 1)); #endif /* ACE_HAS_THREADS */ } #if !defined (ACE_WIN32) else if (ACE_OS::fork (ACE_TEXT_CHAR_TO_TCHAR (Options::instance ()->program_name ())) == 0) { if (Options::instance ()->exec_slave ()) { char iterations[20]; char msg_size[20]; ACE_OS::sprintf (iterations, "%lu", (unsigned long) Options::instance ()->iteration_count ()); ACE_OS::sprintf (msg_size, "%lu", (unsigned long) Options::instance ()->max_msg_size ()); const char *cp = 0; if (Options::instance ()->debug ()) cp = "-d"; else cp = ""; const char *argv[] = { Options::instance ()->slave_name (), "-p", "-n", iterations, "-L", msg_size, cp, 0 }; if (ACE_OS::execv (Options::instance ()->program_name (), (char *const *) argv) == -1) ACE_ERROR ((LM_ERROR, "%p\n", "exec failed")); ACE_OS::_exit (1); } else { ACE_DEBUG ((LM_INFO, "(%P|%t) about to recurse with iteration count = %d\n", Options::instance ()->iteration_count ())); malloc_recurse (Options::instance ()->iteration_count ()); Malloc::instance ()->remove (); ACE_OS::exit (0); } } #endif /* ACE_WIN32 */ } // Wait for all the child processes/threads to exit. static void wait_for_children (void) { if (Options::instance ()->spawn_threads ()) { #if defined (ACE_HAS_THREADS) // Wait for the threads to terminate. ACE_Thread_Manager::instance ()->wait (); #else malloc_recurse (Options::instance ()->iteration_count ()); #endif /* ACE_HAS_THREADS */ } #if !defined (ACE_WIN32) else { pid_t pid; while ((pid = ACE_OS::wait (0)) != -1) ACE_DEBUG ((LM_DEBUG, "(%P|%t) reaped pid = %d\n", pid)); } #endif /* ACE_WIN32 */ } extern "C" void handler (int) { Malloc::instance ()->remove (); ACE_ERROR ((LM_ERROR, "(%P|%t) removed handler\n%a", 0)); } int ACE_TMAIN (int argc, ACE_TCHAR *argv[]) { // Register a signal handler. ACE_Sig_Action sa ((ACE_SignalHandler) handler, SIGINT); ACE_UNUSED_ARG (sa); Options::instance ()->parse_args (argc, argv); #if !defined (ACE_WIN32) if (Options::instance ()->child ()) { ACE_DEBUG ((LM_INFO, "(%P|%t) about to recurse with iteration count = %d, debug = %d\n", Options::instance ()->iteration_count ())); // We've been forked... malloc_recurse (Options::instance ()->iteration_count ()); Malloc::instance ()->remove (); } else #endif /* ACE_WIN32 */ { for (size_t i = 0; i < Options::instance ()->spawn_count (); i++) spawn (); wait_for_children (); Malloc::instance ()->remove (); } return 0; }