diff options
Diffstat (limited to 'ACE/tests/Priority_Task_Test.cpp')
-rw-r--r-- | ACE/tests/Priority_Task_Test.cpp | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/ACE/tests/Priority_Task_Test.cpp b/ACE/tests/Priority_Task_Test.cpp new file mode 100644 index 00000000000..3c4cf5c7bd6 --- /dev/null +++ b/ACE/tests/Priority_Task_Test.cpp @@ -0,0 +1,251 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Priority_Task_Test.cpp +// +// = DESCRIPTION +// This is a simple test to illustrate the priority mechanism of +// ACE Tasks. The test requires no options, but the -d option +// enables LM_DEBUG output. +// +// = AUTHOR +// Carlos O'Ryan <coryan@cs.wustl.edu> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/Task.h" +#include "ace/Sched_Params.h" +#include "ace/OS_NS_errno.h" +#include "ace/OS_NS_string.h" + +ACE_RCSID(tests, Priority_Task_Test, "$Id$") + +static const ACE_TCHAR *usage = ACE_TEXT ("usage: %s [-d]\n"); + +#if defined (ACE_HAS_THREADS) + +class Priority_Task : public ACE_Task<ACE_MT_SYNCH> +{ + // = TITLE + // A simple Task that runs itself a different priorities. + // + // = DESCRIPTION + // This task uses the void* argument on open to run the svc() + // method at a different priority. The point is execise the thread + // priority features of ACE. +public: + Priority_Task (void); + // The constructor + + int open (void *); + // Receives the priority and run svc() on a separate thread at that + // priority. + + int svc (void); + // Runs on a separate thread an checks the priority. + + int succeeded (void) { return error_ == 0; } + // Returns 1 if priority was set properly, 0 otherwise. + +private: + int priority_; + u_int error_; +}; + +Priority_Task::Priority_Task (void) + : ACE_Task<ACE_MT_SYNCH> (ACE_Thread_Manager::instance ()), + priority_ (0), + error_ (0) +{ +} + +int +Priority_Task::open (void *arg) +{ + this->priority_ = *(int *) arg; + + long flags = THR_NEW_LWP; + + // To get FIFO scheduling with PTHREADS. + ACE_SET_BITS (flags, + THR_SCHED_FIFO); + + // Become an active object. + if (this->activate (flags, + 1, + 0, + this->priority_) == -1) + { + // On Linux, for example, only the superuser can set the policy + // to other than ACE_SCHED_OTHER. But with ACE_SCHED_OTHER, + // there is only one thread priority value, for example, 0. So, + // let the superuser run an interesting test, but for other + // users use the minimum ACE_SCHED_OTHER thread priority. + + long fallback_priority = + ACE_Sched_Params::priority_min (ACE_SCHED_OTHER, + ACE_SCOPE_THREAD); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%t) task activation at priority %d with ") + ACE_TEXT ("flags 0x%X failed; retry at priority %d with ") + ACE_TEXT ("flags 0x%X (errno is %d%p)\n"), + this->priority_, + flags, + fallback_priority, + THR_NEW_LWP, + errno, + ACE_TEXT (""))); + + flags = THR_NEW_LWP; + this->priority_ = fallback_priority; + + if (this->activate (flags, + 1, + 1, + this->priority_) == -1) + { +#if !defined (ACE_HAS_WINCE) + if (ACE_OS::last_error () == EPERM) + ACE_ERROR_RETURN ((LM_INFO, + ACE_TEXT ("Insufficient privilege to run this test.\n")), + -1); + else +#endif // ACE_HAS_WINCE + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%t) task activation at priority %d failed, ") + ACE_TEXT ("exiting!\n%a"), + this->priority_, + -1)); + } + } + return 0; +} + +int +Priority_Task::svc (void) +{ + ACE_hthread_t thr_handle; + ACE_Thread::self (thr_handle); + int prio; + + if (ACE_Thread::getprio (thr_handle, prio) == -1) + { + if (errno == ENOTSUP) + { + ACE_DEBUG((LM_DEBUG, + ACE_TEXT ("getprior not supported on this platform\n") + )); + return 0; + } + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("%p\n"), + ACE_TEXT ("getprio failed")), + -1); + } + + if (prio == this->priority_) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%t) actual prio of %d equals desired priority\n"), + prio)); + else + { + ACE_DEBUG ((LM_ERROR, + ACE_TEXT ("(%t) actual prio = %d, desired priority_ = %d!\n"), + prio, + this->priority_)); + ++error_; + } + + return 0; +} + +#endif /* ACE_HAS_THREADS */ + +int +run_main (int argc, ACE_TCHAR *argv[]) +{ + ACE_START_TEST (ACE_TEXT ("Priority_Task_Test")); + + if (argc <= 1) + // Disable LM_DEBUG messages. + ACE_Log_Msg::instance ()->priority_mask + (ACE_Log_Msg::instance ()->priority_mask () &~ LM_DEBUG); + else if (argc == 2) + { + if (ACE_OS::strcmp (argv[1], + ACE_TEXT ("-d")) != 0) + ACE_ERROR_RETURN ((LM_ERROR, + usage, + argv [0]), + -1); + // else -d option: don't disable LM_DEBUG messages + } + else + ACE_ERROR_RETURN ((LM_ERROR, + usage, + argv [0]), + -1); + + int status = 0; + +#if defined (ACE_HAS_THREADS) + + Priority_Task tasks[ACE_MAX_ITERATIONS]; + + size_t i; + + // Spawn off ACE_MAX_ITERATIONS of tasks, passing each one their + // iteration number as their priority. + + // NOTE: on Solaris, for example, this requests the min FIFO + // priority. But, this test doesn't use the Realtime scheduling + // class. The FIFO priorities are used because they're all + // nonnegative. + + ACE_Sched_Priority_Iterator priority (ACE_SCHED_FIFO, + ACE_SCOPE_THREAD); + + for (i = 0; i < ACE_MAX_ITERATIONS; i++) + { + int p = priority.priority (); + if (tasks[i].open ((void *) &p) == -1) + break; // Out of enclosing loop. + + // If there are more priorities get the next one... + if (priority.more ()) + priority.next (); + } + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%t) %d tasks spawned, wait for them to exit . . .\n"), + ACE_MAX_ITERATIONS)); + + // Wait for all tasks to exit. + ACE_Thread_Manager::instance ()->wait (); + + for (i = 0; i < ACE_MAX_ITERATIONS; i++) + if (!tasks[i].succeeded ()) + { + ++status; + break; + } + +#else + ACE_ERROR ((LM_DEBUG, + ACE_TEXT ("threads not supported on this platform\n"))); +#endif /* ACE_HAS_THREADS */ + + // Re-enable LM_DEBUG messages. + ACE_Log_Msg::instance ()->priority_mask + (ACE_Log_Msg::instance ()->priority_mask () | LM_DEBUG); + + ACE_END_TEST; + return status; +} |