diff options
-rw-r--r-- | ChangeLog-97a | 21 | ||||
-rw-r--r-- | README | 1 | ||||
-rw-r--r-- | ace/Process.cpp | 25 | ||||
-rw-r--r-- | ace/Process.h | 2 | ||||
-rw-r--r-- | ace/Process_Manager.cpp | 131 | ||||
-rw-r--r-- | ace/Process_Manager.h | 62 | ||||
-rw-r--r-- | ace/Thread_Manager.cpp | 5 | ||||
-rw-r--r-- | ace/Thread_Manager.h | 2 | ||||
-rw-r--r-- | tests/Naming_Test.cpp | 21 | ||||
-rw-r--r-- | tests/Timer_Queue_Test.cpp | 50 | ||||
-rw-r--r-- | tests/test_config.h | 22 |
11 files changed, 211 insertions, 131 deletions
diff --git a/ChangeLog-97a b/ChangeLog-97a index 739d500450f..924dee9db52 100644 --- a/ChangeLog-97a +++ b/ChangeLog-97a @@ -1,5 +1,26 @@ Sun Apr 13 11:40:26 1997 Douglas C. Schmidt <schmidt@flamenco.cs.wustl.edu> + * ace/Thread_Manager: Changed the 'int n' of spawn_n() to size_t n + since this is more appropriate because we can't spawn a negative + number of threads... + + * ace/Thread_Manager.cpp (close): Make sure to lock the calls to + close() in case things get amiss. + + * ace/Process.cpp (start): Updated ACE_Process::start() to that it + doesn't try to exec() a program if argv == 0. This allows us to + use ACE_Process to fork() a process without exec'ing. + + * tests/Timer_Queue_Test.cpp (randomize_array): Added a new + "randomization" test that determines the performance of randomly + canceling items in the array. Thanks to Darrell Brunsch + <brunsch@cs.wustl.edu> for this enhancement. + + * tests/test_config.h: Moved the randomize() function from + Naming_Test.cpp to test_config.h so that we can use it in other + tests (e.g., the new Timer_Queue_Test.cpp that Darrell is + working on). + * ace/OS: Added a new #define called ACE_HAS_NONCONST_MSGSND which can be used for platforms (e.g., SCO) that don't have a const parameter for msgsend(). Thanks to Arturo Montes @@ -499,6 +499,7 @@ Ganesh Pai <gpai@voicetek.com> Berni Merkle <merkle@io.freinet.de> Tom Wright <twright@gem-net.demon.co.uk> Torbjorn Lindgren <tl@funcom.no> +Darrell Brunsch <brunsch@cs.wustl.edu> I would particularly like to thank Paul Stephenson, who worked with me at Ericsson and is now at ObjectSpace. Paul devised the recursive diff --git a/ace/Process.cpp b/ace/Process.cpp index f97ddab6c31..76d3b5d5710 100644 --- a/ace/Process.cpp +++ b/ace/Process.cpp @@ -119,7 +119,7 @@ ACE_Process::set_cwd (const TCHAR *cwd) return 0; } -int +pid_t ACE_Process::start (char *argv[], char *envp[]) { #if defined (ACE_WIN32) @@ -179,17 +179,20 @@ ACE_Process::start (char *argv[], char *envp[]) if (this->cwd_[0] != '\0') ::chdir (cwd_); - // Child process executes the command. - int result; + if (argv != 0) + { + // Child process executes the command. + int result; - if (envp == 0) - result = ACE_OS::execv (argv[0], argv); - else - result = ACE_OS::execve (argv[0], argv, envp); - - if (result == -1) - // If the execv fails, this child needs to exit. - ACE_OS::exit (errno); + if (envp == 0) + result = ACE_OS::execv (argv[0], argv); + else + result = ACE_OS::execve (argv[0], argv, envp); + + if (result == -1) + // If the execv fails, this child needs to exit. + ACE_OS::exit (errno); + } default: // Server process. The fork succeeded. return 0; diff --git a/ace/Process.h b/ace/Process.h index 3d5781bfe00..82cc94d4b40 100644 --- a/ace/Process.h +++ b/ace/Process.h @@ -66,7 +66,7 @@ public: int set_cwd (const TCHAR *cwd); // Set the working directory for the process. - int start (char *argv[], char *envp[] = 0); + pid_t start (char *argv[], char *envp[] = 0); // Start the new process. <argv> must be specified. It should be // of the following form: argv = { "c:\full\path\to\foo.exe", "-a", // "arg1", "etc", 0 }. If <envp> is specified, it is passed as the diff --git a/ace/Process_Manager.cpp b/ace/Process_Manager.cpp index 1ef354593f1..027e5b68fe9 100644 --- a/ace/Process_Manager.cpp +++ b/ace/Process_Manager.cpp @@ -1,8 +1,8 @@ -#if 0 // $Id$ // Process_Manager.cpp #define ACE_BUILD_DLL +#include "ace/Process.h" #include "ace/Process_Manager.h" #if !defined (__ACE_INLINE__) @@ -27,7 +27,21 @@ int ACE_Process_Manager::resize (size_t size) { ACE_TRACE ("ACE_Process_Manager::resize"); - return -1; + + ACE_TRACE ("ACE_Thread_Manager::resize"); + ACE_Process_Descriptor *temp; + + ACE_NEW_RETURN (temp, ACE_Process_Descriptor[size], -1); + + for (size_t i = 0; i < this->max_table_size_; i++) + temp[i] = this->proc_table_[i]; // Structure assignment. + + this->max_table_size_ = size; + + delete [] this->proc_table_; + + this->proc_table_ = temp; + return 0; } // Create and initialize the table to keep track of the process pool. @@ -36,14 +50,29 @@ int ACE_Process_Manager::open (size_t size) { ACE_TRACE ("ACE_Process_Manager::open"); - return -1; + + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + + if (this->max_table_size_ < size) + this->resize (size); + return 0; + } // Initialize the synchronization variables. ACE_Process_Manager::ACE_Process_Manager (size_t size) + : proc_table_ (0), + max_table_size_ (0), + current_count_ (0) +#if defined (ACE_HAS_THREADS) + , zero_cond_ (lock_) +#endif /* ACE_HAS_THREADS */ { ACE_TRACE ("ACE_Process_Manager::ACE_Process_Manager"); + + if (this->open (size) == -1) + ACE_ERROR ((LM_ERROR, "%p\n", "ACE_Process_Manager")); } // Close up and release all resources. @@ -52,7 +81,17 @@ int ACE_Process_Manager::close (void) { ACE_TRACE ("ACE_Process_Manager::close"); - return -1; + + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + + if (this->proc_table_ != 0) + { + delete [] this->proc_table_; + this->proc_table_ = 0; + this->max_table_size_ = 0; + this->current_count_ = 0; + } + return 0; } ACE_Process_Manager::~ACE_Process_Manager (void) @@ -61,61 +100,72 @@ ACE_Process_Manager::~ACE_Process_Manager (void) this->close (); } -// Call the appropriate OS routine to spawn a process. Should *not* -// be called with the lock_ held... - -int -ACE_Process_Manager::spawn_i (ACE_THR_FUNC func, - void *args, - long flags, - pid_t *t_id, - u_int priority, - void *stack, - size_t stack_size) -{ - ACE_TRACE ("ACE_Process_Manager::spawn_i"); - return -1; -} - // Create a new process running FUNC. *Must* be called with the lock_ // held... -int -ACE_Process_Manager::spawn (ACE_THR_FUNC func, - void *args, - long flags, - pid_t *t_id, - u_int priority, - void *stack, - size_t stack_size) -{ - ACE_TRACE ("ACE_Process_Manager::spawn"); - return -1; +pid_t +ACE_Process_Manager::start (char *argv[], + char *envp[]) +{ + ACE_TRACE ("ACE_Process_Manager::start"); + + // Create a new process, potentially causing an exec(), as well. + // This API clearly needs to be improved to pass more information + // in... + pid_t pid = ACE_Process process (argv, + ACE_INVALID_HANDLE, + ACE_INVALID_HANDLE, + ACE_INVALID_HANDLE, + envp); + if (pid == -1) + return -1; + else + return this->append_proc (pid); } // Create N new processs running FUNC. int -ACE_Process_Manager::spawn_n (int n, - ACE_THR_FUNC func, - void *args, - long flags, - u_int priority) +ACE_Process_Manager::start_n (size_t n, + char *argv[], + char *envp[]) { ACE_TRACE ("ACE_Process_Manager::spawn_n"); - return -1; + + for (size_t i = 0; i < n; i++) + if (this->start (argv, envp) == -1) + return -1; + + return 0; + } // Append a process into the pool (does not check for duplicates). // Must be called with locks held. int -ACE_Process_Manager::append_proc (pid_t t_id, - ACE_Process_Descriptor::Process_State proc_state) +ACE_Process_Manager::append_proc (pid_t pid, + ACE_Process_Descriptor::Process_State proc_state) { ACE_TRACE ("ACE_Process_Manager::append_proc"); - return -1; + // Try to resize the array to twice its existing size if we run out + // of space... + if (this->current_count_ >= this->max_table_size_ + && this->resize (this->max_table_size_ * 2) == -1) + return -1; + else + { + ACE_Thread_Descriptor &proc_desc = + this->proc_table_[this->current_count_]; + + proc_desc.proc_id_ = pid; + proc_desc.proc_id_ = + proc_desc.proc_state_ = proc_state; + + this->current_count_++; + return 0; + } } // Insert a process into the pool (checks for duplicates and doesn't @@ -328,4 +378,3 @@ ACE_Process_Control::exit (void *exit_status) return 0; } -#endif diff --git a/ace/Process_Manager.h b/ace/Process_Manager.h index b2557e2522f..96896b96a4b 100644 --- a/ace/Process_Manager.h +++ b/ace/Process_Manager.h @@ -19,7 +19,6 @@ #include "ace/Synch.h" -#if 0 class ACE_Export ACE_Process_Descriptor // = Title // Information for controlling groups of processs. @@ -31,7 +30,6 @@ public: IDLE, SPAWNED, RUNNING, - SUSPENDED, TERMINATED }; private: @@ -41,7 +39,7 @@ private: pid_t proc_id_; // Unique process ID. - int grp_id_; + gid_t grp_id_; // Unique group ID. Process_State proc_state_; @@ -76,51 +74,24 @@ public: int close (void); // Release all resources. - int spawn (ACE_THR_FUNC func, - void *args, - long flags, - pid_t * = 0, - u_int priority = 0, - void *stack = 0, - size_t stack_size = 0); - // Create a new process, which executes <func>. + pid_t start (char *argv[], char *envp[] = 0); + // Create a new process using <ACE_Process::start>. // Returns: on success a unique group id that can be used to control // other processs added to the same group. On failure, returns -1. - int spawn_n (int n, - ACE_THR_FUNC func, - void *args, - long flags, - u_int priority = 0); - // Create N new processs, all of which execute <func>. + int start_n (size_t n, + char *argv[], + char *envp[] = 0); + // Create N new processs. // Returns: on success a unique group id that can be used to control // all of the processs in the same group. On failure, returns -1. - void *exit (void *status); - // Called to clean up when a process exits. - int wait (ACE_Time_Value *timeout = 0); // Block until there are no more processs running or <timeout> // expires. Returns 0 on success and -1 on failure. - // = Suspend methods. - int suspend_all (void); - // Suspend all processs - int suspend (pid_t); - // Suspend a single process. - int suspend_grp (int grp_id); - // Suspend a group of processs. - - // = Resume methods. - int resume_all (void); - // Resume all stopped processs - int resume (pid_t); - // Resume a single process. - int resume_grp (int grp_id); - // Resume a group of processs. - // = Kill methods (send signals...). int kill_all (int signum); // Send signum to all stopped processs @@ -143,15 +114,6 @@ private: int resize (size_t); // Resize the pool of Process_Descriptors. - int spawn_i (ACE_THR_FUNC func, - void *args, - long flags, - pid_t * = 0, - u_int priority = 0, - void *stack = 0, - size_t stack_size = 0); - // Create a new process (must be called with locks held). - int find (pid_t p_id); // Locate the index of the table slot occupied by <p_id>. Returns // -1 if <p_id> is not in the table doesn't contain <p_id>. @@ -178,12 +140,6 @@ private: int apply_all (PROC_FUNC, int = 0); // Apply <func> to all members of the table. - int resume_proc (int i); - // Resume the process at index <i>. - - int suspend_proc (int i); - // Suspend the process at index <i>. - int kill_proc (int i, int signum); // Send signal <signum> to the process at index <i>. @@ -196,9 +152,6 @@ private: size_t current_count_; // Current number of processs we are managing. - - int grp_id_; - // Keeps track of the next group id to assign. }; class ACE_Export ACE_Process_Control @@ -242,7 +195,6 @@ private: #if defined (__ACE_INLINE__) #include "ace/Process_Manager.i" #endif /* __ACE_INLINE__ */ -#endif #endif /* ACE_PROCESS_MANAGER_H */ diff --git a/ace/Thread_Manager.cpp b/ace/Thread_Manager.cpp index 41fa8bf7e9d..4ea8f97baf0 100644 --- a/ace/Thread_Manager.cpp +++ b/ace/Thread_Manager.cpp @@ -135,6 +135,9 @@ int ACE_Thread_Manager::close (void) { ACE_TRACE ("ACE_Thread_Manager::close"); + + ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, -1)); + if (this->thr_table_ != 0) { delete [] this->thr_table_; @@ -236,7 +239,7 @@ ACE_Thread_Manager::spawn_n (int n, if (grp_id == -1) grp_id = this->grp_id_++; // Increment the group id. - for (int i = 0; i < n; i++) + for (size_t i = 0; i < n; i++) { // @@ What should happen if this fails?! e.g., should we try to // cancel the other threads that we've already spawned or what? diff --git a/ace/Thread_Manager.h b/ace/Thread_Manager.h index afca7b8a833..83a5528d279 100644 --- a/ace/Thread_Manager.h +++ b/ace/Thread_Manager.h @@ -105,7 +105,7 @@ public: // Returns: on success a unique group id that can be used to control // other threads added to the same group. On failure, returns -1. - int spawn_n (int n, + int spawn_n (size_t n, ACE_THR_FUNC func, void *args = 0, long flags = THR_NEW_LWP, diff --git a/tests/Naming_Test.cpp b/tests/Naming_Test.cpp index 8951b2051ba..df39a4fe2f1 100644 --- a/tests/Naming_Test.cpp +++ b/tests/Naming_Test.cpp @@ -27,27 +27,6 @@ static char name[BUFSIZ]; static char value[BUFSIZ]; static char type[BUFSIZ]; -static void -randomize (int array[], size_t size) -{ - size_t i; - - for (i = 0; i < size; i++) - array [i] = i; - - ACE_OS::srand (ACE_OS::time (0L)); - - // Generate an array of random numbers from 0 .. size - 1. - - for (i = 0; i < size; i++) - { - int index = ACE_OS::rand() % size--; - int temp = array [index]; - array [index] = array [size]; - array [size] = temp; - } -} - static void print_time (ACE_Profile_Timer &timer, const char *test) diff --git a/tests/Timer_Queue_Test.cpp b/tests/Timer_Queue_Test.cpp index 7cd92fc486f..d08b8518f9c 100644 --- a/tests/Timer_Queue_Test.cpp +++ b/tests/Timer_Queue_Test.cpp @@ -25,6 +25,24 @@ #include "ace/Timer_Heap.h" #include "test_config.h" +static void +randomize_array (int array[], size_t size) +{ + size_t i; + + ACE_OS::srand (ACE_OS::time (0L)); + + // Randomize the array. + + for (i = 0; i < size; i++) + { + int index = ACE_OS::rand() % size--; + int temp = array [index]; + array [index] = array [size]; + array [size] = temp; + } +} + // Number of iterations for the performance tests. static int max_iterations = ACE_DEFAULT_TIMERS * 100 ; @@ -200,6 +218,38 @@ test_performance (ACE_Timer_Queue *tq, ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n", (et.user_time / double (max_iterations)) * 1000000)); + + // Test the amount of time required to randomly expire all the + // timers. + + for (i = 0; i < max_iterations; i++) + { + timer_ids[i] = tq->schedule (&eh, (const void *) 42, + ACE_OS::gettimeofday ()); + ACE_ASSERT (timer_ids[i] != -1); + } + + ACE_ASSERT (tq->is_empty () == 0); + + randomize_array (timer_ids, max_iterations); + + timer.start (); + + for (i = max_iterations - 1; i >= 0; i--) + tq->cancel (timer_ids[i]); + + ACE_ASSERT (tq->is_empty ()); + + timer.stop (); + + timer.elapsed_time (et); + + ACE_DEBUG ((LM_DEBUG, "time to randomly expire %d timers for %s\n", + max_iterations, test_name)); + ACE_DEBUG ((LM_DEBUG, "real time = %f secs, user time = %f secs, system time = %f secs\n", + et.real_time, et.user_time, et.system_time)); + ACE_DEBUG ((LM_DEBUG, "time per call = %f usecs\n", + (et.user_time / double (max_iterations)) * 1000000)); } struct Timer_Queues diff --git a/tests/test_config.h b/tests/test_config.h index 4f964ccb05e..034dacb76f0 100644 --- a/tests/test_config.h +++ b/tests/test_config.h @@ -192,4 +192,26 @@ ACE_Test_Output::close (void) this->output_file_.flush (); this->output_file_.close (); } + +static void +randomize (int array[], size_t size) +{ + size_t i; + + for (i = 0; i < size; i++) + array [i] = i; + + ACE_OS::srand (ACE_OS::time (0L)); + + // Generate an array of random numbers from 0 .. size - 1. + + for (i = 0; i < size; i++) + { + int index = ACE_OS::rand() % size--; + int temp = array [index]; + array [index] = array [size]; + array [size] = temp; + } +} + #endif /* ACE_TEST_CONFIG_H */ |