static int parent (char *shm) { // This for loop executes in a critical section proteced by // <parent_mutex>. for (int i = 0; i < SHMSZ; i++) shm[i] = SHMDATA[i]; int result; result = parent_mutex->release (); ACE_ASSERT (result != -1); result = parent_synch->acquire (); ACE_ASSERT (result != -1); result = myallocator ().remove (); ACE_ASSERT (result != -1); result = parent_mutex->remove (); ACE_ASSERT (result != -1); result = parent_synch->remove (); ACE_ASSERT (result != -1); return 0; }
static int parent (Test_Data *data) { MALLOC *myalloc = myallocator (); { ACE_GUARD_RETURN (ACE_Process_Mutex, guard, myalloc->mutex (), -1); print ("parent", data); } // Sleep for a 200 msecs so that the child will have a chance to spin! ACE_OS::sleep (ACE_Time_Value (0, 200 * 1000)); #if defined (ACE_TEST_REMAP_ON_FAULT) char *small_buf[1024]; int cntr; for (cntr = 0 ; cntr < 1024; ++cntr) small_buf[cntr] = (char *) myalloc->malloc (1); char *big_buf = (char *) myalloc->malloc (1024 * 4069); #endif /* ACE_TEST_REMAP_ON_FAULT */ int result = myalloc->bind ("bar", data); #if defined (ACE_TEST_REMAP_ON_FAULT) myalloc->free (big_buf); for (cntr = 0 ; cntr < 1024; ++cntr) myalloc->free (small_buf[cntr]); #endif /* ACE_TEST_REMAP_ON_FAULT */ ACE_TEST_ASSERT (result != -1); return 0; }
static int child (void) { void *bar = 0; // Perform "busy waiting" here until the parent stores data under a // new name called "bar" in <ACE_Malloc>. This isn't a good design // -- it's just to test that synchronization is working across // processes via <ACE_Malloc>. for (ACE_Time_Value timeout (0, 1000 * 10); myallocator ()->find ("bar", bar) == -1; ) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P) sleeping for 10 milliseconds!\n"))); ACE_OS::sleep (timeout); } print ("child", reinterpret_cast<Test_Data *> (bar)); return 0; }
int run_main (int argc, ACE_TCHAR *argv[]) { #if defined (ACE_WIN32) get_base_addrs(); #endif if (argc == 1) { ACE_START_TEST (ACE_TEXT ("Malloc_Test")); ACE_INIT_LOG (ACE_TEXT ("Malloc_Test-child")); init_test (PARENT_BASE_ADDR); ACE_Control_Block::print_alignment_info (); # if (ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1) ACE_PI_Control_Block::print_alignment_info (); # endif /* ACE_HAS_POSITION_INDEPENDENT_POINTERS == 1 */ // No arguments means we're the parent process. ACE_Process_Options options (1); #if !defined (ACE_WIN32) && defined (ACE_USES_WCHAR) static const ACE_TCHAR* format = ACE_TEXT ("%ls%ls%ls"); #else static const ACE_TCHAR* format = ACE_TEXT ("%s%s%s"); #endif /* !ACE_WIN32 && ACE_USES_WCHAR */ options.command_line (format, EXE_LOCATION, argc > 0 ? argv[0] : ACE_TEXT ("Malloc_Test"), ACE_TEXT (" run_as_test")); MALLOC *myalloc = myallocator (PARENT_BASE_ADDR); Test_Data *data = initialize (myalloc); ACE_TEST_ASSERT (data != 0); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P) PARENT allocator at = %@, ") ACE_TEXT ("data allocated at %@\n"), myalloc, data)); myalloc->dump (); int result = myalloc->bind ("foo", data); ACE_TEST_ASSERT (result != -1); ACE_Process p; pid_t pid = p.spawn (options); if (pid == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn")), 1); parent (data); // Synchronize on the exit of the child. result = p.wait (); if (result == -1) ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("wait")), 1); ACE_TEST_ASSERT (myalloc->ref_counter () == 1); myalloc->remove (); ACE_END_TEST; return 0; } else { // In this case we're the child process. ACE_APPEND_LOG (ACE_TEXT ("Malloc_Test-child")); void *data = 0; MALLOC *myalloc = myallocator (CHILD_BASE_ADDR); int result = myalloc->find ("foo", data); ACE_TEST_ASSERT (result != -1); ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P) CHILD allocator at = %@, ") ACE_TEXT ("data allocated at %@\n"), myalloc, data)); myalloc->dump (); child (); myalloc->release (); ACE_END_LOG; return 0; } }
// $Id: SV_Shared_Memory_Test.cpp 79346 2007-08-14 23:29:36Z sowayaa $ // ============================================================================ // // = LIBRARY // tests // // = FILENAME // SV_Shared_Memory_Test.cpp // // = DESCRIPTION // This is a simple test of <ACE_SV_Shared_Memory> and // <ACE_Malloc> using the <ACE_Shared_Memory_Pool>. The test // forks two processes and then executes client and server // allowing them to exchange data using shared memory. No user // input is required as far as command line arguments are // concerned. // // = AUTHOR // Prashant Jain <*****@*****.**> // and Douglas C. Schmidt <*****@*****.**> // // ============================================================================ #include "test_config.h" #include "ace/Malloc_T.h" #include "ace/Shared_Memory_Pool.h" #include "ace/SV_Semaphore_Simple.h" #include "ace/SV_Semaphore_Complex.h" #include "ace/OS_NS_unistd.h" ACE_RCSID(tests, SV_Shared_Memory_Test, "$Id: SV_Shared_Memory_Test.cpp 79346 2007-08-14 23:29:36Z sowayaa $") #if defined (ACE_HAS_SYSV_IPC) && !defined(ACE_LACKS_SYSV_SHMEM) // The shared memory allocator, which uses up the ACE_DEFAULT_SEM_KEY. // We hide the allocator inside this function so that it doesn't get // constructed until after the ACE_Object_Manager gets constructed, // even with ACE_HAS_NONSTATIC_OBJECT_MANAGER. static ACE_Malloc<ACE_SHARED_MEMORY_POOL, ACE_SV_Semaphore_Simple> & myallocator (void) { static ACE_Malloc<ACE_SHARED_MEMORY_POOL, ACE_SV_Semaphore_Simple> myallocator; return myallocator; } // Create some more keys that are different from the // ACE_DEFAULT_SEM_KEY used by the allocator. static const int SEM_KEY_1 = ACE_DEFAULT_SEM_KEY + 1; static const int SEM_KEY_2 = ACE_DEFAULT_SEM_KEY + 2; static const int SHMSZ = 27; static const char SHMDATA[SHMSZ] = "abcdefghijklmnopqrstuvwxyz"; static ACE_SV_Semaphore_Complex *parent_mutex = 0; static ACE_SV_Semaphore_Complex *parent_synch = 0; static int parent (char *shm) { // This for loop executes in a critical section proteced by // <parent_mutex>. for (int i = 0; i < SHMSZ; i++) shm[i] = SHMDATA[i]; int result; result = parent_mutex->release (); ACE_ASSERT (result != -1); result = parent_synch->acquire (); ACE_ASSERT (result != -1); result = myallocator ().remove (); ACE_ASSERT (result != -1); result = parent_mutex->remove (); ACE_ASSERT (result != -1); result = parent_synch->remove (); ACE_ASSERT (result != -1); return 0; } static int child (char *shm) { int result; ACE_SV_Semaphore_Complex mutex; // This semaphore is initially created with a count of 0, i.e., it // is "locked." result = mutex.open (SEM_KEY_1, ACE_SV_Semaphore_Complex::ACE_CREATE, 0); ACE_ASSERT (result != -1); ACE_SV_Semaphore_Complex synch; // This semaphore is initially created with a count of 0, i.e., it // is "locked." result = synch.open (SEM_KEY_2, ACE_SV_Semaphore_Complex::ACE_CREATE, 0); ACE_ASSERT (result != -1); // Perform "busy waiting" here until we acquire the semaphore. This // isn't really a good design -- it's just to illustrate that you // can do non-blocking acquire() calls with the ACE System V // semaphore wrappers. while ((result = mutex.tryacquire ()) == -1) if (errno == EAGAIN) ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P) spinning in child!\n"))); else { ACE_ERROR ((LM_ERROR, ACE_TEXT ("(%P) child mutex.tryacquire"))); ACE_ASSERT (result != -1); } for (int i = 0; i < SHMSZ; i++) ACE_ASSERT (SHMDATA[i] == shm[i]); result = synch.release (); ACE_ASSERT (result != -1); return 0; } #endif /* ACE_HAS_SYSV_IPC */ int run_main (int, ACE_TCHAR *[]) { ACE_START_TEST (ACE_TEXT ("SV_Shared_Memory_Test")); #if defined (ACE_HAS_SYSV_IPC) && !defined (ACE_LACKS_FORK) && \ !defined(ACE_LACKS_SYSV_SHMEM) // Check whether allocator was initialized. if (myallocator ().bad ()) { ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("Unable to initialize allocator\n")), -1); } char *shm = reinterpret_cast<char *> (myallocator ().malloc (SHMSZ)); // Create the mutex and synch before spawning the child process, to // avoid race condition between their creation in the parent and use // in the child. ACE_NEW_RETURN (parent_mutex, ACE_SV_Semaphore_Complex, -1); ACE_NEW_RETURN (parent_synch, ACE_SV_Semaphore_Complex, -1); // This semaphore is initially created with a count of 0, i.e., it // is "locked." int result = parent_mutex->open (SEM_KEY_1, ACE_SV_Semaphore_Complex::ACE_CREATE, 0); ACE_ASSERT (result != -1); // This semaphore is initially created with a count of 0, i.e., it // is "locked." result = parent_synch->open (SEM_KEY_2, ACE_SV_Semaphore_Complex::ACE_CREATE, 0); ACE_ASSERT (result != -1); switch (ACE_OS::fork (ACE_TEXT ("SV_Shared_Memory_Test.cpp"))) { case -1: ACE_ERROR_RETURN ((LM_ERROR, ACE_TEXT ("(%P) fork failed\n")), -1); /* NOTREACHED */ case 0: child (shm); break; default: parent (shm); delete parent_mutex; delete parent_synch; break; } #else ACE_ERROR ((LM_INFO, ACE_TEXT ("SYSV IPC, SYSV SHMEM, or fork ") ACE_TEXT ("are not supported on this platform\n"))); #endif /* ACE_HAS_SYSV_IPC */ ACE_END_TEST; return 0; }