summaryrefslogtreecommitdiff
path: root/ACE/performance-tests
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/performance-tests')
-rw-r--r--ACE/performance-tests/Makefile.am18
-rw-r--r--ACE/performance-tests/Misc/Makefile.am150
-rw-r--r--ACE/performance-tests/Misc/Misc.mpc66
-rw-r--r--ACE/performance-tests/Misc/basic_func.cpp49
-rw-r--r--ACE/performance-tests/Misc/basic_func.h77
-rw-r--r--ACE/performance-tests/Misc/basic_perf.cpp646
-rw-r--r--ACE/performance-tests/Misc/childbirth_time.cpp401
-rw-r--r--ACE/performance-tests/Misc/context_switch_time.cpp1318
-rw-r--r--ACE/performance-tests/Misc/preempt.cpp461
-rw-r--r--ACE/performance-tests/Misc/test_guard.cpp113
-rw-r--r--ACE/performance-tests/Misc/test_mutex.cpp238
-rw-r--r--ACE/performance-tests/Misc/test_naming.cpp193
-rw-r--r--ACE/performance-tests/Misc/test_singleton.cpp179
-rw-r--r--ACE/performance-tests/Misc/test_singleton.h24
-rw-r--r--ACE/performance-tests/README16
-rw-r--r--ACE/performance-tests/RPC/README6
-rw-r--r--ACE/performance-tests/RPC/RPC.mpc17
-rw-r--r--ACE/performance-tests/RPC/client.cpp72
-rw-r--r--ACE/performance-tests/RPC/ping.x12
-rwxr-xr-xACE/performance-tests/RPC/run_test.pl34
-rw-r--r--ACE/performance-tests/RPC/server.c15
-rw-r--r--ACE/performance-tests/SCTP/Makefile.am117
-rw-r--r--ACE/performance-tests/SCTP/Options_Manager.cpp542
-rw-r--r--ACE/performance-tests/SCTP/Options_Manager.h67
-rw-r--r--ACE/performance-tests/SCTP/README81
-rw-r--r--ACE/performance-tests/SCTP/README.LKSCTP46
-rw-r--r--ACE/performance-tests/SCTP/README.OpenSS7271
-rw-r--r--ACE/performance-tests/SCTP/README.SCIOP63
-rw-r--r--ACE/performance-tests/SCTP/README.SCTP81
-rw-r--r--ACE/performance-tests/SCTP/README.SCTP_PERF_TEST405
-rw-r--r--ACE/performance-tests/SCTP/README.SCTP_in_ACE269
-rw-r--r--ACE/performance-tests/SCTP/SCTP.mpc61
-rw-r--r--ACE/performance-tests/SCTP/SOCK_SEQPACK_Association_Test.cpp152
-rw-r--r--ACE/performance-tests/SCTP/SOCK_SEQPACK_clt.cpp308
-rw-r--r--ACE/performance-tests/SCTP/SOCK_SEQPACK_srv.cpp359
-rwxr-xr-xACE/performance-tests/SCTP/SOCK_SEQPACK_wrapper_facade.jpgbin0 -> 47984 bytes
-rw-r--r--ACE/performance-tests/SCTP/SOCK_STREAM_clt.cpp318
-rw-r--r--ACE/performance-tests/SCTP/SOCK_STREAM_srv.cpp358
-rw-r--r--ACE/performance-tests/SCTP/THANKS30
-rw-r--r--ACE/performance-tests/SCTP/hist.cpp306
-rw-r--r--ACE/performance-tests/SCTP/hist.h71
-rw-r--r--ACE/performance-tests/SCTP/run_spectrum.config12
-rwxr-xr-xACE/performance-tests/SCTP/run_spectrum.pl260
-rw-r--r--ACE/performance-tests/SCTP/sample-spectrum.pngbin0 -> 5369 bytes
-rw-r--r--ACE/performance-tests/Server_Concurrency/Latency_Stats.h219
-rw-r--r--ACE/performance-tests/Server_Concurrency/Leader_Follower/Makefile.am58
-rw-r--r--ACE/performance-tests/Server_Concurrency/Leader_Follower/RT_CORBA_Leader_Follower.cpp401
-rw-r--r--ACE/performance-tests/Server_Concurrency/Leader_Follower/RT_CORBA_Leader_Follower.h109
-rw-r--r--ACE/performance-tests/Server_Concurrency/Leader_Follower/Svr_Conc_Leader_Follower.mpc18
-rw-r--r--ACE/performance-tests/Server_Concurrency/Leader_Follower/leader_follower.cpp333
-rw-r--r--ACE/performance-tests/Server_Concurrency/Makefile.am14
-rw-r--r--ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/Makefile.am58
-rw-r--r--ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/RT_CORBA_Workers.cpp589
-rw-r--r--ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/RT_CORBA_Workers.h166
-rw-r--r--ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/Svr_Conc_Queue_Based_Workers.mpc18
-rw-r--r--ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/workers.cpp414
-rwxr-xr-xACE/performance-tests/Server_Concurrency/run_test.sh13
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Base_Test/Baseline_Test.cpp233
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Base_Test/Baseline_Test.h153
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Base_Test/Baseline_Test.i43
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Base_Test/Makefile.am43
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Base_Test/Synch_Benchmarks_Base_Test.mpc11
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Base_Test/base_test.cpp62
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Base_Test/mutex_test.cpp205
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Makefile.am40
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/Adaptive_Lock_Performance_Test_Base.cpp48
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/Adaptive_Lock_Performance_Test_Base.h24
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/Benchmark_Performance.cpp59
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/Benchmark_Performance.h48
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/Makefile.am64
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test.cpp122
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test.h32
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test_Options.cpp469
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test_Options.h133
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test_Options.i269
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/README76
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/Synch_Benchmarks_Perf_Test.mpc11
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/adaptive_mutex_test.cpp32
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/adaptive_recursive_lock_test.cpp33
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/adaptive_sema_test.cpp38
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/condb_test.cpp69
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/conds_test.cpp72
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/context_test.cpp38
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/guard_test.cpp124
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/memory_test.cpp42
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/mutex_test.cpp45
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/pipe_proc_test.cpp86
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/pipe_thr_test.cpp79
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/recursive_lock_test.cpp44
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/rwrd_test.cpp45
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/rwwr_test.cpp45
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/sema_test.cpp45
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/sysvsema_test.cpp67
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Perf_Test/token_test.cpp46
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/README46
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Synch_Benchmarks.mpc12
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Benchmark_Base.cpp95
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Benchmark_Base.h114
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Makefile.am36
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Synch_Lib/README4
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Synch_Benchmarks_Synch_Lib.mpc7
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/Synch_Lib/export_mac.h40
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/benchmarks19
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/context.c73
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/context.csh16
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/orig-results73
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/results/.no_prune1
-rwxr-xr-xACE/performance-tests/Synch-Benchmarks/run_tests.pl131
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/base_acquire.conf20
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/base_acquire_read.conf20
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/base_acquire_write.conf20
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/base_tryacquire.conf20
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/base_tryacquire_read.conf20
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/base_tryacquire_write.conf20
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t1.conf32
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t16.conf32
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t2.conf32
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t32.conf32
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t4.conf32
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t64.conf32
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t8.conf32
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/svcconf/svc.conf29
-rw-r--r--ACE/performance-tests/Synch-Benchmarks/synch_driver.cpp52
-rw-r--r--ACE/performance-tests/TCP/Makefile.am38
-rw-r--r--ACE/performance-tests/TCP/README17
-rw-r--r--ACE/performance-tests/TCP/TCP.mpc7
-rwxr-xr-xACE/performance-tests/TCP/run_test.pl34
-rw-r--r--ACE/performance-tests/TCP/tcp_test.cpp692
-rw-r--r--ACE/performance-tests/TTCP/ACE-C++/How_to_run_tests29
-rw-r--r--ACE/performance-tests/TTCP/ACE-C++/run_test35
-rw-r--r--ACE/performance-tests/TTCP/ACE-C++/wrapper-new-ttcp.cpp956
-rw-r--r--ACE/performance-tests/TTCP/C/How_to_run_tests30
-rw-r--r--ACE/performance-tests/TTCP/C/README35
-rw-r--r--ACE/performance-tests/TTCP/C/new-ttcp.cpp970
-rw-r--r--ACE/performance-tests/TTCP/C/run_test35
-rw-r--r--ACE/performance-tests/UDP/Makefile.am38
-rw-r--r--ACE/performance-tests/UDP/README17
-rw-r--r--ACE/performance-tests/UDP/UDP.mpc10
-rwxr-xr-xACE/performance-tests/UDP/run_test.pl34
-rw-r--r--ACE/performance-tests/UDP/udp_test.cpp759
-rw-r--r--ACE/performance-tests/perf.mwc5
141 files changed, 18620 insertions, 0 deletions
diff --git a/ACE/performance-tests/Makefile.am b/ACE/performance-tests/Makefile.am
new file mode 100644
index 00000000000..1aac8a5c388
--- /dev/null
+++ b/ACE/performance-tests/Makefile.am
@@ -0,0 +1,18 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ Misc \
+ SCTP \
+ Server_Concurrency \
+ Synch-Benchmarks \
+ TCP \
+ UDP
+
diff --git a/ACE/performance-tests/Misc/Makefile.am b/ACE/performance-tests/Misc/Makefile.am
new file mode 100644
index 00000000000..d6b7af67f43
--- /dev/null
+++ b/ACE/performance-tests/Misc/Makefile.am
@@ -0,0 +1,150 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Misc_Basic_Perf.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += basic_perf
+
+basic_perf_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+basic_perf_SOURCES = \
+ basic_func.cpp \
+ basic_perf.cpp \
+ basic_func.h
+
+basic_perf_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Misc_Childbirth_Time.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += childbirth_time
+
+childbirth_time_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+childbirth_time_SOURCES = \
+ childbirth_time.cpp \
+ basic_func.h \
+ test_singleton.h
+
+childbirth_time_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Misc_Context_Switch_Time.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += context_switch_time
+
+context_switch_time_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+context_switch_time_SOURCES = \
+ context_switch_time.cpp \
+ basic_func.h \
+ test_singleton.h
+
+context_switch_time_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Misc_Preempt.am
+noinst_PROGRAMS += preempt
+
+preempt_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+preempt_SOURCES = \
+ preempt.cpp \
+ basic_func.h \
+ test_singleton.h
+
+preempt_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Makefile.Misc_Test_Mutex.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += test_mutex
+
+test_mutex_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_mutex_SOURCES = \
+ test_mutex.cpp \
+ basic_func.h \
+ test_singleton.h
+
+test_mutex_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Misc_Test_Naming.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += test_naming
+
+test_naming_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_naming_SOURCES = \
+ test_naming.cpp \
+ basic_func.h \
+ test_singleton.h
+
+test_naming_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Misc_Test_Singleton.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += test_singleton
+
+test_singleton_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+test_singleton_SOURCES = \
+ test_singleton.cpp \
+ test_singleton.h
+
+test_singleton_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/performance-tests/Misc/Misc.mpc b/ACE/performance-tests/Misc/Misc.mpc
new file mode 100644
index 00000000000..3bffd12d021
--- /dev/null
+++ b/ACE/performance-tests/Misc/Misc.mpc
@@ -0,0 +1,66 @@
+// -*- MPC -*-
+// $Id$
+
+project(*basic_perf) : aceexe {
+ avoids += ace_for_tao
+ exename = basic_perf
+ Source_Files {
+ basic_func.cpp
+ basic_perf.cpp
+ }
+}
+
+project(*childbirth_time) : aceexe {
+ avoids += ace_for_tao
+ exename = childbirth_time
+ Source_Files {
+ childbirth_time.cpp
+ }
+}
+
+project(*context_switch_time) : aceexe {
+ avoids += ace_for_tao
+ exename = context_switch_time
+ Source_Files {
+ context_switch_time.cpp
+ }
+}
+
+project(*test_mutex) : aceexe {
+ avoids += ace_for_tao
+ exename = test_mutex
+ Source_Files {
+ test_mutex.cpp
+ }
+}
+
+project(*test_naming) : aceexe {
+ avoids += ace_for_tao
+ exename = test_naming
+ Source_Files {
+ test_naming.cpp
+ }
+}
+
+project(*test_singleton) : aceexe {
+ avoids += ace_for_tao
+ exename = test_singleton
+ Source_Files {
+ test_singleton.cpp
+ }
+}
+
+project(*preempt) : aceexe {
+ exename = preempt
+ Source_Files {
+ preempt.cpp
+ }
+}
+
+// May need to add an ace_obsolete_guard_class feature
+//project(*test_guard) : aceexe {
+// exename = test_guard
+// Source_Files {
+// test_guard.cpp
+// }
+//}
diff --git a/ACE/performance-tests/Misc/basic_func.cpp b/ACE/performance-tests/Misc/basic_func.cpp
new file mode 100644
index 00000000000..84943e0b22a
--- /dev/null
+++ b/ACE/performance-tests/Misc/basic_func.cpp
@@ -0,0 +1,49 @@
+// $Id$
+
+#include "basic_func.h"
+
+ACE_RCSID(Misc, basic_func, "$Id$")
+
+int A, B, C, D, E, F;
+
+void
+func ()
+{
+ DO_SOMETHING
+}
+
+
+void
+Foo::func ()
+{
+ DO_SOMETHING
+}
+
+
+Foo_v::~Foo_v ()
+{
+}
+
+
+void
+Foo_v::func ()
+{
+ DO_SOMETHING
+}
+
+
+void
+Foo_v::v_func ()
+{
+ DO_SOMETHING
+}
+
+
+void
+Foo_d_v::v_func ()
+{
+ DO_SOMETHING
+}
+
+
+// EOF
diff --git a/ACE/performance-tests/Misc/basic_func.h b/ACE/performance-tests/Misc/basic_func.h
new file mode 100644
index 00000000000..dcb70bae5da
--- /dev/null
+++ b/ACE/performance-tests/Misc/basic_func.h
@@ -0,0 +1,77 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// performance-tests/Misc
+//
+// = FILENAME
+// basic_func.h
+//
+// = DESCRIPTION
+// For use with basic_perf.cpp.
+//
+// = AUTHOR
+// David Levine
+//
+// ============================================================================
+
+#ifndef BASIC_FUNC_H
+#define BASIC_FUNC_H
+
+#include "ace/ACE.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+extern int A,B,C,D,E,F;
+
+// If your compiler optimizes away Empty_Iteration_Test::run (), then
+// #defining ACE_HAS_OPTIMIZED_NULL_FUNCTIONS may help produce more
+// reasonable numbers.
+#if defined (_MSC_VER)
+ // MSVC 5.0 needs it . . .
+# define ACE_HAS_OPTIMIZED_NULL_FUNCTIONS
+#endif /* _MSC_VER */
+
+#if defined (ACE_HAS_OPTIMIZED_NULL_FUNCTIONS)
+# define EXPR(R,A,B,C,D) (R=(A*B + C*D))
+# define DO_SOMETHING EXPR(A,B,EXPR(F,A,E,C,B),EXPR(B,F,A,D,E),EXPR(E,B,F,A,C));
+#else /* ACE_HAS_OPTIMIZED_NULL_FUNCTIONS */
+# define DO_SOMETHING
+#endif /* ACE_HAS_OPTIMIZED_NULL_FUNCTIONS */
+
+
+// An external (global) function.
+void func ();
+
+
+// A class with no virtual functions.
+class Foo
+{
+ public:
+ void inline_func () { DO_SOMETHING }
+ void func ();
+};
+
+
+// A class with a virtual function.
+class Foo_v
+{
+ public:
+ virtual ~Foo_v ();
+ void inline_func () { DO_SOMETHING }
+ void func ();
+ virtual void v_func ();
+};
+
+
+// A derived class.
+class Foo_d_v : public Foo_v
+{
+ public:
+ virtual void v_func ();
+};
+
+#endif /* BASIC_FUNC_H */
diff --git a/ACE/performance-tests/Misc/basic_perf.cpp b/ACE/performance-tests/Misc/basic_perf.cpp
new file mode 100644
index 00000000000..d084e84e1b2
--- /dev/null
+++ b/ACE/performance-tests/Misc/basic_perf.cpp
@@ -0,0 +1,646 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// performance-tests/Misc
+//
+// = FILENAME
+// basic_perf.cpp
+//
+// = DESCRIPTION
+// Times various simple operations.
+//
+// With Sun C++, use -O2: make CFLAGS="-mt -O2" BIN=basic_perf
+// -fast seems to produce slower times.
+//
+// = AUTHOR
+// David Levine
+//
+// ============================================================================
+
+#include "basic_func.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_main.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_sys_utsname.h"
+
+ACE_RCSID(Misc, basic_perf, "$Id$")
+
+static const char usage [] = "[-? |\n"
+ " [-i <iterations> [1000000]]";
+
+// These are global. They appear to bust the CPU cache, on an Ultra 2
+// w/Sun C++ 4.2.
+static u_int iterations = 1000000;
+Foo foo;
+Foo_v foo_v;
+
+inline
+void
+inline_func ()
+{
+ DO_SOMETHING
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// function per_iteration
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// Given an elapsed time in nanoseconds, returns the time per iteration
+// in microseconds.
+static
+inline
+double
+per_iteration (const ACE_hrtime_t elapsed /* nanoseconds */)
+{
+ double ms_per_iteration = (double) ACE_CU64_TO_CU32 (elapsed) / 1000.0 /
+ (double) iterations;
+
+ // Don't print out "-0.000" or "-0.001" . . .
+ return -0.002 < ms_per_iteration && ms_per_iteration < 0.0
+ ? 0.0
+ : ms_per_iteration;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Basic_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+class Basic_Test
+{
+public:
+ Basic_Test (ACE_High_Res_Timer &timer,
+ ACE_hrtime_t empty_iteration_time);
+ virtual ~Basic_Test (void);
+
+ virtual void run (void) = 0;
+
+ double iteration_time (void);
+
+ void print_iteration_time (const char *message);
+
+protected:
+ ACE_hrtime_t elapsed_time_;
+
+ void start_timing (void)
+ {
+ timer_.reset ();
+ timer_.start ();
+ }
+
+ void stop_timing (void)
+ {
+ timer_.stop ();
+ timer_.elapsed_time (elapsed_time_);
+ }
+
+private:
+ ACE_High_Res_Timer &timer_;
+ ACE_hrtime_t empty_iteration_time_;
+
+ // Require the timer reference.
+ Basic_Test (void);
+
+ // Force construction of independent instances by prohibiting copying.
+ Basic_Test (const Basic_Test &);
+ Basic_Test &operator= (const Basic_Test &);
+};
+
+Basic_Test::Basic_Test (ACE_High_Res_Timer &timer,
+ ACE_hrtime_t empty_iteration_time)
+ : elapsed_time_ (0),
+ timer_ (timer),
+ empty_iteration_time_ (empty_iteration_time)
+{
+}
+
+Basic_Test::~Basic_Test (void)
+{
+}
+
+double
+Basic_Test::iteration_time (void)
+{
+ return per_iteration (elapsed_time_ > empty_iteration_time_ ?
+ elapsed_time_ - empty_iteration_time_ :
+ static_cast<ACE_hrtime_t> (0));
+}
+
+void
+Basic_Test::print_iteration_time (const char *message)
+{
+ ACE_DEBUG ((LM_INFO, " %-41s %8.3f\n",
+ message,
+ this->iteration_time ()));
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Empty_Iteration_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+class Empty_Iteration_Test : public Basic_Test
+{
+public:
+ Empty_Iteration_Test (ACE_High_Res_Timer &timer) : Basic_Test (timer, 0) {}
+ virtual ~Empty_Iteration_Test (void) {};
+
+ virtual void run (void);
+
+ ACE_hrtime_t empty_iteration_time (void) const
+ {
+ return elapsed_time_;
+ }
+
+private:
+ // Require the timer reference.
+ Empty_Iteration_Test (void);
+
+ // Force construction of independent instances by prohibiting copying.
+ Empty_Iteration_Test (const Empty_Iteration_Test &);
+ Empty_Iteration_Test &operator= (const Empty_Iteration_Test &);
+};
+
+void
+Empty_Iteration_Test::run (void)
+{
+ this->start_timing ();
+
+ for (u_int i = 0; i < iterations; ++i)
+ {
+ DO_SOMETHING
+ }
+
+ this->stop_timing ();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Inline_Call_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+class Inline_Call_Test : public Basic_Test
+{
+public:
+ Inline_Call_Test (ACE_High_Res_Timer &timer,
+ ACE_hrtime_t empty_iteration_time)
+ : Basic_Test (timer, empty_iteration_time) {}
+ virtual ~Inline_Call_Test (void) {};
+
+ virtual void run (void);
+
+private:
+ // Require the timer reference.
+ Inline_Call_Test (void);
+
+ // Force construction of independent instances by prohibiting copying.
+ Inline_Call_Test (const Inline_Call_Test &);
+ Inline_Call_Test &operator= (const Inline_Call_Test &);
+};
+
+void
+Inline_Call_Test::run (void)
+{
+ this->start_timing ();
+
+ for (u_int i = 0; i < iterations; ++i)
+ inline_func ();
+
+ this->stop_timing ();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Noninline_Call_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+class Noninline_Call_Test : public Basic_Test
+{
+public:
+ Noninline_Call_Test (ACE_High_Res_Timer &timer,
+ ACE_hrtime_t empty_iteration_time)
+ : Basic_Test (timer, empty_iteration_time) {}
+ virtual ~Noninline_Call_Test (void) {};
+
+ virtual void run (void);
+
+private:
+ // Require the timer reference.
+ Noninline_Call_Test (void);
+
+ // Force construction of independent instances by prohibiting copying.
+ Noninline_Call_Test (const Noninline_Call_Test &);
+ Noninline_Call_Test &operator= (const Noninline_Call_Test &);
+};
+
+void
+Noninline_Call_Test::run (void)
+{
+ this->start_timing ();
+
+ for (u_int i = 0; i < iterations; ++i)
+ func ();
+
+ this->stop_timing ();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Inline_Member_Call_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+class Inline_Member_Call_Test : public Basic_Test
+{
+public:
+ Inline_Member_Call_Test (ACE_High_Res_Timer &timer,
+ ACE_hrtime_t empty_iteration_time)
+ : Basic_Test (timer, empty_iteration_time) {}
+ virtual ~Inline_Member_Call_Test (void) {};
+
+ virtual void run (void);
+
+private:
+ // Require the timer reference.
+ Inline_Member_Call_Test (void);
+
+ // Force construction of independent instances by prohibiting copying.
+ Inline_Member_Call_Test (const Inline_Member_Call_Test &);
+ Inline_Member_Call_Test &operator= (const Inline_Member_Call_Test &);
+};
+
+void
+Inline_Member_Call_Test::run (void)
+{
+ this->start_timing ();
+
+ for (u_int i = 0; i < iterations; ++i)
+ foo.inline_func ();
+
+ this->stop_timing ();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Noninline_Member_Call_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+class Noninline_Member_Call_Test : public Basic_Test
+{
+public:
+ Noninline_Member_Call_Test (ACE_High_Res_Timer &timer,
+ ACE_hrtime_t empty_iteration_time)
+ : Basic_Test (timer, empty_iteration_time) {}
+ virtual ~Noninline_Member_Call_Test (void) {};
+
+ virtual void run (void);
+
+private:
+ // Require the timer reference.
+ Noninline_Member_Call_Test (void);
+
+ // Force construction of independent instances by prohibiting copying.
+ Noninline_Member_Call_Test (const Noninline_Member_Call_Test &);
+ Noninline_Member_Call_Test &operator= (const Noninline_Member_Call_Test &);
+};
+
+void
+Noninline_Member_Call_Test::run (void)
+{
+ this->start_timing ();
+
+ for (u_int i = 0; i < iterations; ++i)
+ foo.func ();
+
+ this->stop_timing ();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Inline_Member_With_Virtual_Call_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+class Inline_Member_With_Virtual_Call_Test : public Basic_Test
+{
+public:
+ Inline_Member_With_Virtual_Call_Test (ACE_High_Res_Timer &timer,
+ ACE_hrtime_t empty_iteration_time)
+ : Basic_Test (timer, empty_iteration_time) {}
+ virtual ~Inline_Member_With_Virtual_Call_Test (void) {};
+
+ virtual void run (void);
+
+private:
+ // Require the timer reference.
+ Inline_Member_With_Virtual_Call_Test (void);
+
+ // Force construction of independent instances by prohibiting copying.
+ Inline_Member_With_Virtual_Call_Test (
+ const Inline_Member_With_Virtual_Call_Test &);
+ Inline_Member_With_Virtual_Call_Test &operator= (
+ const Inline_Member_With_Virtual_Call_Test &);
+};
+
+void
+Inline_Member_With_Virtual_Call_Test::run (void)
+{
+ this->start_timing ();
+
+ for (u_int i = 0; i < iterations; ++i)
+ foo_v.inline_func ();
+
+ this->stop_timing ();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Noninline_Member_With_Virtual_Call_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+class Noninline_Member_With_Virtual_Call_Test : public Basic_Test
+{
+public:
+ Noninline_Member_With_Virtual_Call_Test (ACE_High_Res_Timer &timer,
+ ACE_hrtime_t empty_iteration_time)
+ : Basic_Test (timer, empty_iteration_time) {}
+ virtual ~Noninline_Member_With_Virtual_Call_Test (void) {};
+
+ virtual void run (void);
+
+private:
+ // Require the timer reference.
+ Noninline_Member_With_Virtual_Call_Test (void);
+
+ // Force construction of independent instances by prohibiting copying.
+ Noninline_Member_With_Virtual_Call_Test
+ (const Noninline_Member_With_Virtual_Call_Test &);
+ Noninline_Member_With_Virtual_Call_Test &operator=
+ (const Noninline_Member_With_Virtual_Call_Test &);
+};
+
+void
+Noninline_Member_With_Virtual_Call_Test::run (void)
+{
+ this->start_timing ();
+
+ for (u_int i = 0; i < iterations; ++i)
+ foo_v.func ();
+
+ this->stop_timing ();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Virtual_Member_Optimizable_Call_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+class Virtual_Member_Optimizable_Call_Test : public Basic_Test
+{
+public:
+ Virtual_Member_Optimizable_Call_Test (ACE_High_Res_Timer &timer,
+ ACE_hrtime_t empty_iteration_time)
+ : Basic_Test (timer, empty_iteration_time) {}
+ virtual ~Virtual_Member_Optimizable_Call_Test (void) {};
+
+ virtual void run (void);
+
+private:
+ // Require the timer reference.
+ Virtual_Member_Optimizable_Call_Test (void);
+
+ // Force construction of independent instances by prohibiting copying.
+ Virtual_Member_Optimizable_Call_Test (
+ const Virtual_Member_Optimizable_Call_Test &);
+ Virtual_Member_Optimizable_Call_Test &operator= (
+ const Virtual_Member_Optimizable_Call_Test &);
+};
+
+void
+Virtual_Member_Optimizable_Call_Test::run (void)
+{
+ Foo_v &fv_o = foo_v;
+
+ this->start_timing ();
+
+ for (u_int i = 0; i < iterations; ++i)
+ fv_o.v_func ();
+
+ this->stop_timing ();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Virtual_Member_Call_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+class Virtual_Member_Call_Test : public Basic_Test
+{
+public:
+ Virtual_Member_Call_Test (ACE_High_Res_Timer &timer,
+ ACE_hrtime_t empty_iteration_time)
+ : Basic_Test (timer, empty_iteration_time) {}
+ virtual ~Virtual_Member_Call_Test (void) {};
+
+ virtual void run (void);
+
+private:
+ // Require the timer reference.
+ Virtual_Member_Call_Test (void);
+
+ // Force construction of independent instances by prohibiting copying.
+ Virtual_Member_Call_Test (const Virtual_Member_Call_Test &);
+ Virtual_Member_Call_Test &operator= (const Virtual_Member_Call_Test &);
+};
+
+void
+Virtual_Member_Call_Test::run (void)
+{
+ Foo_v *fv;
+
+ if (iterations < 2)
+ fv = new Foo_v;
+ else
+ fv = new Foo_d_v;
+
+ this->start_timing ();
+
+ for (u_int i = 0; i < iterations; ++i)
+ fv->v_func ();
+
+ this->stop_timing ();
+
+ delete fv;
+ fv = 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// function get_options
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+static
+unsigned int
+get_options (int argc, ACE_TCHAR *argv [])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("i:?"));
+ int opt;
+
+ while ((opt = get_opt ()) != EOF)
+ {
+ switch (opt)
+ {
+ case 'i':
+ {
+ int temp = ACE_OS::atoi (get_opt.opt_arg ());
+ if (temp > 0)
+ iterations = (u_int) temp;
+ else
+ {
+ ACE_DEBUG ((LM_ERROR, "%s: number of iterations must be > 0\n",
+ argv [0]));
+ return 1;
+ }
+ break;
+ }
+ case '?':
+ ACE_DEBUG ((LM_INFO, "usage: %s %s\n", argv [0], usage));
+ ACE_OS::exit (0);
+ break;
+ default:
+ ACE_DEBUG ((LM_ERROR, "%s: unknown arg, %c\n", argv [0],
+ (char) opt));
+ ACE_DEBUG ((LM_ERROR, "usage: %s %s\n", argv [0], usage));
+ return 1;
+ }
+ }
+
+ switch (argc - get_opt.opt_ind ())
+ {
+ case 0:
+ // OK
+ break;
+ default:
+ ACE_DEBUG ((LM_ERROR, "%s: too many arguments\n", argv [0]));
+ ACE_DEBUG ((LM_ERROR, "usage: %s %s\n", argv [0], usage));
+ return 1;
+ }
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// function main
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ if (get_options (argc, argv))
+ ACE_OS::exit (-1);
+
+ ACE_utsname name;
+
+ if (ACE_OS::uname (&name) != -1)
+ ACE_DEBUG ((LM_INFO, "%s (%s), %s %s at %T\n",
+ name.nodename, name.machine, name.sysname, name.release));
+
+ ACE_DEBUG ((LM_INFO, "%u iterations\n", iterations));
+
+
+ // Use one timer for all the tests. No particular reason why.
+ ACE_High_Res_Timer timer;
+
+ // Calculate the time for an "empty iteration", and subtract it
+ // from each test time.
+ ACE_hrtime_t iteration_time;
+
+ Empty_Iteration_Test empty_iteration_test (timer);
+ empty_iteration_test.run ();
+ ACE_DEBUG ((LM_INFO, "An empty iteration costs %8.3f microseconds.\n\n",
+ empty_iteration_test.iteration_time ()));
+ iteration_time = empty_iteration_test.empty_iteration_time ();
+
+
+ // Run the real tests . . .
+ Inline_Call_Test inline_call_test (timer, iteration_time);
+ inline_call_test.run ();
+
+ Noninline_Call_Test noninline_call_test (timer, iteration_time);
+ noninline_call_test.run ();
+
+ Inline_Member_Call_Test inline_member_call_test (timer, iteration_time);
+ inline_member_call_test.run ();
+
+ Noninline_Member_Call_Test noninline_member_call_test (
+ timer, iteration_time);
+ noninline_member_call_test.run ();
+
+ Inline_Member_With_Virtual_Call_Test
+ inline_member_with_virtual_call_test (timer, iteration_time);
+ inline_member_with_virtual_call_test.run ();
+
+ Noninline_Member_With_Virtual_Call_Test
+ noninline_member_with_virtual_call_test (timer, iteration_time);
+ noninline_member_with_virtual_call_test.run ();
+
+ Virtual_Member_Optimizable_Call_Test
+ virtual_member_optimizable_call_test (timer, iteration_time);
+ virtual_member_optimizable_call_test.run ();
+
+ Virtual_Member_Call_Test virtual_member_call_test (timer, iteration_time);
+ virtual_member_call_test.run ();
+
+
+ // Print results . . .
+ ACE_DEBUG ((LM_INFO, "operation "
+ "time, microseconds\n"));
+ ACE_DEBUG ((LM_INFO, "========= "
+ "=================="));
+
+ ACE_DEBUG ((LM_INFO, "\nglobal function calls:\n"));
+ inline_call_test.print_iteration_time ("inline function call");
+ noninline_call_test.print_iteration_time ("non-inline function call");
+
+ ACE_DEBUG ((LM_INFO, "\nmember function calls:\n"));
+ inline_member_call_test.print_iteration_time (
+ "inline member function call");
+ noninline_member_call_test.print_iteration_time (
+ "non-inline member function call");
+
+ ACE_DEBUG ((LM_INFO, "\nmember function calls, class has a virtual "
+ "function:\n"));
+ inline_member_with_virtual_call_test.print_iteration_time (
+ "inline member function with virtual call");
+ noninline_member_with_virtual_call_test.print_iteration_time (
+ "non-inline member function w/virtual call");
+
+ ACE_DEBUG ((LM_INFO, "\nvirtual member function calls:\n"));
+ virtual_member_optimizable_call_test.print_iteration_time (
+ "virtual member function call, optimizable");
+ virtual_member_call_test.print_iteration_time (
+ "virtual member function call");
+
+ return 0;
+}
+
+
+// EOF
diff --git a/ACE/performance-tests/Misc/childbirth_time.cpp b/ACE/performance-tests/Misc/childbirth_time.cpp
new file mode 100644
index 00000000000..739d676a5fb
--- /dev/null
+++ b/ACE/performance-tests/Misc/childbirth_time.cpp
@@ -0,0 +1,401 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// (none)
+//
+// = FILENAME
+// childbirth_time.cpp
+//
+// = DESCRIPTION
+// This program is used to measure various child-creation mechanisms
+// on various platforms. By default, the program measure the time
+// to 'fork' a new process using ACE_Process.spawn (). Other tests
+// are possible as described below. James Hu provides the idea to
+// batch measuring threads creation.
+//
+// Usage: childbirth_time [-n ###] [-l ###] [-p|-f|-t|-a|-m|-x] [-h] [-e]
+//
+// -n ###: Specify number of iteration in tens. If this
+// option is not specified, the default is
+// MULTIPLY_FACTOR * (100 iterations,) which is
+// equivalent to -n 10.
+//
+// -l ###: Specify MULTIPLY_FACTOR. Default is 10.
+//
+// *-p: Measure the performance of forking a child process
+// and exec an "empty" program. This test uses
+// ACE_Process.spawn (). (Default)
+//
+// -f: Measure the performance of native "fork" function
+// call. Notice that there is no equivalent NT
+// function calls and this option is only available
+// on UN*X platform.
+//
+// -t: Measure the performance of native thread creation
+// mechanisms. On Solaris, this is thr_create ().
+// On NT, this is CreateThread (). Currently, only
+// these two platforms are implemented.
+//
+// -m: Measure the performance of Thread_Manager::spawn_n
+// method.
+//
+// -x: Test the baseline performance of ACE_Thread_Mutex.
+// This really doesn't belong here
+//
+// -a: Measure the performance of thread creation using
+// ACE_OS::thr_create ().
+//
+// -h: Use High Resolution Timer if supported by platform.
+//
+// -e: Exec a program after fork (). This option has no
+// effect on NT.
+//
+// = CREATION DATE
+// June 29, 1997
+//
+// = AUTHOR
+// Nanbor Wang
+//
+// ============================================================================
+
+// Process Creation profiling
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_main.h"
+#include "ace/Get_Opt.h"
+#include "ace/Process.h"
+#include "ace/Profile_Timer.h"
+#include "ace/Thread_Manager.h"
+
+ACE_RCSID(Misc, childbirth_time, "$Id$")
+
+#define ACE_STOP_SIGN ACE_OS::sleep (0)
+
+#define MAX_NO_ITERATION 10000
+#if defined (ACE_WIN32)
+#define SUBPROGRAM ACE_TEXT ("date.exe")
+#else
+#define SUBPROGRAM ACE_TEXT ("date")
+#endif
+
+size_t MULTIPLY_FACTOR = 10;
+typedef double (*Profiler)(size_t);
+static int do_exec_after_fork = 0;
+
+/// do nothing thread function
+extern "C" void *ace_empty (void*)
+{
+ return 0;
+}
+
+static double
+prof_ace_process (size_t iteration)
+{
+ if (iteration != 0)
+ {
+ ACE_Process_Options popt;
+ ACE_Process aProcess;
+
+ popt.command_line (SUBPROGRAM);
+
+ iteration *= MULTIPLY_FACTOR;
+
+ if (do_exec_after_fork == 0)
+ popt.creation_flags (ACE_Process_Options::NO_EXEC);
+
+ ACE_Profile_Timer ptimer;
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ double time = 0;
+ pid_t result;
+
+ for (size_t c = 0; c < iteration; c++)
+ {
+ ACE_STOP_SIGN;
+ ptimer.start ();
+ result = aProcess.spawn (popt);
+ ptimer.stop ();
+
+ if (result == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "process.spawn"), -1);
+ else if (do_exec_after_fork == 0 && result == 0)
+ ACE_OS::exit (0) ;
+ else
+ {
+ ptimer.elapsed_time (et);
+ time += et.real_time;
+ }
+ }
+
+ return time / iteration;
+ }
+ else
+ return -1.0;
+}
+
+static double
+prof_fork (size_t iteration)
+{
+#if !defined (ACE_LACKS_EXEC)
+ if (iteration != 0)
+ {
+ ACE_Profile_Timer ptimer;
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ double time = 0;
+
+ iteration *= MULTIPLY_FACTOR;
+
+ for (size_t i = 0; i < iteration; i++)
+ {
+ ACE_STOP_SIGN;
+ ptimer.start ();
+ switch (ACE_OS::fork ())
+ {
+ case -1:
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "process.spawn"), -1);
+ /* NOTREACHED */
+ case 0:
+ exit (0);
+ /* NOTREACHED */
+ break;
+ default:
+ ptimer.stop ();
+ ptimer.elapsed_time (et);
+ time += et.real_time;
+ }
+ }
+ return time / iteration;
+ }
+ else
+ return -1.0;
+#else
+ ACE_UNUSED_ARG (iteration);
+ ACE_ERROR_RETURN ((LM_ERROR, "fork () is not supported on this platform."), -1);
+#endif
+}
+
+static double
+prof_native_thread (size_t iteration)
+{
+#if defined (ACE_HAS_THREADS) && (defined (ACE_HAS_WTHREADS) || defined (ACE_HAS_STHREADS))
+ if (iteration != 0)
+ {
+ ACE_Profile_Timer ptimer;
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ double time = 0;
+
+ for (size_t i = 0; i < iteration; i++)
+ {
+ ACE_STOP_SIGN;
+ ptimer.start ();
+ for (size_t j = 0; j < MULTIPLY_FACTOR; j++)
+ {
+#if defined (ACE_HAS_WTHREADS)
+ if (::CreateThread (0,
+ 0,
+ LPTHREAD_START_ROUTINE (ace_empty),
+ 0,
+ CREATE_SUSPENDED,
+ 0) == 0)
+#elif defined (ACE_HAS_STHREADS)
+ if (::thr_create (0,
+ 0,
+ &ace_empty,
+ 0,
+ THR_SUSPENDED,
+ 0) != 0)
+#endif
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "CreateThread"), -1);
+ }
+ ptimer.stop ();
+ ptimer.elapsed_time (et);
+ time += et.real_time;
+ }
+ iteration *= MULTIPLY_FACTOR;
+ return time / iteration;
+ }
+ else
+ return -1.0;
+#else
+ ACE_UNUSED_ARG (iteration);
+ ACE_ERROR_RETURN ((LM_ERROR, "Testing of native threads is not supported on this platform.\n"), -1);
+#endif
+}
+
+static double
+prof_ace_os_thread (size_t iteration)
+{
+#if defined (ACE_HAS_THREADS)
+ if (iteration != 0)
+ {
+ ACE_Profile_Timer ptimer;
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ double time = 0;
+
+ for (size_t i = 0; i < iteration; i++)
+ {
+ ACE_STOP_SIGN;
+ ptimer.start ();
+
+ for (size_t j = 0; j < MULTIPLY_FACTOR; j++)
+ if (ACE_OS::thr_create ((ACE_THR_FUNC) ace_empty,
+ 0,
+ THR_SUSPENDED,
+ 0) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "CreateThread"), -1);
+
+ ptimer.stop ();
+ ptimer.elapsed_time (et);
+ time += et.real_time;
+ }
+ iteration *= MULTIPLY_FACTOR;
+ return time / iteration;
+ }
+ else
+ return -1.0;
+#else
+ ACE_UNUSED_ARG (iteration);
+ ACE_ERROR_RETURN ((LM_ERROR, "Threads are not supported on this platform.\n"), -1);
+#endif
+}
+
+static double
+prof_tm_thread (size_t iteration)
+{
+#if defined (ACE_HAS_THREADS)
+ if (iteration != 0)
+ {
+ ACE_Profile_Timer ptimer;
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ double time = 0;
+
+ for (size_t i = 0; i < iteration; i++)
+ {
+ ACE_STOP_SIGN;
+ ptimer.start ();
+
+ if (ACE_Thread_Manager::instance ()->spawn_n (MULTIPLY_FACTOR,
+ (ACE_THR_FUNC) ace_empty,
+ 0,
+ THR_SUSPENDED) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "CreateThread"), -1);
+
+ ptimer.stop ();
+ ptimer.elapsed_time (et);
+ time += et.real_time;
+ }
+ iteration *= MULTIPLY_FACTOR;
+ return time / iteration;
+ }
+ else
+ return -1.0;
+#else
+ ACE_UNUSED_ARG (iteration);
+ ACE_ERROR_RETURN ((LM_ERROR, "Threads are not supported on this platform."), -1);
+#endif
+}
+
+static double
+prof_mutex_base (size_t iteration)
+{
+#if defined (ACE_HAS_THREADS)
+ ACE_Thread_Mutex plain;
+ if (iteration != 0)
+ {
+ ACE_Profile_Timer ptimer;
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ double time = 0;
+
+ for (size_t i = 0; i < iteration; i++)
+ {
+ ACE_STOP_SIGN;
+ ptimer.start ();
+
+ for (size_t j=0; j < MULTIPLY_FACTOR; j++)
+ {
+ plain.acquire ();
+ plain.release ();
+ }
+
+ ptimer.stop ();
+ ptimer.elapsed_time (et);
+ time += et.real_time;
+ }
+ iteration *= MULTIPLY_FACTOR;
+ return time / iteration;
+ }
+ else
+ return -1.0;
+#else
+ ACE_UNUSED_ARG (iteration);
+ ACE_ERROR_RETURN ((LM_ERROR, "Threads are not supported on this platform."), -1);
+#endif
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR* argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("n:l:pftahmxe"));
+ int c;
+ size_t iteration = 10;
+ Profiler profiler = 0;
+ const char *profile_name = 0 ;
+
+ while ((c=get_opt ()) != -1)
+ {
+ switch (c)
+ {
+ case 'n':
+ iteration = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'l':
+ MULTIPLY_FACTOR = static_cast<size_t> (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'p': // test ACE_Process.spawn ()
+ profiler = prof_ace_process;
+ profile_name = "ACE_Process.spawn ()";
+ break;
+ case 'f': // test fork ()
+ profiler = prof_fork;
+ profile_name = "fork ()";
+ break;
+ case 't': // test native thread creation
+ profiler = prof_native_thread;
+ profile_name = "native threads";
+ break;
+ case 'a': // test ACE_OS::thr_create
+ profiler = prof_ace_os_thread;
+ profile_name = "ACE_OS::thr_create ()";
+ break;
+ case 'm':
+ profiler = prof_tm_thread;
+ profile_name = "ACE_Thread_Manager::spawn_n ()";
+ break;
+ case 'x':
+ profiler = prof_mutex_base;
+ profile_name = "ACE_Thread_Mutex Baseline";
+ break;
+ case 'h': // use high resolution timer
+ ACE_High_Res_Timer::get_env_global_scale_factor ();
+ break;
+ case 'e':
+ do_exec_after_fork = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (profiler == 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "Usage: childbirth_time {-p|-f|-t|-a|-m|-x} [-n ###] [-L ###] [-h] [-e]\n"), 1);
+ else
+ {
+ double time = profiler (iteration);
+ if (time > 0)
+ ACE_DEBUG ((LM_DEBUG,
+ "Average performance of %d iterations of %s: %.0f usec\n",
+ iteration * MULTIPLY_FACTOR, profile_name, time * 1e6));
+ }
+ return 0;
+}
diff --git a/ACE/performance-tests/Misc/context_switch_time.cpp b/ACE/performance-tests/Misc/context_switch_time.cpp
new file mode 100644
index 00000000000..084d85eaca6
--- /dev/null
+++ b/ACE/performance-tests/Misc/context_switch_time.cpp
@@ -0,0 +1,1318 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// (none)
+//
+// = FILENAME
+// context_switch_time.cpp
+//
+// = DESCRIPTION
+// Program that calculates context switch time between threads.
+// The Suspend-Resume test is based on the Task Context Switching
+// measurement approach described in:
+// Darren Cathey<br>
+// "RTOS Benchmarking -- All Things Considered . . ."<br>
+// <a href="http://www.realtime-info.be"><em>Real-Time Magazine</em></a>,
+// Second Quarter 1993,
+// <em>reprinted by <a href="http://www.wrs.com/artreqfm.html">Wind River
+// Systems</a></em><p>
+// which in turn is based on Superconducting Super Collider (SSC)
+// Laboratory Ping Suspend/Resume Task and Suspend/Resume Task benchmarks.
+// It measures two different times:
+// 1) The time to resume a blocked high priority task, which does
+// nothing other than block immediately. A lower priority task
+// resumes the high priority task, so the elapsed time includes
+// two context switches, one task suspend, and one task resume.
+// 2) The time to suspend and resume a low priority task that does
+// nothing. There is no context switching. This time is subtracted
+// from the one described in 1) above, and the result is divided by
+// two to yield the context switch time.
+//
+// Notes:
+// On Solaris 2.5.1, it appears that the lowest context switching times,
+// at least on a single-CPU machine, are obtained _without_ creating new
+// LWPs for new threads (THR_NEW_LWP). The -n option enables the use of
+// THR_NEW_LWP for testing.
+//
+// = CREATION DATE
+// 17 January 1997
+//
+// = AUTHOR
+// David L. Levine
+//
+// ============================================================================
+
+static const char usage [] = "[-? |\n"
+ " [-c <repeat count, 0 means forever>]\n"
+ " [-n to spawn a new LWP with each thread\n"
+ "[<iterations>]]";
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_main.h"
+#include "ace/Task.h"
+#include "ace/Sched_Params.h"
+#include "ace/Stats.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Get_Opt.h"
+#include "ace/Thread_Semaphore.h"
+#include "ace/Barrier.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_errno.h"
+
+ACE_RCSID(Misc, context_switch_time, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+#if !defined (ACE_DEBUG_CST)
+# define ACE_DEBUG_CST 0
+#endif /* ACE_DEBUG_CST */
+
+static const u_int LOW_PRIORITY = ACE_THR_PRI_FIFO_DEF;
+static u_int HIGH_PRIORITY;
+
+// Global test configuration parameters.
+static ACE_UINT32 count = 1;
+static ACE_UINT32 num_iterations = 1000;
+static ACE_UINT32 new_lwp = 0;
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Low_Priority_Null_Task
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class Low_Priority_Null_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Low_Priority_Null_Task ();
+ virtual ~Low_Priority_Null_Task ();
+
+ virtual int svc ();
+
+ // Called by other task: it returns when this task is ready to
+ // continue.
+ void ready () { initialized_.acquire (); }
+
+ void done ();
+
+ ACE_hthread_t thread_id () const { return thread_id_; }
+private:
+ ACE_hthread_t thread_id_;
+ ACE_Semaphore initialized_; // Blocks until thread_id_ is assigned.
+ ACE_Semaphore blocked_semaphore_;
+
+ // Force proper construction of independent instances.
+ Low_Priority_Null_Task (const Low_Priority_Null_Task &);
+ Low_Priority_Null_Task &operator= (const Low_Priority_Null_Task &);
+};
+
+inline
+Low_Priority_Null_Task::Low_Priority_Null_Task() :
+ ACE_Task<ACE_MT_SYNCH> (ACE_Thread_Manager::instance ()),
+ initialized_ (0), // initialize to locked, then unlock when ready
+ blocked_semaphore_ (0)
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Low_Priority_Null_Task ctor\n"));
+#endif /* ACE_DEBUG_CST */
+
+ if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
+ 1, 0, LOW_PRIORITY))
+ ACE_OS::perror (ACE_TEXT("activate"));
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Low_Priority_Null_Task ctor, activated\n"));
+#endif /* ACE_DEBUG_CST */
+}
+
+Low_Priority_Null_Task::~Low_Priority_Null_Task()
+{
+}
+
+int
+Low_Priority_Null_Task::svc ()
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Low_Priority_Null_Task::svc (), entering"));
+#endif /* ACE_DEBUG_CST */
+
+ ACE_Thread_Manager::instance ()->thr_self (thread_id_);
+ initialized_.release ();
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "; thread ID is %u\n", thread_id_));
+#endif /* ACE_DEBUG_CST */
+
+ // This task must never actually execute, so just have it block
+ // on a semaphore forever . . .
+ blocked_semaphore_.acquire ();
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Low_Priority_Task::svc, finishing\n"));
+#endif /* ACE_DEBUG_CST */
+
+ return 0;
+}
+
+void
+Low_Priority_Null_Task::done ()
+{
+ blocked_semaphore_.release ();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Suspend_Resume_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class Suspend_Resume_Test : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Suspend_Resume_Test (const ACE_UINT32 iterations);
+ virtual ~Suspend_Resume_Test ();
+
+ virtual int svc ();
+
+ ACE_hrtime_t elapsed_time () const { return elapsed_time_; }
+private:
+ const ACE_UINT32 iterations_;
+
+ Low_Priority_Null_Task low_;
+
+ ACE_High_Res_Timer timer_;
+
+ ACE_hrtime_t elapsed_time_;
+
+ // Force proper construction of independent instances.
+ Suspend_Resume_Test ();
+ Suspend_Resume_Test (const Suspend_Resume_Test &);
+ Suspend_Resume_Test &operator= (const Suspend_Resume_Test &);
+};
+
+Suspend_Resume_Test::Suspend_Resume_Test (const ACE_UINT32 iterations) :
+ ACE_Task<ACE_MT_SYNCH> (),
+ iterations_ (iterations),
+ low_ (),
+ timer_ ()
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Suspend_Resume_Test ctor\n"));
+#endif /* ACE_DEBUG_CST */
+
+ if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
+ 1, 0, HIGH_PRIORITY))
+ ACE_OS::perror (ACE_TEXT("activate"));
+}
+
+Suspend_Resume_Test::~Suspend_Resume_Test()
+{
+}
+
+int
+Suspend_Resume_Test::svc ()
+{
+#if ACE_DEBUG_CST > 0
+ ACE_hthread_t thread_id;
+ ACE_Thread_Manager::instance ()->thr_self (thread_id);
+
+ ACE_DEBUG ((LM_DEBUG, "Suspend_Resume_Test::svc (), thread ID is %d\n",
+ thread_id));
+#endif /* ACE_DEBUG_CST */
+
+ low_.ready ();
+
+ // For information: the cost of the just the loop itself below,
+ // without the suspend and resume calls, on a 166 MHz Ultrasparc
+ // is about 12.3 nanoseconds per iteration.
+
+ timer_.start ();
+
+ for (ACE_UINT32 i = 0; i < iterations_; ++i)
+ {
+#if ACE_DEBUG_CST > 0
+ if (i % (iterations_ >= 10 ? iterations_ / 10 : 1) == 0)
+ ACE_DEBUG ((LM_DEBUG, "Suspend_Resume_Test::svc (), iteration %u\n",
+ i));
+#endif /* ACE_DEBUG_CST */
+
+ if (ACE_OS::thr_suspend (low_.thread_id ()) != 0)
+ {
+ ACE_ERROR ((LM_ERROR, "%p\n", "thr_suspend"));
+ low_.done ();
+ return -1;
+ }
+
+ if (ACE_OS::thr_continue (low_.thread_id ()) != 0 &&
+ errno != EINVAL)
+ // EINVAL is OK: it just means that the thread needs to be joined.
+ {
+ ACE_ERROR ((LM_ERROR, "%p\n", "thr_continue"));
+ low_.done ();
+ return -1;
+ }
+ }
+
+ timer_.stop ();
+ timer_.elapsed_microseconds (elapsed_time_);
+
+ low_.done ();
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Suspend_Resume_Test::svc, finishing\n"));
+#endif /* ACE_DEBUG_CST */
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class High_Priority_Simple_Task
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class High_Priority_Simple_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ High_Priority_Simple_Task ();
+ virtual ~High_Priority_Simple_Task ();
+
+ virtual int svc ();
+
+ // called by other task: it returns when this task is ready to
+ // continue
+ void ready () { initialized_.acquire (); }
+
+ void done ();
+
+ ACE_hthread_t thread_id () const { return thread_id_; }
+ ACE_UINT32 iterations () const { return iterations_; }
+private:
+ ACE_hthread_t thread_id_;
+ ACE_Semaphore initialized_; // Block until thread_id_ is assigned.
+ int terminate_;
+ ACE_UINT32 iterations_;
+
+ // Force proper construction of independent instances.
+ High_Priority_Simple_Task (const High_Priority_Simple_Task &);
+ High_Priority_Simple_Task &operator= (const High_Priority_Simple_Task &);
+};
+
+inline
+High_Priority_Simple_Task::High_Priority_Simple_Task() :
+ ACE_Task<ACE_MT_SYNCH> (ACE_Thread_Manager::instance ()),
+ initialized_ (0), // Initialize to locked, then unlock when ready.
+ terminate_ (0),
+ iterations_ (0)
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "High_Priority_Simple_Task ctor\n"));
+#endif /* ACE_DEBUG_CST */
+
+ if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
+ 1, 0, HIGH_PRIORITY))
+ ACE_OS::perror (ACE_TEXT("activate"));
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "High_Priority_Simple_Task ctor, activated\n"));
+#endif /* ACE_DEBUG_CST */
+}
+
+High_Priority_Simple_Task::~High_Priority_Simple_Task()
+{
+}
+
+int
+High_Priority_Simple_Task::svc ()
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "High_Priority_Simple_Task::svc (), entering"));
+#endif /* ACE_DEBUG_CST */
+
+ ACE_Thread_Manager::instance ()->thr_self (thread_id_);
+ initialized_.release ();
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "; thread ID is %u\n", thread_id_));
+#endif /* ACE_DEBUG_CST */
+
+ for (ACE_UINT32 i = 0; ! terminate_; ++i)
+ {
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "High_Priority_Simple_Task::svc, suspend self ("
+ "%u)\n", thread_id_));
+#endif /* ACE_DEBUG_CST */
+
+ ++iterations_;
+
+ // immediately suspend self
+ if (ACE_OS::thr_suspend (thread_id_) != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "thr_suspend"), -1);
+ }
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "High_Priority_Simple_Task::svc, resumed (%u)\n",
+ thread_id_));
+#endif /* ACE_DEBUG_CST */
+ }
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "High_Priority_Simple_Task::svc, finishing\n"));
+#endif /* ACE_DEBUG_CST */
+
+ return 0;
+}
+
+inline
+void
+High_Priority_Simple_Task::done ()
+{
+ terminate_ = 1;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Ping_Suspend_Resume_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class Ping_Suspend_Resume_Test : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Ping_Suspend_Resume_Test (const ACE_UINT32 iterations);
+ virtual ~Ping_Suspend_Resume_Test ();
+
+ virtual int svc ();
+
+ ACE_hrtime_t elapsed_time () const { return elapsed_time_; }
+private:
+ const ACE_UINT32 iterations_;
+
+ High_Priority_Simple_Task high_;
+
+ ACE_High_Res_Timer timer_;
+
+ ACE_hrtime_t elapsed_time_;
+
+ // Force proper construction of independent instances.
+ Ping_Suspend_Resume_Test ();
+ Ping_Suspend_Resume_Test (const Ping_Suspend_Resume_Test &);
+ Ping_Suspend_Resume_Test &operator= (const Ping_Suspend_Resume_Test &);
+};
+
+Ping_Suspend_Resume_Test::Ping_Suspend_Resume_Test (
+ const ACE_UINT32 iterations)
+:
+ ACE_Task<ACE_MT_SYNCH> (),
+ iterations_ (iterations),
+ high_ (),
+ timer_ ()
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test ctor\n"));
+#endif /* ACE_DEBUG_CST */
+
+ if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
+ 1, 0, LOW_PRIORITY))
+ ACE_OS::perror (ACE_TEXT("activate"));
+}
+
+Ping_Suspend_Resume_Test::~Ping_Suspend_Resume_Test()
+{
+}
+
+int
+Ping_Suspend_Resume_Test::svc ()
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test::svc (), entering"));
+
+ ACE_hthread_t thread_id;
+ ACE_Thread_Manager::instance ()->thr_self (thread_id);
+
+ ACE_DEBUG ((LM_DEBUG, "; thread ID is %u\n", thread_id));
+#endif /* ACE_DEBUG_CST */
+
+ high_.ready ();
+
+#if ACE_DEBUG_CST > 0
+ int priority, high_priority;
+ ACE_OS::thr_getprio (thread_id, priority);
+ ACE_OS::thr_getprio (high_.thread_id (), high_priority);
+ ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test::svc (), priority is %d, "
+ ", high thread priority is %d\n",
+ priority, high_priority));
+#endif /* ACE_DEBUG_CST */
+
+ // For information: the cost of the just the loop itself below,
+ // without the suspend and resume calls, on a 166 MHz Ultrasparc
+ // is about 12.3 nanoseconds per iteration.
+
+ timer_.start ();
+
+ ACE_UINT32 i;
+
+ for (i = 0; i < iterations_; ++i)
+ {
+#if ACE_DEBUG_CST > 0
+ if (i % (iterations_ >= 10 ? iterations_ / 10 : 1) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test::svc (), iteration "
+ "%d, continue high-priority thread %u\n",
+ i, high_.thread_id ()));
+ }
+#endif /* ACE_DEBUG_CST */
+ if (ACE_OS::thr_continue (high_.thread_id ()) != 0 &&
+ errno != EINVAL)
+ // EINVAL is OK: it just means that the thread needs to be joined.
+ {
+ ACE_ERROR ((LM_ERROR, "%p\n", "thr_continue"));
+ high_.done ();
+ return -1;
+ }
+ }
+
+ timer_.stop ();
+ timer_.elapsed_microseconds (elapsed_time_);
+
+ high_.done ();
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test::svc: told high priority "
+ "task to terminate\n"));
+#endif /* ACE_DEBUG_CST */
+
+ // Resume the thread until thr_continue fails, indicating that it has
+ // finished.
+ for (i = 0; i < 10000 && ! ACE_OS::thr_continue (high_.thread_id ());
+ ++i) /* null */;
+
+ // Don't count the one iteration that was used to allow the high-priority
+ // thread to terminate.
+ if (high_.iterations () < iterations_)
+ ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test: high priority task "
+ "executed only %u iterations!\n",
+ high_.iterations ()));
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Ping_Suspend_Resume_Test::svc, finishing\n"));
+#endif /* ACE_DEBUG_CST */
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Yield_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class Yield_Test : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Yield_Test (const ACE_UINT32 iterations);
+ virtual ~Yield_Test ();
+
+ virtual int svc ();
+
+ ACE_hrtime_t elapsed_time () const { return elapsed_time_; }
+private:
+ const ACE_UINT32 iterations_;
+#if defined (VXWORKS)
+ ACE_Thread_Mutex mutex_;
+ u_int started_;
+ u_int stopped_;
+#else /* ! VXWORKS */
+ ACE_Barrier timer_barrier_;
+#endif /* ! VXWORKS */
+ ACE_High_Res_Timer timer_;
+ ACE_hrtime_t elapsed_time_;
+
+ // Force proper construction of independent instances.
+ Yield_Test ();
+ Yield_Test (const Yield_Test &);
+ Yield_Test &operator= (const Yield_Test &);
+};
+
+Yield_Test::Yield_Test (const ACE_UINT32 iterations) :
+ ACE_Task<ACE_MT_SYNCH> (),
+ iterations_ (iterations),
+#if defined (VXWORKS)
+ mutex_ (),
+ started_ (0),
+ stopped_ (0),
+#else /* ! VXWORKS */
+ timer_barrier_ (3),
+#endif /* ! VXWORKS */
+ timer_ ()
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Yield_Test ctor\n"));
+#endif /* ACE_DEBUG_CST */
+
+#if !defined (VXWORKS)
+ timer_.start ();
+#endif /* ! VXWORKS */
+
+ if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
+ 2, 0, LOW_PRIORITY))
+ ACE_OS::perror (ACE_TEXT("activate"));
+
+#if !defined (VXWORKS)
+ timer_barrier_.wait ();
+ timer_.stop ();
+#endif /* ! VXWORKS */
+
+ timer_.elapsed_microseconds (elapsed_time_);
+}
+
+Yield_Test::~Yield_Test()
+{
+}
+
+int
+Yield_Test::svc ()
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Yield_Test::svc (), entering"));
+
+ ACE_hthread_t thread_id;
+ ACE_Thread_Manager::instance ()->thr_self (thread_id);
+
+ int priority;
+ ACE_OS::thr_getprio (thread_id, priority);
+
+ ACE_DEBUG ((LM_DEBUG, "; thread ID is %u, priority is %u\n", thread_id,
+ priority));
+#endif /* ACE_DEBUG_CST */
+
+#if defined (VXWORKS)
+ // Start the timer, if it hasn't already been started.
+ if (! started_)
+ {
+ // Double-check.
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1);
+
+ if (! started_)
+ {
+ started_ = 1;
+ timer_.start ();
+ }
+ }
+#endif /* VXWORKS */
+
+ for (ACE_UINT32 i = 0; i < iterations_; ++i)
+ {
+#if ACE_DEBUG_CST > 0
+ if (i % (iterations_ >= 10 ? iterations_ / 10 : 1) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "Yield_Test::svc () [%u], iteration %u\n",
+ thread_id, i));
+ }
+#endif /* ACE_DEBUG_CST */
+
+ ACE_OS::thr_yield ();
+ }
+
+#if defined (VXWORKS)
+ // Stop the timer, if it hasn't already been started.
+ if (! stopped_)
+ {
+ // Maybe it would be better to read the clock before grabbing
+ // the mutex. Then, only apply the clock reading below, instead
+ // of reading the clock after grabbing the mutex.
+
+ // Double-check.
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1);
+
+ if (! stopped_)
+ {
+ stopped_ = 1;
+ timer_.stop ();
+ timer_.elapsed_time (elapsed_time_); /* nanoseconds */
+ }
+ }
+#else /* ! VXWORKS */
+ timer_barrier_.wait ();
+#endif /* ! VXWORKS */
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Yield_Test::svc, finishing\n"));
+#endif /* ACE_DEBUG_CST */
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Mutex_Acquire_Release_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class Mutex_Acquire_Release_Test
+{
+public:
+ Mutex_Acquire_Release_Test (const ACE_UINT32 iterations);
+ virtual ~Mutex_Acquire_Release_Test ();
+
+ virtual int svc ();
+
+ ACE_hrtime_t elapsed_time () const { return elapsed_time_; }
+private:
+ ACE_Thread_Mutex mutex_;
+ // Mutex used for acquire/release time measurement.
+
+ ACE_Thread_Semaphore sem_;
+ // Semaphore used for acquire/release time measurement.
+
+ const ACE_UINT32 iterations_;
+
+ ACE_High_Res_Timer timer_;
+
+ ACE_hrtime_t elapsed_time_;
+
+ // Force proper construction of independent instances.
+ Mutex_Acquire_Release_Test ();
+ Mutex_Acquire_Release_Test (const Mutex_Acquire_Release_Test &);
+ Mutex_Acquire_Release_Test &operator= (const Mutex_Acquire_Release_Test &);
+};
+
+Mutex_Acquire_Release_Test::Mutex_Acquire_Release_Test (
+ const ACE_UINT32 iterations) :
+ mutex_ (),
+ sem_ (),
+ iterations_ (iterations),
+ timer_ ()
+{
+}
+
+Mutex_Acquire_Release_Test::~Mutex_Acquire_Release_Test()
+{
+}
+
+int
+Mutex_Acquire_Release_Test::svc ()
+{
+#if ACE_DEBUG_CST > 0
+ ACE_hthread_t thread_id;
+ ACE_Thread_Manager::instance ()->thr_self (thread_id);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "Mutex_Acquire_Release_Test::svc (), thread ID is %d\n",
+ thread_id));
+#endif /* ACE_DEBUG_CST */
+
+ timer_.start ();
+
+ for (ACE_UINT32 i = 0; i < iterations_; ++i)
+ {
+ // Block on the mutex.
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1);
+
+ // Release the mutex so that the low priority thread can
+ // proceed. The ACE_GUARD_RETURN macro implicity releases the
+ // mutex.
+ }
+
+ timer_.stop ();
+ timer_.elapsed_time (elapsed_time_); /* nanoseconds */
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Mutex_Acquire_Release_Test::svc, finishing\n"));
+#endif /* ACE_DEBUG_CST */
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class High_Priority_Synchronized_Task
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class High_Priority_Synchronized_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ High_Priority_Synchronized_Task (ACE_Thread_Semaphore &sem,
+ ACE_Thread_Mutex &mutex,
+ ACE_High_Res_Timer &timer);
+ virtual ~High_Priority_Synchronized_Task ();
+
+ virtual int svc ();
+
+ void ready () { initialized_.acquire (); }
+ // Called by other task: it returns when this task is ready to
+ // continue
+
+ void done ();
+
+ ACE_UINT32 average_context_switch_time () const;
+
+ ACE_hthread_t thread_id () const { return thread_id_; }
+ ACE_UINT32 iterations () const { return iterations_; }
+private:
+ ACE_hthread_t thread_id_;
+ ACE_Semaphore initialized_; // Block until thread_id_ is assigned.
+ int terminate_;
+ ACE_UINT32 iterations_;
+
+ ACE_Thread_Semaphore &sem_;
+ // Semaphore used to resume the task.
+
+ ACE_Thread_Mutex &mutex_;
+ // Mutex used to block the task.
+
+ ACE_High_Res_Timer &timer_;
+ // Clock shared between low and high priority tasks.
+
+ ACE_hrtime_t total_time_;
+ // Running total context switch time, nsec.
+
+ // Force proper construction of independent instances.
+ High_Priority_Synchronized_Task ();
+ High_Priority_Synchronized_Task (const High_Priority_Synchronized_Task &);
+ High_Priority_Synchronized_Task &
+ operator= (const High_Priority_Synchronized_Task &);
+};
+
+High_Priority_Synchronized_Task::High_Priority_Synchronized_Task (
+ ACE_Thread_Semaphore &sem,
+ ACE_Thread_Mutex &mutex,
+ ACE_High_Res_Timer &timer) :
+ ACE_Task<ACE_MT_SYNCH> (ACE_Thread_Manager::instance ()),
+ initialized_ (0), // Initialize to locked, then unlock when ready.
+ terminate_ (0),
+ iterations_ (0),
+ sem_ (sem),
+ mutex_ (mutex),
+ timer_ (timer),
+ total_time_ (0)
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "High_Priority_Synchronized_Task ctor\n"));
+#endif /* ACE_DEBUG_CST */
+
+ if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
+ 1, 0, HIGH_PRIORITY))
+ ACE_OS::perror (ACE_TEXT("activate"));
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "High_Priority_Synchronized_Task ctor, activated\n"));
+#endif /* ACE_DEBUG_CST */
+}
+
+High_Priority_Synchronized_Task::~High_Priority_Synchronized_Task()
+{
+}
+
+int
+High_Priority_Synchronized_Task::svc ()
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "High_Priority_Synchronized_Task::svc (), entering"));
+#endif /* ACE_DEBUG_CST */
+
+ ACE_Thread_Manager::instance ()->thr_self (thread_id_);
+
+ ACE_UINT32 mutex_acquire_release_time = 0;
+ {
+ Mutex_Acquire_Release_Test mutex_acquire_release_test (num_iterations);
+ mutex_acquire_release_test.svc ();
+ mutex_acquire_release_time =
+ static_cast<ACE_UINT32> (mutex_acquire_release_test.elapsed_time () /
+ num_iterations);
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "mutex_acquire_release: %u nsec\n",
+ mutex_acquire_release_time));
+#endif /* ACE_DEBUG_CST */
+ }
+
+ initialized_.release ();
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "; thread ID is %u\n", thread_id_));
+#endif /* ACE_DEBUG_CST */
+
+ for (ACE_UINT32 i = 0; ! terminate_; ++i)
+ {
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG,
+ "High_Priority_Synchronized_Task::svc, wait on sem ("
+ "%u)\n", thread_id_));
+#endif /* ACE_DEBUG_CST */
+
+ if (sem_.acquire () != 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "sem_.acquire"), -1);
+ }
+
+ {
+ // Block on the mutex.
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, guard, mutex_, -1);
+
+ timer_.stop ();
+
+ ++iterations_;
+
+ ACE_hrtime_t nsec;
+ timer_.elapsed_time (nsec);
+ const ACE_UINT32 context_switch_time =
+ ACE_U64_TO_U32 (nsec) >= mutex_acquire_release_time ?
+ ACE_U64_TO_U32 (nsec) - mutex_acquire_release_time : 0;
+
+ total_time_ += context_switch_time;
+
+ // Release the mutex so that the low priority thread can
+ // proceed. The ACE_GUARD_RETURN macro implicity releases the
+ // mutex.
+ }
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG,
+ "High_Priority_Synchronized_Task::svc, resumed (%u)\n",
+ thread_id_));
+#endif /* ACE_DEBUG_CST */
+ }
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "High_Priority_Synchronized_Task::svc, finishing\n"));
+#endif /* ACE_DEBUG_CST */
+
+ return 0;
+}
+
+inline
+void
+High_Priority_Synchronized_Task::done ()
+{
+ terminate_ = 1;
+}
+
+ACE_UINT32
+High_Priority_Synchronized_Task:: average_context_switch_time () const
+{
+ return iterations_ > 0 ? static_cast<ACE_UINT32> (total_time_ / iterations_)
+ : 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Synchronized_Suspend_Resume_Test
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class Synchronized_Suspend_Resume_Test : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ Synchronized_Suspend_Resume_Test (const ACE_UINT32 iterations);
+ virtual ~Synchronized_Suspend_Resume_Test ();
+
+ virtual int svc ();
+
+ ACE_UINT32 average_context_switch_time ();
+
+ ACE_hrtime_t elapsed_time () const { return elapsed_time_; }
+private:
+ const ACE_UINT32 iterations_;
+
+ ACE_Thread_Semaphore sem_;
+ // Used by the low priority thread to resume the high priority thread.
+
+ ACE_Thread_Mutex mutex_;
+ // Used by the low priority thread to block the high priority thread.
+
+ ACE_High_Res_Timer timer_;
+ // Clock shared between low and high priority tasks.
+
+ High_Priority_Synchronized_Task high_;
+ // The high priority task.
+
+ ACE_hrtime_t elapsed_time_;
+
+ ACE_UINT32 mutex_acquire_release_time_;
+
+ // Force proper construction of independent instances.
+ Synchronized_Suspend_Resume_Test ();
+ Synchronized_Suspend_Resume_Test (const Synchronized_Suspend_Resume_Test &);
+ Synchronized_Suspend_Resume_Test &
+ operator= (const Synchronized_Suspend_Resume_Test &);
+};
+
+Synchronized_Suspend_Resume_Test::Synchronized_Suspend_Resume_Test (
+ const ACE_UINT32 iterations)
+:
+ ACE_Task<ACE_MT_SYNCH> (),
+ iterations_ (iterations),
+ sem_ (0),
+ mutex_ (),
+ timer_ (),
+ high_ (sem_, mutex_, timer_),
+ mutex_acquire_release_time_ (0)
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Synchronized_Suspend_Resume_Test ctor\n"));
+#endif /* ACE_DEBUG_CST */
+
+ if (this->activate (THR_BOUND | THR_DETACHED | THR_SCHED_FIFO | new_lwp,
+ 1, 0, LOW_PRIORITY))
+ ACE_OS::perror (ACE_TEXT("activate"));
+}
+
+Synchronized_Suspend_Resume_Test::~Synchronized_Suspend_Resume_Test()
+{
+}
+
+int
+Synchronized_Suspend_Resume_Test::svc ()
+{
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Synchronized_Suspend_Resume_Test::svc (), entering"));
+
+ ACE_hthread_t thread_id;
+ ACE_Thread_Manager::instance ()->thr_self (thread_id);
+
+ ACE_DEBUG ((LM_DEBUG, "; thread ID is %u\n", thread_id));
+#endif /* ACE_DEBUG_CST */
+
+ {
+ Mutex_Acquire_Release_Test mutex_acquire_release_test (num_iterations);
+ mutex_acquire_release_test.svc ();
+ mutex_acquire_release_time_ =
+ static_cast<ACE_UINT32> (mutex_acquire_release_test.elapsed_time () /
+ num_iterations);
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "mutex_acquire_release: %u nsec\n",
+ mutex_acquire_release_time_));
+#endif /* ACE_DEBUG_CST */
+ }
+
+ high_.ready ();
+
+#if ACE_DEBUG_CST > 0
+ int priority, high_priority;
+ ACE_OS::thr_getprio (thread_id, priority);
+ ACE_OS::thr_getprio (high_.thread_id (), high_priority);
+ ACE_DEBUG ((LM_DEBUG,
+ "Synchronized_Suspend_Resume_Test::svc (), priority is %d, "
+ ", high thread priority is %d\n",
+ priority, high_priority));
+#endif /* ACE_DEBUG_CST */
+
+ // For information: the cost of the just the loop itself below,
+ // without the suspend and resume calls, on a 166 MHz Ultrasparc
+ // is about 12.3 nanoseconds per iteration.
+
+ ACE_UINT32 i;
+
+ for (i = 0; i < iterations_; ++i)
+ {
+#if ACE_DEBUG_CST > 0
+ if (i % (iterations_ >= 10 ? iterations_ / 10 : 1) == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Synchronized_Suspend_Resume_Test::svc (), iteration "
+ "%d, continue high-priority thread %u\n",
+ i, high_.thread_id ()));
+ }
+#endif /* ACE_DEBUG_CST */
+
+ {
+ // Acquire the mutex so that the high priority thread will
+ // block after we signal it via the condition variable.
+ ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, mutex_, -1);
+
+ // Release the semaphore so that the high priority thread can
+ // proceed.
+ if (sem_.release () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "sem_.release"), -1);
+
+ timer_.start ();
+
+ // Release the mutex so that the high priority thread can
+ // proceed. The ACE_GUARD_RETURN macro implicity releases
+ // the mutex.
+ }
+ }
+
+ high_.done ();
+
+ // The high priority thread will be block on the semaphore, so
+ // release it.
+ if (sem_.release () != 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "sem_.release"), -1);
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG,
+ "Synchronized_Suspend_Resume_Test::svc: told high priority "
+ "task to terminate\n"));
+#endif /* ACE_DEBUG_CST */
+
+ // Resume the thread until thr_continue fails, indicating that it has
+ // finished.
+ for (i = 0; i < 10000 && ! ACE_OS::thr_continue (high_.thread_id ());
+ ++i) /* null */;
+
+#if ACE_DEBUG_CST > 0
+ ACE_DEBUG ((LM_DEBUG, "Synchronized_Suspend_Resume_Test::svc, finishing\n"));
+#endif /* ACE_DEBUG_CST */
+
+ return 0;
+}
+
+ACE_UINT32
+Synchronized_Suspend_Resume_Test::average_context_switch_time ()
+{
+ return high_.average_context_switch_time ();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// function get_options
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static
+u_int
+get_options (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("c:n?"));
+ int opt;
+ while ((opt = get_opt ()) != EOF) {
+ switch (opt) {
+ case 'c':
+ if (ACE_OS::atoi (get_opt.opt_arg ()) >= 0)
+ {
+ count = ACE_OS::atoi (get_opt.opt_arg ());
+ }
+ else
+ {
+ ACE_DEBUG ((LM_ERROR, "%n: count must be >= 0\n"));
+ return 1;
+ }
+ break;
+ case 'n':
+ new_lwp = THR_NEW_LWP;
+ break;
+ case '?':
+ ACE_DEBUG ((LM_ERROR, "usage: %n %s\n", usage));
+ ACE_OS::exit (1);
+ /* NOTREACHED */
+ break;
+ default:
+ ACE_DEBUG ((LM_ERROR, "%n: unknown arg, %c\n", opt));
+ ACE_DEBUG ((LM_ERROR, "usage: %n %s\n", usage));
+ return 1;
+ }
+ }
+
+ switch (argc - get_opt.opt_ind ()) {
+ case 0:
+ // use default number of iterations
+ break;
+ case 1:
+ if (ACE_OS::atoi (argv [get_opt.opt_ind ()]) > 0)
+ num_iterations = ACE_OS::atoi (argv [get_opt.opt_ind ()]);
+ else
+ {
+ ACE_DEBUG ((LM_ERROR, "%n: iterations must be > 0\n"));
+ return 1;
+ }
+ break;
+ default:
+ ACE_DEBUG ((LM_ERROR, "%n: too many arguments\n"));
+ ACE_DEBUG ((LM_ERROR, "usage: %n %s\n", usage));
+ return 1;
+ }
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// function main
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv [])
+{
+ ACE_LOG_MSG->open (argv[0] > 0 ? argv[0] : ACE_TEXT("context_switch_time"));
+
+ if (get_options (argc, argv))
+ ACE_OS::exit (-1);
+
+ // Disable LM_DEBUG.
+ ACE_Log_Msg::instance ()->priority_mask (ACE_LOG_MSG->priority_mask () ^
+ LM_DEBUG);
+
+#if defined (ACE_HAS_PENTIUM) && \
+ !defined (ACE_HAS_HI_RES_TIMER) && !defined (ACE_WIN32)
+ // Just to verify that ACE_High_Res_Timer::global_scale_factor ()
+ // correctly determines the clock speed.
+ ACE_DEBUG ((LM_INFO, "clock speed: %u MHz\n",
+ ACE_High_Res_Timer::global_scale_factor ()));
+#endif /* ACE_HAS_PENTIUM && ! ACE_HAS_HI_RES_TIMER && ! ACE_WIN32 */
+
+ if (ACE_OS::sched_params (
+ ACE_Sched_Params (
+ ACE_SCHED_FIFO,
+ ACE_Sched_Params::priority_min (ACE_SCHED_FIFO),
+ ACE_SCOPE_PROCESS)) != 0)
+ {
+ if (ACE_OS::last_error () == EPERM)
+ {
+ ACE_DEBUG ((LM_MAX, "context_switch_time: user is not superuser, "
+ "so remain in time-sharing class\n"));
+ }
+ else
+ {
+ ACE_OS::perror (ACE_TEXT("context_switch_time"));
+ ACE_OS::exit (-1);
+ }
+ }
+
+ HIGH_PRIORITY = ACE_Sched_Params::next_priority (ACE_SCHED_FIFO,
+ LOW_PRIORITY);
+ ACE_DEBUG ((LM_INFO, "low priority: %d, high priority: %d\n",
+ LOW_PRIORITY, HIGH_PRIORITY));
+
+ // Set the priority of this thread so that it's higher than any of
+ // the test threads. That might help avoid problems when waiting on
+ // those threads, below. It also seems to help the times
+ // significantly on LynxOS.
+ ACE_hthread_t self;
+ ACE_OS::thr_self (self);
+ ACE_OS::thr_setprio (ACE_Sched_Params::next_priority (ACE_SCHED_FIFO,
+ HIGH_PRIORITY));
+
+ int forever = count == 0;
+
+ ACE_Stats context_switch_test_stats;
+ ACE_Stats yield_test_stats;
+ ACE_Stats synchronized_suspend_resume_test_stats;
+
+ int suspend_resume_supported = 0;
+ // Check to see if thr_continue (), and therefore thr_suspend (),
+ // probably, are supported.
+ if (ACE_OS::thr_continue (self) == 0 || errno != ENOTSUP)
+ suspend_resume_supported = 1;
+
+ while (forever || count-- > 0)
+ {
+ if (suspend_resume_supported)
+ {
+ // Run suspend/resume test first . . .
+ Suspend_Resume_Test suspend_resume_test (num_iterations);
+ // Wait for all tasks to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+
+ // Then Ping Suspend/Resume test.
+ Ping_Suspend_Resume_Test ping_suspend_resume_test (num_iterations);
+ // Wait for all tasks to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+
+ if (ping_suspend_resume_test.elapsed_time () >
+ suspend_resume_test.elapsed_time ())
+ {
+ context_switch_test_stats.
+ sample (ACE_U64_TO_U32 (
+ ping_suspend_resume_test.elapsed_time () -
+ suspend_resume_test.elapsed_time ()));
+
+ ACE_DEBUG ((LM_INFO, "context switch time is (%.3f - %.3f)/2 = "
+ "%.3f microseconds\n",
+ (double) ACE_UINT64_DBLCAST_ADAPTER (
+ ping_suspend_resume_test.elapsed_time ()) /
+ num_iterations,
+ (double) ACE_UINT64_DBLCAST_ADAPTER (
+ suspend_resume_test.elapsed_time ()) /
+ num_iterations,
+ (double) ACE_UINT64_DBLCAST_ADAPTER (
+ ping_suspend_resume_test.elapsed_time () -
+ suspend_resume_test.elapsed_time ()) /
+ num_iterations / 2u));
+ }
+ else
+ {
+ ACE_DEBUG ((LM_INFO, "ping suspend/resume time of %u usec was "
+ "less than suspend/resume time of %u\n",
+ ping_suspend_resume_test.elapsed_time () /
+ num_iterations,
+ suspend_resume_test.elapsed_time () /
+ num_iterations));
+ }
+ }
+
+ // Then Yield test.
+ Yield_Test yield_test (num_iterations);
+ // Wait for all tasks to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+
+ yield_test_stats.sample (ACE_U64_TO_U32 (yield_test.elapsed_time ()));
+
+ // Try _really_ hard not to use floating point.
+ ACE_DEBUG ((LM_INFO, "context switch time from yield test is %u.%03u "
+ "microseconds\n",
+ (ACE_UINT32)
+ (yield_test.elapsed_time () / num_iterations / 2u),
+ (ACE_UINT32)
+ (yield_test.elapsed_time () % (num_iterations * 2u)) *
+ 1000u / num_iterations / 2u));
+
+ Synchronized_Suspend_Resume_Test
+ synchronized_suspend_resume_test (num_iterations);
+ // Wait for all tasks to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+
+ synchronized_suspend_resume_test_stats.sample (
+ synchronized_suspend_resume_test.average_context_switch_time ());
+
+ ACE_DEBUG ((LM_INFO, "context switch time from synch susp/resume test "
+ "is %u.%03u microseconds\n",
+ synchronized_suspend_resume_test.
+ average_context_switch_time () / 1000u,
+ synchronized_suspend_resume_test.
+ average_context_switch_time () % 1000u));
+
+ // Give, e.g., Draft 4 Posix platforms a chance to cleanup threads.
+ const ACE_Time_Value half_sec (0L, 500000L);
+ ACE_OS::sleep (half_sec);
+ }
+
+ if (suspend_resume_supported)
+ {
+ ACE_OS::printf ("suspend-resume test: ");
+ context_switch_test_stats.print_summary (3, num_iterations * 2u);
+ }
+
+ ACE_OS::printf ("\nyield_test: ");
+ yield_test_stats.print_summary (3, num_iterations * 2u);
+
+ ACE_OS::printf ("\nsynchronized suspend-resume test: ");
+ synchronized_suspend_resume_test_stats.print_summary (3,
+ 1000u /* nsec/usec */);
+
+ return 0;
+}
+#else
+int
+main (int, char *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
+
+
+// EOF
diff --git a/ACE/performance-tests/Misc/preempt.cpp b/ACE/performance-tests/Misc/preempt.cpp
new file mode 100644
index 00000000000..56a961031e8
--- /dev/null
+++ b/ACE/performance-tests/Misc/preempt.cpp
@@ -0,0 +1,461 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// performance-tests/Misc
+//
+// = FILENAME
+// preempt.cpp
+//
+// = DESCRIPTION
+// This is a simple test to illustrate OS thread preemption. One
+// ore more high priority threads periodically (every half
+// second, by default) reads the clock. They use select () to
+// block for that duration. Meanwhile, a low priority thread
+// continually chews up the CPU. Without preemption, the high
+// priority thread won't have a chance to read the clock in a
+// timely manner.
+//
+// At the end of the test, the actual clock read intervals by the
+// high priority task(s) are printed out. With proper
+// preemption, the intervals should correspond to the requested
+// clock read interval.
+//
+// There is a -y option for the low priority thread to periodically
+// yield. It shouldn't be necessary to use that option, if preemption
+// is supported. It's a handy option for testing.
+//
+// = AUTHOR
+// David L. Levine
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+#include "ace/ACE.h"
+#include "ace/Task.h"
+#include "ace/Sched_Params.h"
+#include "ace/Get_Opt.h"
+#include "ace/OS_NS_sys_select.h"
+#include "ace/OS_NS_time.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_unistd.h"
+
+ACE_RCSID(Misc, preempt, "$Id$")
+
+#if defined (ACE_HAS_THREADS) || ! defined (ACE_LACKS_FORK)
+
+#if defined (ACE_HAS_STHREADS)
+# include <sys/lwp.h> /* for _lwp_self () */
+#endif /* ACE_HAS_STHREADS */
+
+static const char usage [] = "[-? |\n"
+#if defined (ACE_HAS_THREADS)
+ " [-f use fork instead of spawn]\n"
+#endif /* ACE_HAS_THREADS */
+ " [-h <high pri iterations, default 10>]\n"
+ " [-l <low pri iterations, default 25000>]\n"
+ " [-n <high priority threads, default 1>]\n"
+ " [-p <read period, default 500000 usec>]\n"
+ " [-y to yield the low priority thread]]\n";
+
+// Configuration options.
+#if defined (ACE_HAS_THREADS)
+u_int use_fork = 0;
+#else /* ! ACE_HAS_THREADS */
+u_int use_fork = 1;
+#endif /* ! ACE_HAS_THREADS */
+u_int high_iterations = 10;
+u_int high_priority_tasks = 1;
+u_int low_iterations = 25000; /* Big enough to keep the low priority task
+ cranking for a while */
+u_long read_period = 500000; /* usec */
+u_int low_yield = 0;
+
+// To permit calculation of relative times.
+ACE_hrtime_t starttime;
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class High_Priority_Task
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class High_Priority_Task : public ACE_Task<ACE_SYNCH>
+{
+public:
+ High_Priority_Task (void);
+ ~High_Priority_Task (void);
+
+ int open (void *);
+ int svc (void);
+ int done () const { return done_; }
+ void print_times () const;
+
+private:
+ int priority_;
+ int done_;
+ u_long *time_;
+};
+
+High_Priority_Task::High_Priority_Task (void)
+ : ACE_Task<ACE_SYNCH> (ACE_Thread_Manager::instance ()),
+ priority_ (ACE_Sched_Params::next_priority (
+ ACE_SCHED_FIFO,
+ ACE_Sched_Params::priority_min (ACE_SCHED_FIFO,
+ ACE_SCOPE_THREAD),
+ ACE_SCOPE_THREAD)),
+ done_ (0)
+{
+ ACE_NEW (time_, u_long[high_iterations]);
+}
+
+High_Priority_Task::~High_Priority_Task (void)
+{
+ delete [] time_;
+ time_ = 0;
+}
+
+int
+High_Priority_Task::open (void *)
+{
+ if (use_fork == 1)
+ {
+ ACE_hthread_t thr_handle;
+ ACE_Thread::self (thr_handle);
+
+ if (ACE_Thread::setprio (thr_handle, priority_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "setprio failed"), -1);
+
+ return svc ();
+ }
+ else
+ {
+ long flags = THR_BOUND | THR_NEW_LWP | THR_SCHED_FIFO;
+
+ // Become an active object.
+ if (this->activate (flags, 1, 0, this->priority_) == -1)
+ {
+ ACE_DEBUG ((LM_ERROR, "(%P|%t) task activation failed, exiting!\n"));
+ ACE_OS::exit (1);
+ }
+
+ return 0;
+ }
+}
+
+int
+High_Priority_Task::svc (void)
+{
+ ACE_hthread_t thr_handle;
+ ACE_Thread::self (thr_handle);
+ int prio;
+
+ if (ACE_Thread::getprio (thr_handle, prio) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "getprio failed"), -1);
+
+#if defined (ACE_HAS_STHREADS)
+ ACE_DEBUG ((LM_DEBUG, "(%P|%u|%t) High: prio = %d, priority_ = %d\n",
+ _lwp_self (), prio, this->priority_));
+#else /* ! ACE_HAS_STHREADS */
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) High: prio = %d, priority_ = %d\n",
+ prio, this->priority_));
+#endif /* ! ACE_HAS_STHREADS */
+ ACE_ASSERT (this->priority_ == prio);
+
+ ACE_Time_Value pause (0, read_period);
+
+ for (u_int i = 0; i < high_iterations; ++i)
+ {
+ time_ [i] = (u_long) ((ACE_OS::gethrtime () - starttime)/
+ (ACE_UINT32) 1000000u);
+ ACE_OS::select (0, 0, 0, 0, &pause);
+ }
+
+ done_ = 1;
+
+ return 0;
+}
+
+void
+High_Priority_Task::print_times () const
+{
+ for (u_int i = 0; i < high_iterations; ++i)
+ {
+ ACE_DEBUG ((LM_INFO, " iteration %u, time %u msec\n",
+ i, time_ [i]));
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// class Low_Priority_Task
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+class Low_Priority_Task : public ACE_Task<ACE_SYNCH>
+{
+public:
+ Low_Priority_Task (const High_Priority_Task &);
+
+ int open (void *);
+ int svc (void);
+
+private:
+ int priority_;
+ const High_Priority_Task &high_priority_task_;
+};
+
+Low_Priority_Task::Low_Priority_Task (
+ const High_Priority_Task &high_priority_task)
+ : ACE_Task<ACE_SYNCH> (ACE_Thread_Manager::instance ()),
+ priority_ (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO,
+ ACE_SCOPE_THREAD)),
+ high_priority_task_ (high_priority_task)
+{
+}
+
+int
+Low_Priority_Task::open (void *)
+{
+ if (use_fork == 1)
+ {
+ ACE_hthread_t thr_handle;
+ ACE_Thread::self (thr_handle);
+
+ if (ACE_Thread::setprio (thr_handle, priority_) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "setprio failed"), -1);
+
+ return svc ();
+ }
+ else
+ {
+ long flags = THR_BOUND | THR_NEW_LWP | THR_SCHED_FIFO;
+
+ // Become an active object.
+ if (this->activate (flags, 1, 0, this->priority_) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "(%P|%t) task activation failed, exiting!\n%a",
+ -1));
+ return 0;
+ }
+}
+
+int
+Low_Priority_Task::svc (void)
+{
+ ACE_hthread_t thr_handle;
+ ACE_Thread::self (thr_handle);
+ int prio;
+
+ if (ACE_Thread::getprio (thr_handle, prio) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "getprio failed"), -1);
+
+#if defined (ACE_HAS_STHREADS)
+ ACE_DEBUG ((LM_DEBUG, "(%P|%u|%t) Low: prio = %d, priority_ = %d\n",
+ _lwp_self (), prio, this->priority_));
+#else /* ! ACE_HAS_STHREADS */
+ ACE_DEBUG ((LM_DEBUG, "(%P|%t) Low: prio = %d, priority_ = %d\n",
+ prio, this->priority_));
+#endif /* ! ACE_HAS_STHREADS */
+ ACE_ASSERT (this->priority_ == prio);
+
+ u_long iterations = 0;
+
+ // Chew up CPU for the entire interval.
+ for (;
+ ! high_priority_task_.done () && iterations < low_iterations;
+ ++iterations)
+ {
+ u_long n = 1279ul; /* Takes about 40.2 usecs on a 168 MHz Ultra2. */
+ ACE::is_prime (n,
+ 2ul /* min_factor */,
+ n/2 /* max_factor */);
+
+ if (low_yield)
+ ACE_OS::thr_yield ();
+ }
+
+ ACE_DEBUG ((LM_INFO, "Low completed %u iterations\n", iterations));
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// function get_options
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+static int
+get_options (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("fh:l:n:p:y?"));
+ int opt;
+ while ((opt = get_opt ()) != EOF) {
+ switch (opt) {
+ case 'f':
+ use_fork = 1;
+ break;
+ case 'h':
+ if (ACE_OS::atoi (get_opt.opt_arg ()) >= 2)
+ high_iterations = ACE_OS::atoi (get_opt.opt_arg ());
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, "%n: high iterations must be >= 2\n"),
+ -1);
+ break;
+ case 'l':
+ if (ACE_OS::atoi (get_opt.opt_arg ()) >= 2)
+ low_iterations = ACE_OS::atoi (get_opt.opt_arg ());
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, "%n: low iterations must be >= 2\n"), -1);
+ break;
+ case 'n':
+ if (ACE_OS::atoi (get_opt.opt_arg ()) >= 1)
+ high_priority_tasks = ACE_OS::atoi (get_opt.opt_arg ());
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, "%n: number of high priority threads "
+ "must be >= 1\n"), -1);
+ break;
+ case 'p':
+ if (ACE_OS::atoi (get_opt.opt_arg ()) > 0)
+ read_period = ACE_OS::atoi (get_opt.opt_arg ());
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, "%n: read period > 0\n"), -1);
+ break;
+ case 'y':
+ low_yield = 1;
+ break;
+ case '?':
+ ACE_DEBUG ((LM_ERROR, "usage: %n %s\n%a", usage, 0));
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%n: unknown arg, %c\nusage: %n %s\n", opt, usage),
+ -1);
+ }
+ }
+
+ switch (argc - get_opt.opt_ind ()) {
+ case 0:
+ // OK, no non-flag arguments.
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%n: too many arguments\nusage: %n %s\n", usage),
+ -1);
+ }
+
+ return 0;
+}
+
+#endif /* ACE_HAS_THREADS || ! ACE_LACKS_FORK */
+
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+// function main
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_LOG_MSG->open (argv[0] ? argv[0] : ACE_TEXT("preempt"));
+
+#if defined (ACE_HAS_THREADS) || !defined (ACE_LACKS_FORK)
+
+ u_int i;
+
+ if (get_options (argc, argv))
+ ACE_OS::exit (-1);
+
+ // Enable FIFO scheduling, e.g., RT scheduling class on Solaris.
+ if (ACE_OS::sched_params (
+ ACE_Sched_Params (
+ ACE_SCHED_FIFO,
+ ACE_Sched_Params::priority_min (ACE_SCHED_FIFO),
+ ACE_SCOPE_PROCESS)) != 0)
+ {
+ if (ACE_OS::last_error () == EPERM)
+ ACE_DEBUG ((LM_MAX, "preempt: user is not superuser, "
+ "so remain in time-sharing class\n"));
+ else
+ ACE_ERROR_RETURN ((LM_ERROR, "%n: ACE_OS::sched_params failed\n%a"),
+ -1);
+ }
+
+ High_Priority_Task *high_priority_task;
+ ACE_NEW_RETURN (high_priority_task, High_Priority_Task [high_priority_tasks],
+ 1);
+
+ Low_Priority_Task low_priority_task (high_priority_task[0]);
+
+ if (! use_fork)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) main (), wait for threads to exit . . .\n"));
+ }
+
+ // Save the start time, so that deltas can be displayed later.
+ starttime = ACE_OS::gethrtime ();
+
+ // Spawn the threads/processes . . .
+ pid_t child = 0;
+ if (use_fork == 1)
+ {
+ switch ((child = ACE_OS::fork (ACE_TEXT("preempt-low_priority_process"))))
+ {
+ case -1:
+ ACE_ERROR ((LM_ERROR, "%p\n%a", "fork failed"));
+ return -1;
+ case 0: // In child
+ {
+ low_priority_task.open (0);
+ break;
+ }
+ default: // In parent
+ for (i = 0; i < high_priority_tasks; ++i)
+ {
+ high_priority_task[i].open (0);
+ }
+ break;
+ }
+ }
+ else
+ {
+ for (i = 0; i < high_priority_tasks; ++i)
+ {
+ high_priority_task[i].open (0);
+ }
+ low_priority_task.open (0);
+
+#if defined (ACE_HAS_THREADS)
+ // Wait for all threads to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+#endif /* ACE_HAS_THREADS */
+ }
+
+ // Display the time deltas. They should be about a half second apart.
+ if (child || ! use_fork)
+ {
+ for (i = 0; i < high_priority_tasks; ++i)
+ {
+ ACE_DEBUG ((LM_DEBUG, "High priority task %u:\n", i + 1));
+ high_priority_task[i].print_times ();
+ }
+ }
+
+ delete [] high_priority_task;
+
+#else /* ! ACE_HAS_THREADS && ACE_LACKS_FORK */
+ ACE_UNUSED_ARG (argc);
+ ACE_UNUSED_ARG (argv);
+ ACE_ERROR ((LM_ERROR, "threads and fork not supported on this platform\n"));
+#endif /* ! ACE_HAS_THREADS && ACE_LACKS_FORK */
+
+ return 0;
+}
diff --git a/ACE/performance-tests/Misc/test_guard.cpp b/ACE/performance-tests/Misc/test_guard.cpp
new file mode 100644
index 00000000000..507f22bfff7
--- /dev/null
+++ b/ACE/performance-tests/Misc/test_guard.cpp
@@ -0,0 +1,113 @@
+// $Id$
+
+// This test program illustrates the performance of ACE_Guard and
+// ACE_Thread_Mutex_Guard.
+
+#include "ace/Log_Msg.h"
+#include "ace/Get_Opt.h"
+#include "ace/Profile_Timer.h"
+
+#if !defined (ACE_USES_OBSOLETE_GUARD_CLASSES)
+#error You must compile ACE and this program with ACE_USES_OBSOLETE_GUARD_CLASSES defined!
+#endif /* ACE_USES_OBSOLETE_GUARD_CLASSES */
+
+ACE_RCSID(Misc, test_guard, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+# define ACE_THREAD_GUARD(OBJ,LOCK) \
+ ACE_Thread_Mutex_Guard OBJ (LOCK); \
+ if (OBJ.locked () == 0) return;
+
+static const int DEFAULT_ITERATIONS = 100000000;
+
+enum
+{
+ TEST_GUARD,
+ TEST_THR_GUARD,
+ TEST_END
+};
+
+ACE_Thread_Mutex lock_;
+typedef void (*guard_func)(void);
+int test_type = TEST_GUARD;
+int dummy = 0;
+
+void guard (void)
+{
+ ACE_GUARD (ACE_Thread_Mutex, _ace_mon, lock_);
+ dummy++;
+}
+
+void thr_guard (void)
+{
+ ACE_THREAD_GUARD (_ace_mon, lock_);
+ dummy++;
+}
+
+char *test_name[TEST_END] = { "ACE_Guard", "ACE_Thread_Mutex_Guard" };
+
+guard_func test_function=guard;
+
+int
+main (int argc, char *argv[])
+{
+ ACE_Profile_Timer timer;
+ ACE_Get_Opt getopt (argc, argv, "gtn:");
+ int iterations = DEFAULT_ITERATIONS;
+ int c, i;
+
+ while ((c = getopt()) != -1)
+ switch (c)
+ {
+#if defined (ACE_USES_OBSOLETE_GUARD_CLASSES)
+ case 't':
+ test_type = TEST_THR_GUARD;
+ test_function = thr_guard;
+ break;
+#endif /* ACE_USES_OBSOLETE_GUARD_CLASSES */
+ case 'g':
+ test_type = TEST_GUARD;
+ test_function = guard;
+ break;
+ case 'n':
+ iterations = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Invalid option\n"), -1);
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "%s for iterations = %d\n", test_name[test_type], iterations));
+
+ timer.start ();
+
+ // Test the thread mutex (which doesn't use inheritance or dynamic
+ // binding).
+
+ for (i = 0; i < iterations; i++)
+ test_function ();
+
+ timer.stop ();
+
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG, "Thread_Mutex\n"));
+ 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.real_time / double (iterations)) * 1000000));
+
+ return 0;
+}
+#else
+int
+main (int, char *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Misc/test_mutex.cpp b/ACE/performance-tests/Misc/test_mutex.cpp
new file mode 100644
index 00000000000..51c0b07a41c
--- /dev/null
+++ b/ACE/performance-tests/Misc/test_mutex.cpp
@@ -0,0 +1,238 @@
+// $Id$
+
+// This test program illustrates the performance difference between
+// three versions of wrappers for thread mutexes. These three
+// versions exercise various combinations of the following classes:
+//
+// Thread_Mutex --
+// This version is just like ACE_Thread_Mutex, which doesn't use
+// inheritance and dynamic binding.
+//
+// Mutex_Base --
+// This is an abstract base class that defines the
+// acquire()/release() interface.
+//
+// Thread_Mutex_Derived --
+// This derived from Mutex_Base and uses inheritance and
+// dynamic binding.
+//
+// The following are the results I got when running this on our
+// SPARCstation 20 model 712:
+//
+// ./test_mutex 1000000
+// iterations = 1000000
+// Thread_Mutex
+// real time = 1.727843 secs, user time = 1.729262 secs, system time = 0.000325 secs
+// time per call = 1.747843 usecs
+// Thread_Mutex_Derived
+// real time = 1.730225 secs, user time = 1.724744 secs, system time = 0.000096 secs
+// time per call = 1.730225 usecs
+// Mutex_Base
+// real time = 2.112831 secs, user time = 2.104245 secs, system time = 0.000095 secs
+// time per call = 2.112831 usecs
+//
+// My conclusions are as follows:
+//
+// 1. If your C++ compiler optimizes calls to virtual functions that
+// are made through instances of derived classes, then the
+// performance of the Thread_Mutex and Thread_Mutex_Derived are
+// essentially identical.
+//
+// 2. The overhead from using virtual functions is approximately
+// 20%. Naturally, as the amount of contention goes up, the
+// relative overhead of the virtual function calls will decrease.
+//
+// Keep in mind, however, that using virtual functions to implement
+// the Thread_Mutex will make it infeasible to put instances of
+// Thread_Mutex into shared memory since the vptrs won't point to the
+// correct vtables...
+
+#include "ace/Log_Msg.h"
+#include "ace/Profile_Timer.h"
+#include "ace/OS_main.h"
+#include "ace/OS_NS_Thread.h"
+
+ACE_RCSID(Misc, test_mutex, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+static const int DEFAULT_ITERATIONS = 100000000;
+
+// A thread mutex that doesn't use virtual functions.
+class Thread_Mutex
+{
+public:
+ Thread_Mutex (void);
+ ~Thread_Mutex (void);
+ int acquire (void);
+ int release (void);
+
+private:
+ ACE_mutex_t mutex_;
+};
+
+Thread_Mutex::Thread_Mutex (void)
+{
+ ACE_OS::mutex_init (&this->mutex_);
+}
+
+Thread_Mutex::~Thread_Mutex (void)
+{
+ ACE_OS::mutex_destroy (&this->mutex_);
+}
+
+inline int
+Thread_Mutex::acquire (void)
+{
+ return ACE_OS::mutex_lock (&this->mutex_);
+}
+
+inline int
+Thread_Mutex::release (void)
+{
+ return ACE_OS::mutex_unlock (&this->mutex_);
+}
+
+// Base class for mutex, declares pure virtual functions.
+class Mutex_Base
+{
+public:
+ virtual ~Mutex_Base (void);
+ virtual int acquire (void) = 0;
+ virtual int release (void) = 0;
+};
+
+Mutex_Base::~Mutex_Base (void)
+{
+}
+
+// Subclass for threaded mutex, defines virtual functions.
+class Thread_Mutex_Derived : public Mutex_Base
+{
+public:
+ Thread_Mutex_Derived (void);
+ virtual ~Thread_Mutex_Derived (void);
+ virtual int acquire (void);
+ virtual int release (void);
+
+private:
+ ACE_mutex_t mutex_;
+};
+
+Thread_Mutex_Derived::Thread_Mutex_Derived (void)
+{
+ ACE_OS::mutex_init (&this->mutex_);
+}
+
+Thread_Mutex_Derived::~Thread_Mutex_Derived (void)
+{
+ ACE_OS::mutex_destroy (&this->mutex_);
+}
+
+inline int
+Thread_Mutex_Derived::acquire (void)
+{
+ return ACE_OS::mutex_lock (&this->mutex_);
+}
+
+inline int
+Thread_Mutex_Derived::release (void)
+{
+ return ACE_OS::mutex_unlock (&this->mutex_);
+}
+
+static Thread_Mutex thread_mutex;
+static Thread_Mutex_Derived thread_mutex_derived;
+static Mutex_Base *mutex_base = &thread_mutex_derived;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Profile_Timer timer;
+ int iterations = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_ITERATIONS;
+ int i;
+
+ ACE_DEBUG ((LM_DEBUG, "iterations = %d\n", iterations));
+
+ timer.start ();
+
+ // Test the thread mutex (which doesn't use inheritance or dynamic
+ // binding).
+
+ for (i = 0; i < iterations; i++)
+ {
+ thread_mutex.acquire ();
+ thread_mutex.release ();
+ }
+
+ timer.stop ();
+
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG, "Thread_Mutex\n"));
+ 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.real_time / double (iterations)) * 1000000));
+
+ // Test the thread mutex derived (which does use inheritance or
+ // dynamic binding). Note that we call this via an instance of the
+ // derived class, so good C++ compilers should optimize the virtual
+ // function calls in this case.
+
+ timer.start ();
+
+ for (i = 0; i < iterations; i++)
+ {
+ thread_mutex_derived.acquire ();
+ thread_mutex_derived.release ();
+ }
+
+ timer.stop ();
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG, "Thread_Mutex_Derived\n"));
+ 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.real_time / double (iterations)) * 1000000));
+
+ // Test the thread mutex derived (which does use inheritance or
+ // dynamic binding). Note that we call this via a pointer to the
+ // base class, which points to an instance of the derived class.
+ // Thus, C++ compilers won't be able to optimize the virtual
+ // function calls in this case.
+
+ timer.start ();
+
+ for (i = 0; i < iterations; i++)
+ {
+ mutex_base->acquire ();
+ mutex_base->release ();
+ }
+
+ timer.stop ();
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG, "Mutex_Base\n"));
+ 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.real_time / double (iterations)) * 1000000));
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Misc/test_naming.cpp b/ACE/performance-tests/Misc/test_naming.cpp
new file mode 100644
index 00000000000..f152053a16e
--- /dev/null
+++ b/ACE/performance-tests/Misc/test_naming.cpp
@@ -0,0 +1,193 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// performance_tests
+//
+// = FILENAME
+// test_naming.cpp
+//
+// = DESCRIPTION
+// This is an example to do performance testing of the Naming Service
+// using both the normal Memory Pool as well as the light Memory Pool.
+//
+// = AUTHOR
+// Prashant Jain
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+#include "ace/ACE.h"
+#include "ace/SString.h"
+#include "ace/Naming_Context.h"
+#include "ace/Profile_Timer.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+
+ACE_RCSID(Misc, test_naming, "$Id$")
+
+
+#define ACE_NS_MAX_ENTRIES 4000
+
+static char name[BUFSIZ];
+static char value[BUFSIZ];
+static char type[BUFSIZ];
+
+void
+bind (ACE_Naming_Context *ns_context, int result)
+{
+ // do the binds
+ for (int i = 1; i <= ACE_NS_MAX_ENTRIES; i++)
+ {
+ if (i % 50 == 0)
+ ACE_DEBUG ((LM_DEBUG, "."));
+ ACE_OS::sprintf (name, "%s%d", "name", i);
+ ACE_NS_WString w_name (name);
+
+ ACE_OS::sprintf (value, "%s%d", "value", i);
+ ACE_NS_WString w_value (value);
+
+ ACE_OS::sprintf (type, "%s%d", "type", i);
+ if (ns_context->bind (w_name, w_value, type) != result) {
+ ACE_ERROR ((LM_ERROR, "bind failed!"));
+ }
+ }
+ ACE_DEBUG ((LM_DEBUG, "\n"));
+}
+
+void
+rebind (ACE_Naming_Context *ns_context, int result)
+{
+ // do the rebinds
+ for (int i = 1; i <= ACE_NS_MAX_ENTRIES; i++)
+ {
+ ACE_OS::sprintf (name, "%s%d", "name", i);
+ ACE_NS_WString w_name (name);
+ ACE_OS::sprintf (value, "%s%d", "value", -i);
+ ACE_NS_WString w_value (value);
+ ACE_OS::sprintf (type, "%s%d", "type", -i);
+ if (ns_context->rebind (w_name, w_value, type) != result) {
+ ACE_ERROR ((LM_ERROR, "rebind failed!"));
+ }
+ }
+}
+
+void
+unbind (ACE_Naming_Context *ns_context, int result)
+{
+ // do the unbinds
+ for (int i = 1; i <= ACE_NS_MAX_ENTRIES; i++)
+ {
+ ACE_OS::sprintf (name, "%s%d", "name", i);
+ ACE_NS_WString w_name (name);
+ if (ns_context->unbind (w_name) != result) {
+ ACE_ERROR ((LM_ERROR, "unbind failed!"));
+ }
+ }
+}
+
+void
+find (ACE_Naming_Context *ns_context, int sign, int result)
+{
+ char temp_val[BUFSIZ];
+ char temp_type[BUFSIZ];
+
+ // do the finds
+ for (int i = 1; i <= ACE_NS_MAX_ENTRIES; i++)
+ {
+ ACE_OS::sprintf (name, "%s%d", "name", i);
+ ACE_NS_WString w_name (name);
+
+ ACE_NS_WString w_value;
+ char *type_out;
+
+ if (sign == 1)
+ {
+ ACE_OS::sprintf (temp_val, "%s%d", "value", i);
+ ACE_OS::sprintf (temp_type, "%s%d", "type", i);
+ }
+ else
+ {
+ ACE_OS::sprintf (temp_val, "%s%d", "value", -i);
+ ACE_OS::sprintf (temp_type, "%s%d", "type", -i);
+ }
+
+ ACE_NS_WString val (temp_val);
+
+ int resolve_result = ns_context->resolve (w_name, w_value, type_out);
+ if (resolve_result != result) {
+ ACE_ERROR ((LM_ERROR, "resolved failed!"));
+ }
+ ACE_ASSERT (resolve_result == result);
+ ACE_UNUSED_ARG (resolve_result); // To avoid compile warning
+ // with ACE_NDEBUG.
+
+ if (w_value.char_rep ())
+ {
+ ACE_DEBUG ((LM_DEBUG, "Name: %s\tValue: %s\tType: %s\n",
+ name, w_value.char_rep (), type_out));
+ ACE_ASSERT (w_value == val);
+ if (type_out)
+ {
+ ACE_ASSERT (::strcmp (type_out, temp_type) == 0);
+ delete[] type_out;
+ }
+ }
+ }
+}
+
+void do_testing (int argc, ACE_TCHAR *argv[], int light)
+{
+ ACE_Profile_Timer timer;
+
+ ACE_Naming_Context ns_context;
+ ACE_Name_Options *name_options = ns_context.name_options ();
+ name_options->parse_args (argc, argv);
+
+ if (light == 0) // Use SYNC
+ {
+ name_options->database (ACE::basename (name_options->process_name (),
+ ACE_DIRECTORY_SEPARATOR_CHAR));
+ ns_context.open (ACE_Naming_Context::PROC_LOCAL);
+ }
+ else // Use NO-SYNC
+ {
+ const ACE_TCHAR *p = ACE::basename (name_options->process_name (),
+ ACE_DIRECTORY_SEPARATOR_CHAR);
+ ACE_TCHAR s[5 /* strlen ("light") */ + MAXNAMELEN + 1];
+ ACE_OS::sprintf (s, ACE_TEXT("light%s"), p);
+ name_options->database (s);
+ ns_context.open (ACE_Naming_Context::PROC_LOCAL, 1);
+ }
+
+ // Add bindings to the database
+ ACE_DEBUG ((LM_DEBUG, "Binding\n"));
+
+ timer.start ();
+ bind (&ns_context, 0);
+
+ ACE_DEBUG ((LM_DEBUG, "Unbinding\n"));
+ unbind (&ns_context, 0);
+ timer.stop ();
+
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+
+ timer.elapsed_time (et);
+ 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));
+}
+
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ // Do testing with SYNC on
+ ACE_DEBUG ((LM_DEBUG, "SYNC is ON\n"));
+ do_testing (argc, argv, 0);
+
+ // Do testing with SYNC off
+ ACE_DEBUG ((LM_DEBUG, "SYNC is OFF\n"));
+ do_testing (argc, argv, 1);
+ return 0;
+}
diff --git a/ACE/performance-tests/Misc/test_singleton.cpp b/ACE/performance-tests/Misc/test_singleton.cpp
new file mode 100644
index 00000000000..68d01388766
--- /dev/null
+++ b/ACE/performance-tests/Misc/test_singleton.cpp
@@ -0,0 +1,179 @@
+// $Id$
+
+// This example illustrates the performance impact of using the
+// Double-Checked Locking pattern compared with using the "standard"
+// practice of acquiring and releasing a lock on every instance()
+// call. In addition, we compare the performance of using the
+// ACE_Singleton (which encapsulates the Double-Check Locking pattern)
+// vs. hand-coding the pattern.
+//
+// Here's the output from running this test on our SPARCstation 20, model 712s.
+//
+// ./test_singleton 1000000
+// iterations = 1000000
+// ACE_Singleton
+// real time = 0.193731 secs, user time = 0.190416 secs, system time = 0.000549 secs
+// time per call = 0.193731 usecs
+// DC_Singleton
+// real time = 0.176208 secs, user time = 0.176045 secs, system time = 0.000092 secs
+// time per call = 0.176208 usecs
+// Mutex_Singleton
+// real time = 3.160998 secs, user time = 3.121434 secs, system time = 0.000109 secs
+// time per call = 3.160998 usecs
+//
+// As you can see, both Double-Checked Locking implementations are about
+// 15 times faster than the standard mutex version. Moreover,
+// this test is run with only a single thread, so there's no contention
+// for the lock. If there were multiple threads contending for the lock,
+// the Mutex_Singleton performance would get increasing worse...
+
+#include "ace/OS_main.h"
+#include "ace/Guard_T.h"
+#include "ace/Profile_Timer.h"
+#include "ace/Singleton.h"
+#include "ace/Synch_Traits.h"
+#include "ace/Log_Msg.h"
+
+#include "test_singleton.h"
+
+ACE_RCSID(Misc, test_singleton, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+static const int DEFAULT_ITERATIONS = 100000000;
+
+class Mutex_Singleton
+{
+public:
+ Mutex_Singleton (void) {}
+ void svc (void) {}
+ static Mutex_Singleton *instance (void);
+
+private:
+ static ACE_SYNCH_MUTEX lock_;
+ static Mutex_Singleton *instance_;
+};
+
+ACE_SYNCH_MUTEX Mutex_Singleton::lock_;
+
+Mutex_Singleton *Mutex_Singleton::instance_;
+
+Mutex_Singleton *
+Mutex_Singleton::instance (void)
+{
+ // Acquire the lock every time in.
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, Mutex_Singleton::lock_, 0);
+
+ if (Mutex_Singleton::instance_ == 0)
+ ACE_NEW_RETURN (Mutex_Singleton::instance_, Mutex_Singleton, 0);
+
+ return Mutex_Singleton::instance_;
+}
+
+ACE_SYNCH_MUTEX DC_Singleton::lock_;
+
+DC_Singleton *DC_Singleton::instance_;
+
+DC_Singleton *
+DC_Singleton::instance (void)
+{
+ if (DC_Singleton::instance_ == 0)
+ {
+ // Only lock if instance_ isn't 0.
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, DC_Singleton::lock_, 0);
+
+ // Perform the Double-Check.
+ if (DC_Singleton::instance_ == 0)
+ ACE_NEW_RETURN (DC_Singleton::instance_, DC_Singleton, 0);
+ }
+
+ return DC_Singleton::instance_;
+}
+
+typedef ACE_Singleton <DC_Singleton, ACE_SYNCH_MUTEX> My_Singleton;
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Profile_Timer timer;
+ int iterations = argc > 1 ? ACE_OS::atoi (argv[1]) : DEFAULT_ITERATIONS;
+ int i;
+
+ ACE_DEBUG ((LM_DEBUG, "iterations = %d\n", iterations));
+
+ // Test the ACE_Singleton performance (which uses Double-Checked
+ // Locking).
+
+ timer.start ();
+
+ for (i = 0; i < iterations; i++)
+ My_Singleton::instance ()->svc ();
+
+ timer.stop ();
+
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG, "ACE_Singleton\n"));
+ 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.real_time / double (iterations)) * 1000000));
+
+ // Test the hand-coded Singleton performance (which uses
+ // Double-Checked Locking).
+
+ timer.start ();
+
+ for (i = 0; i < iterations; i++)
+ DC_Singleton::instance ()->svc ();
+
+ timer.stop ();
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG, "DC_Singleton\n"));
+ 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.real_time / double (iterations)) * 1000000));
+
+ // Test the Mutex_Singleton implementation (which does not use
+ // Double-Checked Locking).
+
+ timer.start ();
+
+ for (i = 0; i < iterations; i++)
+ Mutex_Singleton::instance ()->svc ();
+
+ timer.stop ();
+
+ timer.elapsed_time (et);
+
+ ACE_DEBUG ((LM_DEBUG, "Mutex_Singleton\n"));
+ 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.real_time / double (iterations)) * 1000000));
+
+ return 0;
+}
+
+#if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
+template ACE_Singleton<DC_Singleton, ACE_SYNCH_MUTEX> *
+ ACE_Singleton<DC_Singleton, ACE_SYNCH_MUTEX>::singleton_;
+#endif /* ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION */
+
+
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR ((LM_ERROR, "threads not supported on this platform\n"));
+ return 0;
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Misc/test_singleton.h b/ACE/performance-tests/Misc/test_singleton.h
new file mode 100644
index 00000000000..70aef65d89b
--- /dev/null
+++ b/ACE/performance-tests/Misc/test_singleton.h
@@ -0,0 +1,24 @@
+// $Id$
+
+// Define the DC_Singleton here - it needs to be in a separate file to
+// get picked up correctly on AIX with auto template instantiation using
+// IBM C++ compiler (xlC).
+
+#ifndef __TEST_SINGLETON_H
+#define __TEST_SINGLETON_H
+
+#include "ace/Synch_Traits.h"
+
+class DC_Singleton
+{
+public:
+ DC_Singleton (void) {}
+ void svc (void) {}
+ static DC_Singleton *instance (void);
+
+private:
+ static ACE_SYNCH_MUTEX lock_;
+ static DC_Singleton *instance_;
+};
+
+#endif /* __TEST_SINGLETON_H */
diff --git a/ACE/performance-tests/README b/ACE/performance-tests/README
new file mode 100644
index 00000000000..36751c061fe
--- /dev/null
+++ b/ACE/performance-tests/README
@@ -0,0 +1,16 @@
+The subdirectories in this directory provide a number of benchmarks
+that use ACE features to determine performance of various concurrency
+and communication mechanisms.
+
+ . Synch-Benchmarks -- Implements a number of benchmarks
+ that test the performance of various synchronization
+ mechanisms.
+
+ . TTCP -- Implements several variants of the TTCP benchmarking
+ test for TCP and UCP using C sockets and ACE C++ wrappers.
+
+ . UDP -- Contains UDP test, which measures UDP round-trip
+ performance.
+
+ . Misc -- Miscellaneous tests, e.g., Double-Checked Locking,
+ context switching, mutexes, naming, etc.
diff --git a/ACE/performance-tests/RPC/README b/ACE/performance-tests/RPC/README
new file mode 100644
index 00000000000..49b9131733e
--- /dev/null
+++ b/ACE/performance-tests/RPC/README
@@ -0,0 +1,6 @@
+# $Id$
+
+ Measure latency over RPC, run as:
+
+$ server
+$ client -n <samples> -k host
diff --git a/ACE/performance-tests/RPC/RPC.mpc b/ACE/performance-tests/RPC/RPC.mpc
new file mode 100644
index 00000000000..feccec74ce5
--- /dev/null
+++ b/ACE/performance-tests/RPC/RPC.mpc
@@ -0,0 +1,17 @@
+// -*- MPC -*-
+// $Id$
+
+project(*client) : aceexe, rpc {
+ source_files {
+ client.cpp
+ ping_clnt.c
+ }
+}
+
+project(*server) : aceexe, rpc {
+ exename = server
+ source_files {
+ server.c
+ ping_svc.c
+ }
+} \ No newline at end of file
diff --git a/ACE/performance-tests/RPC/client.cpp b/ACE/performance-tests/RPC/client.cpp
new file mode 100644
index 00000000000..b0f4a476600
--- /dev/null
+++ b/ACE/performance-tests/RPC/client.cpp
@@ -0,0 +1,72 @@
+/*
+ * $Id$
+ */
+#include "ace/Stats.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Get_Opt.h"
+
+#include "ping.h"
+
+int main (int argc, char* argv[])
+{
+ const char* host = 0;
+ int nsamples = 10000;
+ int c;
+
+ ACE_Get_Opt getopt (argc, argv, "h:i:");
+
+ while ((c = getopt ()) != -1)
+ {
+ switch ((char) c)
+ {
+ case 'h':
+ host = getopt.opt_arg ();
+ break;
+
+ case 'i':
+ nsamples = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ }
+ }
+
+ if (host == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "Usage: client -h host -i iterations\n"));
+ return 1;
+ }
+
+ CLIENT *cl =
+ clnt_create (host, PINGPROG, PINGVERS, "tcp");
+
+ if (cl == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "Cannot create client handle\n"));
+ return 1;
+ }
+
+ ACE_Throughput_Stats throughput;
+
+ ACE_hrtime_t test_start = ACE_OS::gethrtime ();
+ for (int i = 0; i != nsamples; ++i)
+ {
+ ACE_hrtime_t start = ACE_OS::gethrtime ();
+
+ int p = 0;
+ (void) ping_1 (&p, cl);
+
+ ACE_hrtime_t end = ACE_OS::gethrtime ();
+
+ throughput.sample (end - test_start,
+ end - start);
+
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "Calibrating high resolution timer . . ."));
+ ACE_UINT32 gsf = ACE_High_Res_Timer::global_scale_factor ();
+ ACE_DEBUG ((LM_DEBUG, " done\n"));
+
+ throughput.dump_results ("Client", gsf);
+
+
+ return 0;
+}
diff --git a/ACE/performance-tests/RPC/ping.x b/ACE/performance-tests/RPC/ping.x
new file mode 100644
index 00000000000..ea078ffe139
--- /dev/null
+++ b/ACE/performance-tests/RPC/ping.x
@@ -0,0 +1,12 @@
+/*
+ * $Id$
+ */
+
+/*
+ * A small program to test RPC round-trip delays.
+ */
+program PINGPROG {
+ version PINGVERS {
+ int PING (int) = 1;
+ } = 1;
+} = 0x20000001;
diff --git a/ACE/performance-tests/RPC/run_test.pl b/ACE/performance-tests/RPC/run_test.pl
new file mode 100755
index 00000000000..305509dc83a
--- /dev/null
+++ b/ACE/performance-tests/RPC/run_test.pl
@@ -0,0 +1,34 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib '../../bin';
+use PerlACE::Run_Test;
+
+$SV = new PerlACE::Process ("server");
+$CL = new PerlACE::Process ("client", "-i 10000 -h localhost");
+
+$status = 0;
+
+$SV->Spawn ();
+
+sleep 5;
+
+$client = $CL->SpawnWaitKill (60);
+
+$server = $SV->WaitKill (5);
+
+if ($server != 0) {
+ print "ERROR: server returned $server\n";
+ $status = 1;
+}
+
+if ($client != 0) {
+ print "ERROR: client returned $client\n";
+ $status = 1;
+}
+
+exit $status;
diff --git a/ACE/performance-tests/RPC/server.c b/ACE/performance-tests/RPC/server.c
new file mode 100644
index 00000000000..2f8526a6733
--- /dev/null
+++ b/ACE/performance-tests/RPC/server.c
@@ -0,0 +1,15 @@
+/*
+ * $Id$
+ */
+
+#include "ping.h"
+#include <rpc/rpc.h>
+#include <stdio.h>
+
+static int return_value = 0;
+
+int* ping_1_svc (int* value, struct svc_req* r)
+{
+ return_value = *value;
+ return &return_value;
+}
diff --git a/ACE/performance-tests/SCTP/Makefile.am b/ACE/performance-tests/SCTP/Makefile.am
new file mode 100644
index 00000000000..8532440e3f6
--- /dev/null
+++ b/ACE/performance-tests/SCTP/Makefile.am
@@ -0,0 +1,117 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.SCTP_SOCK_SEQPACK_Association_Test.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += SOCK_SEQPACK_Association_Test
+
+SOCK_SEQPACK_Association_Test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+SOCK_SEQPACK_Association_Test_SOURCES = \
+ SOCK_SEQPACK_Association_Test.cpp \
+ Options_Manager.h \
+ hist.h
+
+SOCK_SEQPACK_Association_Test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.SCTP_SOCK_SEQPACK_Clt.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += SOCK_SEQPACK_clt
+
+SOCK_SEQPACK_clt_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+SOCK_SEQPACK_clt_SOURCES = \
+ Options_Manager.cpp \
+ SOCK_SEQPACK_clt.cpp \
+ hist.cpp \
+ Options_Manager.h \
+ hist.h
+
+SOCK_SEQPACK_clt_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.SCTP_SOCK_SEQPACK_Srv.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += SOCK_SEQPACK_srv
+
+SOCK_SEQPACK_srv_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+SOCK_SEQPACK_srv_SOURCES = \
+ Options_Manager.cpp \
+ SOCK_SEQPACK_srv.cpp \
+ Options_Manager.h
+
+SOCK_SEQPACK_srv_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.SCTP_SOCK_STREAM_Clt.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += SOCK_STREAM_clt
+
+SOCK_STREAM_clt_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+SOCK_STREAM_clt_SOURCES = \
+ Options_Manager.cpp \
+ SOCK_STREAM_clt.cpp \
+ hist.cpp \
+ Options_Manager.h \
+ hist.h
+
+SOCK_STREAM_clt_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.SCTP_SOCK_STREAM_Srv.am
+noinst_PROGRAMS += SOCK_STREAM_srv
+
+SOCK_STREAM_srv_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+SOCK_STREAM_srv_SOURCES = \
+ Options_Manager.cpp \
+ SOCK_STREAM_srv.cpp \
+ Options_Manager.h
+
+SOCK_STREAM_srv_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/performance-tests/SCTP/Options_Manager.cpp b/ACE/performance-tests/SCTP/Options_Manager.cpp
new file mode 100644
index 00000000000..6d28a393fdf
--- /dev/null
+++ b/ACE/performance-tests/SCTP/Options_Manager.cpp
@@ -0,0 +1,542 @@
+// -*- C++ -*-
+// $Id$
+
+#include "ace/Get_Opt.h"
+#include "ace/os_include/netinet/os_in.h"
+#include "ace/os_include/sys/os_types.h"
+#include "ace/OS_NS_stdlib.h"
+#include "ace/OS_NS_string.h"
+
+// make sure that the code compiles cleanly even if SCTP is not
+// available. If SCTP is not installed, program will exit early in
+// main() with an error message.
+#ifdef ACE_HAS_SCTP
+extern "C" {
+#include <netinet/sctp.h>
+};
+#else
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132 /* always the same value on every platform */
+#endif
+#endif
+
+#include "Options_Manager.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_arpa_inet.h"
+
+// Set default values
+ACE_CDR::ULong Options_Manager::test_iterations=1000000;
+ACE_CDR::Boolean Options_Manager::test_enable_nagle=0;
+ACE_CDR::Long Options_Manager::test_transport_protocol=IPPROTO_SCTP;
+ACE_CDR::Double Options_Manager::histogram_min_bin=0.0;
+ACE_CDR::Double Options_Manager::histogram_max_bin=10000.0;
+ACE_CDR::ULong Options_Manager::histogram_num_outliers=100;
+ACE_CDR::ULong Options_Manager::histogram_bin_count=1000;
+ACE_CDR::UShort Options_Manager::client_port = 0;
+ACE_CDR::ULong Options_Manager::client_connect_addr=INADDR_ANY;
+ACE_CDR::UShort Options_Manager::server_port = 45453;
+ACE_TCHAR Options_Manager::server_host[Options_Manager::string_len];
+ACE_CDR::ULong Options_Manager::server_accept_addr=INADDR_ANY;
+ACE_CDR::UShort Options_Manager::payload_size_power_of_2=31;
+ACE_CDR::ULong Options_Manager::secondary_connect_addrs[max_num_secondary_connect_addrs];
+ACE_CDR::UShort Options_Manager::num_secondary_connect_addrs = 0;
+ACE_CDR::ULong Options_Manager::secondary_accept_addrs[max_num_secondary_accept_addrs];
+ACE_CDR::UShort Options_Manager::num_secondary_accept_addrs = 0;
+ACE_CDR::UShort Options_Manager::_usage = 0;
+ACE_CDR::UShort Options_Manager::_error = 0;
+ACE_TCHAR Options_Manager::__program_name[Options_Manager::string_len];
+ACE_CDR::Boolean Options_Manager::__initialized=0;
+const ACE_TCHAR* Options_Manager::_error_message;
+
+
+Options_Manager::Options_Manager(int argc, ACE_TCHAR **argv, ACE_TCHAR const * const opts_set)
+{
+ if (!__initialized) {
+ // Set default values that were not set during static initialization
+ ACE_OS::strcpy(server_host, ACE_LOCALHOST);
+
+ // Remember argv[0]
+ if (ACE_OS::strlen(argv[0]) < Options_Manager::string_len)
+ ACE_OS::strcpy(__program_name, argv[0]);
+ else{
+ ACE_OS::strncpy(__program_name, argv[0], (Options_Manager::string_len-1));
+ __program_name[Options_Manager::string_len - 1] = '\0';
+ }
+
+ // Declare options with ACE_Get_Opt
+ int c;
+ ACE_Get_Opt * get_opt = 0;
+ if (!ACE_OS::strcmp(ACE_TEXT ("client-opts"), opts_set)){
+ get_opt = new ACE_Get_Opt(argc, argv, ACE_TEXT("c:nt:m:M:x:b:C:i:p:H:s:h"));
+
+ get_opt->long_option (ACE_TEXT ("test_iterations"), 'c',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("test_enable_nagle"), 'n');
+ get_opt->long_option (ACE_TEXT ("test_transport_protocol"), 't',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("histogram_min_bin"), 'm',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("histogram_max_bin"), 'M',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("histogram_num_outliers"), 'x',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("histogram_bin_count"), 'b',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("client_port"), 'C',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("client_accept_addr"), 'i',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("server_port"), 'p',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("server_host"), 'H',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("payload_size_power_of_2"), 's',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("help"), 'h');
+ } else if (!ACE_OS::strcmp (ACE_TEXT ("server-opts"), opts_set)){
+ get_opt = new ACE_Get_Opt(argc, argv, ACE_TEXT("nt:p:a:u"));
+ get_opt->long_option (ACE_TEXT ("test_enable_nagle"), 'n');
+ get_opt->long_option (ACE_TEXT ("test_transport_protocol"), 't',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("server_port"), 'p',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("server_accept_addr"), 'a',
+ ACE_Get_Opt::ARG_REQUIRED);
+ get_opt->long_option (ACE_TEXT ("help"), 'h');
+ } else {
+ _error = 1;
+ _error_message = ACE_TEXT ("invalid options set specified");
+ delete get_opt;
+ return;
+ }
+
+ // Parse options with ACE_Get_Opt
+ while ((c = (*get_opt)()) != -1)
+ {
+ switch ((char) c)
+ {
+ case 'c':
+ test_iterations = ACE_OS::atoi(get_opt->opt_arg ());
+ break;
+ case 'n':
+ test_enable_nagle = 1;
+ break;
+ case 't':{
+ ACE_TCHAR const * const str = get_opt->opt_arg ();
+ if (!ACE_OS::strcmp (str, ACE_TEXT ("tcp")))
+ test_transport_protocol = IPPROTO_TCP;
+ else if (!ACE_OS::strcmp (str, ACE_TEXT ("sctp")))
+ test_transport_protocol = IPPROTO_SCTP;
+ else
+ test_transport_protocol = -1;
+ break;
+ }
+ case 'm':
+ histogram_min_bin = ACE_OS::strtod(get_opt->opt_arg (), 0);
+ break;
+ case 'M':
+ histogram_max_bin = ACE_OS::strtod(get_opt->opt_arg (), 0);
+ break;
+ case 'x':
+ histogram_num_outliers = ACE_OS::atoi(get_opt->opt_arg ());
+ break;
+ case 'b':
+ histogram_bin_count = ACE_OS::atoi(get_opt->opt_arg ());
+ break;
+ case 'C':
+ client_port = ACE_OS::atoi(get_opt->opt_arg ());
+ break;
+ case 'i':{
+
+ // The argument to this option is a comma-separated list
+ // of dotted-decimal ipv4 addresses.
+
+ // Create a writable copy of the options argument
+ ACE_TCHAR str[Options_Manager::string_len];
+ ACE_OS::strncpy(str, get_opt->opt_arg(), Options_Manager::string_len);
+
+ // Get a pointer to the first comma in the list
+ ACE_TCHAR *next_secondary_addr = ACE_OS::strchr(str, ',');
+
+ // If found, the comma is replaced with \0 and pointer
+ // updated to point to the string that begins immediately
+ // after the comma.
+ if (next_secondary_addr) {
+ *next_secondary_addr = '\0';
+ ++next_secondary_addr;
+ }
+
+ // Obtain the 32-bit, host-byte-order representation of
+ // the primary address.
+ struct in_addr foo;
+ int aton_retval = ACE_OS::inet_aton(ACE_TEXT_ALWAYS_CHAR (str),
+ &foo);
+
+ // If this representation was not obtained, terminate with
+ // an error.
+ if (!aton_retval) {
+
+ ACE_TCHAR error_message[Options_Manager::string_len + 100];
+ ACE_OS::strcpy
+ (error_message,
+ ACE_TEXT ("Could not make sense of primary address: "));
+ ACE_OS::strcat (error_message, str);
+
+ _error = 1;
+ _error_message = ACE_OS::strdup(error_message);
+ break;
+ }
+
+ // Otherwise, store the representation in the
+ // client_connect_addr member variable.
+ client_connect_addr = ntohl(foo.s_addr);
+
+// ACE_DEBUG ((LM_DEBUG,
+// "Primary connect addr: %s retval = %d\n",
+// str,
+// aton_retval));
+
+// if (next_secondary_addr) {
+// ACE_DEBUG ((LM_DEBUG,
+// "Secondary addr(s) remaining to be parsed: %s\n",
+// next_secondary_addr));
+// } else {
+// ACE_DEBUG ((LM_DEBUG,
+// "No secondary addr remaining to be parsed.\n"));
+// }
+
+ // The following loop parses secondary addresses from the
+ // list. The loop repeats as long as ACE_OS::strchr
+ // returns non-null (i.e., as long as yet another comma is
+ // found.
+ while (next_secondary_addr &&
+ num_secondary_connect_addrs <
+ max_num_secondary_connect_addrs) {
+
+ // Get a pointer to the next comma in the list.
+ ACE_TCHAR *next_next_secondary_addr = ACE_OS::strchr(next_secondary_addr, ',');
+
+ // If found, the comma is replaced with \0 and pointer
+ // updated to point to the string that begins immediately
+ // after the comma.
+ if (next_next_secondary_addr) {
+ *next_next_secondary_addr = '\0';
+ ++next_next_secondary_addr;
+ }
+
+ // Obtain the 32-bit, host-byte-order representation of
+ // a secondary address.
+ aton_retval =
+ ACE_OS::inet_aton(ACE_TEXT_ALWAYS_CHAR (next_secondary_addr),
+ &foo);
+
+ // If the representation was obtained without error,
+ // store it in the next available slot of the
+ // secondary_connect_addrs array. Otherwise, terminate
+ // with an error.
+ if (aton_retval) {
+ secondary_connect_addrs[num_secondary_connect_addrs++] =
+ ntohl(foo.s_addr);
+ } else {
+
+ ACE_TCHAR error_message[Options_Manager::string_len + 100];
+ ACE_OS::strcpy
+ (error_message,
+ ACE_TEXT ("Could not make sense of secondary address: "));
+ ACE_OS::strcat (error_message, next_secondary_addr);
+ _error = 1;
+ _error_message = ACE_OS::strdup(error_message);
+ break;
+ }
+
+// ACE_DEBUG ((LM_DEBUG,
+// "secondary_addr[%d] = %s retval = %d\n",
+// num_secondary_connect_addrs - 1,
+// next_secondary_addr,
+// aton_retval));
+
+ next_secondary_addr = next_next_secondary_addr;
+ }
+
+ break;
+ }
+ case 'p':
+ server_port = ACE_OS::atoi(get_opt->opt_arg ());
+ break;
+ case 'a':{
+
+ // The argument to this option is a comma-separated list
+ // of dotted-decimal ipv4 addresses.
+
+ // Create a writable copy of the options argument
+ ACE_TCHAR str[Options_Manager::string_len];
+ ACE_OS::strncpy(str, get_opt->opt_arg(), Options_Manager::string_len);
+
+ // Get a pointer to the first comma in the list
+ ACE_TCHAR *next_secondary_addr = ACE_OS::strchr(str, ',');
+
+ // If found, the comma is replaced with \0 and pointer
+ // updated to point to the string that begins immediately
+ // after the comma.
+ if (next_secondary_addr) {
+ *next_secondary_addr = '\0';
+ ++next_secondary_addr;
+ }
+
+ // Obtain the 32-bit, host-byte-order representation of
+ // the primary address.
+ struct in_addr foo;
+ int aton_retval = ACE_OS::inet_aton (ACE_TEXT_ALWAYS_CHAR (str),
+ &foo);
+
+ // If this representation was not obtained, terminate with
+ // an error.
+ if (!aton_retval) {
+
+ ACE_TCHAR error_message[Options_Manager::string_len + 100];
+ ACE_OS::strcpy
+ (error_message,
+ ACE_TEXT ("Could not make sense of primary address: "));
+ ACE_OS::strcat (error_message, str);
+
+ _error = 1;
+ _error_message = ACE_OS::strdup(error_message);
+ break;
+ }
+
+ // Otherwise, store the representation in the
+ // server_accept_addr member variable.
+ server_accept_addr = ntohl(foo.s_addr);
+
+// ACE_DEBUG ((LM_DEBUG,
+// "Primary accept addr: %s retval = %d\n",
+// str,
+// aton_retval));
+
+// if (next_secondary_addr) {
+// ACE_DEBUG ((LM_DEBUG,
+// "Secondary addr(s) remaining to be parsed: %s\n",
+// next_secondary_addr));
+// } else {
+// ACE_DEBUG ((LM_DEBUG,
+// "No secondary addr remaining to be parsed.\n"));
+// }
+
+ // The following loop parses secondary addresses from the
+ // list. The loop repeats as long as ACE_OS::strchr
+ // returns non-null (i.e., as long as yet another comma is
+ // found.
+ while (next_secondary_addr &&
+ num_secondary_accept_addrs <
+ max_num_secondary_accept_addrs) {
+
+ // Get a pointer to the next comma in the list.
+ ACE_TCHAR *next_next_secondary_addr = ACE_OS::strchr(next_secondary_addr, ',');
+
+ // If found, the comma is replaced with \0 and pointer
+ // updated to point to the string that begins immediately
+ // after the comma.
+ if (next_next_secondary_addr) {
+ *next_next_secondary_addr = '\0';
+ ++next_next_secondary_addr;
+ }
+
+ // Obtain the 32-bit, host-byte-order representation of
+ // a secondary address.
+ aton_retval =
+ ACE_OS::inet_aton (ACE_TEXT_ALWAYS_CHAR (next_secondary_addr),
+ &foo);
+
+ // If the representation was obtained without error,
+ // store it in the next available slot of the
+ // secondary_accept_addrs array. Otherwise, terminate
+ // with an error.
+ if (aton_retval) {
+ secondary_accept_addrs[num_secondary_accept_addrs++] =
+ ntohl(foo.s_addr);
+ } else {
+
+ ACE_TCHAR error_message[Options_Manager::string_len + 100];
+ ACE_OS::strcpy
+ (error_message,
+ ACE_TEXT ("Could not make sense of secondary address: "));
+ ACE_OS::strcat (error_message, next_secondary_addr);
+
+ _error = 1;
+ _error_message = ACE_OS::strdup(error_message);
+ break;
+ }
+
+// ACE_DEBUG ((LM_DEBUG,
+// "secondary_addr[%d] = %s retval = %d\n",
+// num_secondary_accept_addrs - 1,
+// next_secondary_addr,
+// aton_retval));
+
+ next_secondary_addr = next_next_secondary_addr;
+ }
+
+ break;
+ }
+ case 'H':{
+ ACE_TCHAR const * const str=get_opt->opt_arg();
+ if (ACE_OS::strlen (str) < Options_Manager::string_len)
+ ACE_OS::strcpy(server_host, str);
+ else{
+ ACE_OS::strncpy(server_host, str, (Options_Manager::string_len-1));
+ server_host[Options_Manager::string_len - 1] = '\0';
+ }
+ break;
+ }
+ case 's':
+ payload_size_power_of_2 = ACE_OS::atoi(get_opt->opt_arg ());
+ break;
+ case 'h':
+ _usage = 1;
+ break;
+ }
+ }
+
+ // Check option values
+ if (test_iterations < 1)
+ {
+ _error = 1;
+ _error_message = ACE_TEXT ("test_iterations must be no less than than 1");
+ }
+
+ if (histogram_min_bin < 0.0)
+ {
+ _error = 1;
+ _error_message = ACE_TEXT ("histogram_min_bin must be no less than 0.0");
+ }
+
+ if (histogram_max_bin < histogram_min_bin)
+ {
+ _error = 1;
+ _error_message = ACE_TEXT ("histogram_max_bin must be no less than histogram_min_bin");
+ }
+
+ if (histogram_num_outliers < 1)
+ {
+ _error = 1;
+ _error_message = ACE_TEXT ("histogram_num_outliers must be no less than 1");
+ }
+
+ if (histogram_bin_count < 1)
+ {
+ _error = 1;
+ _error_message = ACE_TEXT ("histogram_bin_count must be no less than 1");
+ }
+
+ if ((server_port < 1010 ||
+ server_port > 65000) && server_port != 0)
+ {
+ _error = 1;
+ _error_message = ACE_TEXT ("server_port must be between 1010 and 65000 inclusive, or zero.");
+ }
+
+ if ((!ACE_OS::strcmp(ACE_TEXT ("client-opts"), opts_set)) && payload_size_power_of_2 > 17)
+ {
+ _error = 1;
+ _error_message = ACE_TEXT("payload_size_power_of_2 must be specified between 0 and 16 inclusive");
+ }
+
+ if (test_transport_protocol == -1) {
+ _error = 1;
+ _error_message = ACE_TEXT ("test_transport_protocol may only take 'sctp' and 'tcp' as values");
+ }
+
+ __initialized = 1;
+
+ delete get_opt;
+ }
+}
+
+void Options_Manager::_show_usage(FILE* out, ACE_TCHAR const * const opts_set)
+{
+ // Show usage message. KEEP THE DEFAULTS DISPLAYED HERE IN SYNC
+ // WITH THE DEFAULTS SET AT THE BEGINNING OF THE CONSTRUCTOR.
+
+ ACE_OS::fprintf (out, "%s - Measures round trip latency statistics of ACE synchronous\n", __program_name);
+ // indent past program name
+ for (unsigned int i=0;i<ACE_OS::strlen(__program_name);++i)
+ ACE_OS::fprintf (out, " ");
+
+ if (ACE_OS::strstr(__program_name, ACE_TEXT ("SOCK_STREAM_clt")) ||
+ ACE_OS::strstr(__program_name, ACE_TEXT ("SOCK_STREAM_srv")) ) {
+ ACE_OS::fprintf (out, " messaging (SOCK_Stream) using unmarshalled ACE_CDR::Octet.\n");
+ } else {
+ ACE_OS::fprintf (out, " messaging (SOCK_SEQPACK) using unmarshalled ACE_CDR::Octet.\n");
+ }
+
+ ACE_OS::fprintf (out, "USAGE: %s [ -<flag> [<val>] | --<name> [<val>] ]...\n\n", __program_name);
+
+ if (!ACE_OS::strcmp (ACE_TEXT ("client-opts"), opts_set)){
+ ACE_OS::fprintf (out, " Flag Args Option-Name Default\n"
+ " -c int test-iterations 1000000\n"
+ " -n none test-enable-nagle NO NAGLING\n");
+ if (ACE_OS::strstr(__program_name, ACE_TEXT ("SOCK_STREAM_clt"))) {
+ ACE_OS::fprintf (out, " -t str (sctp|tcp) test-transport-protocol sctp\n");
+ }
+
+ ACE_OS::fprintf (out, "\n");
+
+ ACE_OS::fprintf (out, " -m dbl histogram-min-bin 0\n"
+ " -M dbl histogram-max-bin 10000\n"
+ " -x int histogram-num-outliers 100\n"
+ " -b int histogram-bin-count 1000\n");
+
+ ACE_OS::fprintf (out, "\n");
+
+ ACE_OS::fprintf (out, " -C int client-port assigned by kernel\n"
+ " -i str client-connect-addr INADDR_ANY\n");
+
+ ACE_OS::fprintf (out, "\n");
+
+ ACE_OS::fprintf (out, " -p int server-port 45453\n"
+ " -H str server-host localhost\n");
+
+ ACE_OS::fprintf (out, "\n");
+
+ ACE_OS::fprintf (out, " -s int (0-16) payload-size-power-of-2 <MUST SET VALUE>\n");
+
+ ACE_OS::fprintf (out, "\n");
+
+ ACE_OS::fprintf (out, " -h none help\n");
+
+ ACE_OS::fprintf (out, "\n");
+
+ } else if (!ACE_OS::strcmp(ACE_TEXT ("server-opts"), opts_set)){
+ ACE_OS::fprintf (out, " Flag Args Option-Name Default\n"
+ " -n none test-enable-nagle NO NAGLING\n");
+ if (ACE_OS::strstr(__program_name, ACE_TEXT ("SOCK_STREAM_srv"))) {
+ ACE_OS::fprintf (out, " -t str (sctp|tcp) test-transport-protocol sctp\n");
+ }
+
+ ACE_OS::fprintf (out, "\n");
+
+ ACE_OS::fprintf (out, " -p int server-port 45453\n");
+
+ if (ACE_OS::strstr(__program_name, ACE_TEXT ("SOCK_SEQPACK_srv"))) {
+ ACE_OS::fprintf (out, " -a w.x.y.z,a.b.c.d,... server-accept-addr INADDR_ANY\n"
+ " (comma-separated \n"
+ " list of one or more \n"
+ " addresses) \n");
+ } else {
+ ACE_OS::fprintf (out, " -a w.x.y.z server-accept-addr INADDR_ANY\n");
+ }
+
+ ACE_OS::fprintf (out, " -h none help\n");
+
+ ACE_OS::fprintf (out, "\n");
+
+ } else {
+ ACE_OS::fprintf (out, "Invalid options set specified.\n");
+ }
+
+ return;
+}
diff --git a/ACE/performance-tests/SCTP/Options_Manager.h b/ACE/performance-tests/SCTP/Options_Manager.h
new file mode 100644
index 00000000000..7fbcc2dbfcc
--- /dev/null
+++ b/ACE/performance-tests/SCTP/Options_Manager.h
@@ -0,0 +1,67 @@
+// -*- C++ -*-
+
+// $Id$
+
+// The types defined in ACE_CDR are more complete that those in Basic_Types.h
+
+
+#ifndef OPTIONS_MANAGER_H
+#define OPTIONS_MANAGER_H
+
+#ifndef ACE_CDR_BASE_H
+#include "ace/CDR_Base.h"
+#endif
+
+#include "ace/streams.h"
+#include "ace/OS_NS_stdio.h"
+
+class Options_Manager
+{
+public:
+
+ Options_Manager(int argc, ACE_TCHAR **argv, ACE_TCHAR const * const opts_set);
+
+ // constant string size
+ enum { string_len = 100 };
+
+ static ACE_CDR::ULong test_iterations;
+ static ACE_CDR::Boolean test_enable_nagle;
+ static ACE_CDR::Long test_transport_protocol;
+
+ static ACE_CDR::Double histogram_min_bin;
+ static ACE_CDR::Double histogram_max_bin;
+ static ACE_CDR::ULong histogram_bin_count;
+ static ACE_CDR::ULong histogram_num_outliers;
+
+ static ACE_CDR::UShort client_port;
+ static ACE_CDR::ULong client_connect_addr;
+
+ static ACE_CDR::UShort server_port;
+ static ACE_TCHAR server_host[string_len];
+ static ACE_CDR::ULong server_accept_addr;
+
+ static ACE_CDR::UShort payload_size_power_of_2;
+
+ // Secondary client_connect_addrs for SCTP SOCK_SEQPACK test
+ enum { max_num_secondary_connect_addrs = 100 };
+ static ACE_CDR::ULong secondary_connect_addrs[max_num_secondary_connect_addrs];
+ static ACE_CDR::UShort num_secondary_connect_addrs;
+
+ // Secondary server_accept_addrs for SCTP SOCK_SEQPACK test
+ enum { max_num_secondary_accept_addrs = 100 };
+ static ACE_CDR::ULong secondary_accept_addrs[max_num_secondary_accept_addrs];
+ static ACE_CDR::UShort num_secondary_accept_addrs;
+
+ static ACE_CDR::UShort _error;
+ static const ACE_TCHAR* _error_message;
+
+ static ACE_CDR::UShort _usage;
+ void _show_usage(FILE* out, ACE_TCHAR const * const opts_set);
+
+private:
+ static ACE_CDR::Boolean __initialized;
+ static ACE_TCHAR __program_name[string_len];
+
+};
+
+#endif /* OPTIONS_MANAGER_H */
diff --git a/ACE/performance-tests/SCTP/README b/ACE/performance-tests/SCTP/README
new file mode 100644
index 00000000000..f6d0ac65954
--- /dev/null
+++ b/ACE/performance-tests/SCTP/README
@@ -0,0 +1,81 @@
+This directory provides programs that measure the round trip latency
+of synchronous octet messaging using ACE wrapper-facades for the SCTP
+protocol. Currently these programs provide the only example code on
+how to use ACE's wrapper-facades for SCTP. In the future additional
+code will be placed in the ACE_wrappers/examples/IPC_SAP/SOCK_SAP
+directory.
+
+SOCK_STREAM_clt and SOCK_STREAM_srv use the SOCK_STREAM service
+provided by SCTP via ACE's SOCK_Connector, SOCK_Stream,
+SOCK_Association wrapper-facade classes.
+
+SOCK_SEQPACK_clt and SOCK_SEQPACK_srv use the SOCK_SEQPACKET service
+provided by SCTP via ACE's SOCK_SEQPACK_Connector,
+SOCK_SEQPACK_Association and SOCK_SEQPACK_Acceptor wrapper-facade
+classes.
+
+The following table provides a summary of relationships between two main
+Linux SCTP implementations (OpenSS7 and LKSCTP), and ACE Wrapper Facades
+support that is provided. Built on top of the ACE Wrapper Facade support is
+the SCIOP support in TAO. SCIOP works identically on both OpenSS7 and
+LKSCTP implementations. Please read additional README* files listed below.
+
+-------------------------------------------------------------------------------
+ SCTP Transport Transport ACE
+ Protocol Service Service Wrapper
+ Impl. Type Characteristics Facades
+ ------------------------------------------------------------------------------
+ OpenSS7 SOCK_SEQPACKET {Connected, ACE_SOCK_SEQPACKET_Acceptor
+ Reliable, ACE_SOCK_SEQPACKET_Connector
+ Messages} ACE_SOCK_SEQPACKET_Association
+
+ OpenSS7 SOCK_STREAM {Connected, ACE_SOCK_Acceptor(IPPROTO_SCTP)
+ Reliable, ACE_SOCK_Connector(IPPROTO_SCTP)
+ Byte Stream} ACE_SOCK_Stream(IPPROTO_SCTP)
+
+ OpenSS7 SOCK_RDM {Connectionless, NOT IMPLEMENTED IN ACE
+ Reliable,
+ Messages}
+
+
+ LKSCTP SOCK_SEQPACKET {Connectionless, NOT USED IN ACE
+ UNRELIABLE,
+ Messages}
+
+ LKSCTP SOCK_STREAM {Connected, ACE_SOCK_SEQPACKET_Acceptor
+ Reliable, ACE_SOCK_SEQPACKET_Connector
+ Messages} ACE_SOCK_SEQPACKET_Association
+ ACE_SOCK_Acceptor(IPPROTO_SCTP)
+ ACE_SOCK_Connector(IPPROTO_SCTP)
+ ACE_SOCK_Stream(IPPROTO_SCTP)
+
+
+Additional information can be found in the following README files also
+located in this directory.
+
+ README.SCTP - Brief description of the major features and benefits
+ SCTP protocol and references for further information.
+
+ README.SCTP_in_ACE - Description of the wrapper-facade classes that
+ ACE provides to use SCTP, general usage
+ guidance, release notes, technical point of
+ contact information.
+
+ README.SCTP_PERF_TEST - Detailed description on how to use the
+ performance tests and the run_spectrum.pl
+ script contained in this directory.
+ Discussion of the baseline performance
+ results obtained by LM ATL.
+
+ THANKS - Documents all the people who contributed to the development
+ of the ACE wrapper-facades for SCTP and the SCIOP (SCTP
+ Inter-ORB Protocol) for TAO. Information on that can be
+ found in ACE_wrappers/TAO/tao/Strategies/README.SCIOP
+
+General requests for information beyond what is contained in these
+files can be sent to either of the following individuals.
+
+Patrick Lardieri plardier@atl.lmco.com
+Gautam Thaker gthaker@atl.lmco.com
+
+This work was sponsored by DARPA/IXO PCES Program.
diff --git a/ACE/performance-tests/SCTP/README.LKSCTP b/ACE/performance-tests/SCTP/README.LKSCTP
new file mode 100644
index 00000000000..494167abe30
--- /dev/null
+++ b/ACE/performance-tests/SCTP/README.LKSCTP
@@ -0,0 +1,46 @@
+This README describes the LKSCTP implementation of SCTP for Linux.
+
+June 2003 - 1.0
+
+Overview
+--------
+
+The LKSCTP project is the Linux Kernel implementation of SCTP. As of this
+writing it has been incorporated into the Linux 2.6 test series of
+kernels.
+
+LKSCTP adheres to the IETF's SCTP Sockets Draft API. Please refer to that
+document for API specifics.
+
+You MUST use Linux 2.6-test4 or later. Earlier versions have a different
+api.
+
+Building ACE/TAO with LKSCTP support
+--------------------------------
+
+ - compile kernel with SCTP support
+ + if compiled as a module, be sure to load it.
+
+ - download LKSCTP userspace functions library from
+ http://lksctp.sourceforge.net/
+
+ - install userspace library (libsctp.a) into /usr/local/lib
+
+ - install header file (sctp.h) into /usr/local/include/sctp.h
+
+ - make ACE/TAO with "sctp=lksctp"
+
+Caveats
+---------------------------------
+
+ - Both services interfaces (SOCK_STREAM and SOCK_SEQPACKET) will
+ preserve message boundaries.
+
+Resources
+---------------------------------
+
+ - LKSCTP Homepage: http://lksctp.sourceforge.net/
+ - Latest Patches
+ - Userspace Library
+ - Mailing Lists
+--
diff --git a/ACE/performance-tests/SCTP/README.OpenSS7 b/ACE/performance-tests/SCTP/README.OpenSS7
new file mode 100644
index 00000000000..5183e872e12
--- /dev/null
+++ b/ACE/performance-tests/SCTP/README.OpenSS7
@@ -0,0 +1,271 @@
+// $Id$
+
+This document describes the OpenSS7 API in detail.
+
+Introduction
+=============
+
+OpenSS7 defines two types of services, UDP style and TCP style. How OpenSS7
+distinguishes the two styles is by the way in which the data is presented to
+the application. In OpenSS7, data is presented as byte streams or datagrams.
+The stream style is considered the TCP style socket, and the datagram is
+considered the UDP style socket. The UDP style socket does not represent a one
+to many mapping of file descriptors to associations as the IETF compatible
+sockets does.
+
+Instead of adding new system calls, OpenSS7 decided to modify some of the
+existing system calls to play nicely with multi-homing. So, to bind to
+multiple addresses, you pass in an array of struct sockaddr* structures and the
+total length in bytes of the array. Also, when accepting connections from a
+peer, you would pass in a pointer to an array of struct sockaddr* and the
+length of the array in bytes.
+
+
+Building ACE/TAO with support for OpenSS7 SCTP
+==============================================
+
+ - apply OpenSS7's SCTP patch (see OpenSS7's readme for details)
+
+ - compile kernel with the following kernel variables (.config file)
+ + CONFIG_SCTP=y
+ + CONFIG_SCTP_TCP_COMPATIBLE=y
+ + CONFIG_SCTP_HMAC_SHA1=y
+ + CONFIG_SCTP_HMAC_MD5=y
+ + CONFIG_SCTP_ADLER_32=y
+ + CONFIG_SCTP_CRC_32C=y
+
+ - install header file (sctp.h) into /usr/local/include/sctp.h
+
+ - make ACE/TAO with "sctp=openss7" -- ie. "make sctp=openss7"
+
+Common Calls
+============
+
+There are a few common calls which have the same semantics no matter which
+interface you are using (UDP style or TCP style). So, the usual calls used in
+a client are:
+
+ 1) socket()
+ 2) bind()
+ 3) setsockopt()
+ 4) connect()
+ 5) send/recv()
+ 6) close()
+
+while the usual calls for a server are as follows:
+
+ 1) socket()
+ 2) bind()
+ 3) setsockopt()
+ 4) listen()
+ 5) accept()
+ 6) close()
+
+The previous example mimics the way in which the TCP protocol is used.
+There are some exceptions to the above sequence which we will get into a little
+later. So, let's talk about the system calls above.
+
+Socket()
+--------
+The socket() call creates a file descriptor for the application to use to
+communicate with the SCTP stack. The signature of socket() is as follows:
+
+ int socket(int network, int service, int proto)
+ Where:
+ network - AF_INET or AF_INET6 (AF_INET6 is not currently supported)
+ service - SOCK_SEQPACKET which gives us the UDP style interface
+ SOCK_STREAM which gives us the TCP style interface
+ proto - IPPROTO_SCTP which is the SCTP protocol number(132)
+
+Bind()
+------
+The bind() call is used to attach the socket descriptor to the given array of
+addresses. bind() may only be called once. The address structures sent in as
+arguments to bind must have the same port number. That is, you may have
+multiple addresses, but only 1 port number. The signature of bind() is as
+follows:
+
+ int bind(int fd, struct sockaddr* addrs, socklen_t addrs_len)
+ Where:
+ fd - A SCTP socket descriptor
+ addrs - An array of struct sockaddr* which have the same port number
+ addrs_len - The total length in bytes of the addrs array
+
+If an address structure is sent in with the address of INADDR_ANY, then SCTP
+will bind to all the addresses on the host and either pick an ephemeral port or
+use the one specified in the address structure.
+
+Setsockopt()
+------------
+The setsockopt() call is used to adjust many different parameters to the SCTP
+protocol. Please see the sctp(7) man page for more details.
+
+Connect()
+---------
+The connect() call can be used to initialize a connection with a peer SCTP
+machine. A connection can be initialized in 2 ways. The first is this
+call(connect()). The second way is to allow implicit initialization when the
+application calls sendmsg or sendto with the address of the remote host
+specified. To allow data to be piggybacked with the COOKIE_ECHO chunk, you
+must use the second initialization technique. The signature of connect is as
+follows:
+
+ int connect(int fd, struct sockaddr* r_addr, socklen_t r_addr_len)
+ Where:
+ fd - An SCTP socket descriptor
+ r_addr - A single address structure with the address of the remote host
+ r_addr_len - Length in bytes of the the address structure
+
+Note that only one address is sent into the connect call. The SCTP protocol
+will negotiate the valid IP addresses to use with multi-homing.
+
+Listen()
+--------
+The listen() call prepares the SCTP socket to accept new associations. The
+signature is as follows:
+
+ int listen(int fd, int backlog)
+ Where:
+ fd - An SCTP socket descriptor
+ backlog - The maximum number of unaccepted connections
+
+Accept()
+--------
+The accept() call allows the application to explicitly accept an incoming
+association initialization attempt. accept() returns a new file descriptor
+which can be used to send data to the client. accept() has a slightly
+different semantic which allows it to take an array of address structures.
+This gives the application the chance to get a specified number of addresses
+from the peer on initialization. The signature of accept() is as follows:
+
+ int accept(int fd, struct sockaddr* r_addr, socklen_t *r_addr_len)
+ Where:
+ fd - A SCTP socket descriptor
+ r_addr - An array of address structures which will be filled with the
+ addresses of the remote host
+ r_addr_len - The length of the array of address structures passed in.
+
+accept() will only put as many addresses in the address array as is specified
+by the r_addr_len argument.
+
+Close()
+-------
+Start the association shutdown sequence. The signature is as follows:
+
+ int close(int fd)
+ Where:
+ fd - A SCTP socket descriptor
+
+Data Interfaces
+===============
+This section describes the sending and receiving of data on an SCTP socket.
+This is where the differences between the TCP style and UDP style sockets
+shows. SCTP uses the standard pairs of calls:
+
+ 1) send()/recv()
+ 2) sendmsg()/recvmsg()
+ 3) sendto()/readfrom()
+ 4) write()/read()
+ 5) writev()/readv()
+
+When the SCTP socket is opened as a UDP style socket, data is presented to the
+application as datagrams. This means that calls to the receive class of system
+calls returns only datagrams. For example, assume a sender sends 2 100 byte
+datagrams. Now assume that the receiver calls one of the receive routines with
+a max buffer size of 120 bytes. Assuming no errors are encountered, only 100
+bytes are returned to the receiver (only 1 datagram), leaving the last 20 bytes
+empty in the receivers buffer. When the last of a datagram is read, the
+MSG_EOR flag is returned, and if the datagram is too big to fit into the
+specified buffer, the MSG_TRUNC flag is returned.
+
+With TCP styles sockets, the data is presented to the application as a stream
+of bytes (like TCP). For example, assume the sender sends 2 100 byte
+datagrams. Now assume that the receiver calls one of the receive routines with
+a max buffer size of 120. Assuming no errors are encountered, 120 bytes are
+returned (100 from the first datagram and 20 from the next datagram), leaving
+80 bytes in the second datagram. MSG_EOR and MSG_TRUNC are never returned.
+
+Send()/Recv()
+-------------
+The send/recv interface is one of the easiest ways of sending data back and
+forth between peers. When send/recv is called, data is sent/read from the
+default stream. The signature of send/recv is as follows:
+
+ int send(int fd, void *data, size_t d_len, int flags)
+ Where:
+ fd - A SCTP socket descriptor
+ data - Data to be sent to the peer
+ d_len - The length of the data in bytes
+ flags - Possible flags to be sent to be passed to the SCTP stack
+ (see send(3))
+
+Sendmsg()/Recvmsg()
+-------------------
+The sendmsg/recvmsg interface is the most powerful and hard to use interface
+in the SCTP stack. This interface allows the specification of which stream to
+send data out or receive data from. It also allows the sending of data with a
+specified protocol payload identifier. The signature is as follows:
+
+ int sendmsg(int fd, struct msghdr *msg, int flags)
+ Where:
+ fd - A SCTP socket descriptor
+ msg - A struct msghdr structure which holds miscellaneous information
+ flags - Possible flags to be passed to the SCTP stack
+ (see sendmsg(3))
+
+The msg argument holds the data to be sent to the peer. It also can take an
+address to send the data to. So, for example, if you had an association with 2
+addresses for the peer and the default path used the first address, and you
+wanted to send data to the other address, you could specify that address in the
+msg structure. If this address field is NULL, then data is sent out the
+default address.
+
+This interface also allows other functions by using the ancillary data field
+in the msg structure. By using the ancillary data field, you may send data out
+a different stream by using the SCTP_SID control message. This type of control
+message would take an integer representing the stream to send data out as it's
+data. Another option is to use the SCTP_PPI control message which allows the
+setting of the protocol payload identifier to the specified integer argument.
+Both of these options only set their values for the current data being sent out.
+
+Sendto()/Recvfrom()
+-------------------
+The sendto/recvfrom interface allows the specification of which remote address
+to send data. The signature of sendto/recvfrom is as follows:
+
+ int sendto(int fd, void *data, size_t d_len, int flags,
+ struct sockaddr* r_addr, socklen_t r_addr_len)
+ Where:
+ fd - A SCTP socket descriptor
+ data - Data to send to peer
+ d_len - Length of the data to be sent
+ flags - Possible flags to be passed to the SCTP stack
+ r_addr - Address of peer to send data to
+ r_addr_len - Length of peer address
+
+Write()/Read()
+--------------
+This interface is the simplest way of sending data to a peer. When this
+interface is used, data is sent/received through the default stream (as set by
+SCTP_SID). The signature is as follows:
+
+ int write(int fd, void *data, size_t d_len)
+ Where:
+ fd - A SCTP socket descriptor
+ data - Data to be sent to peer
+ d_len - Length of data
+
+Writev()/Readv()
+----------------
+This interface allows the sending of multiple buffers of data in one system
+call. This call places all the buffers into one SCTP data chunk. The signature is as follows:
+
+ int writev(int fd, struct iovec *iov, int ct)
+ Where:
+ fd - A SCTP socket descriptor
+ iov - An array of iovec structures. The order they are in the array is the
+ order they are placed in the data chunk
+ ct - The number of iovec structures to send
+
+--
+
diff --git a/ACE/performance-tests/SCTP/README.SCIOP b/ACE/performance-tests/SCTP/README.SCIOP
new file mode 100644
index 00000000000..503b81f7eaf
--- /dev/null
+++ b/ACE/performance-tests/SCTP/README.SCIOP
@@ -0,0 +1,63 @@
+README.SCIOP
+------------
+
+Author: Jason Cohen
+Lockheed Martin, Advanced Technology Labs
+
+
+The SCIOP pluggable protocol for TAO uses the SCTP transport protocol through
+the use of the SOCK_SEQPACK ACE wrappers for sequence based transport. The
+current implementation supported is the OpenSS7 SCTP protocol layer, tested
+under Linux 2.4.18.
+
+For more information on SOCK_SEQPACK and OpenSS7 SCTP see
+ACE_wrappers/performance-tests/SCTP/README*
+
+Features Currently Supported:
+-----------------------------
+
+o) Sequenced delivery via SOCK_SEQPACK
+Currently, only one stream is supported as there are no available bindings to
+provide a user with stream designation for messages.
+
+o) SCIOR compliance to OMG GIOP SCTP Protocol Mapping submission mars/2002-09-01.
+
+o) Multiple address SCIOR profiles
+When multiple addresses are included in a SCIOR profile, each address is
+handled separately during the connection process. Specifying multiple
+addresses for a single connection attempt remains as work to be done.
+However, multiple path discovery during connection time in OpenSS7's
+SCTP implementation has been tested to work properly with SCIOP.
+
+The catior utility under ACE_wrappers/TAO/utils/catior has also modified
+to display SCIOR profile information.
+
+To test SCIOP after installing an SCTP implementation supported by
+SOCK_SEQPACK, try using a performance test specifying an sciop address as the
+ORBEndpoint. One way to do this is with the test found under:
+ACE_wrappers/TAO/performance-tests/Pluggable/
+
+Make sure to build the pluggable protocols into the executable:
+gmake LIBS+=-lTAO_Strategies
+
+Run the server with an sciop endpoint specified:
+./server -ORBEndpoint sciop://${HOSTNAME} -o test.ior &
+
+Finally, run the client on the same machine or another that has file
+access to your IOR file:
+./client -f test.ior
+
+TO-DO:
+------
+
+o) Multiple association connection using Multihomed_INET_Addr
+Currently, only one address connection is attempted at a time, even when a
+profile contains multiple address. Later, we hope to allow this
+implementation of SCIOP to exploit the multiple address connection
+capabilities of STCP.
+
+o) SCTP ProtocolManagement/SCTPProtocolProperties
+
+o) Support for max_streams > 1
+
+o) SCIOR Profile Components
diff --git a/ACE/performance-tests/SCTP/README.SCTP b/ACE/performance-tests/SCTP/README.SCTP
new file mode 100644
index 00000000000..95c3cb0b53a
--- /dev/null
+++ b/ACE/performance-tests/SCTP/README.SCTP
@@ -0,0 +1,81 @@
+# $Id$
+
+This document provides general information about the SCTP protocol.
+
+
+Introduction
+=============
+SCTP (Stream Control Transmission Protocol) is a new transport layer protocol
+developed by the IETF and defined by RFC2960. Originally designed for the
+transmission of message-oriented applications such as the transportation of
+signaling data for PSTNs (Public Switched Telephone Networks), SCTP can be used
+in any application that uses TCP.
+
+ Major Features
+ --------------
+
+ - Direct support for multi-homing
+ - Support for multiple streams per connection (known as associations)
+ to reduce "head of line" blocking problems.
+ - Four way handshake reducing the possibility for blind denial of
+ service attacks.
+ - Adjustment of congestion control parameters
+ - Cookie mechanism to protect against "SYN" attacks
+
+API's
+========
+
+The SCTP drafts have defined several different API's. The first reference
+implementation was a user level library. This allowed an application to use
+SCTP through several functions and callbacks. As of this writing a
+transition from the user level libraries to the kernel is underway.
+
+The IETF TSVWG (Transport Area Working Group) has published a draft
+(draft-ietf-tsvwg-sctpsocket-06.txt) that defines a mapping between SCTP and
+the BSD sockets interface. This interface has made porting TCP applications to
+SCTP as simple as changing one socket call.
+
+ OpenSS7
+ --------
+ OpenSS7 has defined, a similar BSD style sockets interface. It is
+ slightly different from the one defined by the IETF, however, at the
+ time of our evaluation it was the most stable implementation.
+
+ Please see README.OpenSS7 for details and build instructions.
+
+ LKSCTP
+ ------
+ The LKSCTP implementation is based on the TSVWG's sockets draft.
+ It is included with the Linux 2.6 series test kernels. Backported
+ (Linux 2.4) patches are also available from the LKSCTP website.
+
+ Please see README.LKSCTP for more details and build instructions.
+
+Resources
+===========
+
+ RFCs
+ -----
+ RFC2960: Stream Control Transmission Protocol
+ RFC3309: Stream Control Transmission Protocol Checksum Change
+
+ Internet-Drafts
+ ----------------
+
+ draft-ietf-tsvwg-sctpsocket-07.txt:
+ Sockets API Extensions for Stream Control Transmission Protocol
+
+ draft-ietf-tsvwg-sctpimpguide-08.txt
+ Stream Control Transmission Protocol Implementer's Guide
+
+ Internet Links
+ ---------------
+ IETF: Transport Area Working Group (tsvwg):
+ http://www.ietf.org/html.charters/tsvwg-charter.html
+
+ The OpenSS7 Project: http://www.openss7.org/sctp.html
+
+ The LKSCTP Project: http://lksctp.sourceforge.net/
+
+--
+
diff --git a/ACE/performance-tests/SCTP/README.SCTP_PERF_TEST b/ACE/performance-tests/SCTP/README.SCTP_PERF_TEST
new file mode 100644
index 00000000000..81cacef02e0
--- /dev/null
+++ b/ACE/performance-tests/SCTP/README.SCTP_PERF_TEST
@@ -0,0 +1,405 @@
+$Id$
+
+Release 1.0 - January 2003
+
+***********************************
+* Performance Test Overview *
+***********************************
+
+This directory contains performance tests for measuring round-trip
+latency statistics of ACE synchronous messaging using unmarshalled
+ACE_CDR::Octet.
+
+In terms of protocol and service type, three different tests are
+available:
+
+ * TCP over SOCK_STREAM
+ * SCTP over SOCK_STREAM
+ * SCTP over SOCK_SEQPACK
+
+All three of these tests share the same architecture, which is
+described in the following section.
+
+***************************
+* Test Architecture *
+***************************
+
+As mentioned above, the performance tests measure round-trip latency
+statistics. We are talking about the round trip between two service
+endpoints, a client and a server. The client sends the server an
+arbitrary message with a specific length---up to 2^16 bytes---and the
+server responds with a 2-byte reply. The client measures and records
+the time it takes to complete this exchange. The whole test is then
+repeated through many iterations, and finally the client outputs the
+resulting statistics.
+
+In detail,
+
+1. The server program is started first. It creates a passive-mode
+ socket and runs an infinite loop waiting for clients to connect.
+
+2. The client program is started next. It may be configured with
+ numerous parameters, which include:
+
+ * the hostname and port where the server's passive-mode socket
+ is listening,
+ * the desired message length, which may be any power of two
+ between 2^0 and 2^16,
+ * the desired number of iterations (by default 1 million)
+
+3. The client connects to the server's passive-mode socket. If all
+ goes well, the client and server will each obtain a data-mode
+ socket that serves as a communication endpoint.
+
+4. The client sends an initial header message containing the intended
+ number of iterations and the message length (which will be
+ the same for each iteration). Armed with this information, the
+ server spawns a separate thread to handle these iterations.
+
+5. The client creates an in-memory data structure that serves as a
+ histogram. The histogram is configured with a range of possible
+ round-trip latencies, and this range is divided into a number of
+ "bins". The latency measured for each test entry will either
+ fall into one of these "bins", or it will fall outside the entire
+ range and will be logged as an outlier.
+
+6. The client and server repeat the following interaction for each
+ test iteration.
+
+ a. The client starts a stopwatch.
+
+ b. The client sends the server an arbitrary message of the
+ established length.
+
+ c. After receiving this entire message from the client, the
+ server sends the client a 2-byte reply.
+
+ d. After receiving the 2-byte reply from the server, the client
+ stops the stopwatch.
+
+ e. The round-trip latency, as measureed by the stopwatch, is
+ logged to the in-memory histogram.
+
+7. After all these iterations are complete, the client disconnects
+ from the server. The client then takes the in-memory histogram
+ and dumps its text representation to STDOUT.
+
+8. The client exits. The server thread dedicated to this client
+ exits. The main thread of the server continues to run an infinite
+ loop waiting for more clients to connect to the passive-mode
+ socket.
+
+**************************
+* Test Executables *
+**************************
+
+You must use a different pair of client and server executables
+depending on whether you desire to use the SOCK_STREAM service or the
+SOCK_SEQPACK service.
+
+The SOCK_STREAM client and server are called SOCK_STREAM_clt and
+SOCK_STREAM_srv, respectively. The SOCK_SEQPACK client and server are
+called SOCK_SEQPACK_clt and SOCK_SEQPACK_srv, respectively.
+
+Each of these executables uses SCTP as its default protocol. As an
+extra feature, SOCK_STREAM_clt and SOCK_STREAM_srv offer TCP as an
+alternate protocol. The choice between TCP and SCTP is exposed via
+the '-t' option. (Individual instances of SOCK_STREAM_clt and
+SOCK_STREAM_srv must use the same protocol in order to connect and
+function.)
+
+Any of the four executables will show usage information if you run it
+with the '-h' option. For instance, here is the usage message
+produced by SOCK_STREAM_clt:
+
+./SOCK_STREAM_clt - Measures round trip latency statistics of ACE synchronous
+ messaging (SOCK_Stream) using unmarshalled ACE_CDR::Octet.
+USAGE: ./SOCK_STREAM_clt [ -<flag> [<val>] | --<name> [<val>] ]...
+
+ Flag Args Option-Name Default
+ -c int test-iterations 1000000
+ -n none test-enable-nagle NO NAGLING
+ -t str (sctp|tcp) test-transport-protocol sctp
+
+ -m dbl histogram-min-bin 0
+ -M dbl histogram-max-bin 10000
+ -x int histogram-num-outliers 100
+ -b int histogram-bin-count 1000
+
+ -C int client-port assigned by kernel
+ -i str client-connect-addr INADDR_ANY
+
+ -p int server-port 45453
+ -H str server-host localhost
+
+ -s int (0-16) payload-size-power-of-2 <MUST SET VALUE>
+
+ -h none help
+
+For each option, the long "Option-Name" may be prefixed by two dashes
+and used on the command line in place of the shorter "Flag". Hence
+
+ ./SOCK_STREAM_clt -s 5
+
+is equivalent to
+
+ ./SOCK_STREAM_clt --payload-size-power-of-2 5
+
+The options shown above for SOCK_STREAM_clt (and the similar options
+available for SOCK_SEQPACK_clt) are discussed in the next section.
+
+*****************************
+* Client-Side Options *
+*****************************
+
+The following options are available for both SOCK_STREAM_clt and
+SOCK_SEQPACK_clt.
+
+ test-iterations [ -c int ]
+
+ the number of times to repeat the round-trip-latency test
+ loop. The default is 1000000.
+
+ test-enable-nagle [ -n ]
+
+ Enable Nagle's algorithm (which is disabled by default).
+
+ histogram-min-bin [ -m double ]
+
+ the lower boundary on the range of the histogram.
+ The default is 0. The unit of measurement is the millisecond.
+
+ histogram-max-bin [ -M double ]
+
+ the upper boundary on the range of the histogram.
+ The default is 10000. The unit of measurement is the
+ millisecond.
+
+ histogram-num-outliers [ -x int ]
+
+ the maximum number of outliers to maintain in the histogram.
+ The default is 100.
+
+ histogram-bin-count [ -b int ]
+
+ the number of histogram bins. The default is 1000. The width
+ of each bin will be
+
+ (histogram-max-bin - histogram-min-bin) / histogram-bin-count
+
+ client-port [ -C int ]
+ client-connect-addr [ -i string ]
+
+ the port and network address where the client's data-mode
+ socket is to be bound. By default, the port number is
+ assigned by the kernel, and the socket is bound to all network
+ interfaces.
+
+ server-port [ -p int ]
+ server-host [ -H string ]
+
+ the port and hostname where the server's passive-mode socket
+ is bound. The default port is 45453 and the default host is
+ localhost.
+
+ payload-size-power-of-2 [ -s int ]
+
+ an integer X. The size of the payload will be 2^X bytes.
+
+ help [ -h ]
+
+ Show usage message.
+
+The following option is available only for SOCK_STREAM_clt:
+
+ test-transport-protocol [ -t (sctp|tcp) ]
+
+ the protocol for the test. The default is sctp.
+
+In contrast, SOCK_SEQPACK_clt always uses SCTP as its protocol.
+
+*****************************
+* Server-Side Options *
+*****************************
+
+The following options are available for both SOCK_STREAM_srv and
+SOCK_SEQPACK_srv:
+
+ test-enable-nagle [ -n ]
+
+ Enable Nagle's algorithm (which is disabled by default).
+
+ server-port [ -p int ]
+
+ the port where the server's passive-mode socket will be
+ bound. The default is 45453.
+
+ help [ -h ]
+
+ Show usage message.
+
+The following option is available for both SOCK_STREAM_srv and
+SOCK_SEQPACK_srv, but the latter offers additional functionality:
+
+ server-accept-addr [ -a w.x.y.z ] (for SOCK_STREAM_srv)
+ [ -a w.x.y.z,a.b.c.d,... ] (for SOCK_SEQPACK_srv)
+
+ the network address (or addresses) to which the server's
+ passive-mode socket will be bound.
+
+ The default value of INADDR_ANY should be sufficient for
+ machines that have only one network interface.
+
+ If your machine has two interfaces, and you wish to bind the
+ socket only to one of these, then you may explicitly specify
+ the desired interface with an expression such as
+ "-a 192.168.221.104" or "-a 192.168.1.43".
+
+ If your machine has three or more interfaces, and you wish to
+ bind the socket only to a subset of two or more, AND you are
+ using SOCK_SEQPACK_srv, THEN you may explicitly specify the
+ desired interface with an expression such as
+ "-a 192.168.221.104,192.168.1.43". The argument here is a
+ comma-delimited list of dotted-decimal IPv4 addresses with no
+ whitespace interspersed. This level of control is not
+ possible with SOCK_STREAM_srv.
+
+The following option is available only for SOCK_STREAM_srv:
+
+ test-transport-protocol [ -t (sctp|tcp) ]
+
+ the protocol for the test. The default is sctp.
+
+In contrast, SOCK_SEQPACK_srv always uses SCTP as its protocol.
+
+***************************
+* Test Walk-Through *
+***************************
+
+This section shows a walk-through of a typical scenario using
+SOCK_STREAM_clt and SOCK_STREAM_srv to run an SCTP performance test.
+
+You can run the equivalent TCP performance test by adding "-t tcp" to
+the command line of both programs. Alternately, you can run a
+SOCK_SEQPACK-based SCTP performance test by substituting
+SOCK_SEQPACK_clt and SOCK_SEQPACK_srv for SOCK_STREAM_clt and
+SOCK_STREAM_srv, respectively.
+
+In this scenario, both client and server run on the same machine. We
+use a message size of 2^7 bytes and a relatively small number of
+iterations, 1000, in order to make the test go quickly. The server's
+passive-mode socket binds to the default port, 45453, which is also
+the default port expected by the client. We invoke no other special
+or unusual options.
+
+For clarity, we envision starting the client and server in two
+separate shells.
+
+The steps of the walk-through are as follows:
+
+1. Start the server.
+
+ $ ./SOCK_STREAM_srv
+ (12761|1024) Accepting connections on port 45453
+ on interface INADDR_ANY using IPPROTO_SCTP
+ (12761|1024) starting server at port 45453
+ (12761|1024) select timed out
+ (12761|1024) select timed out
+ (12761|1024) select timed out
+ (12761|1024) select timed out
+ ...
+
+ The server will continue to print, periodically, the message
+ "select timed out" as it waits for clients to connect.
+
+2. Start the client.
+
+ $ ./SOCK_STREAM_clt -s 7 -c 1000
+
+3. Observing the debugging output from the server, you should see
+ evidence that the client has connected.
+
+ (12761|1024) select timed out
+ (12761|1024) select timed out
+ (12761|1024) select timed out
+ (12761|1024) spawning server
+ (12761|1024) client utica-b connected from 32768
+ (12761|1024) Test for 1100 iterations
+ (12761|1024) select timed out
+ (12761|1024) select timed out
+
+ Note that the server expects 1100 iterations, even though we
+ configured the client for only 1000 iterations. The reason for
+ this discrepencany is that the client always runs 100 primer
+ iterations before the requested test iterations.
+
+4. When the 1100 iterations are complete, observing the output from
+ the client, you should see the histogram:
+
+
+ Histogram ACE Unmarshalled Msg Synchronous Latency Test
+ (Message Size 128, Message Type octet)
+ version: 1.1
+ minimum: 41
+ maximum: 60182
+ mean: 106.858
+ variance: 3.62659e+06
+ num_points: 1000
+ num_bins: 1000 0 10000
+
+ Low - High Count Fraction Cumulative
+ below - 0.000 : 0 0.000 0.000
+ 0.000 - 10.000 : 0 0.000 0.000
+ 10.000 - 20.000 : 0 0.000 0.000
+ 20.000 - 30.000 : 0 0.000 0.000
+ 30.000 - 40.000 : 0 0.000 0.000
+ 40.000 - 50.000 : 988 0.988 0.988
+ 50.000 - 60.000 : 5 0.005 0.993
+ 60.000 - 70.000 : 2 0.002 0.995
+ 70.000 - 80.000 : 0 0.000 0.995
+ 80.000 - 90.000 : 1 0.001 0.996
+ 90.000 - 100.000 : 0 0.000 0.996
+ 100.000 - 110.000 : 0 0.000 0.996
+ ...
+ 9960.000 - 9970.000 : 0 0.000 0.999
+ 9970.000 - 9980.000 : 0 0.000 0.999
+ 9980.000 - 9990.000 : 0 0.000 0.999
+ 9990.000 - 10000.000 : 0 0.000 0.999
+ 10000.000 - above : 1 0.001 1.000
+
+ outliers:
+ 60182.000
+
+******************************************
+* Running a Complete Test Spectrum *
+******************************************
+
+People who are interested in round-trip latency often want to see a
+"spectrum" of statistics for a range of payload sizes. This directory
+includes a script, run_spectrum.pl, that automates running
+SOCK_STREAM_clt or SOCK_SEQPACK_clt multiple times in order to
+generate a spectrum. (The appropriate server program must be started
+manually.)
+
+The run_spectrum.pl script offers embedded documentation. To see the
+full documentation, please run
+
+ ./run_spectrum.pl --manual
+
+************************
+* Sample Results *
+************************
+
+The file sample-spectrum.png plots the spectrum data for a test run at
+LM ATL facilities on the following systems: two Linux 2.4.18, 1600 MHz
+Pentium 4 machines on an isolated 100Mbps Ethernet network.
+
+The test conditions include several critical parameters that were set
+as follows:
+
+ sctp_rto_initial = 20
+ sctp_rto_min = 20
+ sctp_rto_max = 20
+
+Testing has shown that these parameters affect maximum round-trip
+latency.
diff --git a/ACE/performance-tests/SCTP/README.SCTP_in_ACE b/ACE/performance-tests/SCTP/README.SCTP_in_ACE
new file mode 100644
index 00000000000..b51cd6b3fe6
--- /dev/null
+++ b/ACE/performance-tests/SCTP/README.SCTP_in_ACE
@@ -0,0 +1,269 @@
+Release 1.1 - June 2003
+
+Overview of SCTP sockets
+------------------------
+
+In order to support multiple implementations of SCTP, we had to standardize
+on a set of semantics.
+
+The IETF sockets draft states that service type SOCK_SEQPACKET indicates a UDP
+style socket (i.e. connection-less), while service type SOCK_STREAM indicates
+a TCP style socket. However, this conflicts with the POSIX definition for
+SOCK_SEQPACKET as connection-oriented.
+
+In ACE we choose to support the standard POSIX definition. In doing so, certain
+socket semantics will be guaranteed regardless of implementation.
+
+ [1] SOCK_SEQPACKET sockets will always be message-based,
+ connection-oriented, and reliable.
+
+ [2] SOCK_STREAM sockets will be message-based or byte-stream based,
+ connection-oriented, and reliable.
+
+
+SCTP Features Accessible Within ACE
+-----------------------------------
+
+ * SOCK_STREAM (byte stream oriented or msg oriented) data transport service
+
+ * SOCK_SEQPACKET (message oriented) data transport service (this is
+ the service used by TAO's SCIOP pluggable protocol)
+
+ * Explicit control of binding network interfaces (all, one, or any
+ subset) to server-side passive- and active- mode sockets on
+ multi-homed machines. (for SOCK_SEQPACKET service only. The
+ SOCK_STREAM service may only bind one or all interfaces because we
+ avoided changing the interface of ACE_SOCK_Acceptor.)
+
+ * Setting and getting of all parameters exposed by SCTP
+ (e.g. retransmission timeout (RTO)) via ACE_SOCK::set_option(...)
+ and ACE_SOCK::get_option(...) for both SOCK_STREAM and
+ SOCK_SEQPACKET sockets. You must set the socket level appropriately.
+
+ * Multiplexing of lightweight "SCTP Streams" (over the SOCK_STREAM
+ and SOCK_SEQPACKET services) via ACE_SOCK::set_option(...)
+
+ * Network path multiplexing (provided opaquely by the protocol---no
+ explicit support required in ACE other than the ability to
+ configure various parameters and the set of interfaces as described
+ above)
+
+
+Supported SCTP Implementations
+------------------------------
+
+ * OpenSS7's Linux Implementation (Berkeley UNIX Network API)
+ Linux 2.4.18 patch available at: http://www.openss7.org/linux-sctp-0.2.14.tgz
+ (as of April 2003)
+
+ * The LKSCTP Linux Kernel Implementation (IETF Sockets Draft API compliant)
+ Available in the Linux 2.5 kernels (http://www.kernel.org/)
+ Tools/Libs available at http://lksctp.sourceforge.net/
+ (All socket interfaces are message-based -- please see README.LKSCTP)
+
+
+BUGS
+----
+
+ * OpenSS7 BUGS
+
+ - protocol crashes when transmitting message sizes greater than
+ PATH MTU in the presence of network failures (message size
+ includes SCTP and IP headers and data.)
+
+ * LKSCTP BUGS
+
+ - certain combinations of SCTP parameters will cause a kernel panic
+ (ie. setting rto_initial, rto_max, or rto_min to 0)
+
+
+TO-DO
+----
+
+ * Provide explicit control of binding network interfaces to
+ client-side active-mode sockets on multi-homed machines. Current
+ implementation supports all interfaces but not restriction to one
+ or to an arbitrary subset. (This will be done for SOCK_SEQPACKET
+ service only. We want to avoid changing the existing interfaces for
+ the SOCK_STREAM service).
+
+ * Integrate management and use of "SCTP Streams" into the
+ ACE_SOCK_SEQPACK_* wrapper-facade. (currently they can only be
+ accessed indirectly through ACE_SOCK::set_option(...))
+
+ * Support SOCK_RDM service (connection-less) within ACE for OpenSS7.
+
+ * Convert ATL's histogram utility (located under
+ performance-tests/SCTP) into a ACE utility and integrate with other
+ ACE provided statistics classes.
+
+ * Support Draft API msg notifications via sendmsg() and recvmsg().
+
+
+USAGE
+-----
+
+ SOCK_STREAM - Use the ACE_SOCK_Connector, ACE_SOCK_Stream and
+ ACE_SOCK_Acceptor classes. In ACE_SOCK_Connector pass
+ the value IPPROTO_SCTP for the protocol parameter in
+ either the constructor or the connect(...) method
+ as shown in SOCK_STREAM_clt.cpp. In ACE_SOCK_Acceptor
+ pass the value IPPROTO_SCTP for the protocol parameter
+ in either the constructor or the open(...) method
+ as shown in SOCK_STREAM_srv.cpp.
+
+ You must include the file sctp.h in order for
+ IPPROTO_SCTP to be defined. This file should be under
+ /usr/include/netinet
+
+ Aside from these changes, the classes can be used as
+ they are under TCP (the protocol they use by
+ default). Be cautious to use SCTP protocol options when
+ setting socket options on SCTP sockets (e.g., use
+ SCTP_NODELAY, not TCP_NODELAY, to disable Nagle's
+ algorithm on an SCTP socket.)
+
+ SOCK_SEQPACKET - Use the ACE_SOCK_SEQPACK_Connector,
+ ACE_SOCK_SEQPACK_Association, and
+ ACE_SOCK_SEQPACK_Acceptor classes, which parallel
+ the familiar ACE_SOCK_Connector, ACE_SOCK_Stream,
+ and ACE_SOCK_Acceptor classes, respectively. Please
+ see SOCK_SEQPACK_clt.cpp and SOCK_SEQPACK_srv.cpp for
+ more details.
+
+ In the special case where you want to specify a set
+ of interfaces---other than one or all
+ interfaces---for an ACE_SOCK_SEQPACK_Acceptor, use
+ an ACE_Multihomed_INET_Addr in place of the familiar
+ ACE_INET_Addr. (See SOCK_SEQPACK_srv.cpp for an
+ example.)
+
+ SCTP associations may have more than one local and
+ more than one remote address bound to them.
+ Accordingly, ACE_SOCK_SEQPACK_Association provides
+ methods get_local_addrs(...) and
+ get_remote_addrs(...). These methods return the list
+ of local and remote addresses bound to an active
+ mode SCTP socket. Alternately, the familiar
+ ACE_SOCK::get_local_addr(...) and
+ ACE_SOCK::get_remote_addr(...) methods will work
+ properly with an active mode SCTP socket, but each
+ will only return a single address. These functions
+ are only NOT available on ACE_SOCK_SEQPACK_Acceptor
+ even though that is an SCTP socket as well. This is
+ because the functions getpeername() and
+ getsockname() called on a passive SCTP acceptor
+ socket returns the same values as a TCP socket. As
+ such, the current ACE methods get_local_addr() and
+ get_remote_addr() defined in ACE_SOCK are sufficient.
+
+
+DESIGN
+------
+
+SCTP supports two types of network service: SOCK_STREAM and
+SOCK_SEQPACKET. To integrate SCTP's SOCK_STREAM service into ACE we
+had to make a small modification to the current SOCK_STREAM wrapper
+facade. We had to add a protocol parameter to one constructor and one
+connect method of the ACE_SOCK_Connector class. After this
+modification the ACE SOCK_STREAM wrapper facade worked properly over
+both TCP and SCTP.
+
+To integrate SCTP's SOCK_SEQPACKET service into ACE we had to create a
+new wrapper facade, which we refer to as SOCK_SEQPACK. We closely
+emulated the current SOCK_STREAM wrapper facade to develop our new
+SOCK_SEQPACK wrapper facade. SOCK_SEQPACK_wrapper_facade.jpg depicts
+the classes that implement this new wrapper facade. Also indicated are
+those methods that have a substantial change from their SOCK_STREAM
+wrapper façade counterparts. Not depicted in the figure but noteworthy
+is the removal of the QoS enabled constructor and accept method that
+were imported to SOCK_SEQPACK_Acceptor from SOCK_Acceptor and the
+removal of the QoS enabled constructor and connect method that were
+imported into SOCK_SEQPACK_Connector from SOCK_Connector. SOCK_SEQPACK
+association provides two methods to get the list of secondary
+addresses associated with the local and remote socket (explained in
+more detail in the usage section above).
+
+
+To enable the user to fully exploit the network path multiplexing
+features of SCTP we created a new subclass of ACE_INET_Addr called
+ACE_INET_Multihomed_Addr. This class enables applications to specify
+restricted subsets of network interfaces for inclusion on SCTP
+associations on the client and server side. Multihomed_INET_Addr
+provides a subset of the ACE_INET_Addr API with the addition of
+optional parameters for lists of secondary addresses or hostnames. If
+just a primary address or hostname is provided
+ACE_Multihomed_INET_Addr behaves as an ACE_INET_Addr (in fact it just
+populates the base ACE_INET_Addr) This is also depicted in
+SOCK_SEQPACK_wrapper_facade.jpg. Multihomed_INET_Addr is only used by
+the SOCK_SEQPACK wrapper facade.
+
+
+All SCTP socket options can be read and written from the current
+socket options methods provided by ACE_SOCK.
+
+Finally, our SOCK_SEQPACK wrapper facade does not yet support SCTP
+stream multiplexing.
+
+Here are the files under $(ACE_ROOT) that were either modified or
+added. NO files were removed.
+
+$(ACE_ROOT)/ace/ace_dll.dsp MODIFIED
+$(ACE_ROOT)/ace/OS.h MODIFIED
+$(ACE_ROOT)/ace/Makefile.ace MODIFIED
+$(ACE_ROOT)/ace/SOCK_Connector.h MODIFIED
+$(ACE_ROOT)/ace/SOCK_Connector.cpp MODIFIED
+
+$(ACE_ROOT)/ace/SOCK_SEQPACK_Acceptor.h ADDED
+$(ACE_ROOT)/ace/SOCK_SEQPACK_Acceptor.i ADDED
+$(ACE_ROOT)/ace/SOCK_SEQPACK_Acceptor.cpp ADDED
+
+$(ACE_ROOT)/ace/SOCK_SEQPACK_Connector.h ADDED
+$(ACE_ROOT)/ace/SOCK_SEQPACK_Connector.i ADDED
+$(ACE_ROOT)/ace/SOCK_SEQPACK_Connector.cpp ADDED
+
+$(ACE_ROOT)/ace/SOCK_SEQPACK_Association.h ADDED
+$(ACE_ROOT)/ace/SOCK_SEQPACK_Association.i ADDED
+$(ACE_ROOT)/ace/SOCK_SEQPACK_Association.cpp ADDED
+
+$(ACE_ROOT)/ace/Multihomed_INET_Addr.h ADDED
+$(ACE_ROOT)/ace/Multihomed_INET_Addr.i ADDED
+$(ACE_ROOT)/ace/Multihomed_INET_Addr.cpp ADDED
+
+$(ACE_ROOT)/bin/PerlACE/Process_Unix.pm MODIFIED
+$(ACE_ROOT)/bin/PerlACE/Process_Win32.pm MODIFIED
+
+$(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU MODIFIED
+$(ACE_ROOT)/include/makeinclude/platform_linux.GNU MODIFIED
+
+$(ACE_ROOT)/tests/Makefile MODIFIED
+$(ACE_ROOT)/tests/Multihomed_INET_Addr_Test.cpp ADDED
+$(ACE_ROOT)/tests/Multihomed_INET_Addr_Test.dsp ADDED
+$(ACE_ROOT)/tests/SOCK_SEQPACK_Association_Test.cpp ADDED
+$(ACE_ROOT)/tests/SOCK_SEQPACK_Association_Test.dsp ADDED
+$(ACE_ROOT)/tests/run_test.lst MODIFIED
+$(ACE_ROOT)/tests/run_tests.bat MODIFIED
+$(ACE_ROOT)/tests/tests.dsw MODIFIED
+
+$(ACE_ROOT)/performance-tests/SCTP/THANKS ADDED
+$(ACE_ROOT)/performance-tests/SCTP/README ADDED
+$(ACE_ROOT)/performance-tests/SCTP/README.SCTP ADDED
+$(ACE_ROOT)/performance-tests/SCTP/README.SCTP_in_ACE ADDED
+$(ACE_ROOT)/performance-tests/SCTP/README.SCTP_PERF_TEST ADDED
+$(ACE_ROOT)/performance-tests/SCTP/README.OpenSS7 ADDED
+$(ACE_ROOT)/performance-tests/SCTP/README.LKSCTP ADDED
+
+$(ACE_ROOT)/performance-tests/SCTP/Makefile ADDED
+$(ACE_ROOT)/performance-tests/SCTP/run_spectrum.pl ADDED
+
+$(ACE_ROOT)/performance-tests/SCTP/hist.h ADDED
+$(ACE_ROOT)/performance-tests/SCTP/hist.cpp ADDED
+
+$(ACE_ROOT)/performance-tests/SCTP/Options_Manager.h ADDED
+$(ACE_ROOT)/performance-tests/SCTP/Options_Manager.cpp ADDED
+
+$(ACE_ROOT)/performance-tests/SCTP/SOCK_STREAM_clt.cpp ADDED
+$(ACE_ROOT)/performance-tests/SCTP/SOCK_STREAM_srv.cpp ADDED
+
+$(ACE_ROOT)/performance-tests/SCTP/SOCK_SEQPACK_clt.cpp ADDED
+$(ACE_ROOT)/performance-tests/SCTP/SOCK_SEQPACK_srv.cpp ADDED
diff --git a/ACE/performance-tests/SCTP/SCTP.mpc b/ACE/performance-tests/SCTP/SCTP.mpc
new file mode 100644
index 00000000000..cba52013c32
--- /dev/null
+++ b/ACE/performance-tests/SCTP/SCTP.mpc
@@ -0,0 +1,61 @@
+// -*- MPC -*-
+// $Id$
+
+project(*SOCK_STREAM_clt) : aceexe {
+ avoids += ace_for_tao
+ exename = SOCK_STREAM_clt
+ source_files {
+ SOCK_STREAM_clt.cpp
+ Options_Manager.cpp
+ hist.cpp
+ }
+
+ // Some source code uses the sqrt and pow function and
+ // some UNIX operating systems need the math library to
+ // get the symbol.
+ verbatim(gnuace, local) {
+ LDLIBS += $(MATHLIB)
+ }
+}
+
+project(*SOCK_STREAM_srv) : aceexe {
+ exename = SOCK_STREAM_srv
+ source_files {
+ SOCK_STREAM_srv.cpp
+ Options_Manager.cpp
+ }
+}
+
+project(*SOCK_SEQPACK_clt) : aceexe {
+ avoids += ace_for_tao
+ exename = SOCK_SEQPACK_clt
+ source_files {
+ SOCK_SEQPACK_clt.cpp
+ Options_Manager.cpp
+ hist.cpp
+ }
+
+ // Some source code uses the sqrt and pow function and
+ // some UNIX operating systems need the math library to
+ // get the symbol.
+ verbatim(gnuace, local) {
+ LDLIBS += $(MATHLIB)
+ }
+}
+
+project(*SOCK_SEQPACK_srv) : aceexe {
+ avoids += ace_for_tao
+ exename = SOCK_SEQPACK_srv
+ source_files {
+ SOCK_SEQPACK_srv.cpp
+ Options_Manager.cpp
+ }
+}
+
+project(*SOCK_SEQPACK_Association_Test) : aceexe {
+ avoids += ace_for_tao
+ exename = SOCK_SEQPACK_Association_Test
+ source_files {
+ SOCK_SEQPACK_Association_Test.cpp
+ }
+}
diff --git a/ACE/performance-tests/SCTP/SOCK_SEQPACK_Association_Test.cpp b/ACE/performance-tests/SCTP/SOCK_SEQPACK_Association_Test.cpp
new file mode 100644
index 00000000000..bb423300062
--- /dev/null
+++ b/ACE/performance-tests/SCTP/SOCK_SEQPACK_Association_Test.cpp
@@ -0,0 +1,152 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// tests
+//
+// = FILENAME
+// SOCK_SEQPACK_Association_Test.cpp
+//
+// = DESCRIPTION
+//
+// Tests the methods get_local_addrs and get_remote_addrs of class
+// ACE_SOCK_SEQPACK_Association.
+//
+// This is not an automated "one-button" test. Rather, it prints
+// some output to a log file, so that an interested human can
+// inspect the output and get a vague notion of whether or not
+// the methods are working properly.
+//
+// = AUTHOR
+// Edward Mulholland (emulholl@atl.lmco.com)
+//
+// ============================================================================
+
+#include "ace/SOCK_SEQPACK_Association.h"
+#include "ace/SOCK_SEQPACK_Connector.h"
+#include "ace/INET_Addr.h"
+#include "ace/Log_Msg.h"
+
+void dump_names(const ACE_SOCK_SEQPACK_Association& assoc);
+
+int ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int status = 0; // Innocent until proven guilty
+
+ // object that manages the connection to the server
+ ACE_SOCK_SEQPACK_Connector connector;
+
+ // object that manages the data xfer between the client and server
+ ACE_SOCK_SEQPACK_Association dataStream;
+
+ // object that represents the server's IP address and port
+ ACE_INET_Addr serverAddr;
+
+ if (argc < 2) {
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("Usage: SOCK_SEQPACK_Association_Test hostname:port\n")));
+ status = 1;
+
+ } else if (serverAddr.set(argv[1])) {
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_INET_Addr::set")));
+ status = 1;
+
+ } else if (connector.connect (dataStream, serverAddr)) {
+
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_SOCK_SEQPACK_Connector::connect")));
+ status = 1;
+
+ } else {
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("Connected to server at %s\n"),
+ argv[1]));
+
+ dump_names(dataStream);
+ }
+
+ dataStream.close();
+
+ return status;
+}
+
+void dump_names(const ACE_SOCK_SEQPACK_Association& assoc)
+{
+ // Pre-declare for-loop index
+ size_t i = 0;
+
+ size_t in_out_size = 100;
+ ACE_INET_Addr in_out[100];
+
+ // Output char buffer
+ const size_t outbuf_size = 1024;
+ ACE_TCHAR outbuf[outbuf_size];
+
+ // Get local addresses of the association
+ if (assoc.get_local_addrs(in_out, in_out_size)) {
+
+ ACE_ERROR((LM_ERROR,
+ "%p\n",
+ "get_local_addrs"));
+ return;
+ }
+
+ ACE_DEBUG((LM_DEBUG, "Called get_local_addrs\n"));
+
+ // Print individual results of get_local_addrs
+ for (i = 0; i < in_out_size; ++i) {
+
+ if (in_out[i].addr_to_string(outbuf, outbuf_size)) {
+
+ ACE_ERROR((LM_ERROR,
+ "%p\n",
+ "addr_to_string"));
+ return;
+ }
+
+ ACE_DEBUG((LM_DEBUG,
+ "get_local_addrs[%i] = %s\n",
+ i,
+ outbuf));
+ }
+
+ // Reset in_out_size
+ in_out_size = 100;
+
+ // Get remote addresses of the association
+ if (assoc.get_remote_addrs(in_out, in_out_size)) {
+
+ ACE_ERROR((LM_ERROR,
+ "%p\n",
+ "get_remote_addrs"));
+ return;
+ }
+
+ ACE_DEBUG((LM_DEBUG, "Called get_remote_addrs\n"));
+
+ // Print individual results of get_remote_addrs
+ for (i = 0; i < in_out_size; ++i) {
+
+ if (in_out[i].addr_to_string(outbuf, outbuf_size)) {
+
+ ACE_ERROR((LM_ERROR,
+ "%p\n",
+ "addr_to_string"));
+ return;
+ }
+
+ ACE_DEBUG((LM_DEBUG,
+ "get_remote_addrs[%i] = %s\n",
+ i,
+ outbuf));
+ }
+}
+
+
diff --git a/ACE/performance-tests/SCTP/SOCK_SEQPACK_clt.cpp b/ACE/performance-tests/SCTP/SOCK_SEQPACK_clt.cpp
new file mode 100644
index 00000000000..7f98883bfad
--- /dev/null
+++ b/ACE/performance-tests/SCTP/SOCK_SEQPACK_clt.cpp
@@ -0,0 +1,308 @@
+// $Id$
+
+#include "ace/OS_Memory.h"
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_SEQPACK_Association.h"
+#include "ace/SOCK_SEQPACK_Connector.h"
+#include "ace/Log_Msg.h"
+#include "ace/CDR_Stream.h"
+#include "ace/High_Res_Timer.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/os_include/arpa/os_inet.h"
+
+// make sure that the code compiles cleanly even if SCTP is not
+// available. If SCTP is not installed, program will exit early in
+// main() with an error message
+#ifdef ACE_HAS_SCTP
+extern "C" {
+#include <netinet/sctp.h>
+};
+#else
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132
+#endif // !IPPROTO_SCTP
+#define SCTP_NODELAY 1
+#endif // ACE_HAS_SCTP
+
+// class that manages setting of options
+#include "Options_Manager.h"
+
+// histogram code
+#include "hist.h"
+
+// global constants
+ACE_CDR::UShort const primerIterations = 100;
+// ace/High_Res_Timer.h describes the need for the following.
+ACE_UINT32 const microsec_clock_scale_factor = ACE_High_Res_Timer::global_scale_factor();
+
+// forward declations of functions. Bodies follow main() to improve
+// file readability.
+ACE_SCTP::HIST runTest(ACE_SOCK_SEQPACK_Association &);
+
+int ACE_TMAIN (int argc, ACE_TCHAR **argv){
+
+ // Initialize the options manager
+ Options_Manager optsMgr(argc, argv, ACE_TEXT ("client-opts"));
+
+ // show usage is requested
+ if (optsMgr._usage) {
+ optsMgr._show_usage(stderr, ACE_TEXT ("client-opts"));
+ return 1;
+ }
+
+#ifndef ACE_HAS_SCTP
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("SCTP was NOT installed/accessible when this binary was compiled.\n")),
+ 1);
+#endif
+
+ // check that valid options were specified
+ if (optsMgr._error) {
+ ACE_OS::fprintf (stderr, "ERROR: %s\n", ACE_TEXT_ALWAYS_CHAR (optsMgr._error_message));
+ return 1;
+ }
+
+
+ // Create the address that we want the client to connect to
+ ACE_INET_Addr serverAddr(Options_Manager::server_port,
+ Options_Manager::server_host);
+
+ // Create the address that we want the client to connect FROM
+ ACE_Multihomed_INET_Addr clientAddr;
+ clientAddr.set(optsMgr.client_port,
+ optsMgr.client_connect_addr,
+ 1,
+ optsMgr.secondary_connect_addrs,
+ optsMgr.num_secondary_connect_addrs);
+
+ // object that manages the connection to the server
+ ACE_SOCK_SEQPACK_Connector connector;
+
+ // object that manages the data xfer between the client and server
+ ACE_SOCK_SEQPACK_Association dataStream;
+
+ // connect to the server
+ if (connector.connect (dataStream,
+ serverAddr,
+ 0,clientAddr, 0, 0, 0, optsMgr.test_transport_protocol) == -1) /*, // ALL DEFAULT ARGUMENTS
+ Options_Manager::test_transport_protocol) == -1) */
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("connection failed")),
+ 1);
+
+ // run the test
+ ACE_SCTP::HIST testResultsHistogram = 0;
+ // connection is closed by runTest* functions
+ testResultsHistogram = runTest(dataStream);
+
+ // report out the test statistics IF NO EXECPTIONS have been thrown
+ // all histograms created are placed onto a linked list that report()
+ // can access. So the histogram created in one of the *_test() functions
+ // will be reported out by the report() call
+ if (testResultsHistogram)
+ ACE_SCTP::report();
+
+ return 0;
+}
+
+// create a histogram to store test results
+ACE_SCTP::HIST createHistogram(ACE_CDR::ULong messageSize){
+ // The histogram created below lives beyond the scope of this
+ // function. So the memory allocated here cannot be cleaned up when
+ // this function goes out of scope. Unfortunately the histogram
+ // implementation does not clean it up either. So it is a small
+ // memory leak.
+ char * histName = (char *) malloc(200);
+
+ sprintf(histName, "%s Unmarshalled Msg Synchronous Latency Test\n\t\t\t\t\t(Message Size %u, Message Type octet)",
+ "ACE", messageSize);
+
+ // actually create the histogram
+ ACE_SCTP::HIST createdHist = ACE_SCTP::histogram(histName,
+ Options_Manager::histogram_bin_count,
+ Options_Manager::histogram_min_bin,
+ Options_Manager::histogram_max_bin);
+
+ // set the maximum number of outliers to maintain in the histogram
+ ACE_SCTP::set_outer(Options_Manager::histogram_num_outliers, createdHist);
+
+ return (createdHist);
+}
+
+// send the test header (only contains number of iterations)
+int sendHeader(ACE_SOCK_SEQPACK_Association & stream) {
+
+ // create an ACE CDR output stream and place the header information
+ // into it
+ ACE_OutputCDR hdrCDR;
+ hdrCDR << ACE_OutputCDR::from_boolean (ACE_CDR_BYTE_ORDER);
+ hdrCDR << ACE_CDR::ULong(Options_Manager::test_iterations+primerIterations);
+ if (!hdrCDR.good_bit())
+ return (0);
+
+ // send the header to the server (HEADER is 8 BYTES LONG)
+ size_t bt;
+ if (stream.send_n(hdrCDR.begin(), 0, &bt) == -1)
+ return 0;
+
+ return 1;
+}
+
+// conduct the UnMarshalled Octet performance test using separate
+// send_n calls with Nagle's algorithm disabled
+ACE_SCTP::HIST runUnmarshalledOctetTest(ACE_CDR::Octet *buf, size_t seqLen, ACE_SOCK_SEQPACK_Association & stream){
+
+ ACE_CDR::ULong const testIterations = Options_Manager::test_iterations;
+
+ size_t bt;
+ ACE_CDR::ULong cnt = 0;
+ // variables for the timing measurements
+ ACE_hrtime_t startTime, endTime;
+ ACE_CDR::Double messageLatency_usec = 0.0;
+ ACE_CDR::ULong msgLen = seqLen*ACE_CDR::OCTET_SIZE;
+
+ // explicity configure Nagling. Default is
+ // Options_Manager::test_enable_nagle=0 so default configurations is
+ // NO NAGLING
+ ACE_CDR::Long nagle;
+ if (Options_Manager::test_enable_nagle)
+ nagle=0;
+ else
+ nagle=1;
+ if (-1 == stream.set_option(IPPROTO_SCTP, SCTP_NODELAY, &nagle, sizeof nagle))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("set_option")),
+ 0);
+
+ // prime the client and server before starting the test
+ for(cnt=0;cnt<primerIterations;++cnt){
+
+ // send message size
+ // TODO : The message length should be CDR encoded
+ ACE_CDR::ULong msgLenExpressed = ACE_HTONL(msgLen);
+ if (-1 == stream.send_n (&msgLenExpressed, ACE_CDR::LONG_SIZE, 0, &bt))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")),
+ 0);
+
+ // send a message
+ if (-1 == stream.send_n (buf, msgLen, 0, &bt))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")),
+ 0);
+
+ // block for a Short reply
+ ACE_CDR::Short reply;
+ if ((stream.recv_n(&reply, ACE_CDR::SHORT_SIZE, 0, &bt)) == -1)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv_n")),
+ 0);
+ }
+
+ // AFTER PRIMING THE PUMP CREATE THE HISTOGRAM
+ ACE_SCTP::HIST aceStream_hist = 0;
+ aceStream_hist = createHistogram(msgLen);
+ if (0 == aceStream_hist)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("histogram create failed")),
+ 0);
+
+ iovec iov[2];
+ // PERFORMANCE TEST LOOP
+ for (cnt = 0; cnt < testIterations; ++cnt){
+
+ // get the start time
+ startTime = ACE_OS::gethrtime();
+ if (!startTime)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_OS::gethrtime()")),
+ 0);
+
+ ACE_CDR::ULong msgLenExpressed = ACE_HTONL(msgLen);
+ iov[0].iov_base = reinterpret_cast<char *> (&msgLenExpressed);
+ iov[0].iov_len = ACE_CDR::LONG_SIZE;
+ iov[1].iov_base = reinterpret_cast<char *> (buf);
+ iov[1].iov_len = msgLen;
+
+ if (-1 == stream.sendv_n (iov, 2))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")),
+ 0);
+
+ // block for a Short reply
+ ACE_CDR::Short reply;
+ if ((stream.recv_n(&reply, ACE_CDR::SHORT_SIZE, 0, &bt)) == -1)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv_n")),
+ 0);
+
+ // get the end time
+ endTime = ACE_OS::gethrtime();
+ if (!endTime)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_OS::gethrtime()")),
+ 0);
+
+ // compute the message latency in micro-seconds
+ messageLatency_usec =
+
+ (static_cast<double> (ACE_UINT64_DBLCAST_ADAPTER(endTime)) -
+ static_cast<double> (ACE_UINT64_DBLCAST_ADAPTER(startTime)))
+
+ / microsec_clock_scale_factor;
+
+
+ // record the message latency in the histogram
+ ACE_SCTP::record(messageLatency_usec, aceStream_hist);
+ }
+
+ // THE HEADER MESSAGE SENT TO THE SERVER CONTAINED THE NUMBER OF
+ // PRIMER AND TEST MESSAGES TO BE SENT AFTER WHICH THE SERVER WILL
+ // CLOSE THE STREAM SO ONCE WE REACH THIS POINT THE STREAM IS NO
+ // LONGER VALID AND WE CLOSE IT.
+ stream.close();
+
+ // allocated by runTest
+ delete[] buf;
+ return aceStream_hist;
+}
+
+// sends the test information to the server and calls the correct test
+// function.
+ACE_SCTP::HIST runTest(ACE_SOCK_SEQPACK_Association & stream)
+{
+ size_t msgLen = 1;
+ for (int i=1; i <= Options_Manager::payload_size_power_of_2; i++)
+ msgLen *= 2;
+
+
+
+ // send a header to the server that contains test parameters
+ if (sendHeader(stream) < 0)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("Could NOT Send CDR Encoded Header")),
+ 0);
+
+ // create the forward message buffer
+
+ ACE_CDR::Octet *o_arr;
+ ACE_CDR::ULong seqLen = msgLen/ACE_CDR::OCTET_SIZE;
+ ACE_NEW_RETURN(o_arr,
+ ACE_CDR::Octet[seqLen],
+ 0);
+ // o_arr is deleted in run_octet_test
+ return(runUnmarshalledOctetTest(o_arr, seqLen, stream));
+}
diff --git a/ACE/performance-tests/SCTP/SOCK_SEQPACK_srv.cpp b/ACE/performance-tests/SCTP/SOCK_SEQPACK_srv.cpp
new file mode 100644
index 00000000000..84db9afc541
--- /dev/null
+++ b/ACE/performance-tests/SCTP/SOCK_SEQPACK_srv.cpp
@@ -0,0 +1,359 @@
+// $Id$
+
+#include "ace/Multihomed_INET_Addr.h"
+#include "ace/SOCK_SEQPACK_Association.h"
+#include "ace/SOCK_SEQPACK_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Handle_Set.h"
+#include "ace/CDR_Stream.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/os_include/arpa/os_inet.h"
+#include "ace/OS_NS_sys_select.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_arpa_inet.h"
+
+// make sure that the code compiles cleanly even if SCTP is not
+// available. If SCTP is not installed, program will exit early in
+// main() with an error message
+#ifdef ACE_HAS_SCTP
+extern "C" {
+#include <netinet/sctp.h>
+};
+#else
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132
+#endif // !IPPROTO_SCTP
+#define SCTP_NODELAY 1
+#endif
+
+// class that manages setting of options
+#include "Options_Manager.h"
+
+// structure to bundle arguments for thread functions
+struct ArgStruct {
+ ACE_SOCK_SEQPACK_Association * stream;
+ ACE_CDR::ULong numIters;
+};
+
+// thread function that serves the client for the UnMarshalled Octet
+// test
+static ACE_THR_FUNC_RETURN unmarshalledOctetServer (void *arg){
+
+ // unbundle the arguments
+ ArgStruct * args = reinterpret_cast<ArgStruct *> (arg);
+ ACE_SOCK_SEQPACK_Association * dataModeStream = args->stream;
+ ACE_CDR::ULong numIterations = args->numIters;
+ delete args;
+
+ // serve the client for numIterations synchronous invocations
+ do {
+
+ // READ A MESSAGE FROM THE CLIENT
+
+ size_t bt;
+ ACE_CDR::ULong msgBufSize=0;
+ // read the size of the buffer to follow
+ if ((dataModeStream->recv_n(&msgBufSize, ACE_CDR::LONG_SIZE, 0, &bt)) == -1)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv_n")),
+ 0);
+ msgBufSize = ACE_NTOHL(msgBufSize);
+
+ // allocate the buffer for the message payload
+ ACE_CDR::Octet * msgBuf = 0;
+ ACE_NEW_RETURN(msgBuf,
+ ACE_CDR::Octet[msgBufSize],
+ 0);
+
+ // read the buffer
+ if ((dataModeStream->recv_n(msgBuf, msgBufSize, 0, &bt)) == -1)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv_n")),
+ 0);
+
+ // clean up the allocated buffer
+ delete[] msgBuf;
+
+ // SEND A REPLY TO THE CLIENT
+
+ // send back a 2 byte reply
+ ACE_CDR::Short reply;
+ if ((dataModeStream->send_n(&reply, ACE_CDR::SHORT_SIZE, 0, &bt)) == -1)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")),
+ 0);
+
+ } while (--numIterations);
+
+ // close and destroy the stream
+ dataModeStream->close();
+ delete dataModeStream;
+
+ return 0;
+}
+
+// sets up the dataModeSocket Stream, reads the test header infomation
+// and launches a thread to handle the requested test.
+static void run_server (ACE_HANDLE handle)
+{
+ ACE_INET_Addr cli_addr;
+ // create a new stream and initialized with the handle returned by
+ // accept
+ ACE_SOCK_SEQPACK_Association * dataModeStream = new ACE_SOCK_SEQPACK_Association;
+ dataModeStream->set_handle (handle);
+
+ // Make sure we're not in non-blocking mode.
+ if (dataModeStream->disable (ACE_NONBLOCK) == -1){
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("disable")));
+ return;
+ }
+ else if (dataModeStream->get_remote_addr (cli_addr) == -1){
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "get_remote_addr"));
+ return;
+ }
+
+ // explicity configure Nagling. Default is
+ // Options_Manager::test_enable_nagle=0 so default configurations is
+ // NO NAGLING
+ ACE_CDR::Long nagle;
+ if (Options_Manager::test_enable_nagle)
+ nagle=0;
+ else
+ nagle=1;
+
+ if (-1 == dataModeStream->set_option(IPPROTO_SCTP, SCTP_NODELAY, &nagle, sizeof nagle)){
+ // can't ise ACE_ERROR_RETURN b/c function has void return value
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("set_option")));
+ return;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT("(%P|%t) client %C connected from %d\n"),
+ cli_addr.get_host_name (),
+ cli_addr.get_port_number ()));
+
+ // hdr bufSize is hardcoded to 8 bytes
+ // (4 for a CDR-encoded boolean and 4 for a CDR-encoded ULong)
+ ACE_CDR::ULong hdrBufSize = 8;
+ // allocate a raw buffer large enough to receive the header and be
+ // properly aligned for the CDR decoding.
+ ACE_CDR::Char * hdrBuf= new ACE_CDR::Char[hdrBufSize+ACE_CDR::MAX_ALIGNMENT];
+ // align the raw buffer before reading data into it.
+ char * hdrBuf_a = ACE_ptr_align_binary(hdrBuf, ACE_CDR::MAX_ALIGNMENT);
+
+ size_t bt;
+ // read the header
+ if ((dataModeStream->recv_n(hdrBuf_a, hdrBufSize, 0, &bt)) == -1){
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv_n")));
+ return;
+ }
+
+ // pass the CDR encoded data into an ACE_InputCDR class. hdrCDR does
+ // NOT copy this data. Nor does it delete. It assumes the buffer
+ // remains valid while it is in scope.
+ ACE_InputCDR hdrCDR(hdrBuf_a, hdrBufSize);
+
+ ACE_CDR::Boolean byteOrder;
+ ACE_CDR::ULong numIterations;
+
+ // extract the data
+ hdrCDR >> ACE_InputCDR::to_boolean (byteOrder);
+ hdrCDR.reset_byte_order(byteOrder);
+ hdrCDR >> numIterations;
+
+ // make sure the stream is good after the extractions
+ if (!hdrCDR.good_bit()){
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("hdrCDR")));
+
+ return;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Test for %u iterations\n"),
+ numIterations));
+
+ // deallocate the header buffer
+ delete[] hdrBuf;
+
+ // bundle up the arguments
+ ArgStruct * args = new ArgStruct;
+ args->stream = dataModeStream;
+ args->numIters = numIterations;
+
+#if defined (ACE_HAS_THREADS)
+ // Spawn a new thread and run the new connection in that thread of
+ // control using the <server> function as the entry point.
+ if (ACE_Thread_Manager::instance ()->spawn (unmarshalledOctetServer,
+ reinterpret_cast<void *> (args),
+ THR_DETACHED) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("spawn")));
+#else
+ (*unmarshalledOctetServer) (reinterpret_cast<void *> (args));
+#endif /* ACE_HAS_THREADS */
+
+}
+
+int ACE_TMAIN (int argc, ACE_TCHAR **argv){
+
+ Options_Manager optsMgr(argc, argv, ACE_TEXT ("server-opts"));
+
+ // show usage is requested
+ if (optsMgr._usage) {
+ optsMgr._show_usage(stderr, ACE_TEXT ("server-opts"));
+ return 1;
+ }
+
+#ifndef ACE_HAS_SCTP
+ // SCTP is not installed. Exit with informative error message.
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("SCTP was NOT installed/accessible when this binary was compiled.\n")),
+ 1);
+#endif
+
+ // check that valid options were specified
+ if (optsMgr._error) {
+ ACE_OS::fprintf (stderr, "ERROR: %s\n", ACE_TEXT_ALWAYS_CHAR (optsMgr._error_message));
+ return 1;
+ }
+
+ // this is the socket that the server will listen on
+ ACE_SOCK_SEQPACK_Acceptor acceptor_socket;
+
+ // Create the address that we want to listen for connections on. If
+ // server_accept_addr=INADDR_ANY (the default), SCTP will listen for
+ // connections on all IP interfaces. If an address is specified,
+ // SCTP will listen for connections on that address ONLY.
+ ACE_Multihomed_INET_Addr serverAddr;
+
+ serverAddr.set(optsMgr.server_port,
+ optsMgr.server_accept_addr,
+ 1,
+ optsMgr.secondary_accept_addrs,
+ optsMgr.num_secondary_accept_addrs);
+
+ // this operation creates a socket, binds the specified internet
+ // address to it and calls listen. As this is a wrapper facade
+ // approach, the ACE_OS::{socket,bind,listen} calls are invoked in
+ // the implementation of open.
+ if (acceptor_socket.open(serverAddr, 1,
+ AF_INET,
+ ACE_DEFAULT_BACKLOG,
+ optsMgr.test_transport_protocol) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")),
+ 1);
+
+ // this function checks that the port that was actually bound was
+ // the port we asked for. Apparently some operating systems will
+ // automatically select new ports if the specified port is currently
+ // used.
+ if (acceptor_socket.get_local_addr(serverAddr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get_local_addr")),
+ 1);
+
+ sockaddr_in *addresses = new sockaddr_in[ 1 + serverAddr.get_num_secondary_addresses() ];
+ serverAddr.get_addresses( addresses, 1 + serverAddr.get_num_secondary_addresses() ) ;
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Accepting connections, using %C on ")
+ ACE_TEXT ("port %u on interfaces %C"),
+ (optsMgr.test_transport_protocol == IPPROTO_SCTP) ? "IPPROTO_SCTP" : "IPPROTO_TCP",
+ serverAddr.get_port_number(),
+ ACE_OS::inet_ntoa( addresses[0].sin_addr) ));
+
+ unsigned int i;
+ for(i=1; i <= serverAddr.get_num_secondary_addresses() ; ++i ) {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT (" and %C"),
+ ACE_OS::inet_ntoa (addresses[i].sin_addr)));
+ }
+ ACE_DEBUG((LM_DEBUG, ACE_TEXT ("\n")));
+
+ delete[] addresses;
+
+ // this is the stream object that will associated with a completed
+ // connection (aka the data mode socket). It will be set when accept
+ // is called below.
+ ACE_SOCK_SEQPACK_Association new_stream;
+
+ // a file decriptor set
+ ACE_Handle_Set handle_set;
+ // add the acceptor socket to the file descriptor set.
+ handle_set.set_bit(acceptor_socket.get_handle());
+
+ for (;;){
+
+ ACE_Time_Value timeout(ACE_DEFAULT_TIMEOUT);
+ ACE_Handle_Set temp = handle_set;
+
+ // wait for connect() call from client. In the original test there
+ // were two different acceptor sockets for two different
+ // services. So select was needed to wait on both sockets
+ // simultaneously. In this test we could just call accept on the
+ // one socket.
+ int result = ACE_OS::select((int) (acceptor_socket.get_handle()) +1,
+ (fd_set *) temp,
+ 0,
+ 0,
+ timeout);
+
+ // check that select did not end with an error.
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("select")));
+ // check to see if select timed out.
+ else if (result == 0){
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) select timed out\n")));
+
+ }
+ else { // case where a file descriptor was actually set
+ if (!(temp.is_set(acceptor_socket.get_handle()))){
+ // CANNOT BE REACHED
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("select: NO ERROR BUT NO FD SET")));
+ } else {
+ // call accept to set up the new stream.
+ if (acceptor_socket.accept(new_stream) == -1) {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("accept")));
+ continue;
+ }
+ else{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) spawning server\n")));
+
+ }
+ // Run the server.
+ run_server (new_stream.get_handle ());
+ }
+
+ }
+
+ }
+ return 0;
+}
diff --git a/ACE/performance-tests/SCTP/SOCK_SEQPACK_wrapper_facade.jpg b/ACE/performance-tests/SCTP/SOCK_SEQPACK_wrapper_facade.jpg
new file mode 100755
index 00000000000..3cb82002fe5
--- /dev/null
+++ b/ACE/performance-tests/SCTP/SOCK_SEQPACK_wrapper_facade.jpg
Binary files differ
diff --git a/ACE/performance-tests/SCTP/SOCK_STREAM_clt.cpp b/ACE/performance-tests/SCTP/SOCK_STREAM_clt.cpp
new file mode 100644
index 00000000000..365890265b1
--- /dev/null
+++ b/ACE/performance-tests/SCTP/SOCK_STREAM_clt.cpp
@@ -0,0 +1,318 @@
+// $Id$
+
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/Log_Msg.h"
+#include "ace/CDR_Stream.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/OS_Memory.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/os_include/netinet/os_tcp.h"
+#include "ace/os_include/arpa/os_inet.h"
+
+// make sure that the code compiles cleanly even if SCTP is not
+// available. If SCTP is not installed, program will exit early in
+// main() with an error message
+#ifdef ACE_HAS_SCTP
+extern "C" {
+#include <netinet/sctp.h>
+};
+#else
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132
+#endif
+#define SCTP_NODELAY -1
+#endif
+
+// class that manages setting of options
+#include "Options_Manager.h"
+
+// histogram code
+#include "hist.h"
+
+// global constants
+ACE_CDR::UShort const primerIterations = 100;
+// ace/High_Res_Timer.h describes the need for the following.
+ACE_UINT32 const microsec_clock_scale_factor = ACE_High_Res_Timer::global_scale_factor();
+
+// forward declations of functions. Bodies follow main() to improve
+// file readability.
+ACE_SCTP::HIST runTest(ACE_SOCK_Stream &);
+
+int ACE_TMAIN (int argc, ACE_TCHAR **argv){
+
+ // Initialize the options manager
+ Options_Manager optsMgr(argc, argv, ACE_TEXT ("client-opts"));
+
+ // show usage if requested
+ if (optsMgr._usage) {
+ optsMgr._show_usage(stderr, ACE_TEXT ("client-opts"));
+ return 1;
+ }
+
+ // If SCTP is not installed then terminate the program, unless TCP
+ // was specified.
+#ifndef ACE_HAS_SCTP
+ if (optsMgr.test_transport_protocol == IPPROTO_SCTP)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("SCTP was NOT installed when this binary was compiled.\nSOCK_STREAM_clt may still be run using TCP via the '-t tcp' option.\n")),
+ 1);
+#endif
+
+ // check that valid options were specified
+ if (optsMgr._error) {
+ ACE_OS::fprintf (stderr, "ERROR: %s\n", ACE_TEXT_ALWAYS_CHAR (optsMgr._error_message));
+ return 1;
+ }
+
+
+ // Create the address that we want the client to connect to
+ ACE_INET_Addr serverAddr(Options_Manager::server_port,
+ Options_Manager::server_host);
+
+ // Create the address that we want the client to connect FROM
+ ACE_INET_Addr clientAddr(Options_Manager::client_port,
+ Options_Manager::client_connect_addr);
+
+ // object that manages the connection to the server
+ ACE_SOCK_Connector connector;
+
+ // object that manages the data xfer between the client and server
+ ACE_SOCK_Stream dataStream;
+
+ // connect to the server
+ if (connector.connect (dataStream,
+ serverAddr,
+ 0,clientAddr, 0, 0, 0, // ALL DEFAULT ARGUMENTS
+ Options_Manager::test_transport_protocol) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("connection failed")),
+ 1);
+
+ // run the test
+ ACE_SCTP::HIST testResultsHistogram = 0;
+ // connection is closed by runTest* functions
+ testResultsHistogram = runTest(dataStream);
+
+ // report out the test statistics.
+ // all histograms created are placed onto a linked list that report()
+ // can access. So the histogram created in one of the *_test() functions
+ // will be reported out by the report() call
+ if (testResultsHistogram)
+ ACE_SCTP::report();
+
+ return 0;
+}
+
+ // create a histogram to store test results
+ ACE_SCTP::HIST createHistogram(ACE_CDR::ULong messageSize){
+
+ // The histogram created below lives beyond the scope of this
+ // function. So the memory allocated here cannot be cleaned up when
+ // this function goes out of scope. Unfortunately the histogram
+ // implementation does not clean it up either. So it is a small
+ // memory leak.
+ char * histName = (char *) malloc(200);
+
+ sprintf(histName, "%s Unmarshalled Msg Synchronous Latency Test\n\t\t\t\t\t(Message Size %u, Message Type octet)",
+ "ACE", messageSize);
+
+ // actually create the histogram
+ ACE_SCTP::HIST createdHist = ACE_SCTP::histogram(histName,
+ Options_Manager::histogram_bin_count,
+ Options_Manager::histogram_min_bin,
+ Options_Manager::histogram_max_bin);
+
+ // set the maximum number of outliers to maintain in the histogram
+ ACE_SCTP::set_outer(Options_Manager::histogram_num_outliers, createdHist);
+
+ return (createdHist);
+}
+
+// send the test header (only contains number of iterations)
+int sendHeader(ACE_SOCK_Stream & stream) {
+
+ // create an ACE CDR output stream and place the header information
+ // into it
+ ACE_OutputCDR hdrCDR;
+ hdrCDR << ACE_OutputCDR::from_boolean (ACE_CDR_BYTE_ORDER);
+ hdrCDR << ACE_CDR::ULong(Options_Manager::test_iterations+primerIterations);
+ if (!hdrCDR.good_bit())
+ return (0);
+
+ // send the header to the server (HEADER IS 8 BYTES LONG)
+ size_t bt;
+ if (stream.send_n(hdrCDR.begin(), 0, &bt) == -1)
+ return 0;
+
+ return 1;
+}
+
+// conduct the UnMarshalled Octet performance test using separate
+// send_n calls with Nagle's algorithm disabled
+ACE_SCTP::HIST runUnmarshalledOctetTest(ACE_CDR::Octet *buf, size_t seqLen, ACE_SOCK_Stream & stream){
+
+ ACE_CDR::ULong const testIterations = Options_Manager::test_iterations;
+
+ size_t bt;
+ ACE_CDR::ULong cnt = 0;
+ // variables for the timing measurements
+ ACE_hrtime_t startTime, endTime;
+ ACE_CDR::Double messageLatency_usec = 0.0;
+ ACE_CDR::ULong msgLen = seqLen*ACE_CDR::OCTET_SIZE;
+
+ // explicity configure Nagling. Default is
+ // Options_Manager::test_enable_nagle=0 so default configurations is
+ // NO NAGLING
+ ACE_CDR::Long nagle;
+ if (Options_Manager::test_enable_nagle)
+ nagle=0;
+ else
+ nagle=1;
+ if (Options_Manager::test_transport_protocol == IPPROTO_SCTP){
+ // default - sctp case
+ if (-1 == stream.set_option(IPPROTO_SCTP, SCTP_NODELAY, &nagle, sizeof nagle))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "set_option"),
+ 0);
+ } else {
+ // tcp case
+ if (-1 == stream.set_option(IPPROTO_TCP, TCP_NODELAY, &nagle, sizeof nagle))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "set_option"),
+ 0);
+ }
+
+ // prime the client and server before starting the test
+ for(cnt=0;cnt<primerIterations;++cnt){
+
+ // send message size
+ // TODO : The message length should be CDR encoded
+ ACE_CDR::ULong msgLenExpressed = ACE_HTONL(msgLen);
+ if (-1 == stream.send_n (&msgLenExpressed, ACE_CDR::LONG_SIZE, 0, &bt))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "send_n"),
+ 0);
+
+ // send a message
+ if (-1 == stream.send_n (buf, msgLen, 0, &bt))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "send_n"),
+ 0);
+
+ // block for a Short reply
+ ACE_CDR::Short reply;
+ if ((stream.recv_n(&reply, ACE_CDR::SHORT_SIZE, 0, &bt)) == -1)
+ ACE_ERROR_RETURN((LM_ERROR,
+ "%p\n",
+ "recv_n"),
+ 0);
+ }
+
+ // AFTER PRIMING THE PUMP CREATE THE HISTOGRAM
+ ACE_SCTP::HIST aceStream_hist = 0;
+ aceStream_hist = createHistogram(msgLen);
+ if (0 == aceStream_hist)
+ ACE_ERROR_RETURN((LM_ERROR,
+ "%p\n",
+ "histogram create failed"),
+ 0);
+
+ iovec iov[2];
+ // PERFORMANCE TEST LOOP
+ for (cnt = 0; cnt < testIterations; ++cnt){
+
+ // get the start time
+ startTime = ACE_OS::gethrtime();
+ if (!startTime)
+ ACE_ERROR_RETURN((LM_ERROR,
+ "%p\n",
+ "ACE_OS::gethrtime()"),
+ 0);
+
+
+ ACE_CDR::ULong msgLenExpressed = ACE_HTONL(msgLen);
+ iov[0].iov_base = reinterpret_cast<char *> (&msgLenExpressed);
+ iov[0].iov_len = ACE_CDR::LONG_SIZE;
+ iov[1].iov_base = reinterpret_cast<char *> (buf);
+ iov[1].iov_len = msgLen;
+
+ if (-1 == stream.sendv_n (iov, 2))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%p\n",
+ "send_n"),
+ 0);
+
+ // block for a Short reply
+ ACE_CDR::Short reply;
+ if ((stream.recv_n(&reply, ACE_CDR::SHORT_SIZE, 0, &bt)) == -1)
+ ACE_ERROR_RETURN((LM_ERROR,
+ "%p\n",
+ "recv_n"),
+ 0);
+
+ // get the end time
+ endTime = ACE_OS::gethrtime();
+ if (!endTime)
+ ACE_ERROR_RETURN((LM_ERROR,
+ "%p\n",
+ "ACE_OS::gethrtime()"),
+ 0);
+
+ // compute the message latency in micro-seconds
+ messageLatency_usec =
+
+ (static_cast<double> (ACE_UINT64_DBLCAST_ADAPTER(endTime)) -
+ static_cast<double> (ACE_UINT64_DBLCAST_ADAPTER(startTime)))
+
+ / microsec_clock_scale_factor;
+
+ // record the message latency in the histogram
+ ACE_SCTP::record(messageLatency_usec, aceStream_hist);
+ }
+
+ // THE HEADER MESSAGE SENT TO THE SERVER CONTAINED THE NUMBER OF
+ // PRIMER AND TEST MESSAGES TO BE SENT AFTER WHICH THE SERVER WILL
+ // CLOSE THE STREAM SO ONCE WE REACH THIS POINT THE STREAM IS NO
+ // LONGER VALID AND WE CLOSE IT.
+ stream.close();
+
+ // allocated by runTest
+ delete[] buf;
+ return aceStream_hist;
+}
+
+// sends the test information to the server and calls the correct test
+// function.
+ACE_SCTP::HIST runTest(ACE_SOCK_Stream & stream)
+{
+
+ size_t msgLen = 1;
+ for (int i=1; i <= Options_Manager::payload_size_power_of_2; i++)
+ msgLen *= 2;
+
+ // send a header to the server that contains test parameters
+ if (sendHeader(stream) < 0)
+ ACE_ERROR_RETURN((LM_ERROR,
+ "Could NOT Send CDR Encoded Header"),
+ 0);
+
+ // create the forward message buffer
+
+ ACE_CDR::Octet *o_arr;
+ ACE_CDR::ULong seqLen = msgLen/ACE_CDR::OCTET_SIZE;
+ ACE_NEW_RETURN(o_arr,
+ ACE_CDR::Octet[seqLen],
+ 0);
+ // o_arr is deleted in run_octet_test
+ return(runUnmarshalledOctetTest(o_arr, seqLen, stream));
+}
diff --git a/ACE/performance-tests/SCTP/SOCK_STREAM_srv.cpp b/ACE/performance-tests/SCTP/SOCK_STREAM_srv.cpp
new file mode 100644
index 00000000000..c2d3cceb1fc
--- /dev/null
+++ b/ACE/performance-tests/SCTP/SOCK_STREAM_srv.cpp
@@ -0,0 +1,358 @@
+// $Id$
+
+#include "ace/INET_Addr.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/Log_Msg.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Handle_Set.h"
+#include "ace/CDR_Stream.h"
+
+// FUZZ: disable check_for_streams_include
+#include "ace/streams.h"
+
+#include "ace/os_include/netinet/os_tcp.h"
+#include "ace/os_include/arpa/os_inet.h"
+#include "ace/OS_NS_sys_select.h"
+
+// make sure that the code compiles cleanly even if SCTP is not
+// available. If SCTP is not installed, program will exit early in
+// main() with an error message
+#ifdef ACE_HAS_SCTP
+extern "C" {
+#include <netinet/sctp.h>
+};
+#else
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132 /* always the same value on every platform */
+#endif
+#define SCTP_NODELAY -1
+#endif
+
+// class that manages setting of options
+#include "Options_Manager.h"
+
+// structure to bundle arguments for thread functions
+struct ArgStruct {
+ ACE_SOCK_Stream * stream;
+ ACE_CDR::ULong numIters;
+};
+
+// thread function that serves the client for the UnMarshalled Octet
+// test
+static ACE_THR_FUNC_RETURN unmarshalledOctetServer (void *arg){
+
+ // unbundle the arguments
+ ArgStruct * args = reinterpret_cast<ArgStruct *> (arg);
+ ACE_SOCK_Stream * dataModeStream = args->stream;
+ ACE_CDR::ULong numIterations = args->numIters;
+ delete args;
+
+ // serve the client for numIterations synchronous invocations
+ do {
+
+ // READ A MESSAGE FROM THE CLIENT
+
+ size_t bt;
+ ACE_CDR::ULong msgBufSize=0;
+ // read the size of the buffer to follow
+ if ((dataModeStream->recv_n(&msgBufSize, ACE_CDR::LONG_SIZE, 0, &bt)) == -1)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv_n")),
+ 0);
+ msgBufSize = ACE_NTOHL(msgBufSize);
+
+ // allocate the buffer for the message payload
+ ACE_CDR::Octet * msgBuf = 0;
+ ACE_NEW_RETURN(msgBuf,
+ ACE_CDR::Octet[msgBufSize],
+ 0);
+
+ // read the buffer
+ if ((dataModeStream->recv_n(msgBuf, msgBufSize, 0, &bt)) == -1)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv_n")),
+ 0);
+
+ // clean up the allocated buffer
+ delete[] msgBuf;
+
+ // SEND A REPLY TO THE CLIENT
+
+ // send back a 2 byte reply
+ ACE_CDR::Short reply;
+ if ((dataModeStream->send_n(&reply, ACE_CDR::SHORT_SIZE, 0, &bt)) == -1)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("send_n")),
+ 0);
+
+ } while (--numIterations);
+
+ // close and destroy the stream
+ dataModeStream->close();
+ delete dataModeStream;
+
+ return 0;
+}
+
+// sets up the dataModeSocket Stream, reads the test header infomation
+// and launches a thread to handle the requested test.
+static void run_server (ACE_HANDLE handle)
+{
+ ACE_INET_Addr cli_addr;
+ // create a new stream and initialized with the handle returned by
+ // accept
+ ACE_SOCK_Stream * dataModeStream = new ACE_SOCK_Stream;
+ dataModeStream->set_handle (handle);
+
+ // Make sure we're not in non-blocking mode.
+ if (dataModeStream->disable (ACE_NONBLOCK) == -1){
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("disable")));
+ return;
+ }
+ else if (dataModeStream->get_remote_addr (cli_addr) == -1){
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get_remote_addr")));
+ return;
+ }
+
+ // explicity configure Nagling. Default is
+ // Options_Manager::test_enable_nagle=0 so default configurations is
+ // NO NAGLING
+ ACE_CDR::Long nagle;
+ if (Options_Manager::test_enable_nagle)
+ nagle=0;
+ else
+ nagle=1;
+
+ if (Options_Manager::test_transport_protocol == IPPROTO_SCTP){
+ // default - sctp case
+ if (-1 == dataModeStream->set_option(IPPROTO_SCTP, SCTP_NODELAY, &nagle, sizeof nagle)){
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("set_option")));
+ return;
+ }
+ } else {
+ // tcp case
+ if (-1 == dataModeStream->set_option(IPPROTO_TCP, TCP_NODELAY, &nagle, sizeof nagle)){
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "set_option"));
+ return;
+ }
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) client %C connected from %d\n"),
+ cli_addr.get_host_name (),
+ cli_addr.get_port_number ()));
+
+ // hdr bufSize is hardcoded to 8 bytes
+ // (4 for a CDR-encoded boolean and 4 for a CDR-encoded ULong)
+ ACE_CDR::ULong hdrBufSize = 8;
+ // allocate a raw buffer large enough to receive the header and be
+ // properly aligned for the CDR decoding.
+ ACE_CDR::Char * hdrBuf= new ACE_CDR::Char[hdrBufSize+ACE_CDR::MAX_ALIGNMENT];
+ // align the raw buffer before reading data into it.
+ char * hdrBuf_a = ACE_ptr_align_binary(hdrBuf, ACE_CDR::MAX_ALIGNMENT);
+
+ size_t bt;
+ // read the header
+ if ((dataModeStream->recv_n(hdrBuf_a, hdrBufSize, 0, &bt)) == -1){
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("recv_n")));
+ return;
+ }
+
+ // pass the CDR encoded data into an ACE_InputCDR class. hdrCDR does
+ // NOT copy this data. Nor does it delete. It assumes the buffer
+ // remains valid while it is in scope.
+ ACE_InputCDR hdrCDR(hdrBuf_a, hdrBufSize);
+
+ ACE_CDR::Boolean byteOrder;
+ ACE_CDR::ULong numIterations;
+
+ // extract the data
+ hdrCDR >> ACE_InputCDR::to_boolean (byteOrder);
+ hdrCDR.reset_byte_order(byteOrder);
+ hdrCDR >> numIterations;
+
+ // make sure the stream is good after the extractions
+ if (!hdrCDR.good_bit()){
+ ACE_ERROR((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("hdrCDR")));
+
+ return;
+ }
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Test for %u iterations\n"),
+ numIterations));
+
+ // deallocate the header buffer
+ delete[] hdrBuf;
+
+ // bundle up the arguments
+ ArgStruct * args = new ArgStruct;
+ args->stream = dataModeStream;
+ args->numIters = numIterations;
+
+#if defined (ACE_HAS_THREADS)
+ // Spawn a new thread and run the new connection in that thread of
+ // control using the <server> function as the entry point.
+ if (ACE_Thread_Manager::instance ()->spawn (unmarshalledOctetServer,
+ reinterpret_cast<void *> (args),
+ THR_DETACHED) == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("spawn")));
+#else
+ (*unmarshalledOctetServer) (reinterpret_cast<void *> (args));
+#endif /* ACE_HAS_THREADS */
+
+}
+
+int ACE_TMAIN (int argc, ACE_TCHAR **argv){
+
+ Options_Manager optsMgr(argc, argv, ACE_TEXT ("server-opts"));
+
+ // show usage is requested
+ if (optsMgr._usage) {
+ optsMgr._show_usage(stderr, ACE_TEXT ("server-opts"));
+ return 1;
+ }
+
+ // If SCTP is not installed then terminate the program, unless TCP
+ // was specified.
+#ifndef ACE_HAS_SCTP
+ if (optsMgr.test_transport_protocol == IPPROTO_SCTP)
+ ACE_ERROR_RETURN((LM_ERROR,
+ ACE_TEXT ("SCTP was NOT installed when this binary was compiled.\n")
+ ACE_TEXT ("SOCK_STREAM_srv may still be run using TCP ")
+ ACE_TEXT ("via the '-t tcp' option.\n")),
+ 1);
+#endif
+
+ // check that valid options were specified
+ if (optsMgr._error) {
+ ACE_OS::fprintf (stderr, "ERROR: %s\n", ACE_TEXT_ALWAYS_CHAR (optsMgr._error_message));
+ return 1;
+ }
+
+ // this is the socket that the server will listen on
+ ACE_SOCK_Acceptor acceptor_socket;
+
+ // Create the address that we want to listen for connections on. If
+ // server_accept_addr=INADDR_ANY (the default), SCTP will listen for
+ // connections on all IP interfaces. If an address is specified,
+ // SCTP will listen for connections on that address ONLY.
+ ACE_INET_Addr serverAddr(optsMgr.server_port,
+ optsMgr.server_accept_addr);
+
+ ACE_DEBUG((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) Accepting connections on port %u on interface %C using %C\n"),
+ serverAddr.get_port_number(),
+ (optsMgr.server_accept_addr == INADDR_ANY) ? "INADDR_ANY" : serverAddr.get_host_addr(),
+ (optsMgr.test_transport_protocol == IPPROTO_SCTP) ? "IPPROTO_SCTP" : "IPPROTO_TCP"));
+
+ // this operation creates a socket, binds the specified internet
+ // address to it and calls listen. As this is a wrapper facade
+ // approach, the ACE_OS::{socket,bind,listen} calls are invoked in
+ // the implementation of open.
+ if (acceptor_socket.open(serverAddr, 1,
+ AF_INET,
+ ACE_DEFAULT_BACKLOG,
+ optsMgr.test_transport_protocol) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("open")),
+ 1);
+
+ // this function checks that the port that was actually bound was
+ // the port we asked for. Apparently some operating systems will
+ // automatically select new ports if the specified port is currently
+ // used.
+ else if (acceptor_socket.get_local_addr(serverAddr) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("get_local_addr")),
+ 1);
+
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) starting server at port %d\n"),
+ serverAddr.get_port_number()));
+
+ // this is the stream object that will associated with a completed
+ // connection (aka the data mode socket). It will be set when accept
+ // is called below.
+ ACE_SOCK_Stream new_stream;
+
+ // a file decriptor set
+ ACE_Handle_Set handle_set;
+ // add the acceptor socket to the file descriptor set.
+ handle_set.set_bit(acceptor_socket.get_handle());
+
+ for (;;){
+
+ ACE_Time_Value timeout(ACE_DEFAULT_TIMEOUT);
+ ACE_Handle_Set temp = handle_set;
+
+ // wait for connect() call from client. In the original test there
+ // were two different acceptor sockets for two different
+ // services. So select was needed to wait on both sockets
+ // simultaneously. In this test we could just call accept on the
+ // one socket.
+ int result = ACE_OS::select((int) (acceptor_socket.get_handle()) +1,
+ (fd_set *) temp,
+ 0,
+ 0,
+ timeout);
+
+ // check that select did not end with an error.
+ if (result == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("select")));
+ // check to see if select timed out.
+ else if (result == 0){
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) select timed out\n")));
+
+ }
+ else { // case where a file descriptor was actually set
+ if (!(temp.is_set(acceptor_socket.get_handle()))){
+ // CANNOT BE REACHED
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("select: NO ERROR BUT NO FD SET")));
+ } else {
+ // call accept to set up the new stream.
+ if (acceptor_socket.accept(new_stream) == -1) {
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("accept")));
+ continue;
+ }
+ else{
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) spawning server\n")));
+
+ }
+ // Run the server.
+ run_server (new_stream.get_handle ());
+ }
+
+ }
+
+ }
+ return 0;
+}
diff --git a/ACE/performance-tests/SCTP/THANKS b/ACE/performance-tests/SCTP/THANKS
new file mode 100644
index 00000000000..eb646d9dae1
--- /dev/null
+++ b/ACE/performance-tests/SCTP/THANKS
@@ -0,0 +1,30 @@
+Lockheed Martin Advanced Technology Laboratories (LM ATL) development
+of the SCIOP pluggable protocol for TAO was funded under DARPA/IXO's
+Program Composition for Embedded Systems (PCES) program.
+
+The LM ATL PCES project leads, Patrick Lardieri and Gautam Thaker,
+thank the following individuals for their contributions to the
+development TAO's SCIOP pluggable protocol.
+
+Jason Cohen LM ATL
+Edward Mulholland LM ATL
+Keith O'Hara LM ATL
+Chuck Winters LM ATL
+
+We also thank Mr. Brian Bidulock of OpenSS7 (www.openss7.org) for his
+rapid development of a fully functional Linux implementation of SCTP
+which made this work possible.
+
+We also thank the following individuals for their valuable review and
+critiques of our SCIOP designs and for the expert advice on the more
+arcane and subtle aspects of ACE and TAO.
+
+Dr. Chris Gill DOC Group
+Balachandran Natarajan DOC Group
+
+Dr. Douglas Schmidt DARPA/IXO, DOC Group
+
+Steve Houston OCI
+
+
+
diff --git a/ACE/performance-tests/SCTP/hist.cpp b/ACE/performance-tests/SCTP/hist.cpp
new file mode 100644
index 00000000000..95bcbe2d25f
--- /dev/null
+++ b/ACE/performance-tests/SCTP/hist.cpp
@@ -0,0 +1,306 @@
+// $Id$
+
+/* Replacement for CSIM histogram created by Alex Carobus 7/20/98
+ #include <std/disclaimer.h>
+ */
+/*
+//
+// Update history:
+//
+// [99.10.18] jcohen
+// version 1.3
+// added optional fields to header
+// to use: add_field("key","value",histogram);
+// or: add_field_n("key",45,histogram);
+//
+// [99.01.08] jcohen
+// version 1.2
+// histogram includes skew and kurtosis
+// call enable_skew(h) to enable skew and kurtosis on histogram h
+//
+// [98.07.29] jcohen
+// added add_histogram function
+// added version 1.1 display, added num_bins display
+// added read_hist
+//
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <float.h>
+#include <string.h>
+#include "ace/os_include/os_math.h"
+#include "hist.h"
+namespace ACE_SCTP
+{
+
+hist_t *head_hist, *tail_hist;
+
+hist_t *histogram(char *name, unsigned int num_bins, double first,
+ double last) {
+ ACE_SCTP::hist_t *hist;
+ if ((hist = (hist_t *)malloc(sizeof(hist_t))) == 0) {
+ fprintf(stderr, "unable to allocate memory for histogram : %s", name);
+ exit(-1);
+ }
+ if ((hist->hs = (unsigned int *)malloc(sizeof(unsigned int) * (num_bins+2))) == 0){
+ fprintf(stderr, "unable to allocate memory for histogram : %s", name);
+ exit(-1);
+ }
+ memset(hist->hs, 0, sizeof(unsigned int) * (num_bins+2));
+ hist->name = name;
+ hist->num_bins = num_bins;
+ hist->first = first;
+ hist->last = last;
+ hist->num_points = 0;
+ hist->max_num_outer = hist->num_outer = 0;
+ hist->sum = 0.0;
+ hist->sum2 = 0.0;
+ hist->sum3 = 0.0;
+ hist->sum4 = 0.0;
+ hist->max = DBL_MIN;
+ hist->min = DBL_MAX;
+ hist->outer = 0;
+ hist->next = 0;
+ hist->skew = 0;
+ hist->firstoptheader = 0;
+ if(head_hist == 0)
+ head_hist = tail_hist = hist;
+ else {
+ tail_hist->next = hist;
+ tail_hist = tail_hist->next;
+ }
+ return hist;
+}
+
+
+void set_outer(unsigned int max_num_outer, hist_t *hist) {
+ hist->outer = (double *)realloc(hist->outer,sizeof(double) * max_num_outer);
+ hist->max_num_outer = max_num_outer;
+}
+
+
+void enable_skew(hist_t *hist) {
+ hist->skew = 1;
+}
+
+
+void add_field(char *key, char *value, hist_t *hist) {
+ struct optheader *nextoptheader, *trace;
+
+ /* create and prepare nextoptheader */
+ nextoptheader = (struct optheader *) malloc(sizeof(struct optheader));
+ nextoptheader->key = (char *) malloc(strlen(key)+1);
+ nextoptheader->value = (char *) malloc(strlen(value)+1);
+ nextoptheader->next = 0;
+ strcpy(nextoptheader->key,key);
+ strcpy(nextoptheader->value,value);
+
+ /* tack nextoptheader onto end of optheader list */
+ if (hist->firstoptheader == 0) {
+ hist->firstoptheader = nextoptheader;
+ } else {
+ trace = hist->firstoptheader;
+ while (trace->next != 0) {
+ trace = trace->next;
+ }
+ trace->next = nextoptheader;
+ }
+}
+
+
+void add_field_n(char *key, int value, hist_t *hist) {
+ char textvalue[40];
+
+ sprintf(textvalue,"%d",value);
+ add_field(key,textvalue,hist);
+}
+
+
+void record(double point, hist_t *hist) {
+ unsigned int bin;
+ double incsum;
+ if (point < hist->min) hist->min = point;
+ if (point > hist->max) hist->max = point;
+ if (point < hist->first) {
+ bin = 0;
+ if (hist->max_num_outer > hist->num_outer)
+ hist->outer[hist->num_outer++] = point;
+ }
+ else if (point >= hist->last) {
+ bin = hist->num_bins+1;
+ if (hist->max_num_outer > hist->num_outer)
+ hist->outer[hist->num_outer++] = point;
+ }
+ else
+ bin = (unsigned int)(((point - hist->first)*(hist->num_bins))/(hist->last - hist->first)+1);
+
+ hist->hs[bin]++;
+ hist->num_points++;
+ hist->sum+=point;
+ incsum = point*point;
+ hist->sum2 += incsum;
+ if (hist->skew) {
+ incsum *= point;
+ hist->sum3 += incsum;
+ incsum *= point;
+ hist->sum4 += incsum;
+ }
+
+/* printf("point : %g, bin %u, points in bin %u\n", point, bin, hist->hs[bin]); */
+}
+
+void report_to(FILE *strm, hist_t *hist) {
+ unsigned int sofar, i;
+ double p1, p2, d, mean;
+ double variance;
+ struct optheader *trace;
+
+ if (hist->num_points == 0) {
+ fprintf(strm, "\n\n\t\t\t\tHistogram %s is empty\n\n", hist->name);
+ return;
+ }
+ fprintf(strm, "\n\n\t\t\t\tHistogram %s\n", hist->name);
+ if (hist->skew) fprintf(strm, "version: %s\n", HIST_VERSION);
+ else fprintf(strm, "version: 1.1\n");
+ fprintf(strm, "minimum: %g\n", hist->min);
+ fprintf(strm, "maximum: %g\n", hist->max);
+ fprintf(strm, "mean: %g\n", mean = hist->sum/hist->num_points);
+ variance = (hist->sum2 -
+ 2*hist->sum*mean +
+ hist->num_points*mean*mean) / (hist->num_points-1);
+ fprintf(strm, "variance: %g\n", variance);
+ if (hist->skew) {
+ fprintf(strm, "skew: %g\n", ((hist->sum3 -
+ 3*hist->sum2*mean +
+ 3*hist->sum*mean*mean -
+ hist->num_points*mean*mean*mean) /
+ pow(sqrt(variance),3) / hist->num_points));
+ fprintf(strm, "kurtosis: %g\n", ((hist->sum4 -
+ 4*hist->sum3*mean +
+ 6*hist->sum2*mean*mean -
+ 4*hist->sum*mean*mean*mean +
+ hist->num_points*mean*mean*mean*mean) /
+ pow(sqrt(variance),4)) / hist->num_points - 3);
+ }
+ fprintf(strm, "num_points: %u\n", hist->num_points);
+ fprintf(strm, "num_bins: %d %g %g\n", hist->num_bins,hist->first,hist->last);
+ if (hist->firstoptheader) {
+ trace = hist->firstoptheader;
+ while(trace->next != 0) {
+ fprintf(strm, "%s: %s\n", trace->key, trace->value);
+ trace = trace->next;
+ }
+ fprintf(strm, "%s: %s\n", trace->key, trace->value);
+ }
+ fprintf(strm, "\n");
+ sofar = hist->hs[0];
+ fprintf(strm, "\t Low - High Count Fraction Cumulative\n");
+ fprintf(strm, "\t below - %12.3f : %5u %0.3f %0.3f\n", hist->first,
+ hist->hs[0], (double)hist->hs[0]/hist->num_points,
+ (double)histfloor(1000.0*sofar/hist->num_points)/1000.0);
+ p2 = hist->first;
+ d = (hist->last - hist->first)/hist->num_bins;
+ for(i = 1; i <= hist->num_bins; i++) {
+ p1 = p2;
+ p2 = i*d+hist->first;
+ sofar += hist->hs[i];
+ fprintf(strm, "\t%12.3f - %12.3f : %5u %0.3f %0.3f\n", p1, p2, hist->hs[i],
+ (double)hist->hs[i]/hist->num_points,
+ (double)histfloor(1000.0*sofar/hist->num_points)/1000.0);
+ }
+ sofar += hist->hs[hist->num_bins+1];
+ fprintf(strm, "\t%12.3f - above : %5u %0.3f %0.3f\n\n",
+ hist->last, hist->hs[hist->num_bins+1],
+ (double)hist->hs[hist->num_bins+1]/hist->num_points,
+ (double)histfloor(1000.0*sofar/hist->num_points)/1000.0);
+ if (hist->num_outer) {
+ fprintf(strm, "outliers:\n");
+ for(i = 0; i < hist->num_outer; i++) fprintf(strm, "\t%12.3f\n",
+ hist->outer[i]);
+ }
+ fprintf(strm, "\n\n");
+}
+
+void report() {
+ hist_t *temp = head_hist;
+ for(; temp; temp = temp->next)
+ report_to(stdout, temp);
+}
+
+void stats_init() {
+ /* this is not necessary */
+}
+
+double get_mean(HIST hist) {
+ return(hist->sum/hist->num_points);
+}
+
+double get_min(HIST hist) {
+ return(hist->min);
+}
+
+double get_max(HIST hist) {
+ return(hist->max);
+}
+
+double get_variance(HIST hist) {
+ double mean = hist->sum/hist->num_points;
+ return((hist->sum2 - 2*hist->sum*mean + hist->num_points*mean*mean)/
+ (hist->num_points-1));
+}
+
+double get_num(HIST hist) {
+ return(hist->num_points);
+}
+
+void set_mean(HIST hist, double mean) {
+ hist->sum = mean*hist->num_points;
+}
+
+void set_min(HIST hist, double min) {
+ hist->min = min;
+}
+
+void set_max(HIST hist, double max) {
+ hist->max = max;
+}
+
+void set_variance(HIST hist, double variance) {
+ /* do this after seting mean */
+ double mean = hist->sum/hist->num_points;
+ hist->sum2 = variance *(hist->num_points-1) + 2*hist->sum*mean - hist->num_points*mean*mean;
+}
+
+void add_histogram(HIST dest, HIST source) {
+ unsigned int i,j;
+ double d,midpoint;
+
+ d = (source->last - source->first)/source->num_bins;
+
+ for(i=1;i<=source->num_bins;i++) {
+ midpoint = source->first + ((i - 0.5) * d);
+ for(j=0;j<source->hs[i];j++) {
+ record(midpoint,dest);
+ }
+ }
+
+ for(i=0;i<source->num_outer;i++)
+ record(source->outer[i],dest);
+
+ set_min(dest, get_min(source));
+ set_max(dest, get_max(source));
+ set_mean(dest, get_mean(source));
+ set_variance(dest, get_variance(source));
+}
+
+double histfloor (double x) {
+
+#ifdef WIN32
+ return floor(x);
+#else
+ return static_cast<double> (static_cast<long long> (x));
+#endif
+
+}
+}
diff --git a/ACE/performance-tests/SCTP/hist.h b/ACE/performance-tests/SCTP/hist.h
new file mode 100644
index 00000000000..efb83716267
--- /dev/null
+++ b/ACE/performance-tests/SCTP/hist.h
@@ -0,0 +1,71 @@
+// $Id$
+
+#include <stdio.h>
+
+#define HIST_VERSION "1.3"
+
+namespace ACE_SCTP
+{
+
+ struct optheader {
+ char *key;
+ char *value;
+ struct optheader *next;
+ };
+
+ typedef struct hist_s {
+ char *name;
+ double max, min, sum, sum2, sum3, sum4;
+ double first, last;
+ unsigned int num_points, num_bins;
+ unsigned int *hs;
+ unsigned int num_outer, max_num_outer;
+ double *outer;
+ struct hist_s *next;
+ int skew;
+ struct optheader *firstoptheader;
+ } hist_t;
+
+ #define HIST hist_t *
+
+ hist_t *histogram(char *name, unsigned int num_bins, double first,
+ double last);
+
+ void set_outer(unsigned int max_num_outer, hist_t *hist);
+
+ void enable_skew(hist_t *hist);
+
+ void add_field(char *key, char *value, hist_t *hist);
+
+ void add_field_n(char *key, int value, hist_t *hist);
+
+ void record(double point, hist_t *hist);
+
+ void report_to(FILE *strm, hist_t *hist);
+
+ void report();
+
+ void stats_init();
+
+ double get_mean(HIST hist);
+
+ double get_min(HIST hist);
+
+ double get_max(HIST hist);
+
+ double get_variance(HIST hist);
+
+ double get_num(HIST hist);
+
+ void set_mean(HIST hist, double mean);
+
+ void set_min(HIST hist, double min);
+
+ void set_max(HIST hist, double max);
+
+ void set_variance(HIST hist, double variance);
+
+ void add_histogram(HIST dest, HIST source);
+
+ double histfloor(double x);
+}
diff --git a/ACE/performance-tests/SCTP/run_spectrum.config b/ACE/performance-tests/SCTP/run_spectrum.config
new file mode 100644
index 00000000000..cb2beb17f5e
--- /dev/null
+++ b/ACE/performance-tests/SCTP/run_spectrum.config
@@ -0,0 +1,12 @@
+#
+# $Id$
+#
+# This is the default configuration file for run_spectrum.pl.
+# Configuration options given in this file will be passed to
+# SOCK_STREAM_clt or SOCK_SEQPACK_clt.
+#
+# Note that the configuration options are defined as "the first
+# double-quote string that is not to the right of a pound sign."
+# (Double-quotes and pound signs cannot be escaped).
+
+"-c 1000"
diff --git a/ACE/performance-tests/SCTP/run_spectrum.pl b/ACE/performance-tests/SCTP/run_spectrum.pl
new file mode 100755
index 00000000000..d6ec34e6075
--- /dev/null
+++ b/ACE/performance-tests/SCTP/run_spectrum.pl
@@ -0,0 +1,260 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+
+use warnings;
+use strict;
+
+use lib '../../bin';
+use PerlACE::Run_Test;
+use Getopt::Long;
+use Pod::Usage;
+
+#### Program Documentation ####
+
+=head1 NAME
+
+run_spectrum.pl - Run a spectrum of performance tests.
+
+=head1 SYNOPSIS
+
+ run_spectrum.pl [ --help ]
+ [ --manual ]
+ [ --service (STREAM|SEQPACK) ]
+ [ --protocol (TCP|SCTP) ]
+ [ --config_file filename ]
+
+=head1 OPTIONS
+
+=over 8
+
+=item B<--help, -h>
+
+Print this help message and exit.
+
+=item B<--manual, -m>
+
+Print full documentation and exit.
+
+=item B<--service, -s> (STREAM|SEQPACK)
+
+Select SOCK_STREAM or SOCK_SEQPACK service respectively. The default
+is SOCK_STREAM.
+
+=item B<--protocol, -p> (TCP|SCTP)
+
+Select TCP or SCTP transport protocol. The default is TCP. Note that
+TCP cannot be used together with the SEQPACK service.
+
+=item B<--config_file, -c> filename
+
+Read configuration parameters from the nominated file. By default,
+parameters are read from C<run_spectrum.config> in the current
+directory.
+
+=back
+
+=head1 DESCRIPTION
+
+This directory contains performance tests for measuring round-trip
+latency statistics of ACE synchronous messaging using unmarshalled
+ACE_CDR::Octet.
+
+The SOCK_STREAM performance test comprises SOCK_STREAM_clt on the
+client side and SOCK_STREAM_srv on the server side. The SOCK_SEQPACK
+performance test comprises SOCK_SEQPACK_clt on the client side and
+SOCK_SEQPACK_srv on the server side.
+
+People who are interested in round-trip latency often want to see a
+I<spectrum> of statistics for a range of payload sizes. The job of
+this script, B<run_spectrum.pl>, is to run the client-side
+performance-test program repeatedly, so as to generate a spectrum of
+statistics.
+
+The script supports two types of services (SOCK_STREAM and
+SOCK_SEQPACK) and two protocols (TCP and UDP). All combinations are
+valid except TCP over SOCK_SEQPACK. Please see L<"OPTIONS"> for
+information about the command-line options that specify the service
+and the protocol.
+
+By default, B<run_spectrum.pl> will execute SOCK_STREAM_clt (or
+SOCK_SEQPACK_clt) with a minimal set of command-line options. You can
+specify additional options in an external configuration file. By
+default, the configuration file is called C<run_spectrum.config>. You
+may name an alternate configuration file using the B<--config_file>
+option.
+
+The configuration file should contain the options that you would
+ordinarly give to SOCK_STREAM_clt or SOCK_SEQPACK_clt on the command
+line. To see the command-line options available for these programs,
+please run C<SOCK_STREAM_clt --help> or C<SOCK_SEQPACK_clt --help>.
+Note that the options B<-s> and B<-t> are used by this script when it
+launches the client. An occurrence of either of these options in the
+configuration file will be ignored as redundant.
+
+The client is executed 15 times: once for each payload size from 2^2
+bytes to 2^16 bytes. (SCTP tests only go up to 2^15 bytes because of
+limitations in our SCTP implementation.) Histograms summarizing the
+round-trip latency performance are dumped to a file called
+C<TIMESTAMP.spectrum> where C<TIMESTAMP> is the current time in
+hyphen-delimited form.
+
+=head1 EXAMPLES
+
+B<Example 1>: Run a spectrum of TCP performance tests using
+SOCK_STREAM with both endpoints on the local machine. Each test in
+the spectrum should have 10,000 data points.
+
+=over 4
+
+=item 1.
+
+Start the SOCK_STREAM server on the local machine with the S<C<-t
+tcp>> option:
+
+ % ./SOCK_STREAM_srv -t tcp
+
+=item 2.
+
+Configure the client to run 10,000 individual trials:
+
+ % echo '"-c 10000"' > run_spectrum.config
+
+=item 3.
+
+Execute B<run_spectrum.pl>:
+
+ % ./run_spectrum.pl
+
+(The script uses TCP and SOCK_STREAM by default.)
+
+=back
+
+B<Example 2>: Run a spectrum of SCTP performance tests using
+SOCK_SEQPACK with one endpoint on the local machine and one endpoint
+on a remote machine that happens to be named oneida. Each test in the
+spectrum should have 50,000 data points.
+
+=over 4
+
+=item 1.
+
+On the remote host oneida, start the SOCK_SEQPACK server:
+
+ % ./SOCK_SEQPACK_srv
+
+=item 2.
+
+On the local host, configure the client to run 50,000 individual
+trials and to look for the server on oneida:
+
+ % echo '"-c 50000 -H oneida"' > run_spectrum.config
+
+=item 3.
+
+On the local host, execute B<run_spectrum.pl>:
+
+ % ./run_spectrum.pl --service SEQPACK --protocol SCTP
+
+=back
+
+=cut
+
+# Global variable declarations
+my $help = 0;
+my $manual = 0;
+my $service = "stream";
+my $protocol = "tcp";
+my $config_file = "run_spectrum.config";
+my $options = "";
+my $output_file;
+
+# Map from services to client programs
+my %client_programs = (stream => "SOCK_STREAM_clt",
+ seqpack => "SOCK_SEQPACK_clt");
+
+#### MAIN PROGRAM ####
+
+# Canonicalize arguments to lower-case
+tr/A-Z/a-z/ for @ARGV;
+
+# Use Getopt::Long to parse options
+GetOptions ("help" => \$help,
+ "manual" => \$manual,
+ "service=s" => \$service,
+ "protocol=s" => \$protocol,
+ "config_file=s" => \$config_file
+ );
+
+# Show help if requested
+pod2usage(1) if $help;
+
+# Show manual if requested
+pod2usage(-verbose => 2) if $manual;
+
+# Validate service option
+$service =~ s/seqpacket/seqpack/; # Accept "seqpacket" as synonym for "seqpack"
+$service =~ /^(stream|seqpack)$/
+ or pod2usage("Service must be STREAM or SEQPACK\n");
+
+$protocol =~ /^(tcp|sctp)$/
+ or pod2usage("Protocol must be TCP or SCTP\n");
+
+$service eq "seqpack" and $protocol eq "tcp"
+ and pod2usage("Cannot use SEQPACK service with TCP\n");
+
+# Open config file
+open CONFIG, "< $config_file"
+ or die "cannot open file: $config_file\n";
+
+# Read options from the config file. The options are defined as the
+# first double-quoted string that is not to the right of a pound sign.
+# (Pound signs and quotes cannot be escaped.)
+
+while (<CONFIG>) {
+ chomp;
+ if (/^[^\#]*?\"(.*?)\"/) {
+ $options = $1;
+ last;
+ }
+}
+
+# Close config file
+close CONFIG;
+
+# Print options
+print "Read options from $config_file: \"$options\"\n\n";
+
+# Name a unique file to store the results in.
+($output_file = localtime() . ".spectrum") =~ tr/ /-/;
+
+# Run the test for message sizes ranging from 2^2 bytes to 2^16 bytes
+# (SCTP tests only go up to 2^15 bytes because of limitations in our
+# SCTP implementation)
+my $max_size = 16;
+$max_size = 15 if $protocol eq "sctp";
+for (my $i = 2; $i <= $max_size; ++$i) {
+
+ # Assemble client parameters and print out the command line
+ my $client_params = "-t $protocol -s $i $options >> $output_file";
+ print "$client_programs{$service} $client_params\n";
+
+ # Configure client
+ my $client =
+ new PerlACE::Process($client_programs{$service}, $client_params);
+
+ # Spawn client
+ $client->Spawn();
+
+ # Wait for client to finish
+ $client->Wait();
+
+ # Remind the client that it's finished running
+ $client->{RUNNING} = 0;
+
+ # Sleep for a while
+ sleep 5;
+}
+
diff --git a/ACE/performance-tests/SCTP/sample-spectrum.png b/ACE/performance-tests/SCTP/sample-spectrum.png
new file mode 100644
index 00000000000..d6fc94f205b
--- /dev/null
+++ b/ACE/performance-tests/SCTP/sample-spectrum.png
Binary files differ
diff --git a/ACE/performance-tests/Server_Concurrency/Latency_Stats.h b/ACE/performance-tests/Server_Concurrency/Latency_Stats.h
new file mode 100644
index 00000000000..2b0694b7ea7
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/Latency_Stats.h
@@ -0,0 +1,219 @@
+// $Id$
+
+class Latency_Stats
+{
+public:
+ Latency_Stats (void);
+
+ void dump_results (const ACE_TCHAR* test_name,
+ const ACE_TCHAR* sub_test);
+
+ void sample (ACE_hrtime_t sample);
+
+ void accumulate (const Latency_Stats& stats);
+ // Useful to merge several Latency_Stats.
+
+private:
+ u_long n_;
+ ACE_hrtime_t sum_;
+ ACE_hrtime_t sum2_;
+ ACE_hrtime_t min_;
+ ACE_hrtime_t max_;
+};
+
+inline
+Latency_Stats::Latency_Stats (void)
+ : n_ (0),
+ sum_ (0),
+ sum2_ (0),
+ min_ (0),
+ max_ (0)
+{
+}
+
+inline void
+Latency_Stats::sample (ACE_hrtime_t sample)
+{
+ this->sum_ += sample;
+#ifndef ACE_LACKS_LONGLONG_T
+ this->sum2_ += sample * sample;
+#else
+ // possible loss of precision here due to lack of 64bit support
+ this->sum2_ += sample * sample.lo();
+#endif
+ if (this->n_ == 0)
+ {
+ this->min_ = sample;
+ this->max_ = sample;
+ }
+ if (this->min_ > sample)
+ this->min_ = sample;
+ if (this->max_ < sample)
+ this->max_ = sample;
+ this->n_++;
+}
+
+inline void
+Latency_Stats::dump_results (const ACE_TCHAR *test_name,
+ const ACE_TCHAR *sub_test)
+{
+ if (this->n_ < 1)
+ return;
+
+ ACE_hrtime_t avg = this->sum_ / this->n_;
+#ifndef ACE_LACKS_LONGLONG_T
+ ACE_hrtime_t dev =
+ this->sum2_ / this->n_ - avg*avg;
+#else
+ ACE_hrtime_t dev =
+ this->sum2_ / this->n_ - avg.lo()*avg.lo();
+#endif
+ ACE_UINT32 gsf = ACE_High_Res_Timer::global_scale_factor ();
+
+ double min_usec = ACE_CU64_TO_CU32 (this->min_) / gsf;
+ double max_usec = ACE_CU64_TO_CU32 (this->max_) / gsf;
+ double avg_usec = ACE_CU64_TO_CU32 (avg) / gsf;
+ double dev_usec = ACE_CU64_TO_CU32 (dev) / (gsf * gsf);
+ ACE_DEBUG ((LM_DEBUG,
+ "%s/%s: %.2f/%.2f/%.2f/%.2f (min/avg/max/var^2) [usecs]\n",
+ test_name, sub_test,
+ min_usec, avg_usec, max_usec, dev_usec));
+}
+
+inline void
+Latency_Stats::accumulate (const Latency_Stats& rhs)
+{
+ if (rhs.n_ == 0)
+ return;
+
+ if (this->n_ == 0)
+ {
+ this->n_ = rhs.n_;
+ this->min_ = rhs.min_;
+ this->max_ = rhs.max_;
+ this->sum_ = rhs.sum_;
+ this->sum2_ = rhs.sum2_;
+ return;
+ }
+
+ if (this->min_ > rhs.min_)
+ this->min_ = rhs.min_;
+ if (this->max_ < rhs.max_)
+ this->max_ = rhs.max_;
+
+ this->sum_ += rhs.sum_;
+ this->sum2_ += rhs.sum2_;
+ this->n_ += rhs.n_;
+}
+
+class Throughput_Stats
+{
+public:
+ Throughput_Stats (void);
+
+ void dump_results (const ACE_TCHAR* test_name,
+ const ACE_TCHAR* sub_test);
+
+ void sample (void);
+ // An event has been received
+
+ void accumulate (const Throughput_Stats& stats);
+ // Useful to merge several Throughput_Stats.
+
+private:
+ u_long n_;
+ ACE_hrtime_t start_;
+ ACE_hrtime_t stop_;
+};
+
+inline void
+Throughput_Stats::accumulate (const Throughput_Stats& rhs)
+{
+ if (rhs.n_ == 0)
+ return;
+
+ if (this->n_ == 0)
+ {
+ this->start_ = rhs.start_;
+ this->stop_ = rhs.stop_;
+ this->n_ = rhs.n_;
+ return;
+ }
+
+ if (this->start_ > rhs.start_)
+ this->start_ = rhs.start_;
+
+ if (this->stop_ < rhs.stop_)
+ this->stop_ = rhs.stop_;
+
+ this->n_ += rhs.n_;
+}
+
+inline void
+Throughput_Stats::dump_results (const ACE_TCHAR *test_name,
+ const ACE_TCHAR *subtest)
+{
+ if (this->n_ == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "%s/%s: no events recorded\n",
+ test_name, subtest));
+ return;
+ }
+
+ ACE_Time_Value tv;
+ ACE_High_Res_Timer::hrtime_to_tv (tv, this->stop_ - this->start_);
+
+ double f = 1.0/(tv.sec () + tv.usec () / 1000000.0);
+ double events_per_second = this->n_ * f;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "%s/%s: "
+ "%d / %d.%06.6d = %.3f events/second\n",
+ test_name, subtest,
+ this->n_,
+ tv.sec (), tv.usec (),
+ events_per_second));
+}
+
+inline
+Throughput_Stats::Throughput_Stats (void)
+ : n_ (0),
+ start_ (),
+ stop_ ()
+{
+}
+
+inline void
+Throughput_Stats::sample (void)
+{
+ if (this->n_ == 0)
+ {
+ this->start_ = ACE_OS::gethrtime ();
+ }
+ this->n_++;
+ this->stop_ = ACE_OS::gethrtime ();
+}
+
+inline void
+move_to_rt_class (void)
+{
+ // Enable FIFO scheduling, e.g., RT scheduling class on Solaris.
+ int priority =
+ (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO)
+ + ACE_Sched_Params::priority_max (ACE_SCHED_FIFO)) / 2;
+
+ int result = ACE_OS::sched_params (ACE_Sched_Params (ACE_SCHED_FIFO,
+ priority,
+ ACE_SCOPE_PROCESS));
+ if (result == 0)
+ {
+ result = ACE_OS::thr_setprio (priority);
+ }
+
+ if (result != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Cannot move program to realtime class.\n"));
+ }
+}
diff --git a/ACE/performance-tests/Server_Concurrency/Leader_Follower/Makefile.am b/ACE/performance-tests/Server_Concurrency/Leader_Follower/Makefile.am
new file mode 100644
index 00000000000..38021abd626
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/Leader_Follower/Makefile.am
@@ -0,0 +1,58 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Svr_Conc_Leader_Follower.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += leader_follower
+
+leader_follower_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+leader_follower_SOURCES = \
+ leader_follower.cpp \
+ RT_CORBA_Leader_Follower.h
+
+leader_follower_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Svr_Conc_Leader_Follower_RT_CORBA.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += RT_CORBA_Leader_Follower
+
+RT_CORBA_Leader_Follower_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+RT_CORBA_Leader_Follower_SOURCES = \
+ RT_CORBA_Leader_Follower.cpp \
+ RT_CORBA_Leader_Follower.h
+
+RT_CORBA_Leader_Follower_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/performance-tests/Server_Concurrency/Leader_Follower/RT_CORBA_Leader_Follower.cpp b/ACE/performance-tests/Server_Concurrency/Leader_Follower/RT_CORBA_Leader_Follower.cpp
new file mode 100644
index 00000000000..59b6844836a
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/Leader_Follower/RT_CORBA_Leader_Follower.cpp
@@ -0,0 +1,401 @@
+// $Id$
+
+#include "RT_CORBA_Leader_Follower.h"
+
+
+
+#if defined (ACE_HAS_THREADS)
+
+// We need the following only if we have threads enabled..
+#include "ace/OS_main.h"
+#include "ace/ACE.h"
+#include "ace/Get_Opt.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Sched_Params.h"
+#include "ace/Profile_Timer.h"
+
+// Number of messages that are used in this experiment
+static size_t number_of_messages = 1000;
+
+// Number of messages that are used in this experiment
+static size_t number_of_messages_left = 0;
+
+// Number of threads used in this experiment
+static size_t number_of_threads = 2;
+
+// Global variable for the availability of the leader
+static size_t leader_available = 0;
+
+// Number of threads that are ready to go/dispatch
+static size_t ready_threads = 0;
+
+// Work in the upcall
+static size_t message_size = 100;
+
+// Debugging condition
+static DEBUGGING_RANGE debug = DEBUG_NONE;
+
+// Timer for the test
+ACE_High_Res_Timer test_timer;
+
+
+
+
+/*******************************************************************/
+// Constructor for Synchronisers
+Synchronisers::Synchronisers (void)
+ : mutex_ (),
+ condition_ (mutex_),
+ event_ ()
+{
+}
+
+
+int
+Synchronisers::start_synchronization (void)
+{
+ // Hold the lock and increment the global variable to indicate
+ // number of ready threads
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1);
+
+ ready_threads ++;
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Ready to go.. \n"));
+ }
+
+ if (ready_threads == number_of_threads)
+ {
+
+ // Reset the ready_threads so that we can wait at the end of
+ // runs
+ ready_threads = 0;
+
+ // Start the timer
+ test_timer.start ();
+
+ // Signal all the threads
+ this->event_.signal ();
+
+ // return to do our work;
+ return 0;
+ }
+
+ // If we are not the last thread, let go off the lock
+ }
+
+ // Wait blisfully till we are woken up
+ this->event_.wait ();
+
+ return 0;
+}
+
+int
+Synchronisers::end_synchronization (void)
+{
+ // Hold the lock and increment the global variable to indicate
+ // number of ready threads
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1);
+
+ ready_threads ++;
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Ready to go.. \n"));
+ }
+
+ if (ready_threads == number_of_threads)
+ {
+
+ // Reset the ready_threads so that we can wait at the end of
+ // runs
+ ready_threads = 0;
+
+ // Start the timer
+ test_timer.stop ();
+
+ // Signal all the threads
+ this->event_.signal ();
+
+ // return to do our work;
+ return 0;
+ }
+
+ // If we are not the last thread, let go off the lock
+ }
+
+ // Wait blisfully till we are woken up
+ this->event_.wait ();
+
+ return 0;
+}
+
+
+/*******************************************************************/
+
+Leader_Follower_Task::Leader_Follower_Task (Synchronisers &synch)
+ : messages_consumed_ (0),
+ synch_ (synch)
+{
+}
+
+int
+Leader_Follower_Task::processed (void)
+{
+ return this->messages_consumed_;
+}
+
+int
+Leader_Follower_Task::svc (void)
+{
+ (void) this->synch_.start_synchronization ();
+
+ for (;;)
+ {
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->synch_.mutex_, -1);
+
+ // Wait until there is no leader.
+ while (leader_available)
+ {
+ int result = this->synch_.condition_.wait ();
+
+ if (result == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Leader_Follower_Task::svc (%t) -> %p\n",
+ "wait error"),
+ -1);
+ }
+ }
+
+ // I am the leader.
+ leader_available = 1;
+
+ //
+ // We are letting go of the leader follower lock before going
+ // in the event loop.
+ //
+ }
+
+ //
+ // It is ok to modify these shared variables without a lock
+ // since we are the only leader.
+ //
+
+ int exit_loop = 0;
+ if (number_of_messages_left == 0)
+ {
+ exit_loop = 1;
+ }
+ else
+ {
+ --number_of_messages_left;
+
+ // Local counter.
+ ++this->messages_consumed_;
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) message for this thread %d\n",
+ this->messages_consumed_));
+ }
+ }
+
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->synch_.mutex_, -1);
+
+ // I am no longer the leader.
+ leader_available = 0;
+
+ // Wake up a follower.
+ this->synch_.condition_.signal ();
+ }
+
+ if (exit_loop)
+ {
+ break;
+ }
+ else
+ {
+ //
+ // Process message here.
+ //
+ for (size_t j = 0; j < message_size; ++j)
+ {
+ // Eat a little CPU
+ /* takes about 40.2 usecs on a 167 MHz Ultra2 */
+ u_long n = 11UL;
+ ACE::is_prime (n, 2, n / 2);
+ }
+
+ }
+ }
+
+ (void) this->synch_.end_synchronization ();
+
+ return 0;
+}
+
+static int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("m:t:d:s:"));
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ {
+ switch (c)
+ {
+ case 'm':
+ number_of_messages = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 't':
+ number_of_threads = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'd':
+ debug = static_cast<DEBUGGING_RANGE> (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 's':
+ message_size = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s\n"
+ "\t[-m number of messages]\n"
+ "\t[-s message size]\n"
+ "\t[-w number of threads]\n"
+ "\t[-b burst size]\n"
+ "\t[-t timeout between bursts]\n"
+ "\t[-d debug]\n",
+ argv[0]),
+ -1);
+ }
+ }
+
+ return 0;
+}
+
+/*******************************************************************/
+
+// Entry point
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int result = parse_args (argc, argv);
+
+ if (result != 0)
+ {
+ return result;
+ }
+
+ Synchronisers synch_forms;
+
+ ACE_High_Res_Timer::calibrate ();
+
+ // Leader Followers.
+ Leader_Follower_Task **leader_followers = 0;
+ ACE_NEW_RETURN (leader_followers,
+ Leader_Follower_Task *[number_of_threads],
+ -1);
+
+ int priority =
+ ACE_Sched_Params::priority_max (ACE_SCHED_FIFO);
+
+ long flags = THR_SCOPE_PROCESS;
+
+ // Number of messages left = Number_Of_messages
+ number_of_messages_left = number_of_messages;
+
+ size_t i = 0;
+ // Create and activate them.
+ for (i = 0; i < number_of_threads; ++i)
+ {
+ ACE_NEW_RETURN (leader_followers[i],
+ Leader_Follower_Task (synch_forms),
+ -1);
+
+ // Activate the leader_followers.
+ result = leader_followers[i]->activate (flags,
+ 1,
+ 1,
+ priority);
+ if (result != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) - Activate failed for RT class "
+ " - Using default priority for thread [%d]\n",
+ i));
+
+ flags = THR_BOUND;
+ priority = ACE_Sched_Params::priority_min (ACE_SCHED_OTHER,
+ ACE_SCOPE_THREAD);
+
+ // Activate the leader_followers.
+ result = leader_followers[i]->activate (flags,
+ 1,
+ 1,
+ priority);
+
+ if (result != 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) - Failed again no hope \n"));
+
+ return 0;
+ }
+
+ }
+ }
+
+ // Wait for all threads to terminate.
+ result = ACE_Thread_Manager::instance ()->wait ();
+
+ ACE_hrtime_t elapsed_time = 0;
+
+ test_timer.elapsed_time (elapsed_time);
+
+ double elapsed_time_per_invocation =
+ static_cast<double> (
+ ACE_UINT64_DBLCAST_ADAPTER (elapsed_time / number_of_messages)
+ );
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Throughput is [%f] \n",
+ 1000000000/ elapsed_time_per_invocation));
+
+
+ for (i = 0; i < number_of_threads; ++i)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Message consumed in thread [%d] is [%d] \n",
+ i, leader_followers[i]->processed ()));
+ delete leader_followers[i];
+ }
+
+ delete[] leader_followers;
+
+ return result;
+}
+
+
+
+
+#else /*if defined (ACE_HAS_THREADS)*/
+
+int
+main (int , char *[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%p|%t) Cannot run in SIngle threaded mode \n"));
+
+ return 0;
+}
+#endif /*ACE_HAS_THREADS*/
diff --git a/ACE/performance-tests/Server_Concurrency/Leader_Follower/RT_CORBA_Leader_Follower.h b/ACE/performance-tests/Server_Concurrency/Leader_Follower/RT_CORBA_Leader_Follower.h
new file mode 100644
index 00000000000..4664bd3cda8
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/Leader_Follower/RT_CORBA_Leader_Follower.h
@@ -0,0 +1,109 @@
+//=============================================================================
+/**
+ * @file RT_CORBA_Leader_Follower.h
+ *
+ * $Id$
+ *
+ * The leader follower test modified to suit RTCORBA tests. The
+ * original leader follower test has too many things that doesnt
+ * get what we are looking for (read it as just confusing enough)
+ * . Hence a new test.
+ *
+ * @author Balachandran Natarajan <bala@cs.wustl.edu>
+ */
+//=============================================================================
+#ifndef PERF_TEST_RT_CORBA_LEADER_FOLLOWER_H
+#define PERF_TEST_RT_CORBA_LEADER_FOLLOWER_H
+#include /**/ "ace/pre.h"
+#include "ace/Task.h"
+
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Manual_Event.h"
+
+enum DEBUGGING_RANGE
+{
+ DEBUG_NONE = 0,
+ DEBUG
+};
+
+
+/**
+ * @class Synchronisers
+ *
+ * @brief This class provides all the synchrnoisers used in this
+ * test.
+ *
+ *
+ */
+
+/// Forward declaration..
+class Leader_Follower_Task;
+
+class Synchronisers
+{
+public:
+ friend class Leader_Follower_Task;
+
+ /// Ctor
+ Synchronisers (void);
+
+ int start_synchronization (void);
+ int end_synchronization (void);
+
+private:
+
+ /// The mutex and condition variable that is used for
+ /// synchronisation.
+ ACE_SYNCH_MUTEX mutex_;
+
+ ACE_SYNCH_CONDITION condition_;
+
+ /// A manual event
+ ACE_Manual_Event event_;
+};
+
+
+/**
+ * @class Leader_Follower_Task
+ *
+ * @brief This class provide the interface and an implementation to
+ * simulate how the LF pattern in the ORB would behave.
+ *
+ *
+ * Basically all threads ready to do an upcall would wait on a token
+ * or lock. The thread that gets the token before it gets ready to do
+ * the upcall would wake up a thread waiting on the token.
+ *
+ */
+
+class Leader_Follower_Task : public ACE_Task_Base
+{
+public:
+
+ /// Ctor with a mutex and a condition variable
+ Leader_Follower_Task (Synchronisers &synch);
+
+ /// Messages consumed
+ int processed (void);
+
+ /// Method that is run by a daemon thread
+ int svc (void);
+
+private:
+ /// Number of messages processed by this thread
+ int messages_consumed_;
+
+ /// Our reference to the synchroniser
+ Synchronisers &synch_;
+};
+
+#endif /*ACE_HAS_THREADS*/
+
+#include /**/ "ace/post.h"
+#endif /*PERF_TEST_RT_CORBA_LEADER_FOLLOWER*/
diff --git a/ACE/performance-tests/Server_Concurrency/Leader_Follower/Svr_Conc_Leader_Follower.mpc b/ACE/performance-tests/Server_Concurrency/Leader_Follower/Svr_Conc_Leader_Follower.mpc
new file mode 100644
index 00000000000..90e800b468a
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/Leader_Follower/Svr_Conc_Leader_Follower.mpc
@@ -0,0 +1,18 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ avoids += ace_for_tao
+ exename = leader_follower
+ source_files {
+ leader_follower.cpp
+ }
+}
+
+project(*RT_CORBA) : aceexe {
+ avoids += ace_for_tao
+ exename = RT_CORBA_Leader_Follower
+ source_files {
+ RT_CORBA_Leader_Follower.cpp
+ }
+}
diff --git a/ACE/performance-tests/Server_Concurrency/Leader_Follower/leader_follower.cpp b/ACE/performance-tests/Server_Concurrency/Leader_Follower/leader_follower.cpp
new file mode 100644
index 00000000000..5703ff2a1af
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/Leader_Follower/leader_follower.cpp
@@ -0,0 +1,333 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/ACE.h"
+#include "ace/Task_T.h"
+#include "ace/Get_Opt.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Sched_Params.h"
+#include "ace/Profile_Timer.h"
+#include "../Latency_Stats.h"
+
+static size_t number_of_messages = 100;
+static size_t message_size = 100;
+static size_t number_of_threads = 10;
+static size_t burst_size = 10;
+static size_t timeout_between_bursts = 1;
+
+static size_t leader_available = 0;
+static size_t messages_in_this_burst = 0;
+static size_t total_messages_consumed = 0;
+static size_t burst = 1;
+
+static ACE_hrtime_t start_of_burst;
+
+enum DEBUGGING_RANGE
+{
+ DEBUG_NONE = 0,
+ DEFAULT = 1,
+ PRINT_INDIVIDUAL_LATENCY = 2
+};
+
+static DEBUGGING_RANGE debug = DEBUG_NONE;
+
+typedef ACE_Task<ACE_SYNCH> TASK;
+
+class Leader_Follower_Task : public TASK
+{
+public:
+ Leader_Follower_Task (ACE_SYNCH_MUTEX &mutex,
+ ACE_SYNCH_CONDITION &condition);
+ int svc (void);
+
+ size_t messages_consumed_;
+ ACE_SYNCH_MUTEX &mutex_;
+ ACE_SYNCH_CONDITION &condition_;
+
+ Latency_Stats latency_stats_;
+ Throughput_Stats throughput_stats_;
+};
+
+Leader_Follower_Task::Leader_Follower_Task (ACE_SYNCH_MUTEX &mutex,
+ ACE_SYNCH_CONDITION &condition)
+ : messages_consumed_ (0),
+ mutex_ (mutex),
+ condition_ (condition)
+{
+}
+
+int
+Leader_Follower_Task::svc (void)
+{
+ for (;;)
+ {
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1);
+
+ // Wait until there is no leader.
+ while (leader_available)
+ {
+ int result = this->condition_.wait ();
+ if (result == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Leader_Follower_Task::svc (%t) -> %p\n",
+ "wait error"),
+ -1);
+ }
+ }
+
+ // I am the leader.
+ leader_available = 1;
+
+ //
+ // We are letting go of the leader follower lock before going
+ // in the event loop.
+ //
+ }
+
+ //
+ // It is ok to modify these shared variables without a lock
+ // since we are the only leader.
+ //
+
+ int exit_loop = 0;
+ if (number_of_messages == 0)
+ {
+ exit_loop = 1;
+ }
+ else
+ {
+ if (messages_in_this_burst == burst_size)
+ {
+ ++burst;
+ messages_in_this_burst = 0;
+ ACE_Time_Value tv (0, timeout_between_bursts);
+ ACE_OS::sleep (tv);
+ }
+
+ if (messages_in_this_burst == 0)
+ {
+ start_of_burst = ACE_OS::gethrtime ();
+ }
+
+ --number_of_messages;
+
+ // Burst counter.
+ ++messages_in_this_burst;
+
+ // Global counter.
+ ++total_messages_consumed;
+
+ // Local counter.
+ ++this->messages_consumed_;
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) burst %d: message %d; overall message %d; message for this thread %d\n",
+ burst,
+ messages_in_this_burst,
+ total_messages_consumed,
+ this->messages_consumed_));
+ }
+ }
+
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1);
+
+ // I am no longer the leader.
+ leader_available = 0;
+
+ // Wake up a follower.
+ this->condition_.signal ();
+ }
+
+ if (exit_loop)
+ {
+ break;
+ }
+ else
+ {
+ //
+ // Process message here.
+ //
+
+ for (size_t j = 0; j < message_size; ++j)
+ {
+ // Eat a little CPU
+ /* takes about 40.2 usecs on a 167 MHz Ultra2 */
+ u_long n = 11UL;
+ ACE::is_prime (n, 2, n / 2);
+ }
+
+ //
+ // Record stats for this message.
+ //
+ ACE_hrtime_t latency_from_start_of_burst =
+ ACE_OS::gethrtime () - start_of_burst;
+ this->latency_stats_.sample (latency_from_start_of_burst);
+
+ this->throughput_stats_.sample ();
+
+ if (debug >= PRINT_INDIVIDUAL_LATENCY)
+ {
+#ifndef ACE_LACKS_LONGLONG_T
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) latency from start of burst: %Q\n",
+ latency_from_start_of_burst));
+#else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) latency from start of burst: %u\n",
+ latency_from_start_of_burst.lo()));
+#endif
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("m:s:w:b:t:d:"));
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ {
+ switch (c)
+ {
+ case 'm':
+ number_of_messages = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 's':
+ message_size = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'w':
+ number_of_threads = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'b':
+ burst_size = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 't':
+ timeout_between_bursts = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'd':
+ debug = static_cast<DEBUGGING_RANGE> (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s\n"
+ "\t[-m number of messages]\n"
+ "\t[-s message size]\n"
+ "\t[-w number of threads]\n"
+ "\t[-b burst size]\n"
+ "\t[-t timeout between bursts]\n"
+ "\t[-d debug]\n",
+ argv[0]),
+ -1);
+ }
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int result = parse_args (argc, argv);
+ if (result != 0)
+ {
+ return result;
+ }
+
+ move_to_rt_class ();
+ ACE_High_Res_Timer::calibrate ();
+
+ ACE_SYNCH_MUTEX mutex;
+ ACE_SYNCH_CONDITION condition (mutex);
+
+ // Leader Followers.
+ Leader_Follower_Task **leader_followers = 0;
+ ACE_NEW_RETURN (leader_followers,
+ Leader_Follower_Task *[number_of_threads],
+ -1);
+
+ ACE_Profile_Timer timer;
+ timer.start ();
+
+ int priority =
+ (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO) +
+ ACE_Sched_Params::priority_max (ACE_SCHED_FIFO)) / 2;
+
+ long flags = THR_BOUND | THR_SCHED_FIFO;
+
+ // Create and activate them.
+ size_t i = 0;
+ for (i = 0; i < number_of_threads; ++i)
+ {
+ ACE_NEW_RETURN (leader_followers[i],
+ Leader_Follower_Task (mutex,
+ condition),
+ -1);
+
+ // Activate the leader_followers.
+ result = leader_followers[i]->activate (flags,
+ 1,
+ 1,
+ priority);
+ if (result != 0)
+ {
+ flags = THR_BOUND;
+ priority = ACE_Sched_Params::priority_min (ACE_SCHED_OTHER,
+ ACE_SCOPE_THREAD);
+ result = leader_followers[i]->activate (flags,
+ 1,
+ 1,
+ priority);
+ if (result != 0)
+ {
+ return result;
+ }
+ }
+ }
+
+ // Wait for all threads to terminate.
+ result = ACE_Thread_Manager::instance ()->wait ();
+
+ timer.stop ();
+ ACE_Rusage rusage;
+ timer.elapsed_rusage (rusage);
+
+ Latency_Stats latency;
+ Throughput_Stats throughput;
+ for (i = 0; i < number_of_threads; ++i)
+ {
+ latency.accumulate (leader_followers[i]->latency_stats_);
+ throughput.accumulate (leader_followers[i]->throughput_stats_);
+ ACE_DEBUG ((LM_DEBUG, "Thread[%d]: ", i));
+ leader_followers[i]->throughput_stats_.dump_results (ACE_TEXT(""), ACE_TEXT(""));
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "\nTotals for latency:\n"));
+ latency.dump_results (argv[0], ACE_TEXT("latency"));
+
+ ACE_DEBUG ((LM_DEBUG, "\nTotals for throughput:\n"));
+ throughput.dump_results (argv[0], ACE_TEXT("throughput"));
+
+#if defined(ACE_HAS_PRUSAGE_T)
+ ACE_DEBUG ((LM_DEBUG, "\n(%t) Context switches %d/%d\n",
+ rusage.pr_vctx,
+ rusage.pr_ictx));
+#endif /* ACE_HAS_PRUSAGE_T */
+
+ for (i = 0; i < number_of_threads; ++i)
+ {
+ delete leader_followers[i];
+ }
+ delete[] leader_followers;
+
+ return result;
+}
diff --git a/ACE/performance-tests/Server_Concurrency/Makefile.am b/ACE/performance-tests/Server_Concurrency/Makefile.am
new file mode 100644
index 00000000000..9a5b0c57e66
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/Makefile.am
@@ -0,0 +1,14 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+SUBDIRS = \
+ Leader_Follower \
+ Queue_Based_Workers
+
diff --git a/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/Makefile.am b/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/Makefile.am
new file mode 100644
index 00000000000..feb7783689d
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/Makefile.am
@@ -0,0 +1,58 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+noinst_PROGRAMS =
+
+## Makefile.Svr_Conc_Queue_Based_Workers.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += workers
+
+workers_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+workers_SOURCES = \
+ workers.cpp \
+ RT_CORBA_Workers.h
+
+workers_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Makefile.Svr_Conc_Queue_Based_Workers_RTCorba.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS += RT_CORBA_Workers
+
+RT_CORBA_Workers_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+RT_CORBA_Workers_SOURCES = \
+ RT_CORBA_Workers.cpp \
+ RT_CORBA_Workers.h
+
+RT_CORBA_Workers_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/RT_CORBA_Workers.cpp b/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/RT_CORBA_Workers.cpp
new file mode 100644
index 00000000000..7f90fc62012
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/RT_CORBA_Workers.cpp
@@ -0,0 +1,589 @@
+// $Id$
+#include "RT_CORBA_Workers.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_main.h"
+#include "ace/ACE.h"
+#include "ace/Get_Opt.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Sched_Params.h"
+#include "ace/Lock_Adapter_T.h"
+
+// The number of messages that is being processed
+static size_t number_of_messages = 100;
+
+// The number of upcall threads
+static size_t number_of_workers = 2;
+
+// The size of the message
+static size_t message_size = 100;
+
+// Number of threads that are ready to go
+static size_t ready_threads = 0;
+
+// Number of input and output threads
+static size_t io_threads = 2; // 1 for output and 1 for input
+
+// High resolution test timer
+static ACE_High_Res_Timer test_timer;
+
+// Debugging condition
+static DEBUGGING_RANGE debug = DEBUG_NONE;
+
+// Data block used by the message blocks
+ACE_Data_Block *data_block = 0;
+
+/*******************************************************************/
+// Constructor for Synchronisers
+Synchronisers::Synchronisers (void)
+ : mutex_ (),
+ event_ ()
+{
+}
+
+
+int
+Synchronisers::start_synchronization (void)
+{
+ // Hold the lock and increment the global variable to indicate
+ // number of ready threads
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1);
+
+ ready_threads ++;
+
+ if (ready_threads == (number_of_workers + io_threads))
+ {
+ // Reset the ready_threads so that we can wait at the end of
+ // runs
+ ready_threads = 0;
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Ready to signal start \n"));
+ }
+ // Start the timer
+ test_timer.start ();
+
+ // Signal all the threads
+ this->event_.signal ();
+
+ // return to do our work;
+ return 0;
+ }
+
+ // If we are not the last thread, let go off the lock
+ }
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Ready to wait () on event.. \n"));
+ }
+
+ // Wait blisfully till we are woken up
+ this->event_.wait ();
+
+ return 0;
+}
+
+int
+Synchronisers::end_synchronization (void)
+{
+ // Hold the lock and increment the global variable to indicate
+ // number of ready threads
+ {
+ ACE_GUARD_RETURN (ACE_SYNCH_MUTEX, ace_mon, this->mutex_, -1);
+
+ ready_threads ++;
+
+ if (ready_threads == (number_of_workers + io_threads))
+ {
+ // Reset the ready_threads so that we can wait at the end of
+ // runs
+ ready_threads = 0;
+
+ // Start the timer
+ test_timer.stop ();
+
+ // Signal all the threads
+ this->event_.signal ();
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Ended peacefully \n"));
+ }
+
+ // return to do our work;
+ return 0;
+ }
+
+
+ // If we are not the last thread, let go off the lock
+ }
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Going to wait .. \n"));
+ }
+
+ // Wait blisfully till we are woken up
+ this->event_.wait ();
+
+ return 0;
+}
+
+/*******************************************************************/
+
+Worker_Task::Worker_Task (Message_Queue *mq,
+ Synchronisers &synch)
+ : ACE_Task<ACE_MT_SYNCH> (0, mq),
+ synch_ (synch),
+ messages_processed_ (0)
+{
+}
+
+int
+Worker_Task::svc (void)
+{
+ // Start synchronization
+ (void) this->synch_.start_synchronization ();
+
+ for (;;)
+ {
+ ACE_Message_Block *mb = 0;
+ int result = this->getq (mb);
+ if (result == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Worker_Task::svc (%t) -> %p\n",
+ "getq error"),
+ -1);
+ }
+
+ // Get the flag in the message blok
+ ACE_Message_Block::Message_Flags flag =
+ mb->self_flags ();
+
+ // The stop flag
+ int stop_flag = 0;
+
+ // Check for the stop flag
+ if (ACE_BIT_ENABLED (flag,
+ Synchronisers::MB_STOP_FLAG))
+ {
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) saw flag after [%d] messages\n",
+ this->messages_processed_));
+ }
+
+ stop_flag = 1;
+ }
+ // Release the message block
+ mb->release ();
+
+ // Counter.
+ ++this->messages_processed_;
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) dequeued my %d message\n",
+ this->messages_processed_));
+ }
+
+ //
+ // Process message here.
+ //
+
+ for (size_t j = 0; j < message_size; ++j)
+ {
+ // Eat a little CPU
+ /* takes about 40.2 usecs on a 167 MHz Ultra2 */
+ u_long n = 11UL;
+ ACE::is_prime (n, 2, n / 2);
+ }
+
+ // Make a message block for writing onto output queue
+ ACE_Message_Block *message_block = 0;
+ ACE_NEW_RETURN (message_block,
+ ACE_Message_Block (data_block),
+ -1);
+
+ // Put this message block into the next queue or the output
+ // queue
+ result = this->put_next (message_block);
+
+ if (result == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Input::svc (%t) -> %p\n",
+ "putq error"),
+ -1);
+ }
+
+ // If the stop_flag is set just break and wait..
+ if (stop_flag)
+ {
+ if (debug)
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Got stop message after [%d] messages \n",
+ this->messages_processed_));
+
+ break;
+ }
+ }
+
+ (void) this->synch_.end_synchronization ();
+ return 0;
+}
+
+int
+Worker_Task::processed (void)
+{
+ return this->messages_processed_;
+}
+
+/*******************************************************************/
+
+Input_Task::Input_Task (Message_Queue *mq,
+ Synchronisers &synch)
+ : ACE_Task<ACE_MT_SYNCH> (0, mq),
+ synch_ (synch)
+{
+}
+
+int
+Input_Task::svc (void)
+{
+ // Synchronise threads
+ (void) this->synch_.start_synchronization ();
+
+
+ size_t i = 0;
+ for (i = 0;
+ i < (number_of_messages - number_of_workers);
+ ++i)
+ {
+ // Make a message block
+ ACE_Message_Block *message_block = 0;
+ ACE_NEW_RETURN (message_block,
+ ACE_Message_Block (data_block),
+ -1);
+
+ int result = this->putq (message_block);
+
+ if (result == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Input::svc (%t) -> %p\n",
+ "putq error"),
+ -1);
+ }
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Input thread -> Sent [%d] messages\n",
+ i));
+ }
+ }
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Sending close messages \n"));
+ }
+
+
+ // Stop messages
+ for (i = 0;
+ i < number_of_workers;
+ ++i)
+ {
+ // Make a message block
+ ACE_Message_Block *message_block = 0;
+ ACE_NEW_RETURN (message_block,
+ ACE_Message_Block (data_block),
+ -1);
+
+ // Set the stop flag in the message block and not in the datablock
+ message_block->set_self_flags (Synchronisers::MB_STOP_FLAG);
+
+ int result = this->putq (message_block);
+
+ if (result == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Input::svc (%t) -> %p\n",
+ "putq error"),
+ -1);
+ }
+ }
+
+
+ (void) this->synch_.end_synchronization ();
+ return 0;
+}
+
+/*******************************************************************/
+
+Output_Task::Output_Task (Message_Queue *mq,
+ Synchronisers &synch)
+ : ACE_Task<ACE_MT_SYNCH> (0, mq),
+ synch_ (synch)
+{
+}
+
+int
+Output_Task::svc (void)
+{
+ // Synchronise threads
+ (void) this->synch_.start_synchronization ();
+
+
+ for (size_t i = 0;
+ i < number_of_messages;
+ ++i)
+ {
+ // Get the message block from queue
+ ACE_Message_Block *mb = 0;
+ int result = this->getq (mb);
+
+ // delete the message block
+ mb->release ();
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) Output thread -> received [%d] message\n",
+ i));
+ }
+
+ if (result == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Input::svc (%t) -> %p\n",
+ "putq error"),
+ -1);
+ }
+ }
+
+ (void) this->synch_.end_synchronization ();
+ return 0;
+}
+
+int
+Output_Task::put (ACE_Message_Block *mb, ACE_Time_Value *)
+{
+ /* if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Sticking message into "
+ " output queue \n"));
+ }*/
+ return this->putq (mb);
+}
+
+/*******************************************************************/
+
+static int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("m:s:t:d:"));
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ {
+ switch (c)
+ {
+ case 'm':
+ number_of_messages = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 't':
+ number_of_workers = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'd':
+ debug = static_cast<DEBUGGING_RANGE> (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 's':
+ message_size = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s\n"
+ "\t[-m number of messages]\n"
+ "\t[-s message size]\n"
+ "\t[-w number of workers]\n"
+ "\t[-b burst size]\n"
+ "\t[-t timeout between bursts]\n"
+ "\t[-d debug]\n",
+ argv[0]),
+ -1);
+ }
+ }
+
+ return 0;
+}
+
+
+/*******************************************************************/
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int result = parse_args (argc, argv);
+ if (result != 0)
+ {
+ return result;
+ }
+
+ ACE_High_Res_Timer::calibrate ();
+
+ // Create the message queue
+ Message_Queue input_message_queue;
+ Message_Queue output_message_queue;
+
+ // Create the datablocks. IF we use the default Message Blocks Ctor,
+ // it is going to do an extra allocation for the data block
+ ACE_NEW_RETURN (data_block,
+ ACE_Locked_Data_Block<ACE_Lock_Adapter<ACE_SYNCH_MUTEX> >,
+ -1);
+
+ // Increment the reference count so that we can share the
+ // datablock. This is donw twice the number of messages for the
+ // input and output queues.
+ size_t i = 0;
+
+ for (i = 0; i < 2*number_of_messages; ++i)
+ {
+ data_block->duplicate ();
+ }
+
+ // Create the Synchronisers
+ Synchronisers synch;
+
+ // Workers.
+ Worker_Task **workers = 0;
+ ACE_NEW_RETURN (workers,
+ Worker_Task *[number_of_workers],
+ -1);
+
+ // Input Task
+ Input_Task input_task (&input_message_queue,
+ synch);
+
+ // Output Task
+ Output_Task output_task (&output_message_queue,
+ synch);
+ int priority =
+ ACE_Sched_Params::priority_max (ACE_SCHED_FIFO);
+
+
+ long flags = THR_SCHED_FIFO | THR_SCOPE_PROCESS;
+
+ // Create and activate the worker threads
+ for (i = 0; i < number_of_workers; ++i)
+ {
+ ACE_NEW_RETURN (workers[i],
+ Worker_Task (&input_message_queue, synch),
+ -1);
+
+ workers[i]->next (&output_task);
+
+ // Activate the workers.
+ result = workers[i]->activate (flags,
+ 1,
+ 1,
+ priority);
+ if (result != 0)
+ {
+ flags = THR_BOUND;
+ priority = ACE_Sched_Params::priority_min (ACE_SCHED_OTHER,
+ ACE_SCOPE_THREAD);
+ result = workers[i]->activate (flags,
+ 1,
+ 1,
+ priority);
+ if (result != 0)
+ {
+ return result;
+ }
+ }
+ }
+
+
+
+ // Activate the input and output threads
+ result = input_task.activate (flags,
+ 1,
+ 1,
+ priority);
+
+ if (result != 0)
+ return result;
+
+
+
+ // Activate the workers.
+ result = output_task.activate (flags,
+ 1,
+ 1,
+ priority);
+
+ if (result != 0)
+ return result;
+
+
+
+ // Wait for all threads to terminate.
+ result = ACE_Thread_Manager::instance ()->wait ();
+
+
+ ACE_hrtime_t elapsed_time = 0;
+
+ test_timer.elapsed_time (elapsed_time);
+
+# if !defined (ACE_WIN32)
+ double elapsed_time_per_invocation =
+ (double) elapsed_time / number_of_messages;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Throughput is [%f] \n",
+ elapsed_time_per_invocation));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Throughput is [%f] \n",
+ 1000000000/ elapsed_time_per_invocation));
+
+#endif /*ACE_WIN32 */
+ for (i = 0; i < number_of_workers; ++i)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Message process for thread [%d] is [%d] \n",
+ i, workers[i]->processed ()));
+ delete workers[i];
+ }
+ delete[] workers;
+
+ return result;
+}
+
+#else /*ACE_HAS_THREADS*/
+
+int
+main (int, char *[])
+{
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) Not supported in single threaded builds \n"));
+
+ return 0;
+}
+
+
+#endif /*ACE_HAS_THREADS*/
diff --git a/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/RT_CORBA_Workers.h b/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/RT_CORBA_Workers.h
new file mode 100644
index 00000000000..46d78e8624c
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/RT_CORBA_Workers.h
@@ -0,0 +1,166 @@
+/* -*- C++ -*- */
+//=============================================================================
+/**
+ * @file RT_CORBA_Workers.h
+ *
+ * $Id$
+ *
+ * The Workes test modified to suit RTCORBA tests. The original
+ * Workers has too many things that doesnt get what we are looking
+ * for (read it as just confusing enough). Hence a new test.
+ *
+ * @author Balachandran Natarajan <bala@cs.wustl.edu>
+ */
+//=============================================================================
+#ifndef PERF_TEST_RT_CORBA_WORKERS_H
+#define PERF_TEST_RT_CORBA_WORKERS_H
+#include /**/ "ace/pre.h"
+
+#include "ace/Task_T.h"
+#include "ace/Manual_Event.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if defined (ACE_HAS_THREADS)
+
+enum DEBUGGING_RANGE
+{
+ DEBUG_NONE = 0,
+ DEBUG
+};
+
+typedef ACE_Message_Queue<ACE_MT_SYNCH> Message_Queue;
+
+/**************************************************************/
+/**
+ * @class Synchronisers
+ *
+ * @brief This class provides all the synchrnoisers used in this
+ * test.
+ *
+ *
+ */
+
+/// Forward declaration..
+class IO_Task;
+class Worker_Task;
+
+class Synchronisers
+{
+public:
+ friend class IO_Task;
+ friend class Worker_Task;
+
+ enum
+ {
+ /// Used in the message block to stop processing of message
+ /// blocks.
+ MB_STOP_FLAG = 0x2000
+ };
+
+ /// Ctor
+ Synchronisers (void);
+
+ int start_synchronization (void);
+ int end_synchronization (void);
+
+private:
+
+ /// The mutex that is used for synchronisation.
+ ACE_SYNCH_MUTEX mutex_;
+
+ /// A manual event
+ ACE_Manual_Event event_;
+};
+
+
+/**************************************************************/
+/**
+ * @class Input_Task
+ *
+ * @brief Class that does the Input work ie. puts the events into the
+ * message queue
+ */
+
+class Input_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ /// Ctor
+ Input_Task (Message_Queue *mq,
+ Synchronisers &synch);
+
+ /// The thread runs inside this method..
+ int svc (void);
+
+private:
+
+ /// Our referance to Synchronisers
+ Synchronisers &synch_;
+};
+
+/**************************************************************/
+/**
+ * @class Output_Task
+ *
+ * @brief Class that does the Output work ie. getsx the events into the
+ * message queue
+ */
+
+class Output_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ /// Ctor
+ Output_Task (Message_Queue *mq,
+ Synchronisers &synch);
+
+ /// The thread runs inside this method..
+ int svc (void);
+
+ /// Need to overload this method to do anything useful..
+ virtual int put (ACE_Message_Block *, ACE_Time_Value * = 0);
+
+private:
+
+ /// Our referance to Synchronisers
+ Synchronisers &synch_;
+};
+
+
+/**************************************************************/
+/**
+ * @class Synchronisers
+ *
+ * @brief This class provides and interface for all the upcall threads
+ * to run and do the actual work
+ */
+
+class Worker_Task : public ACE_Task<ACE_MT_SYNCH>
+{
+public:
+ /// Ctor
+ Worker_Task (Message_Queue *mq,
+ Synchronisers &synch);
+
+ /// Methods in which the threads run on
+ int svc (void);
+
+ /// Processed messages
+ int processed (void);
+private:
+
+ /// Our referance to Synchronisers
+ Synchronisers &synch_;
+
+ /// Number of messages processed by us
+ size_t messages_processed_;
+};
+
+
+
+
+#endif /*ACE_HAS_THREADS*/
+
+#include /**/ "ace/post.h"
+#endif /*PERF_TEST_RT_CORBA_WORKERS_H*/
diff --git a/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/Svr_Conc_Queue_Based_Workers.mpc b/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/Svr_Conc_Queue_Based_Workers.mpc
new file mode 100644
index 00000000000..12566016d17
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/Svr_Conc_Queue_Based_Workers.mpc
@@ -0,0 +1,18 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ avoids += ace_for_tao
+ exename = workers
+ source_files {
+ workers.cpp
+ }
+}
+
+project(*RTCorba) : aceexe {
+ avoids += ace_for_tao
+ exename = RT_CORBA_Workers
+ source_files {
+ RT_CORBA_Workers.cpp
+ }
+}
diff --git a/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/workers.cpp b/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/workers.cpp
new file mode 100644
index 00000000000..5bb58d42397
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/Queue_Based_Workers/workers.cpp
@@ -0,0 +1,414 @@
+// $Id$
+
+#include "ace/OS_main.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/ACE.h"
+#include "ace/Task_T.h"
+#include "ace/Get_Opt.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Sched_Params.h"
+#include "ace/Profile_Timer.h"
+#include "ace/Lock_Adapter_T.h"
+#include "../Latency_Stats.h"
+
+static size_t number_of_messages = 100;
+static size_t message_size = 100;
+static size_t number_of_workers = 10;
+static size_t burst_size = 10;
+static size_t timeout_between_bursts = 1;
+
+enum DEBUGGING_RANGE
+{
+ DEBUG_NONE = 0,
+ DEFAULT = 1,
+ PRINT_INDIVIDUAL_LATENCY = 2
+};
+
+static DEBUGGING_RANGE debug = DEBUG_NONE;
+
+static ACE_Data_Block *data_block = 0;
+
+class Message_Block : public ACE_Message_Block
+{
+public:
+ Message_Block (ACE_Data_Block *data_block,
+ ACE_hrtime_t start_of_burst);
+
+ ACE_hrtime_t start_of_burst_;
+};
+
+Message_Block::Message_Block (ACE_Data_Block *data_block,
+ ACE_hrtime_t start_of_burst)
+ : ACE_Message_Block (data_block),
+ start_of_burst_ (start_of_burst)
+{
+}
+
+typedef ACE_Task<ACE_SYNCH> TASK;
+
+class Worker_Task : public TASK
+{
+public:
+ Worker_Task (ACE_Message_Queue<ACE_SYNCH> *mq);
+ int svc (void);
+
+ size_t messages_dequeued_;
+
+ Latency_Stats latency_stats_;
+ Throughput_Stats throughput_stats_;
+};
+
+class IO_Task : public TASK
+{
+public:
+ IO_Task (ACE_Message_Queue<ACE_SYNCH> *mq);
+ int svc (void);
+};
+
+Worker_Task::Worker_Task (ACE_Message_Queue<ACE_SYNCH> *mq)
+ : TASK (0, mq),
+ messages_dequeued_ (0)
+{
+}
+
+int
+Worker_Task::svc (void)
+{
+ for (;;)
+ {
+ ACE_Message_Block *mb = 0;
+ int result = this->getq (mb);
+ if (result == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Worker_Task::svc (%t) -> %p\n",
+ "getq error"),
+ -1);
+ }
+
+ ACE_Message_Block::ACE_Message_Type message_type =
+ mb->msg_type ();
+
+ // If STOP message, break loop and end the task.
+ if (message_type == ACE_Message_Block::MB_STOP)
+ {
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) stop message dequeued after %d data messages\n",
+ this->messages_dequeued_));
+ }
+
+ mb->release ();
+ break;
+ }
+
+ Message_Block *message_block =
+ dynamic_cast<Message_Block *> (mb);
+
+ ACE_hrtime_t start_of_burst_for_this_message_block =
+ message_block->start_of_burst_;
+
+ mb->release ();
+
+ // Counter.
+ ++this->messages_dequeued_;
+
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) dequeued its %d message\n",
+ this->messages_dequeued_));
+ }
+
+ //
+ // Process message here.
+ //
+
+ for (size_t j = 0; j < message_size; ++j)
+ {
+ // Eat a little CPU
+ /* takes about 40.2 usecs on a 167 MHz Ultra2 */
+ u_long n = 11UL;
+ ACE::is_prime (n, 2, n / 2);
+ }
+
+ //
+ // Record stats for this message.
+ //
+ ACE_hrtime_t latency_from_start_of_burst =
+ ACE_OS::gethrtime () - start_of_burst_for_this_message_block;
+ this->latency_stats_.sample (latency_from_start_of_burst);
+
+ this->throughput_stats_.sample ();
+
+ if (debug >= PRINT_INDIVIDUAL_LATENCY)
+ {
+#ifndef ACE_LACKS_LONGLONG_T
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) latency from start of burst: %Q\n",
+ latency_from_start_of_burst));
+#else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) latency from start of burst: %u\n",
+ latency_from_start_of_burst.lo()));
+#endif
+ }
+ }
+
+ return 0;
+}
+
+IO_Task::IO_Task (ACE_Message_Queue<ACE_SYNCH> *mq)
+ : TASK (0, mq)
+{
+}
+
+int
+IO_Task::svc (void)
+{
+ size_t i = 0;
+ size_t messages_queued = 1;
+ size_t burst = 1;
+
+ // Data messages.
+ while (number_of_messages > 0)
+ {
+ ACE_hrtime_t start_of_burst = ACE_OS::gethrtime ();
+
+ for (i = 1;
+ i <= burst_size && number_of_messages > 0;
+ ++i, --number_of_messages, ++messages_queued)
+ {
+ if (debug)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%t) IO thread -> burst %d: message %d; overall message %d\n",
+ burst,
+ i,
+ messages_queued));
+ }
+
+ Message_Block *message_block = 0;
+ ACE_NEW_RETURN (message_block,
+ Message_Block (data_block,
+ start_of_burst),
+ -1);
+
+ int result = this->putq (message_block);
+ if (result == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "IO::svc (%t) -> %p\n",
+ "putq error"),
+ -1);
+ }
+ }
+
+ ++burst;
+ ACE_Time_Value tv (0, timeout_between_bursts);
+ ACE_OS::sleep (tv);
+ }
+
+ // Terminate messages.
+ for (i = 0; i < number_of_workers; ++i)
+ {
+ ACE_Message_Block *message_block = 0;
+ ACE_NEW_RETURN (message_block,
+ ACE_Message_Block ((size_t)0,
+ (int)ACE_Message_Block::MB_STOP),
+ -1);
+
+ int result = this->putq (message_block);
+ if (result == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "IO::svc (%t) -> %p\n",
+ "putq error"),
+ -1);
+ }
+ }
+
+ return 0;
+}
+
+static int
+parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("m:s:w:b:t:d:"));
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ {
+ switch (c)
+ {
+ case 'm':
+ number_of_messages = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 's':
+ message_size = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'w':
+ number_of_workers = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'b':
+ burst_size = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 't':
+ timeout_between_bursts = ACE_OS::atoi (get_opt.opt_arg ());
+ break;
+ case 'd':
+ debug = static_cast<DEBUGGING_RANGE> (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "usage: %s\n"
+ "\t[-m number of messages]\n"
+ "\t[-s message size]\n"
+ "\t[-w number of workers]\n"
+ "\t[-b burst size]\n"
+ "\t[-t timeout between bursts]\n"
+ "\t[-d debug]\n",
+ argv[0]),
+ -1);
+ }
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int result = parse_args (argc, argv);
+ if (result != 0)
+ {
+ return result;
+ }
+
+ move_to_rt_class ();
+ ACE_High_Res_Timer::calibrate ();
+
+ size_t i = 0;
+
+ ACE_NEW_RETURN (data_block,
+ ACE_Locked_Data_Block<ACE_Lock_Adapter<ACE_SYNCH_MUTEX> >,
+ -1);
+
+ for (i = 0; i < number_of_messages; ++i)
+ {
+ data_block->duplicate ();
+ }
+
+ ACE_Message_Queue<ACE_SYNCH> message_queue;
+
+ // Workers.
+ Worker_Task **workers = 0;
+ ACE_NEW_RETURN (workers,
+ Worker_Task *[number_of_workers],
+ -1);
+
+ ACE_Profile_Timer timer;
+ timer.start ();
+
+ int priority =
+ (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO) +
+ ACE_Sched_Params::priority_max (ACE_SCHED_FIFO)) / 2;
+ // priority = ACE_Sched_Params::next_priority (ACE_SCHED_FIFO, priority);
+
+ long flags = THR_BOUND | THR_SCHED_FIFO;
+
+ // Create and activate them.
+ for (i = 0; i < number_of_workers; ++i)
+ {
+ ACE_NEW_RETURN (workers[i],
+ Worker_Task (&message_queue),
+ -1);
+
+ // Activate the workers.
+ result = workers[i]->activate (flags,
+ 1,
+ 1,
+ priority);
+ if (result != 0)
+ {
+ flags = THR_BOUND;
+ priority = ACE_Sched_Params::priority_min (ACE_SCHED_OTHER,
+ ACE_SCOPE_THREAD);
+ result = workers[i]->activate (flags,
+ 1,
+ 1,
+ priority);
+ if (result != 0)
+ {
+ return result;
+ }
+ }
+ }
+
+ // IO Task.
+ IO_Task io (&message_queue);
+
+ // Activate the workers.
+ priority =
+ (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO) +
+ ACE_Sched_Params::priority_max (ACE_SCHED_FIFO)) / 2;
+ priority = ACE_Sched_Params::next_priority (ACE_SCHED_FIFO, priority);
+
+ flags = THR_BOUND | THR_SCHED_FIFO;
+
+ result = io.activate (THR_BOUND);
+ if (result != 0)
+ {
+ flags = THR_BOUND;
+ priority = ACE_Sched_Params::priority_min (ACE_SCHED_OTHER,
+ ACE_SCOPE_THREAD);
+ result = io.activate (flags,
+ 1,
+ 1,
+ priority);
+ if (result != 0)
+ {
+ return result;
+ }
+ }
+
+ // Wait for all threads to terminate.
+ result = ACE_Thread_Manager::instance ()->wait ();
+
+ timer.stop ();
+ ACE_Rusage rusage;
+ timer.elapsed_rusage (rusage);
+
+ Latency_Stats latency;
+ Throughput_Stats throughput;
+ for (i = 0; i < number_of_workers; ++i)
+ {
+ latency.accumulate (workers[i]->latency_stats_);
+ throughput.accumulate (workers[i]->throughput_stats_);
+ ACE_DEBUG ((LM_DEBUG, "Thread[%d]: ", i));
+ workers[i]->throughput_stats_.dump_results (ACE_TEXT(""), ACE_TEXT(""));
+ }
+
+ ACE_DEBUG ((LM_DEBUG, "\nTotals for latency:\n"));
+ latency.dump_results (argv[0], ACE_TEXT("latency"));
+
+ ACE_DEBUG ((LM_DEBUG, "\nTotals for throughput:\n"));
+ throughput.dump_results (argv[0], ACE_TEXT("throughput"));
+
+#if defined(ACE_HAS_PRUSAGE_T)
+ ACE_DEBUG ((LM_DEBUG, "\n(%t) Context switches %d/%d\n",
+ rusage.pr_vctx,
+ rusage.pr_ictx));
+#endif /* ACE_HAS_PRUSAGE_T */
+
+ for (i = 0; i < number_of_workers; ++i)
+ {
+ delete workers[i];
+ }
+ delete[] workers;
+ delete data_block;
+
+ return result;
+}
+
diff --git a/ACE/performance-tests/Server_Concurrency/run_test.sh b/ACE/performance-tests/Server_Concurrency/run_test.sh
new file mode 100755
index 00000000000..0f45ca8f11a
--- /dev/null
+++ b/ACE/performance-tests/Server_Concurrency/run_test.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# $Id$
+#
+
+for s in 0 25 50 75 100; do
+ for w in 1 2 3 4 5 6; do
+ echo ================ WORK: $s 1>&2
+ echo ================ THREADS: $w 1>&2
+ ./Queue_Based_Workers/workers -m 100000 -b 100000 -s $s -w $w
+ ./Leader_Follower/leader_follower -m 100000 -b 100000 -s $s -w $w
+ done
+done
diff --git a/ACE/performance-tests/Synch-Benchmarks/Base_Test/Baseline_Test.cpp b/ACE/performance-tests/Synch-Benchmarks/Base_Test/Baseline_Test.cpp
new file mode 100644
index 00000000000..ed2703e7401
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Base_Test/Baseline_Test.cpp
@@ -0,0 +1,233 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+
+#include "Baseline_Test.h"
+
+# if defined (ACE_HAS_THREADS)
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/Service_Repository.h"
+#include "ace/Get_Opt.h"
+#include "ace/Thread_Manager.h"
+
+#if !defined (__ACE_INLINE__)
+#include "Baseline_Test.i"
+#endif /* __ACE_INLINE__ */
+
+ACE_RCSID (Base_Test,
+ Baseline_Test,
+ "$Id$")
+
+Baseline_Test_Options baseline_options;
+// Static Baseline Options holds the test configuration information
+// and the test statistics.
+
+Baseline_Test_Base::Baseline_Test_Base (void)
+ : Benchmark_Base (Benchmark_Base::BASELINE),
+ yield_method_ (Baseline_Test_Options::USE_SLEEP_ZERO),
+ iteration_ (DEFAULT_ITERATIONS),
+ what_(TEST_LOCK)
+{
+}
+
+int
+Baseline_Test_Base::init (int argc, ACE_TCHAR *argv[])
+{
+ return this->parse_args (argc, argv);
+}
+
+int
+Baseline_Test_Base::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT("i:ylrw"), 0);
+ int c;
+
+ while ((c = getopt ()) != -1)
+ switch (c)
+ {
+ case 'i': // Total iterations
+ {
+ int tmp = ACE_OS::atoi (getopt.opt_arg ());
+ if (tmp <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%d is not a valid value for iteration\n",
+ tmp), -1);
+ else
+ this->iteration_ = static_cast<size_t> (tmp);
+ }
+ break;
+
+ case 'y': // Use thr_yield.
+ this->yield_method_ = Baseline_Test_Options::USE_THR_YIELD;
+ break;
+
+ case 'l':
+ this->what_ = TEST_LOCK;
+ break;
+
+ case 'r':
+ this->what_ = TEST_READLOCK;
+ break;
+
+ case 'w':
+ this->what_ = TEST_WRITELOCK;
+ break;
+
+ default:
+ ACE_ERROR ((LM_ERROR, "Invalid argument %c used\n", c));
+ break;
+ }
+ return 0;
+}
+
+void
+Baseline_Test_Base::yield (void)
+{
+ if (this->yield_method_ == Baseline_Test_Options::USE_SLEEP_ZERO)
+ ACE_OS::sleep (0);
+ else
+ ACE_OS::thr_yield ();
+}
+
+Baseline_Test_Options::Baseline_Test_Options (void)
+ : test_try_lock_ (0),
+ verbose_ (0),
+ current_yield_method_ (0),
+ current_iteration_ (0),
+ total_iteration_ (DEFAULT_ITERATIONS)
+{
+}
+
+int
+Baseline_Test_Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT("tv"), 0);
+ int c;
+
+ while ((c = getopt ()) != -1)
+ switch (c)
+ {
+ case 't':
+ this->test_try_lock_ = 1;
+ break;
+
+ case 'v':
+ this->verbose_ = 1;
+ break;
+
+ default:
+ ACE_ERROR ((LM_ERROR, "Invalid arguemnt %c used.\n", c));
+ break;
+ }
+ return 0;
+}
+
+int
+Baseline_Test_Options::reset_params (size_t iteration,
+ int yield)
+{
+ this->current_iteration_ = 0;
+ this->timer.reset ();
+
+ this->current_yield_method_ = yield;
+ this->total_iteration_ = iteration;
+ return 0;
+}
+
+void
+Baseline_Test_Options::print_result (void)
+{
+ ACE_Time_Value tv;
+ ACE_hrtime_t nsec;
+
+ this->timer.elapsed_time_incr (tv);
+ this->timer.elapsed_time_incr (nsec);
+ ACE_DEBUG ((LM_DEBUG,
+ "Total Time: %d sec %d usec for a "
+ "total of %d iterations\n"
+ "Average time: %d nanoseconds.\n",
+ tv.sec (), tv.usec (),
+ this->current_iteration_,
+ (int) (nsec / this->current_iteration_)));
+}
+
+Baseline_Test::Baseline_Test (void)
+ : current_test_ (0),
+ get_lock_ (2),
+ let_go_lock_ (2)
+{
+}
+
+// Initialize and run the benchmarks tests.
+
+int
+Baseline_Test::init (int argc, ACE_TCHAR **argv)
+{
+ return baseline_options.parse_args (argc, argv);
+}
+
+int
+Baseline_Test::pre_run_test (Benchmark_Base *bb)
+{
+ this->current_test_ = (Baseline_Test_Base *) bb;
+ baseline_options.reset_params (this->current_test_->iteration (),
+ this->current_test_->yield_method ());
+ if (baseline_options.test_try_lock ())
+ {
+ ACE_Thread_Manager::instance ()->spawn
+ (ACE_THR_FUNC (Baseline_Test::hold_lock),
+ (void *) this);
+
+ this->get_lock_.wait ();
+ // Wait until the lock is held by the spawning thread.
+ }
+
+ return 0;
+}
+
+int
+Baseline_Test::run_test (void)
+{
+ if (baseline_options.test_try_lock ())
+ return this->current_test_->test_try_lock ();
+ else
+ return this->current_test_->test_acquire_release ();
+}
+
+int
+Baseline_Test::post_run_test (void)
+{
+ if (baseline_options.test_try_lock ())
+ {
+ // Release the lock we hold.
+ this->let_go_lock_.wait ();
+
+ ACE_Thread_Manager::instance ()->wait ();
+ }
+
+ baseline_options.print_result ();
+
+ return 0;
+}
+
+int
+Baseline_Test::valid_test_object (Benchmark_Base *bb)
+{
+ return (bb->benchmark_type () == Benchmark_Base::BASELINE);
+}
+
+void *
+Baseline_Test::hold_lock (void *arg)
+{
+ Baseline_Test *this_test = (Baseline_Test *) arg;
+ this_test->current_test_->acquire ();
+ this_test->get_lock_.wait ();
+
+ this_test->let_go_lock_.wait ();
+ return 0;
+}
+
+ACE_SVC_FACTORY_DEFINE (Baseline_Test)
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Base_Test/Baseline_Test.h b/ACE/performance-tests/Synch-Benchmarks/Base_Test/Baseline_Test.h
new file mode 100644
index 00000000000..b19c2158e1f
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Base_Test/Baseline_Test.h
@@ -0,0 +1,153 @@
+// -*- C++ -*-
+// $Id$
+
+#ifndef ACE_BASELINE_TEST_H
+#define ACE_BASELINE_TEST_H
+
+#include "Synch_Lib/Benchmark_Base.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/Profile_Timer.h"
+#include "ace/svc_export.h"
+#include "ace/Barrier.h"
+
+const unsigned long DEFAULT_ITERATIONS = 1000000;
+
+class ACE_Svc_Export Baseline_Test_Base : public Benchmark_Base
+{
+ // = TITLE
+ // This class identifies itself as Benmarking Performance Test class.
+public:
+ enum {
+ TEST_LOCK,
+ TEST_READLOCK,
+ TEST_WRITELOCK
+ };
+
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ // Standard initializing method for Baseline Test.
+
+ int parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parsing the svc.conf file arguments.
+
+ virtual int acquire () = 0;
+ virtual int release () = 0;
+ // These two method are used to test try_acquire performance.
+
+ virtual int test_acquire_release () = 0;
+ virtual int test_try_lock () = 0;
+ // Real test methods.
+
+ virtual int yield_method ();
+ // Query the yield method used.
+
+ virtual void yield ();
+ // Yield to other thread.
+
+ size_t iteration (void);
+ // Access methods.
+
+protected:
+ Baseline_Test_Base (void);
+
+ int yield_method_;
+ // Should we your thr_yield or sleep (0).
+
+ size_t iteration_;
+ // Total number of operations. <iterations_>
+
+ int what_;
+ // What test should be performed?
+};
+
+class ACE_Svc_Export Baseline_Test_Options
+{
+ // = TITLE
+ // This class holds the global settings for Baseline Test.
+public:
+ friend class Baseline_Test;
+
+ enum
+ {
+ USE_SLEEP_ZERO,
+ USE_THR_YIELD
+ };
+
+ Baseline_Test_Options (void);
+ // ctor.
+
+ int parse_args (int argc, ACE_TCHAR *argv[]);
+ // Parse and set the Baseline_Test options and flags.
+
+ int reset_params (size_t iteration, int yield);
+ // Reset test parameters for next round.
+
+ int test_try_lock (void);
+ // Return test configuration.
+
+ void start_inc_timer (void);
+ void stop_inc_timer (void);
+ // Start/stop measuring time.
+
+ int inc_loop_counter (void);
+ // Returns
+
+ size_t current_iteration (void);
+ // Return <iteration_>.
+
+ void print_result (void);
+ // Print out the result.
+
+private:
+ int test_try_lock_;
+ // A flag indicates whether we are testing try_lock or lock and
+ // release.
+
+ int verbose_;
+ // Print out the result in verbose mode.
+
+ int current_yield_method_;
+ // yield or sleep.
+
+ size_t current_iteration_;
+ // Number of iteration.
+
+ size_t total_iteration_;
+ // Total number of target iteration.
+
+ ACE_High_Res_Timer timer;
+ // Profile timer result.
+};
+
+extern Baseline_Test_Options baseline_options;
+
+class ACE_Svc_Export Baseline_Test : public Benchmark_Method_Base
+{
+public:
+ Baseline_Test (void);
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int pre_run_test (Benchmark_Base *bp);
+ virtual int run_test (void);
+ virtual int post_run_test (void);
+ virtual int valid_test_object (Benchmark_Base *);
+
+ static void *hold_lock (void * arg);
+ // This method runs in a separate thread, and is used to hold the lock while
+ // we test the performance of try lock.
+
+private:
+ Baseline_Test_Base *current_test_;
+ ACE_Barrier get_lock_;
+ ACE_Barrier let_go_lock_;
+};
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Test)
+
+#if defined (__ACE_INLINE__)
+#include "Baseline_Test.i"
+#endif /* __ACE_INLINE__ */
+
+#endif /* ACE_HAS_THREADS */
+
+#endif /* ACE_BASELINE_TEST_H */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Base_Test/Baseline_Test.i b/ACE/performance-tests/Synch-Benchmarks/Base_Test/Baseline_Test.i
new file mode 100644
index 00000000000..05aa007478d
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Base_Test/Baseline_Test.i
@@ -0,0 +1,43 @@
+// $Id$
+
+ACE_INLINE size_t
+Baseline_Test_Base::iteration (void)
+{
+ return this->iteration_;
+}
+
+ACE_INLINE int
+Baseline_Test_Base::yield_method (void)
+{
+ return this->yield_method_;
+}
+
+ACE_INLINE int
+Baseline_Test_Options::test_try_lock (void)
+{
+ return this->test_try_lock_;
+}
+
+ACE_INLINE size_t
+Baseline_Test_Options::current_iteration (void)
+{
+ return this->current_iteration_;
+}
+
+ACE_INLINE void
+Baseline_Test_Options::start_inc_timer (void)
+{
+ this->timer.start_incr ();
+}
+
+ACE_INLINE void
+Baseline_Test_Options::stop_inc_timer (void)
+{
+ this->timer.stop_incr ();
+}
+
+ACE_INLINE int
+Baseline_Test_Options::inc_loop_counter (void)
+{
+ return (++this->current_iteration_ < this->total_iteration_);
+}
diff --git a/ACE/performance-tests/Synch-Benchmarks/Base_Test/Makefile.am b/ACE/performance-tests/Synch-Benchmarks/Base_Test/Makefile.am
new file mode 100644
index 00000000000..9fb99ccb193
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Base_Test/Makefile.am
@@ -0,0 +1,43 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Synch_Benchmarks_Base_Test.am
+
+if !BUILD_ACE_FOR_TAO
+
+noinst_LTLIBRARIES = libSynch_Benchmarks_Base_Test.la
+
+libSynch_Benchmarks_Base_Test_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -I$(srcdir)/..
+
+libSynch_Benchmarks_Base_Test_la_SOURCES = \
+ Baseline_Test.cpp \
+ base_test.cpp \
+ mutex_test.cpp
+
+noinst_HEADERS = \
+ Baseline_Test.h \
+ Baseline_Test.i
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/performance-tests/Synch-Benchmarks/Base_Test/Synch_Benchmarks_Base_Test.mpc b/ACE/performance-tests/Synch-Benchmarks/Base_Test/Synch_Benchmarks_Base_Test.mpc
new file mode 100644
index 00000000000..7b0de88e4c9
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Base_Test/Synch_Benchmarks_Base_Test.mpc
@@ -0,0 +1,11 @@
+// -*- MPC -*-
+// $Id$
+
+project : acelib {
+ sharedname = Base_Test
+ avoids += ace_for_tao
+ after += Synch_Lib
+ libs += Synch_Lib
+ libpaths += ../Synch_Lib
+ includes += ..
+}
diff --git a/ACE/performance-tests/Synch-Benchmarks/Base_Test/base_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Base_Test/base_test.cpp
new file mode 100644
index 00000000000..6d3622c27b8
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Base_Test/base_test.cpp
@@ -0,0 +1,62 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+
+#include "Baseline_Test.h"
+
+# if defined (ACE_HAS_THREADS)
+
+#include "ace/Log_Msg.h"
+
+class ACE_Svc_Export Baseline_Base_Test : public Baseline_Test_Base
+{
+public:
+ virtual int acquire ();
+ virtual int release ();
+ // These two method are used to test try_acquire performance.
+
+ virtual int test_acquire_release ();
+ virtual int test_try_lock ();
+ // Real test methods.
+};
+
+int
+Baseline_Base_Test::acquire ()
+{
+ return 0;
+}
+
+int
+Baseline_Base_Test::release ()
+{
+ return 0;
+}
+
+int
+Baseline_Base_Test::test_acquire_release ()
+{
+ baseline_options.start_inc_timer ();
+
+ for (; baseline_options.inc_loop_counter () ; )
+ ;
+
+ baseline_options.stop_inc_timer ();
+ return 0;
+}
+
+int
+Baseline_Base_Test::test_try_lock ()
+{
+ baseline_options.start_inc_timer ();
+
+ for (; baseline_options.inc_loop_counter () ; )
+ ;
+
+ baseline_options.stop_inc_timer ();
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Base_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Base_Test)
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Base_Test/mutex_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Base_Test/mutex_test.cpp
new file mode 100644
index 00000000000..162f60943f6
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Base_Test/mutex_test.cpp
@@ -0,0 +1,205 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+
+#include "Baseline_Test.h"
+
+# if defined (ACE_HAS_THREADS)
+
+#include "ace/Log_Msg.h"
+#include "ace/Token.h"
+#include "ace/Process_Mutex.h"
+#include "ace/RW_Mutex.h"
+#include "ace/RW_Process_Mutex.h"
+#include "ace/RW_Thread_Mutex.h"
+#include "ace/Lock_Adapter_T.h"
+#include "ace/Recursive_Thread_Mutex.h"
+#include "ace/Semaphore.h"
+#include "ace/Null_Semaphore.h"
+#include "ace/Process_Semaphore.h"
+
+
+template<class LOCK>
+class ACE_Svc_Export Baseline_Lock_Test : public Baseline_Test_Base
+{
+public:
+ virtual int acquire ();
+ virtual int release ();
+ // These two method are used to test try_acquire performance.
+
+ virtual int test_acquire_release ();
+ virtual int test_try_lock ();
+ // Real test methods.
+
+private:
+ LOCK lock_;
+ //
+};
+
+template<class LOCK> int
+Baseline_Lock_Test<LOCK>::acquire ()
+{
+ int retv = 0;
+ switch (this->what_)
+ {
+ case TEST_READLOCK:
+ retv = this->lock_.acquire_read ();
+ break;
+ case TEST_WRITELOCK:
+ retv = this->lock_.acquire_write ();
+ break;
+ case TEST_LOCK:
+ default:
+ retv = this->lock_.acquire ();
+ break;
+ }
+
+ return retv;
+}
+
+template<class LOCK> int
+Baseline_Lock_Test<LOCK>::release ()
+{
+ return this->lock_.release ();
+}
+
+template<class LOCK> int
+Baseline_Lock_Test<LOCK>::test_acquire_release ()
+{
+ baseline_options.start_inc_timer ();
+
+ switch (this->what_)
+ {
+ case TEST_READLOCK:
+ for (; baseline_options.inc_loop_counter () ; )
+ {
+ this->lock_.acquire_read ();
+ this->lock_.release ();
+ }
+ break;
+ case TEST_WRITELOCK:
+ for (; baseline_options.inc_loop_counter () ; )
+ {
+ this->lock_.acquire_write ();
+ this->lock_.release ();
+ }
+ break;
+ case TEST_LOCK:
+ default:
+ for (; baseline_options.inc_loop_counter () ; )
+ {
+ this->lock_.acquire ();
+ this->lock_.release ();
+ }
+ break;
+ }
+
+ baseline_options.stop_inc_timer ();
+
+ return 0;
+}
+
+template<class LOCK> int
+Baseline_Lock_Test<LOCK>::test_try_lock ()
+{
+ baseline_options.start_inc_timer ();
+ switch (this->what_)
+ {
+ case TEST_READLOCK:
+ for (; baseline_options.inc_loop_counter () ; )
+ this->lock_.tryacquire_read (); // This should always fail.
+ break;
+ case TEST_WRITELOCK:
+ for (; baseline_options.inc_loop_counter () ; )
+ this->lock_.tryacquire_write (); // This should always fail.
+ break;
+ case TEST_LOCK:
+ default:
+ for (; baseline_options.inc_loop_counter () ; )
+ this->lock_.tryacquire (); // This should always fail.
+ break;
+ }
+
+ for (; baseline_options.inc_loop_counter () ; )
+ this->lock_.tryacquire (); // This should always fail.
+
+ baseline_options.stop_inc_timer ();
+ return 0;
+}
+
+typedef Baseline_Lock_Test<ACE_Thread_Mutex> Baseline_Mutex_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Mutex_Test)
+
+typedef Baseline_Lock_Test<ACE_RW_Thread_Mutex> Baseline_RW_Thread_Mutex_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_RW_Thread_Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_RW_Thread_Mutex_Test)
+
+typedef Baseline_Lock_Test<ACE_RW_Mutex> Baseline_RW_Mutex_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_RW_Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_RW_Mutex_Test)
+
+typedef Baseline_Lock_Test<ACE_Process_Mutex> Baseline_Process_Mutex_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Process_Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Process_Mutex_Test)
+
+typedef Baseline_Lock_Test<ACE_RW_Process_Mutex> Baseline_RW_Process_Mutex_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_RW_Process_Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_RW_Process_Mutex_Test)
+
+typedef Baseline_Lock_Test<ACE_Null_Mutex> Baseline_Null_Mutex_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Null_Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Null_Mutex_Test)
+
+typedef Baseline_Lock_Test< ACE_Lock_Adapter<ACE_Null_Mutex> > Baseline_Adaptive_Null_Mutex_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Adaptive_Null_Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Adaptive_Null_Mutex_Test)
+
+typedef Baseline_Lock_Test<ACE_Recursive_Thread_Mutex> Baseline_Recursive_Mutex_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Recursive_Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Recursive_Mutex_Test)
+
+typedef Baseline_Lock_Test< ACE_Lock_Adapter<ACE_Thread_Mutex> > Baseline_Adaptive_Mutex_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Adaptive_Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Adaptive_Mutex_Test)
+
+typedef Baseline_Lock_Test< ACE_Lock_Adapter<ACE_RW_Mutex> > Baseline_Adaptive_RW_Mutex_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Adaptive_RW_Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Adaptive_RW_Mutex_Test)
+
+typedef Baseline_Lock_Test< ACE_Lock_Adapter<ACE_Recursive_Thread_Mutex> > Baseline_Adaptive_Recursive_Mutex_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Adaptive_Recursive_Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Adaptive_Recursive_Mutex_Test)
+
+typedef Baseline_Lock_Test<ACE_Semaphore> Baseline_Semaphore_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Semaphore_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Semaphore_Test)
+
+typedef Baseline_Lock_Test<ACE_Semaphore> Baseline_Process_Semaphore_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Process_Semaphore_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Process_Semaphore_Test)
+
+typedef Baseline_Lock_Test<ACE_Null_Semaphore> Baseline_Null_Semaphore_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Null_Semaphore_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Null_Semaphore_Test)
+
+typedef Baseline_Lock_Test<ACE_Token> Baseline_Token_Test;
+
+ACE_SVC_FACTORY_DECLARE (Baseline_Token_Test)
+ACE_SVC_FACTORY_DEFINE (Baseline_Token_Test)
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Makefile.am b/ACE/performance-tests/Synch-Benchmarks/Makefile.am
new file mode 100644
index 00000000000..f0272750af1
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Makefile.am
@@ -0,0 +1,40 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+SUBDIRS = \
+ Synch_Lib \
+ Perf_Test \
+ Base_Test \
+ .
+
+## Makefile.Synch_Benchmarks.am
+noinst_PROGRAMS = synch_driver
+
+synch_driver_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+synch_driver_SOURCES = \
+ synch_driver.cpp
+
+synch_driver_LDADD = \
+ $(top_builddir)/performance-tests/Synch-Benchmarks/Synch_Lib/libSynch_Lib.la \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Adaptive_Lock_Performance_Test_Base.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Adaptive_Lock_Performance_Test_Base.cpp
new file mode 100644
index 00000000000..32ad7ea5431
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Adaptive_Lock_Performance_Test_Base.cpp
@@ -0,0 +1,48 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "Performance_Test_Options.h"
+#include "Adaptive_Lock_Performance_Test_Base.h"
+
+ACE_RCSID(Synch_Benchmarks, Adaptive_Lock_Performance_Test_Base_, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+ACE_Lock *Adaptive_Lock_Performance_Test_Base::lock_ = 0;
+
+int
+Adaptive_Lock_Performance_Test_Base::fini (void)
+{
+ delete Adaptive_Lock_Performance_Test_Base::lock_;
+ Adaptive_Lock_Performance_Test_Base::lock_ = 0;
+ return 0;
+}
+
+int
+Adaptive_Lock_Performance_Test_Base::svc (void)
+{
+ // Extract out the unique thread-specific value to be used as an
+ // index...
+ int ni = this->thr_id ();
+ synch_count = 2;
+
+ while (!this->done ())
+ {
+ Adaptive_Lock_Performance_Test_Base::lock_->acquire ();
+ performance_test_options.thr_work_count[ni]++;
+ buffer++;
+ Adaptive_Lock_Performance_Test_Base::lock_->release ();
+ }
+ /* NOTREACHED */
+ return 0;
+}
+
+int
+Adaptive_Lock_Performance_Test_Base::set_lock (ACE_Lock *lock)
+{
+ delete Adaptive_Lock_Performance_Test_Base::lock_;
+ Adaptive_Lock_Performance_Test_Base::lock_ = lock;
+ return (Adaptive_Lock_Performance_Test_Base::lock_ != 0 ? 0 : -1);
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Adaptive_Lock_Performance_Test_Base.h b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Adaptive_Lock_Performance_Test_Base.h
new file mode 100644
index 00000000000..9fb65628ea8
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Adaptive_Lock_Performance_Test_Base.h
@@ -0,0 +1,24 @@
+// $Id$
+
+#ifndef ACE_ADAPTIVE_LOCK_PERFORMANCE_TEST_BASE_H
+#define ACE_ADAPTIVE_LOCK_PERFORMANCE_TEST_BASE_H
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, Adaptive_Lock_Performance_Test_Base, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Adaptive_Lock_Performance_Test_Base : public Benchmark_Performance
+{
+public:
+ virtual int init (int, ACE_TCHAR *[]) = 0;
+ virtual int fini (void);
+ virtual int svc (void);
+
+ int set_lock (ACE_Lock *lock);
+
+private:
+ static ACE_Lock *lock_;
+};
+#endif /* ACE_HAS_THREADS */
+#endif /* ACE_ADAPTIVE_LOCK_PERFORMANCE_TEST_BASE_H */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Benchmark_Performance.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Benchmark_Performance.cpp
new file mode 100644
index 00000000000..12d240b29fe
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Benchmark_Performance.cpp
@@ -0,0 +1,59 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, Benchmark_Performance, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+// Global variables (used by the dynamically linked services).
+ACE_Svc_Export int synch_count;
+int buffer;
+
+// Initialize the static variables.
+/* static */
+sig_atomic_t Benchmark_Performance::done_ = 0;
+
+Benchmark_Performance_Test_Base::Benchmark_Performance_Test_Base (void)
+ : Benchmark_Base (Benchmark_Base::PERFORMANCE)
+{
+}
+
+sig_atomic_t
+Benchmark_Performance::done (void)
+{
+ return Benchmark_Performance::done_;
+}
+
+void
+Benchmark_Performance::done (sig_atomic_t d)
+{
+ Benchmark_Performance::done_ = d;
+}
+
+int
+Benchmark_Performance::init (int, ACE_TCHAR **)
+{
+ return 1;
+}
+
+int
+Benchmark_Performance::info (ACE_TCHAR **, size_t) const
+{
+ return -1;
+}
+
+int
+Benchmark_Performance::fini (void)
+{
+ return -1;
+}
+
+void *
+Benchmark_Performance::svc_run (Benchmark_Performance *bp)
+{
+ return (void *) (bp->svc () == -1 ? (long)-1 : (long)0);
+}
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Benchmark_Performance.h b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Benchmark_Performance.h
new file mode 100644
index 00000000000..b66a83048a7
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Benchmark_Performance.h
@@ -0,0 +1,48 @@
+/* -*- C++ -*- */
+// $Id$
+
+/* Defines the class used to dynamically link in the benchmark tests */
+
+#ifndef ACE_BENCHMARK_PERFORMANCE_H
+#define ACE_BENCHMARK_PERFORMANCE_H
+
+#include "Synch_Lib/Benchmark_Base.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#include "ace/svc_export.h"
+
+extern int buffer;
+extern ACE_Svc_Export int synch_count;
+
+class ACE_Svc_Export Benchmark_Performance_Test_Base : public Benchmark_Base
+{
+ // = TITLE
+ // This class identifies itself as Benmarking Performance Test class.
+protected:
+ Benchmark_Performance_Test_Base (void);
+};
+
+class ACE_Svc_Export Benchmark_Performance : public Benchmark_Performance_Test_Base
+{
+ // = TITLE
+ // Base class for all the timing tests.
+public:
+ // = Hooks inherited from ACE_Service_Object.
+ virtual int svc (void) = 0;
+ virtual int init (int, ACE_TCHAR *[]);
+ virtual int info (ACE_TCHAR **, size_t) const;
+ virtual int fini (void);
+ static void *svc_run (Benchmark_Performance *bp);
+
+ // = Set/get flag that controls how the tests are shut down
+ // gracefully.
+ static void done (sig_atomic_t);
+ static sig_atomic_t done (void);
+
+protected:
+ static sig_atomic_t done_;
+ // Keeps track if we are finished or not.
+};
+#endif /* ACE_HAS_THREADS */
+#endif /* ACE_BENCHMARK_PERFORMANCE_H */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Makefile.am b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Makefile.am
new file mode 100644
index 00000000000..45f9fdea7a4
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Makefile.am
@@ -0,0 +1,64 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.Synch_Benchmarks_Perf_Test.am
+
+if !BUILD_ACE_FOR_TAO
+
+noinst_LTLIBRARIES = libSynch_Benchmarks_Perf_Test.la
+
+libSynch_Benchmarks_Perf_Test_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -I$(srcdir)/..
+
+libSynch_Benchmarks_Perf_Test_la_SOURCES = \
+ Adaptive_Lock_Performance_Test_Base.cpp \
+ Benchmark_Performance.cpp \
+ Performance_Test.cpp \
+ Performance_Test_Options.cpp \
+ adaptive_mutex_test.cpp \
+ adaptive_recursive_lock_test.cpp \
+ adaptive_sema_test.cpp \
+ condb_test.cpp \
+ conds_test.cpp \
+ context_test.cpp \
+ guard_test.cpp \
+ memory_test.cpp \
+ mutex_test.cpp \
+ pipe_proc_test.cpp \
+ pipe_thr_test.cpp \
+ recursive_lock_test.cpp \
+ rwrd_test.cpp \
+ rwwr_test.cpp \
+ sema_test.cpp \
+ sysvsema_test.cpp \
+ token_test.cpp
+
+noinst_HEADERS = \
+ Adaptive_Lock_Performance_Test_Base.h \
+ Benchmark_Performance.h \
+ Performance_Test.h \
+ Performance_Test_Options.h \
+ Performance_Test_Options.i
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test.cpp
new file mode 100644
index 00000000000..42045f5963e
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test.cpp
@@ -0,0 +1,122 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+
+#include "Performance_Test.h"
+
+# if defined (ACE_HAS_THREADS)
+
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+#include "ace/Service_Repository.h"
+#include "ace/Reactor.h"
+
+ACE_RCSID (Perf_Test,
+ Performance_Test,
+ "$Id$")
+
+Performance_Test::Performance_Test (void)
+ : n_lwps_ (0),
+ orig_n_lwps_ (0)
+{
+}
+
+// Initialize and run the benchmarks tests.
+
+int
+Performance_Test::init (int argc, ACE_TCHAR **argv)
+{
+ ACE_DEBUG ((LM_DEBUG, "Performance_Test::init\n"));
+ performance_test_options.parse_args (argc, argv);
+ return 0;
+}
+
+int
+Performance_Test::pre_run_test (Benchmark_Base *bb)
+{
+ this->orig_n_lwps_ = ACE_Thread::getconcurrency ();
+ this->n_lwps_ = performance_test_options.n_lwps ();
+ Benchmark_Performance *bp = (Benchmark_Performance *) bb;
+
+ if (this->n_lwps_ > 0)
+ ACE_Thread::setconcurrency (this->n_lwps_);
+
+ // We should probably use a "barrier" here rather than
+ // THR_SUSPENDED since many OS platforms lack the ability to
+ // create suspended threads...
+ if (ACE_Thread_Manager::instance ()->spawn_n
+ (performance_test_options.thr_count (), ACE_THR_FUNC (bp->svc_run),
+ (void *) bp, performance_test_options.t_flags () | THR_SUSPENDED) == -1)
+ ACE_ERROR ((LM_ERROR, "%p\n%a", "couldn't spawn threads", 1));
+ return 0;
+}
+
+int
+Performance_Test::run_test (void)
+{
+ // Tell the threads that we are not finished.
+ Benchmark_Performance::done (0);
+
+ // Allow thread(s) to make progress.
+ ACE_Thread_Manager::instance ()->resume_all ();
+
+ ACE_Time_Value timeout (performance_test_options.sleep_time ());
+
+ ACE_DEBUG ((LM_DEBUG, "starting timer\n"));
+ performance_test_options.start_timer ();
+
+ // Use Reactor as a timer (which can be interrupted by a signal).
+ ACE_Reactor::run_event_loop (timeout);
+
+ performance_test_options.stop_timer ();
+ ACE_DEBUG ((LM_DEBUG, "\nstopping timer\n"));
+
+ return 0;
+}
+
+int
+Performance_Test::post_run_test (void)
+{
+ // Stop thread(s) from making any further progress.
+ ACE_Thread_Manager::instance ()->suspend_all ();
+
+ // Tell the threads that we are finished.
+ Benchmark_Performance::done (1);
+
+ ACE_DEBUG ((LM_DEBUG, "------------------------------------------------------------------------\n"));
+ ACE_DEBUG ((LM_DEBUG, "targ 0x%x (%s, %s, %s)\n"
+ "n_lwps_orig = %d, n_lwps_set = %d, n_lwps_end = %d\n",
+ performance_test_options.t_flags (),
+ (performance_test_options.t_flags () & THR_DETACHED) ? "THR_DETACHED" : "Not Detached",
+ (performance_test_options.t_flags () & THR_BOUND) ? "THR_BOUND" : "Not Bound",
+ (performance_test_options.t_flags () & THR_NEW_LWP) ? "THR_NEW_LWP" : "No New_LWP",
+ this->orig_n_lwps_, this->n_lwps_, ACE_Thread::getconcurrency ()));
+ int count = performance_test_options.count ();
+ float rate = count / (float (performance_test_options.sleep_time ()));
+
+ ACE_DEBUG ((LM_DEBUG,
+ "to count = %d\nrate = %.3f ops/sec, per operation = %.2f usec\n",
+ count,
+ rate,
+ (1.0e6 / rate) / synch_count));
+ performance_test_options.print_results ();
+ // Allow thread(s) to finish up.
+ ACE_Thread_Manager::instance ()->resume_all ();
+
+ // Wait for all the threads to exit.
+ ACE_Thread_Manager::instance ()->wait ();
+ performance_test_options.init ();
+
+ return 0;
+}
+
+int
+Performance_Test::valid_test_object (Benchmark_Base *bb)
+{
+ return (bb->benchmark_type () == Benchmark_Base::PERFORMANCE);
+}
+
+ACE_SVC_FACTORY_DEFINE (Performance_Test)
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test.h b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test.h
new file mode 100644
index 00000000000..f56e8001e76
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test.h
@@ -0,0 +1,32 @@
+// -*- C++ -*-
+//
+// $Id$
+
+#ifndef ACE_PERFORMANCE_TEST_H
+#define ACE_PERFORMANCE_TEST_H
+
+#include "ace/svc_export.h"
+
+#if defined (ACE_HAS_THREADS)
+
+#include "Synch_Lib/Benchmark_Base.h"
+
+class ACE_Svc_Export Performance_Test : public Benchmark_Method_Base
+{
+public:
+ Performance_Test (void);
+ virtual int init (int argc, ACE_TCHAR *argv[]);
+ virtual int pre_run_test (Benchmark_Base *bp);
+ virtual int run_test (void);
+ virtual int post_run_test (void);
+ virtual int valid_test_object (Benchmark_Base *);
+private:
+ int n_lwps_;
+ int orig_n_lwps_;
+};
+
+ACE_SVC_FACTORY_DECLARE (Performance_Test)
+
+#endif /* ACE_HAS_THREADS */
+
+#endif /* ACE_PERFORMANCE_TEST_H */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test_Options.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test_Options.cpp
new file mode 100644
index 00000000000..d2f5305de07
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test_Options.cpp
@@ -0,0 +1,469 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "Performance_Test_Options.h"
+#include "ace/OS_NS_strings.h"
+
+ACE_RCSID(Synch_Benchmarks, Performance_Test_Options, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+// Manages the options.
+Performance_Test_Options performance_test_options;
+
+size_t
+Performance_Test_Options::count (void)
+{
+ size_t total = 0;
+
+ if (performance_test_options.verbose ())
+ ACE_DEBUG ((LM_DEBUG, "Thread work count size = %d\n", performance_test_options.thr_wc_size));
+
+ for (int i = 0; i < performance_test_options.thr_wc_size; i++)
+ {
+ if (performance_test_options.thr_work_count[i] != 0)
+ {
+ // if (performance_test_options.verbose ())
+ ACE_DEBUG ((LM_DEBUG, "count[%d] = %d\n", i, performance_test_options.thr_work_count[i]));
+ total += performance_test_options.thr_work_count[i];
+ }
+ }
+
+ return total;
+}
+
+void
+Performance_Test_Options::init (void)
+{
+ for (int i = 0; i < this->thr_wc_size; i++)
+ this->thr_work_count[i] = 0;
+}
+
+Performance_Test_Options::Performance_Test_Options (void)
+ : thr_wc_size (10000),
+ _service_entry (0),
+ _mapped_file (0),
+ _pipe_addr (const_cast<ACE_TCHAR *> (ACE_DEFAULT_RENDEZVOUS)),
+ _sleep_time (100),
+ _n_lwps (0),
+ _thr_count (4),
+ _t_flags (0),
+ _high_water_mark (8 * 1024),
+ _low_water_mark (1024),
+ _msg_size (128),
+ _initial_queue_length (0),
+ _logical_connections (1),
+ _physical_connections (1),
+ _iterations (100000),
+ _generate (0),
+ _udp (0),
+ _debugging (0),
+ _verbosity (0),
+ _ack (1),
+ _checksum (1),
+ _xdr (1),
+ _free_memory (1),
+ _zero_copy (0),
+ _print_summary (0),
+ _consecutive_ports (1),
+ _eager_exit (0)
+{
+ this->thr_work_count = new int[this->thr_wc_size];
+ this->init ();
+}
+
+void
+Performance_Test_Options::parse_args (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt get_opt (argc, argv, ACE_TEXT("a:A:bBc:C:dDe:F:g:H:i:L:l:M:m:n:Np:P:s:S:t:T:uvX:Z:"), 0);
+ int c;
+
+ while ((c = get_opt ()) != -1)
+ switch (c)
+ {
+ case 'a': // Not used. (do_ack ???)
+ this->_ack = ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT("ON")) == 0;
+ break;
+ case 'A': // Not used. (set rendezvous point.)
+ this->pipe_addr (get_opt.opt_arg ());
+ break;
+ case 'B': // Create thread with THR_BOUND.
+ this->t_flags (THR_BOUND);
+ break;
+ case 'c': // Not used. (# of connections.)
+ {
+ long connections = ACE_OS::atoi (get_opt.opt_arg ());
+
+ if (connections < 0)
+ this->physical_connections (size_t (-connections));
+ else if (connections > 0)
+ this->logical_connections (size_t (connections));
+ else
+ ACE_DEBUG ((LM_WARNING, "warning, 0 connections!\n"));
+
+ break;
+ }
+ case 'C': // Not used. (Toggle calculate checksum.)
+ this->_checksum = ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT("ON")) == 0;
+ break;
+ case 'd': // Not used. (Enable debugging.)
+ this->_debugging = 1;
+ break;
+ case 'D': // Create thread with THR_DETACHED.
+ this->t_flags (THR_DETACHED);
+ break;
+ case 'e': // Perform eager exit (without cleaning up.)
+ this->_eager_exit = ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT("ON")) == 0;
+ break;
+ case 'F': // Not used.
+ this->_free_memory = ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT("ON")) == 0;
+ break;
+ case 'g': // Not used. (generate data ??)
+ this->_generate = ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT("ON")) == 0;
+ break;
+ case 'H': // Not used. (set high water mark)
+ this->high_water_mark (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'i': // Not used. (# of iterations)
+ this->iterations (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'L': // Not used. (set low water mark)
+ this->low_water_mark (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'l': // Not used. (set initial queue length)
+ this->initial_queue_length (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'M': // Set message size in pipe_[proc|thr]_test.
+ this->msg_size (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'm': // Not used. (set mapped file name)
+ this->mapped_file (get_opt.opt_arg ());
+ break;
+ case 'N': // Create thread with flag THR_NEW_LWP.
+ this->t_flags (THR_NEW_LWP);
+ break;
+ case 'n': // Set # of lwp's
+ this->n_lwps (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'p': // Toggle whether summary is printed.
+ this->_print_summary = ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT("ON")) == 0;
+ break;
+ case 'P': // Not used.
+ this->consecutive_ports (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'S': // Not used (set service_entry ???)
+ this->service_entry (get_opt.opt_arg ());
+ break;
+ case 's': // Set testing duration.
+ this->sleep_time (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'T': // Enable/disable tracing.
+#if defined (ACE_HAS_TRACE)
+ if (ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT("ON")) == 0)
+ ACE_Trace::start_tracing ();
+ else if (ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT("OFF")) == 0)
+ ACE_Trace::stop_tracing ();
+#endif /* ACE_HAS_TRACE */
+ break;
+ case 't': // Set # of threads contending the lock.
+ this->thr_count (ACE_OS::atoi (get_opt.opt_arg ()));
+ break;
+ case 'u': // Not used. (use udp.)
+ this->_udp = 1;
+ break;
+ case 'v': // Not used. (set display verbosely)
+ this->_verbosity = 1;
+ break;
+ case 'X': // Not used. (Use xdr conversion.)
+ this->_xdr = ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT("ON")) == 0;
+ break;
+ case 'Z': // Not used. (Do zero copy.)
+ this->_zero_copy = ACE_OS::strcasecmp (get_opt.opt_arg (), ACE_TEXT("ON")) == 0;
+ break;
+ default:
+ ACE_DEBUG ((LM_INFO,
+ "%s\n"
+ "\t[-a] (send acknowledgement)\n"
+ "\t[-A] address of pipe [%s]\n"
+ "\t[-B] (THR_BOUND)\n"
+ "\t[-c] + number of logical connections\n"
+ "\t[-c] - number of physical connections\n"
+ "\t[-C] (enable checksumming)\n"
+ "\t[-d] (enable debugging)\n"
+ "\t[-D] (THR_DETACHED)\n"
+ "\t[-e] (eager exit)\n"
+ "\t[-F] (free memory)\n"
+ "\t[-g] (generate data)\n"
+ "\t[-H] high water mark\n"
+ "\t[-i] number of test iterations [%d]\n"
+ "\t[-L] low water mark\n"
+ "\t[-m] mapped file\n"
+ "\t[-M] message size\n"
+ "\t[-n] number of LWPs\n"
+ "\t[-N] (THR_NEW_LWP)\n"
+ "\t[-p] (print benchmark summary)\n"
+ "\t[-P] number of consecutive ports\n"
+ "\t[-s] sleep time\n"
+ "\t[-S] service entry\n"
+ "\t[-t] number of threads [%d]\n"
+ "\t[-T] (enable tracing)\n"
+ "\t[-u] (UDP) \n"
+ "\t[-v] (verbose) \n"
+ "\t[-X] (enable xdr conversion)\n"
+ "\t[-Z] (enable zero-copy driver)\n%a",
+ argv[0],
+ this->pipe_addr (),
+ this->iterations (),
+ this->thr_count (),
+ 1));
+ /* NOTREACHED */
+ break;
+ }
+
+ if (this->do_print_summary ())
+ ACE_DEBUG ((LM_INFO,
+ "%8d = total iterations\n"
+ "%8d = logical connections\n"
+ "%8d = physical connections\n"
+ "%8d = message_size\n"
+ "%8d = calculated checksum\n"
+ "%8d = perform xdr conversion\n"
+ "%8d = number of LWPs requested\n"
+ "%8d = number of LWPs used\n",
+ this->iterations (),
+ this->logical_connections (),
+ this->physical_connections (),
+ this->msg_size (),
+ this->do_checksum () != 0,
+ this->do_xdr() != 0,
+ this->n_lwps (),
+ ACE_Thread::getconcurrency ()));
+ else if (this->verbose ())
+ ACE_DEBUG ((LM_INFO,
+ "%8d = total iterations\n"
+ "%8d = logical connections\n"
+ "%8d = physical connections\n"
+ "%8d = thread count\n"
+ "%8d = low water mark\n"
+ "%8d = high water mark\n"
+ "%8d = message_size\n"
+ "%8d = initial queue length\n"
+ "%8d = consecutive ports\n"
+ "%8d = calculated checksum\n"
+ "%8d = perform xdr conversion\n"
+ "%8d = zero-copy driver\n"
+ "%8d = free dynamic memory\n"
+ "%8d = print summary only\n"
+ "%8d = eager exit\n"
+ "%8d = UDP\n"
+ "%8d = send ack\n"
+ "%8d = THR_DETACHED\n"
+ "%8d = THR_BOUND\n"
+ "%8d = THR_NEW_LWP\n"
+ "%8d = sleep time\n",
+ this->iterations (),
+ this->logical_connections (),
+ this->physical_connections (),
+ this->thr_count (),
+ this->low_water_mark (),
+ this->high_water_mark (),
+ this->msg_size (),
+ this->initial_queue_length (),
+ this->consecutive_ports (),
+ this->do_checksum () != 0,
+ this->do_xdr() != 0,
+ this->do_zero_copy () != 0,
+ this->do_delete () != 0,
+ this->do_print_summary () != 0,
+ this->do_eager_exit () != 0,
+ this->do_udp () != 0,
+ this->do_ack () != 0,
+ (this->t_flags () & THR_DETACHED) != 0,
+ (this->t_flags () & THR_BOUND) != 0,
+ (this->t_flags () & THR_NEW_LWP) != 0,
+ this->sleep_time ()));
+}
+
+void
+Performance_Test_Options::print_results (void)
+{
+ ACE_Profile_Timer::ACE_Elapsed_Time et;
+ this->_itimer.elapsed_time (et);
+
+ ACE_Profile_Timer::Rusage rusage;
+ this->_itimer.elapsed_rusage (rusage);
+
+ size_t total = this->count ();
+ double nbytes = total * this->msg_size ();
+ double cpu_time = et.user_time + et.system_time;
+
+#if 0
+ mutex_timer.print_total ("ACE_Thread_Mutex overhead:", mutex_counter, 2);
+ condition_timer.print_total ("ACE_Condition overhead:", condition_counter, 2);
+ ACE_DEBUG ((LM_INFO,
+ "%8d (number of ACE_Thread_Mutex operations)\n"
+ "%8d (number of ACE_Condition operations)",
+ mutex_counter, condition_counter));
+#endif /* NDEBUG */
+
+ if (this->do_print_summary ())
+ {
+#if defined (ACE_HAS_PRUSAGE_T)
+ ACE_DEBUG ((LM_INFO,
+ "\n%8d PEs\n"
+ "%8.2f Mbit/sec\n"
+ "%8d (voluntary context switches)\n"
+ "%8d (involuntary context switches)\n"
+ "%8d (total context switches)\n"
+ "%8d.%d sec (wait-cpu time)\n"
+ "%8d.%d sec (user lock wait sleep time)\n"
+ "%8d.%d sec (all other sleep time)\n"
+ "%8d (major page faults)\n"
+ "%8d (minor page faults)\n"
+ "%8d (number of LWPs)\n",
+ this->thr_count (),
+ (nbytes / et.real_time) * 8.0 / 1024.0 / 1024.0,
+ rusage.pr_vctx,
+ rusage.pr_ictx,
+ rusage.pr_vctx + rusage.pr_ictx,
+ rusage.pr_wtime.tv_sec, rusage.pr_wtime.tv_nsec / 1000000,
+ rusage.pr_ltime.tv_sec, rusage.pr_ltime.tv_nsec / 1000000,
+ rusage.pr_slptime.tv_sec, rusage.pr_slptime.tv_nsec / 1000000,
+ rusage.pr_majf,
+ rusage.pr_minf,
+ ACE_Thread::getconcurrency ()));
+#elif defined (ACE_HAS_GETRUSAGE) && !defined (ACE_WIN32)
+ ACE_DEBUG ((LM_INFO,
+ "\n%8d PEs\n"
+ "%8.2f Mbit/sec\n"
+ "%8d (voluntary context switches)\n"
+ "%8d (involuntary context switches)\n"
+ "%8d (total context switches)\n"
+ "%8d.%d sec (user time)\n"
+ "%8d.%d sec (system time)\n"
+ "%8d (major page faults)\n"
+ "%8d (minor page faults)\n"
+ "%8d (number of LWPs)\n",
+ this->thr_count (),
+ (nbytes / et.real_time) * 8.0 / 1024.0 / 1024.0,
+ rusage.ru_nvcsw,
+ rusage.ru_nivcsw,
+ rusage.ru_nvcsw + rusage.ru_nivcsw,
+ rusage.ru_utime.tv_sec, rusage.ru_utime.tv_usec / 1000000,
+ rusage.ru_stime.tv_sec, rusage.ru_stime.tv_usec / 1000000,
+ rusage.ru_majflt,
+ rusage.ru_minflt,
+ ACE_Thread::getconcurrency ()));
+#elif defined (ACE_HAS_GETRUSAGE) && defined (ACE_WIN32)
+ // Need more stuff for Win32.
+ ACE_DEBUG ((LM_INFO,
+ "\n%8d PEs\n"
+ "%8.2f Mbit/sec\n"
+ "%8d (number of LWPs)\n",
+ this->thr_count (),
+ (nbytes / et.real_time) * 8.0 / 1024.0 / 1024.0,
+ ACE_Thread::getconcurrency ()));
+#endif /* ACE_HAS_PRUSAGE_T */
+ }
+ else
+ {
+ ACE_DEBUG ((LM_INFO,
+ "\ntotal work = %d\n"
+ "(Only interpret the next two statistics for throughput tests)\n"
+ "%f bytes in %.2f real seconds = %.2f Mbit/sec\n"
+ "%f bytes in %.2f CPU seconds = %.2f Mbit/sec\n",
+ total,
+ nbytes, et.real_time, (nbytes / et.real_time) * 8.0 / 1024.0 / 1024.0,
+ nbytes, cpu_time, (nbytes / cpu_time) * 8.0 / 1024.0 / 1024.0));
+
+#if defined (ACE_HAS_PRUSAGE_T)
+ ACE_DEBUG ((LM_INFO,
+ "%8d = lwpid\n"
+ "%8d = lwp count\n"
+ "%8d = minor page faults\n"
+ "%8d = major page faults\n"
+ "%8d = input blocks\n"
+ "%8d = output blocks\n"
+ "%8d = messages sent\n"
+ "%8d = messages received\n"
+ "%8d = signals received\n"
+ "%8ds, %dms = wait-cpu (latency) time\n"
+ "%8ds, %dms = user lock wait sleep time\n"
+ "%8ds, %dms = all other sleep time\n"
+ "%8d = voluntary context switches\n"
+ "%8d = involuntary context switches\n"
+ "%8d = total context switches\n"
+ "%8d = system calls\n"
+ "%8d = chars read/written\n"
+ "%8d = number of LWPs\n"
+ "---------------------\n"
+ "real time = %.3f\n"
+ "user time = %.3f\n"
+ "system time = %.3f\n"
+ "---------------------\n",
+ rusage.pr_lwpid,
+ rusage.pr_count,
+ rusage.pr_minf,
+ rusage.pr_majf,
+ rusage.pr_inblk,
+ rusage.pr_oublk,
+ rusage.pr_msnd,
+ rusage.pr_mrcv,
+ rusage.pr_sigs,
+ rusage.pr_wtime.tv_sec, rusage.pr_wtime.tv_nsec / 1000000,
+ rusage.pr_ltime.tv_sec, rusage.pr_ltime.tv_nsec / 1000000,
+ rusage.pr_slptime.tv_sec, rusage.pr_slptime.tv_nsec / 1000000,
+ rusage.pr_vctx,
+ rusage.pr_ictx,
+ rusage.pr_vctx + rusage.pr_ictx,
+ rusage.pr_sysc,
+ rusage.pr_ioch,
+ ACE_Thread::getconcurrency (),
+ et.real_time, et.user_time, et.system_time));
+#elif defined (ACE_HAS_GETRUSAGE) && !defined (ACE_WIN32)
+ ACE_DEBUG ((LM_INFO,
+ "%8d = minor page faults\n"
+ "%8d = major page faults\n"
+ "%8d = input blocks\n"
+ "%8d = output blocks\n"
+ "%8d = messages sent\n"
+ "%8d = messages received\n"
+ "%8d = signals received\n"
+ "%8d = voluntary context switches\n"
+ "%8d = involuntary context switches\n"
+ "%8d = total context switches\n"
+ "%8d = number of LWPs\n"
+ "---------------------\n"
+ "real time = %.3f\n"
+ "user time = %.3f\n"
+ "system time = %.3f\n"
+ "---------------------\n",
+ rusage.ru_minflt,
+ rusage.ru_majflt,
+ rusage.ru_inblock,
+ rusage.ru_oublock,
+ rusage.ru_msgsnd,
+ rusage.ru_msgrcv,
+ rusage.ru_nsignals,
+ rusage.ru_nvcsw,
+ rusage.ru_nivcsw,
+ rusage.ru_nvcsw + rusage.ru_nivcsw,
+ ACE_Thread::getconcurrency (),
+ et.real_time, et.user_time, et.system_time));
+#elif defined (ACE_HAS_GETRUSAGE) && defined (ACE_WIN32)
+ // need to write more dump ops for rusage on Win32
+ ACE_DEBUG ((LM_INFO,
+ "%8d = number of LWPs\n"
+ "---------------------\n"
+ "real time = %.3f\n"
+ "user time = %.3f\n"
+ "system time = %.3f\n"
+ "---------------------\n",
+ ACE_Thread::getconcurrency (),
+ et.real_time, et.user_time, et.system_time));
+#endif /* ACE_HAS_PRUSAGE_T */
+ }
+ if (performance_test_options.do_eager_exit ())
+ ACE_OS::_exit (0);
+}
+#endif /* ACE_HAS_THREADS */
+
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test_Options.h b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test_Options.h
new file mode 100644
index 00000000000..9d2285ce343
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test_Options.h
@@ -0,0 +1,133 @@
+/* -*- C++ -*- */
+// $Id$
+
+// Option manager for performance tests.
+
+#ifndef _PERFORMANCE_TEST_OPTIONS_H
+#define _PERFORMANCE_TEST_OPTIONS_H
+
+#include "ace/config-all.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#include "ace/Profile_Timer.h"
+#include "ace/Log_Msg.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Atomic_Op.h"
+#include "ace/svc_export.h"
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Performance_Test_Options
+{
+public:
+ Performance_Test_Options (void);
+ void parse_args (int argc, ACE_TCHAR *argv[]);
+
+ void init (void);
+
+ void start_timer (void);
+ void stop_timer (void);
+
+ void thr_count (size_t count);
+ size_t thr_count (void);
+
+ void pipe_addr (ACE_TCHAR pipe[]);
+ ACE_TCHAR *pipe_addr (void);
+
+ void mapped_file (ACE_TCHAR filename[]);
+ ACE_TCHAR *mapped_file (void);
+
+ void service_entry (ACE_TCHAR *service_entry);
+ ACE_TCHAR *service_entry (void);
+
+ void sleep_time (size_t count);
+ size_t sleep_time (void);
+
+ void logical_connections (size_t count);
+ size_t logical_connections (void);
+
+ void physical_connections (size_t count);
+ size_t physical_connections (void);
+
+ void consecutive_ports (size_t count);
+ size_t consecutive_ports (void);
+
+ void initial_queue_length (size_t length);
+ size_t initial_queue_length (void);
+
+ void high_water_mark (size_t size);
+ size_t high_water_mark (void);
+
+ void low_water_mark (size_t size);
+ size_t low_water_mark (void);
+
+ void msg_size (size_t size);
+ size_t msg_size (void);
+
+ void iterations (size_t n);
+ size_t iterations (void);
+
+ void n_lwps (size_t n);
+ size_t n_lwps (void);
+
+ void t_flags (long flag);
+ long t_flags (void);
+
+ size_t count (void);
+
+ int debug (void);
+ int verbose (void);
+ int do_checksum (void);
+ int do_generate (void);
+ int do_ack (void);
+ int do_delete (void);
+ int do_eager_exit (void);
+ int do_print_summary (void);
+ int do_udp (void);
+ int do_xdr (void);
+ int do_zero_copy (void);
+ void print_results (void);
+
+ ACE_Atomic_Op<ACE_Thread_Mutex, size_t> msg_count; // Keep track of number of messages atomically.
+ int *thr_work_count; // Count activity per-thread.
+ int thr_wc_size; // Max number of threads.
+
+private:
+ ACE_Profile_Timer _itimer; // Keep track of time.
+ ACE_TCHAR *_service_entry; // Name of the shared object file and shared object.
+ ACE_TCHAR *_mapped_file; // Name of the mapped file.
+ ACE_TCHAR *_pipe_addr; // Name of the STREAM pipe.
+ size_t _sleep_time; // Time to sleep.
+ size_t _n_lwps; // Number of LWPs.
+ size_t _thr_count; // Number of threads to spawn.
+ long _t_flags; // Flags to thr_create().
+ size_t _high_water_mark; // ACE_Queue high water mark.
+ size_t _low_water_mark; // ACE_Queue low water mark.
+ size_t _msg_size; // Size of a message.
+ size_t _initial_queue_length; // Initial number of items in the queue.
+ size_t _logical_connections; // Number of logical connections.
+ size_t _physical_connections; // Number of physical connections.
+ size_t _iterations; // Number of iterations to run the test program.
+ int _generate; // Generate the data.
+ int _udp; // Use UDP format.
+ int _debugging; // Extra debugging info.
+ int _verbosity; // Extra verbose messages.
+ int _ack; // Do an acknowledgement.
+ int _checksum; // Is checksumming enabled?.
+ int _xdr; // Is xdr conversion enabled?.
+ int _free_memory; // Are we freeing up memory?.
+ int _zero_copy; // Implement a zero-copy driver?.
+ int _print_summary; // Print a summary of the results only.
+ size_t _consecutive_ports; // Number of consecutive messages from same port.
+ int _eager_exit; // Exit eagerly, without cleaning up.
+};
+
+// Make this available to any code that wants to see it!
+extern ACE_Svc_Export Performance_Test_Options performance_test_options;
+
+#include "Performance_Test_Options.i"
+#endif /* ACE_HAS_THREADS */
+#endif /* _PERFORMANCE_TEST_OPTIONS_H */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test_Options.i b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test_Options.i
new file mode 100644
index 00000000000..6856edfa3cd
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Performance_Test_Options.i
@@ -0,0 +1,269 @@
+/* -*- C++ -*- */
+// $Id$
+
+/* Option manager for ustreams */
+
+#include "ace/Get_Opt.h"
+
+// Since this is only included in the .h file, these should be
+// remain inline, not ACE_INLINE.
+// FUZZ: disable check_for_inline
+
+
+inline int
+Performance_Test_Options::do_print_summary (void)
+{
+ return this->_print_summary;
+}
+
+inline int
+Performance_Test_Options::do_udp (void)
+{
+ return this->_udp;
+}
+
+inline void
+Performance_Test_Options::start_timer (void)
+{
+ this->_itimer.start ();
+}
+
+inline void
+Performance_Test_Options::stop_timer (void)
+{
+ this->_itimer.stop ();
+}
+
+inline int
+Performance_Test_Options::do_generate (void)
+{
+ return this->_generate;
+}
+
+inline int
+Performance_Test_Options::do_ack (void)
+{
+ return this->_ack;
+}
+
+inline int
+Performance_Test_Options::do_eager_exit (void)
+{
+ return this->_eager_exit;
+}
+
+inline int
+Performance_Test_Options::do_zero_copy (void)
+{
+ return this->_zero_copy;
+}
+
+inline int
+Performance_Test_Options::do_checksum (void)
+{
+ return this->_checksum;
+}
+
+inline int
+Performance_Test_Options::do_delete (void)
+{
+ return this->_free_memory;
+}
+
+inline int
+Performance_Test_Options::do_xdr (void)
+{
+ return this->_xdr;
+}
+
+inline void
+Performance_Test_Options::n_lwps (size_t count)
+{
+ this->_n_lwps = count;
+}
+
+inline size_t
+Performance_Test_Options::n_lwps (void)
+{
+ return this->_n_lwps;
+}
+
+inline void
+Performance_Test_Options::pipe_addr (ACE_TCHAR *pipe)
+{
+ this->_pipe_addr = pipe;
+}
+
+inline ACE_TCHAR *
+Performance_Test_Options::pipe_addr (void)
+{
+ return this->_pipe_addr;
+}
+
+inline void
+Performance_Test_Options::service_entry (ACE_TCHAR *pipe)
+{
+ this->_service_entry = pipe;
+}
+
+inline ACE_TCHAR *
+Performance_Test_Options::service_entry (void)
+{
+ return this->_service_entry;
+}
+
+inline void
+Performance_Test_Options::mapped_file (ACE_TCHAR *filename)
+{
+ this->_mapped_file = filename;
+}
+
+inline ACE_TCHAR *
+Performance_Test_Options::mapped_file (void)
+{
+ return this->_mapped_file;
+}
+
+inline void
+Performance_Test_Options::sleep_time (size_t count)
+{
+ this->_sleep_time = count;
+}
+
+inline size_t
+Performance_Test_Options::sleep_time (void)
+{
+ return this->_sleep_time;
+}
+
+inline void
+Performance_Test_Options::thr_count (size_t count)
+{
+ this->_thr_count = count;
+}
+
+inline size_t
+Performance_Test_Options::thr_count (void)
+{
+ return this->_thr_count;
+}
+
+inline void
+Performance_Test_Options::consecutive_ports (size_t count)
+{
+ this->_consecutive_ports = count;
+}
+
+inline size_t
+Performance_Test_Options::consecutive_ports (void)
+{
+ return this->_consecutive_ports;
+}
+
+inline void
+Performance_Test_Options::logical_connections (size_t count)
+{
+ this->_logical_connections = count;
+}
+
+inline size_t
+Performance_Test_Options::logical_connections (void)
+{
+ return this->_logical_connections;
+}
+
+inline void
+Performance_Test_Options::physical_connections (size_t count)
+{
+ this->_physical_connections = count;
+}
+
+inline size_t
+Performance_Test_Options::physical_connections (void)
+{
+ return this->_physical_connections;
+}
+
+inline void
+Performance_Test_Options::initial_queue_length (size_t length)
+{
+ this->_initial_queue_length = length;
+}
+
+inline size_t
+Performance_Test_Options::initial_queue_length (void)
+{
+ return this->_initial_queue_length;
+}
+
+inline void
+Performance_Test_Options::high_water_mark (size_t size)
+{
+ this->_high_water_mark = size;
+}
+
+inline size_t
+Performance_Test_Options::high_water_mark (void)
+{
+ return this->_high_water_mark;
+}
+
+inline void
+Performance_Test_Options::low_water_mark (size_t size)
+{
+ this->_low_water_mark = size;
+}
+
+inline size_t
+Performance_Test_Options::low_water_mark (void)
+{
+ return this->_low_water_mark;
+}
+
+inline void
+Performance_Test_Options::msg_size (size_t size)
+{
+ this->_msg_size = size;
+}
+
+inline size_t
+Performance_Test_Options::msg_size (void)
+{
+ return this->_msg_size;
+}
+
+inline void
+Performance_Test_Options::iterations (size_t n)
+{
+ this->_iterations = n;
+}
+
+inline size_t
+Performance_Test_Options::iterations (void)
+{
+ return this->_iterations;
+}
+
+inline void
+Performance_Test_Options::t_flags (long flag)
+{
+ this->_t_flags |= flag;
+}
+
+inline long
+Performance_Test_Options::t_flags (void)
+{
+ return this->_t_flags;
+}
+
+inline int
+Performance_Test_Options::debug (void)
+{
+ return this->_debugging;
+}
+
+inline int
+Performance_Test_Options::verbose (void)
+{
+ return this->_verbosity;
+}
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/README b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/README
new file mode 100644
index 00000000000..28f1f160e8a
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/README
@@ -0,0 +1,76 @@
+The files in this directory support controlled benchmarking of the ACE
+synchronization mechanisms.
+
+ These mechanisms include:
+
+ . Mutexes
+ . Reader/writer locks
+ . Condition variables
+ . Semaphores
+ . Tokens
+ . Adaptive lockings
+
+There are additional tests that measure the memory bandwidth under the
+following conditions:
+
+ . User memory-to-memory copying of data within a single thread
+ . User memory-to-kernel-to-user memory copying via pipes
+ between separate processes, as well as between separate
+ threads in the same process
+
+There are many options available for this module that can be put into
+svc.conf files. See the Performance_Test_Options.[Chi] file for more
+details. Some reasonable options to use to run the tests are:
+
+ -v -B -s 15
+ -v -n 4 -t 4 -s 15
+
+You should experiment with other options as you see fit. Note that on
+Solaris, you should always make sure that you have more than 1 LWP (by
+using either the -B or the -n options) since otherwise the program may
+get into an infinite loop due to the semantics of SunOS unbound
+threads... (This may no longer be the case.)
+
+
+Available Options in Performance_Test module:
+=============================================
+
+Thread Creation:
+----------------
+ -B: Create thread with THR_BOUND
+ -D: Create thread with THR_DETACHED
+ -N: Create thread with flag THR_NEW_LWP
+ -n: Set # of lwp's (default is 0)
+ -t: Set # of threads contending the lock (default is 4)
+
+Run Test:
+---------
+ -s: Set testing duration (in seconds, default is 100)
+ -T: Enable/disable tracing.
+
+Misc:
+-----
+ -p: Toggle whether summary is printed
+ -e: Perform eager exit (without cleaning up)
+ -M: Set message size in pipe_[proc|thr]_test
+
+Reserved Flags:
+---------------
+ -a: Not used. (do_ack ???)
+ -A: Not used. (set rendezvous point)
+ -c: Not used. (# of connections)
+ -C: Not used. (Toggle calculate checksum)
+ -d: Not used. (Enable debugging)
+ -F: Not used. (Free memory)
+ -g: Not used. (generate data ??)
+ -H: Not used. (set high water mark)
+ -i: Not used. (# of iterations)
+ -L: Not used. (set low water mark)
+ -l: Not used. (set initial queue length)
+ -m: Not used. (set mapped file name)
+ -P: Not used. (set consecutive ports)
+ -S: Not used. (set service_entry ???)
+ -u: Not used. (use udp)
+ -v: Not used. (set display verbosely)
+ -X: Not used. (Use xdr conversion)
+ -Z: Not used. (Do zero copy)
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Synch_Benchmarks_Perf_Test.mpc b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Synch_Benchmarks_Perf_Test.mpc
new file mode 100644
index 00000000000..f6a879deacd
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/Synch_Benchmarks_Perf_Test.mpc
@@ -0,0 +1,11 @@
+// -*- MPC -*-
+// $Id$
+
+project : acelib {
+ sharedname = Perf_Test
+ avoids += ace_for_tao
+ after += Synch_Lib
+ libs += Synch_Lib
+ libpaths += ../Synch_Lib
+ includes += ..
+}
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/adaptive_mutex_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/adaptive_mutex_test.cpp
new file mode 100644
index 00000000000..d438e9ac3f4
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/adaptive_mutex_test.cpp
@@ -0,0 +1,32 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "ace/Log_Msg.h"
+#include "Adaptive_Lock_Performance_Test_Base.h"
+#include "ace/Lock_Adapter_T.h"
+
+ACE_RCSID(Synch_Benchmarks, adaptive_mutex_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Adaptive_Mutex_Test : public Adaptive_Lock_Performance_Test_Base
+{
+public:
+ virtual int init (int, ACE_TCHAR *[]);
+};
+
+int
+Adaptive_Mutex_Test::init (int, ACE_TCHAR *[])
+{
+ ACE_Lock *lock;
+ ACE_NEW_RETURN (lock,
+ ACE_Lock_Adapter<ACE_Thread_Mutex> (),
+ -1);
+
+ return this->set_lock (lock);
+}
+
+ACE_SVC_FACTORY_DECLARE (Adaptive_Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Adaptive_Mutex_Test)
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/adaptive_recursive_lock_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/adaptive_recursive_lock_test.cpp
new file mode 100644
index 00000000000..cc49bf1b698
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/adaptive_recursive_lock_test.cpp
@@ -0,0 +1,33 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "ace/Log_Msg.h"
+#include "Adaptive_Lock_Performance_Test_Base.h"
+#include "ace/Lock_Adapter_T.h"
+#include "ace/Recursive_Thread_Mutex.h"
+
+ACE_RCSID(Synch_Benchmarks, adaptive_recursive_lock_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Adaptive_Recursive_Lock_Test : public Adaptive_Lock_Performance_Test_Base
+{
+public:
+ virtual int init (int, ACE_TCHAR *[]);
+};
+
+int
+Adaptive_Recursive_Lock_Test::init (int, ACE_TCHAR *[])
+{
+ ACE_Lock *lock;
+ ACE_NEW_RETURN (lock,
+ ACE_Lock_Adapter<ACE_Recursive_Thread_Mutex> (),
+ -1);
+
+ return this->set_lock (lock);
+}
+
+ACE_SVC_FACTORY_DECLARE (Adaptive_Recursive_Lock_Test)
+ACE_SVC_FACTORY_DEFINE (Adaptive_Recursive_Lock_Test)
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/adaptive_sema_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/adaptive_sema_test.cpp
new file mode 100644
index 00000000000..2644aef7415
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/adaptive_sema_test.cpp
@@ -0,0 +1,38 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "ace/Log_Msg.h"
+#include "Adaptive_Lock_Performance_Test_Base.h"
+#include "ace/Semaphore.h"
+#include "ace/Lock_Adapter_T.h"
+
+ACE_RCSID(Synch_Benchmarks, adaptive_sema_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Adaptive_Sema_Test : public Adaptive_Lock_Performance_Test_Base
+{
+public:
+ virtual int init (int, ACE_TCHAR *[]);
+
+private:
+ static ACE_Semaphore sema;
+};
+
+ACE_Semaphore Adaptive_Sema_Test::sema (1);
+
+int
+Adaptive_Sema_Test::init (int, ACE_TCHAR *[])
+{
+ ACE_Lock *lock;
+ ACE_NEW_RETURN (lock,
+ ACE_Lock_Adapter<ACE_Semaphore> (Adaptive_Sema_Test::sema),
+ -1);
+
+ return this->set_lock (lock);
+}
+
+ACE_SVC_FACTORY_DECLARE (Adaptive_Sema_Test)
+ACE_SVC_FACTORY_DEFINE (Adaptive_Sema_Test)
+
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/condb_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/condb_test.cpp
new file mode 100644
index 00000000000..432f741b9e7
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/condb_test.cpp
@@ -0,0 +1,69 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, condb_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Cond_Brdcast_Test : public Benchmark_Performance
+{
+public:
+ virtual int svc (void);
+
+private:
+ static ACE_Thread_Mutex mutex;
+ static int resources;
+
+ static ACE_Condition_Thread_Mutex notfull;
+ static ACE_Condition_Thread_Mutex notempty;
+};
+
+ACE_Thread_Mutex Cond_Brdcast_Test::mutex;
+int Cond_Brdcast_Test::resources;
+ACE_Condition_Thread_Mutex Cond_Brdcast_Test::notfull (Cond_Brdcast_Test::mutex);
+ACE_Condition_Thread_Mutex Cond_Brdcast_Test::notempty (Cond_Brdcast_Test::mutex);
+
+int
+Cond_Brdcast_Test::svc (void)
+{
+ int ni = this->thr_id ();
+ synch_count = 2;
+
+ // Special case for first thread...
+ if (ni == 4)
+ while (!this->done ())
+ {
+ mutex.acquire ();
+ while (resources > 0)
+ notfull.wait ();
+ performance_test_options.thr_work_count[ni]++;
+ resources = performance_test_options.thr_count () - 1;
+ buffer++;
+ notempty.broadcast ();
+ mutex.release ();
+ }
+ else
+ while (!this->done ())
+ {
+ mutex.acquire ();
+ while (resources == 0)
+ notempty.wait ();
+ performance_test_options.thr_work_count[ni]++;
+ buffer++;
+ if (--resources == 0)
+ notfull.signal ();
+ mutex.release ();
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (Cond_Brdcast_Test)
+ACE_SVC_FACTORY_DEFINE (Cond_Brdcast_Test)
+
+// ACE_Service_Object_Type cbt (&cond_brdcast_test, "Condition_Broadcast_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/conds_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/conds_test.cpp
new file mode 100644
index 00000000000..a930727861b
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/conds_test.cpp
@@ -0,0 +1,72 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, conds_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Cond_Signal_Test : public Benchmark_Performance
+{
+public:
+ virtual int svc (void);
+
+private:
+ static ACE_Thread_Mutex mutex;
+ static int resources;
+
+ static ACE_Condition_Thread_Mutex notfull;
+ static ACE_Condition_Thread_Mutex notempty;
+};
+
+ACE_Thread_Mutex Cond_Signal_Test::mutex;
+int Cond_Signal_Test::resources;
+ACE_Condition_Thread_Mutex Cond_Signal_Test::notfull (Cond_Signal_Test::mutex);
+ACE_Condition_Thread_Mutex Cond_Signal_Test::notempty (Cond_Signal_Test::mutex);
+
+int
+Cond_Signal_Test::svc (void)
+{
+ int ni = this->thr_id ();
+ synch_count = 2;
+
+ // This is a horrible hack and only works for Solaris threads. This
+ // clearly needs to change...
+ if (ni == 4)
+ while (!this->done ())
+ {
+ mutex.acquire ();
+
+ while (resources > 0)
+ notfull.wait ();
+
+ performance_test_options.thr_work_count[ni]++;
+ resources = performance_test_options.thr_count () - 1;
+ buffer++;
+ notempty.signal ();
+ mutex.release ();
+ }
+ else
+ while (!this->done ())
+ {
+ mutex.acquire ();
+ while (resources == 0)
+ notempty.wait ();
+ performance_test_options.thr_work_count[ni]++;
+ buffer++;
+ if (--resources == 0)
+ notfull.signal ();
+ mutex.release ();
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (Cond_Signal_Test)
+ACE_SVC_FACTORY_DEFINE (Cond_Signal_Test)
+
+// ACE_Service_Object_Type cst (&cond_signal_test, "Condition_Signal_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/context_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/context_test.cpp
new file mode 100644
index 00000000000..fc4fa0dc26d
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/context_test.cpp
@@ -0,0 +1,38 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, context_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Context_Test : public Benchmark_Performance
+{
+public:
+ virtual int svc (void);
+};
+
+int
+Context_Test::svc (void)
+{
+ int ni = this->thr_id ();
+
+ synch_count = 1;
+
+ while (!this->done ())
+ {
+ ACE_Thread::yield ();
+ performance_test_options.thr_work_count[ni]++;
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (Context_Test)
+ACE_SVC_FACTORY_DEFINE (Context_Test)
+
+// ACE_Service_Object_Type ct (&context_test, "Context_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/guard_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/guard_test.cpp
new file mode 100644
index 00000000000..e1824f3d4ac
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/guard_test.cpp
@@ -0,0 +1,124 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "ace/Guard_T.h"
+#include "ace/Log_Msg.h"
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, mutex_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Guard_Test : public Benchmark_Performance
+{
+public:
+ enum
+ { // svc.conf options
+ TEST_ACE_GUARD, // -g
+ TEST_ACE_THREAD_MUTEX_GUARD // -t
+ };
+
+ virtual int svc (void);
+ virtual int init (int, ACE_TCHAR *[]);
+
+ void test_guard (int);
+#if defined (ACE_USES_OBSOLETE_GUARD_CLASSES)
+ void test_thread_guard (int);
+#endif /* ACE_USES_OBSOLETE_GUARD_CLASSES */
+private:
+ static int guard_type_;
+ static ACE_Thread_Mutex mutex_;
+};
+
+int Guard_Test::guard_type_ = Guard_Test::TEST_ACE_GUARD;
+ACE_Thread_Mutex Guard_Test::mutex_;
+
+int
+Guard_Test::init (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT("gt"));
+ int c;
+
+ while ((c = getopt()) != -1)
+ {
+ switch (c)
+ {
+#if defined (ACE_USES_OBSOLETE_GUARD_CLASSES)
+ case 't':
+ Guard_Test::guard_type_ = Guard_Test::TEST_ACE_THREAD_MUTEX_GUARD;
+ break;
+#endif /* ACE_USES_OBSOLETE_GUARD_CLASSES */
+ case 'g':
+ Guard_Test::guard_type_ = Guard_Test::TEST_ACE_GUARD;
+ break;
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Invalid option\n"), -1);
+ }
+ }
+ return 0;
+}
+
+int
+Guard_Test::svc (void)
+{
+ // Extract out the unique thread-specific value to be used as an
+ // index...
+ int ni = this->thr_id ();
+ synch_count = 2;
+
+ switch (Guard_Test::guard_type_)
+ {
+ case Guard_Test::TEST_ACE_GUARD:
+ this->test_guard (ni);
+ break;
+#if defined (ACE_USES_OBSOLETE_GUARD_CLASSES)
+ case Guard_Test::TEST_ACE_THREAD_MUTEX_GUARD:
+ this->test_thread_guard (ni);
+ break;
+#endif /* ACE_USES_OBSOLETE_GUARD_CLASSES */
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+void
+Guard_Test::test_guard (int ni)
+{
+ while (!this->done ())
+ {
+ {
+ ACE_GUARD (ACE_Thread_Mutex, _ace_mon, Guard_Test::mutex_);
+
+ performance_test_options.thr_work_count[ni]++;
+ buffer++;
+ }
+ }
+}
+
+#if defined (ACE_USES_OBSOLETE_GUARD_CLASSES)
+# define ACE_THREAD_GUARD(OBJ,LOCK) \
+ ACE_Thread_Mutex_Guard OBJ (LOCK); \
+ if (OBJ.locked () == 0) return;
+
+void
+Guard_Test::test_thread_guard (int ni)
+{
+ while (!this->done ())
+ {
+ {
+ ACE_THREAD_GUARD (_ace_mon, Guard_Test::mutex_);
+
+ performance_test_options.thr_work_count[ni]++;
+ buffer++;
+ }
+ }
+}
+#endif /* ACE_USES_OBSOLETE_GUARD_CLASSES */
+ACE_SVC_FACTORY_DECLARE (Guard_Test)
+ACE_SVC_FACTORY_DEFINE (Guard_Test)
+
+// ACE_Service_Object_Type mut (&mutex_test, "Guard_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/memory_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/memory_test.cpp
new file mode 100644
index 00000000000..9d0bcd6c7d1
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/memory_test.cpp
@@ -0,0 +1,42 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "ace/OS_NS_string.h"
+#include "ace/Log_Msg.h"
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, memory_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Memory_Test : public Benchmark_Performance
+{
+public:
+ virtual int svc (void);
+};
+
+int
+Memory_Test::svc (void)
+{
+ int ni = this->thr_id ();
+ size_t length = performance_test_options.msg_size ();
+ char *from = new char[length];
+ char *to = new char[length];
+
+ synch_count = 1;
+
+ while (!this->done ())
+ {
+ ACE_OS::memcpy (to, from, length);
+ performance_test_options.thr_work_count[ni]++;
+ }
+ /* NOTREACHED */
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (Memory_Test)
+ACE_SVC_FACTORY_DEFINE (Memory_Test)
+
+// ACE_Service_Object_Type mt (&memory_test, "Memory_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/mutex_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/mutex_test.cpp
new file mode 100644
index 00000000000..c1e0a1e0ad0
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/mutex_test.cpp
@@ -0,0 +1,45 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, mutex_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Mutex_Test : public Benchmark_Performance
+{
+public:
+ virtual int svc (void);
+
+private:
+ static ACE_Thread_Mutex mutex;
+};
+
+ACE_Thread_Mutex Mutex_Test::mutex;
+
+int
+Mutex_Test::svc (void)
+{
+ // Extract out the unique thread-specific value to be used as an
+ // index...
+ int ni = this->thr_id ();
+ synch_count = 2;
+
+ while (!this->done ())
+ {
+ mutex.acquire ();
+ performance_test_options.thr_work_count[ni]++;
+ buffer++;
+ mutex.release ();
+ }
+ /* NOTREACHED */
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (Mutex_Test)
+ACE_SVC_FACTORY_DEFINE (Mutex_Test)
+
+// ACE_Service_Object_Type mut (&mutex_test, "Mutex_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/pipe_proc_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/pipe_proc_test.cpp
new file mode 100644
index 00000000000..10bed9b88f3
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/pipe_proc_test.cpp
@@ -0,0 +1,86 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, pipe_proc_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Pipe_Proc_Test : public Benchmark_Performance
+{
+public:
+ int init (int, ACE_TCHAR **);
+ virtual int svc (void);
+
+private:
+ ACE_HANDLE pipe_handles[2];
+
+ void reader (ACE_HANDLE handle);
+};
+
+int
+Pipe_Proc_Test::init (int, ACE_TCHAR **)
+{
+ synch_count = 1;
+
+ if (ACE_OS::pipe (this->pipe_handles) == -1)
+ ACE_OS::perror (ACE_TEXT("pipe")), ACE_OS::exit (1);
+
+ switch (ACE_OS::fork ())
+ {
+ case -1:
+ ACE_OS::perror (ACE_TEXT("fork")), ACE_OS::exit (1);
+ case 0:
+ this->reader (pipe_handles[0]);
+ /* NOTREACHED */
+ break;
+ default:
+ break;
+ }
+ return 1;
+}
+
+void
+Pipe_Proc_Test::reader (ACE_HANDLE handle)
+{
+ int ni = this->thr_id ();
+ int length = performance_test_options.msg_size ();
+ char *to;
+
+ ACE_NEW (to, char[length]);
+
+ while (ACE_OS::read (handle, to, length) > 0)
+ performance_test_options.thr_work_count[ni]++;
+}
+
+
+int
+Pipe_Proc_Test::svc (void)
+{
+ ssize_t length = performance_test_options.msg_size ();
+ int ni = this->thr_id ();
+ ACE_HANDLE handle = this->pipe_handles[1];
+ char *from;
+
+ ACE_NEW_RETURN (from, char[length], -1);
+
+ while (!this->done ())
+ if (ACE_OS::write (handle, from, length) == length)
+ performance_test_options.thr_work_count[ni]++;
+ else
+ ACE_OS::perror (ACE_TEXT("write"));
+
+ ACE_OS::close (this->pipe_handles[0]);
+ ACE_OS::close (this->pipe_handles[1]);
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (Pipe_Proc_Test)
+ACE_SVC_FACTORY_DEFINE (Pipe_Proc_Test)
+
+// ACE_Service_Object_Type ppt (&pipe_proc_test, "Pipe_Proc_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/pipe_thr_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/pipe_thr_test.cpp
new file mode 100644
index 00000000000..895b5a846fe
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/pipe_thr_test.cpp
@@ -0,0 +1,79 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/Thread_Manager.h"
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, pipe_thr_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Pipe_Thr_Test : public Benchmark_Performance
+{
+public:
+ virtual int init (int, ACE_TCHAR **);
+ virtual int svc (void);
+
+private:
+ ACE_HANDLE pipe_handles[2];
+
+ static void *reader (Pipe_Thr_Test *);
+};
+
+void *
+Pipe_Thr_Test::reader (Pipe_Thr_Test *t)
+{
+ ACE_HANDLE handle = t->pipe_handles[0];
+ int ni = t->thr_id ();
+ size_t length = performance_test_options.msg_size ();
+ char *to;
+ ACE_NEW_RETURN (to, char[length], 0);
+
+ while (ACE_OS::read (handle, to, length) > 0)
+ performance_test_options.thr_work_count[ni]++;
+
+ return 0;
+}
+
+int
+Pipe_Thr_Test::init (int, ACE_TCHAR **)
+{
+ synch_count = 1;
+
+ if (ACE_OS::pipe (this->pipe_handles) == -1)
+ ACE_OS::perror (ACE_TEXT("pipe")), ACE_OS::exit (1);
+
+ if (ACE_Thread_Manager::instance ()->spawn
+ (ACE_THR_FUNC (Pipe_Thr_Test::reader),
+ (void *) this, performance_test_options.t_flags ()) == -1)
+ ACE_OS::perror (ACE_TEXT("thr_create")), ACE_OS::exit (1);
+
+ return 1;
+}
+
+int
+Pipe_Thr_Test::svc (void)
+{
+ ssize_t length = performance_test_options.msg_size ();
+ ACE_HANDLE handle = this->pipe_handles[1];
+ char *from;
+ ACE_NEW_RETURN (from, char[length], -1);
+
+ while (!this->done ())
+ if (ACE_OS::write (handle, from, length) != length)
+ ACE_OS::perror (ACE_TEXT("write"));
+
+ ACE_OS::close (this->pipe_handles[0]);
+ ACE_OS::close (this->pipe_handles[1]);
+
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (Pipe_Thr_Test)
+ACE_SVC_FACTORY_DEFINE (Pipe_Thr_Test)
+
+// ACE_Service_Object_Type ptt (&pipe_thr_test, "Pipe_Thr_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/recursive_lock_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/recursive_lock_test.cpp
new file mode 100644
index 00000000000..6246835ee88
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/recursive_lock_test.cpp
@@ -0,0 +1,44 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "ace/Recursive_Thread_Mutex.h"
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, recursive_lock_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Recursive_Lock_Test : public Benchmark_Performance
+{
+public:
+ virtual int svc (void);
+
+private:
+ static ACE_Recursive_Thread_Mutex mutex;
+};
+
+ACE_Recursive_Thread_Mutex Recursive_Lock_Test::mutex;
+
+int
+Recursive_Lock_Test::svc (void)
+{
+ int ni = this->thr_id ();
+ synch_count = 2;
+
+ while (!this->done ())
+ {
+ this->mutex.acquire ();
+ performance_test_options.thr_work_count[ni]++;
+ buffer++;
+ this->mutex.release ();
+ }
+ /* NOTREACHED */
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (Recursive_Lock_Test)
+ACE_SVC_FACTORY_DEFINE (Recursive_Lock_Test)
+
+// ACE_Service_Object_Type rlt (&recursive_lock_test, "Recursive_Lock_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/rwrd_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/rwrd_test.cpp
new file mode 100644
index 00000000000..a0eb5c6cff8
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/rwrd_test.cpp
@@ -0,0 +1,45 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "ace/RW_Mutex.h"
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, rwrd_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export RWRD_Test : public Benchmark_Performance
+{
+public:
+ virtual int svc (void);
+
+private:
+ static ACE_RW_Mutex rw_lock;
+};
+
+ACE_RW_Mutex RWRD_Test::rw_lock;
+
+int
+RWRD_Test::svc (void)
+{
+ int ni = this->thr_id ();
+ synch_count = 2;
+
+ while (!this->done ())
+ {
+ rw_lock.acquire_read ();
+ performance_test_options.thr_work_count[ni]++;
+ buffer++;
+ rw_lock.release ();
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (RWRD_Test)
+ACE_SVC_FACTORY_DEFINE (RWRD_Test)
+
+// ACE_Service_Object_Type rwrdt (&rwrd_test, "RWRD_Mutex_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/rwwr_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/rwwr_test.cpp
new file mode 100644
index 00000000000..1c7a25eae1f
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/rwwr_test.cpp
@@ -0,0 +1,45 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "ace/RW_Mutex.h"
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, rwwr_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export RWWR_Test : public Benchmark_Performance
+{
+public:
+ virtual int svc (void);
+
+private:
+ static ACE_RW_Mutex rw_lock;
+};
+
+ACE_RW_Mutex RWWR_Test::rw_lock;
+
+int
+RWWR_Test::svc (void)
+{
+ int ni = this->thr_id ();
+ synch_count = 2;
+
+ while (!this->done ())
+ {
+ rw_lock.acquire_write ();
+ performance_test_options.thr_work_count[ni]++;
+ buffer++;
+ rw_lock.release ();
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (RWWR_Test)
+ACE_SVC_FACTORY_DEFINE (RWWR_Test)
+
+// ACE_Service_Object_Type rwwrt (&rwwr_test, "RWWR_Mutext_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/sema_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/sema_test.cpp
new file mode 100644
index 00000000000..9f1d7657139
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/sema_test.cpp
@@ -0,0 +1,45 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+#include "ace/Semaphore.h"
+
+ACE_RCSID(Synch_Benchmarks, sema_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Sema_Test : public Benchmark_Performance
+{
+public:
+ virtual int svc (void);
+
+private:
+ static ACE_Semaphore sema;
+};
+
+ACE_Semaphore Sema_Test::sema (1);
+
+int
+Sema_Test::svc (void)
+{
+ int ni = this->thr_id ();
+ synch_count = 2;
+
+ while (!this->done ())
+ {
+ sema.acquire ();
+ performance_test_options.thr_work_count[ni]++;
+ buffer++;
+ sema.release ();
+ }
+
+ /* NOTREACHED */
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (Sema_Test)
+ACE_SVC_FACTORY_DEFINE (Sema_Test)
+
+// ACE_Service_Object_Type semt (&sema_test, "Semaphore_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/sysvsema_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/sysvsema_test.cpp
new file mode 100644
index 00000000000..5899e4f1a75
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/sysvsema_test.cpp
@@ -0,0 +1,67 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "ace/SV_Semaphore_Simple.h"
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, sysvsema_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export SYSVSema_Test : public Benchmark_Performance
+{
+public:
+ virtual int init (int, ACE_TCHAR *[]);
+ virtual int fini (void);
+ virtual int svc (void);
+
+private:
+ static ACE_SV_Semaphore_Simple *sema;
+};
+
+
+ACE_SV_Semaphore_Simple *SYSVSema_Test::sema = 0;
+
+int
+SYSVSema_Test::init (int, ACE_TCHAR *[])
+{
+#if defined (ACE_HAS_SYSV_IPC)
+ ACE_NEW_RETURN (SYSVSema_Test::sema, ACE_SV_Semaphore_Simple ((key_t) 1234), -1);
+ return 0;
+#else
+ ACE_ERROR_RETURN ((LM_ERROR, "SysV Semaphore not supported on this platform.\n"), -1);
+#endif /* ACE_HAS_SYSV_IPC */
+}
+
+int
+SYSVSema_Test::fini (void)
+{
+ delete SYSVSema_Test::sema;
+ return 0;
+}
+
+int
+SYSVSema_Test::svc (void)
+{
+ int ni = this->thr_id ();
+ synch_count = 2;
+
+ while (!this->done ())
+ {
+ SYSVSema_Test::sema->acquire ();
+ performance_test_options.thr_work_count[ni]++;
+ buffer++;
+ SYSVSema_Test::sema->release ();
+ }
+
+ SYSVSema_Test::sema->remove ();
+ /* NOTREACHED */
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (SYSVSema_Test)
+ACE_SVC_FACTORY_DEFINE (SYSVSema_Test)
+
+// ACE_Service_Object_Type st (&sysvsema_test, "SYSVSema_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Perf_Test/token_test.cpp b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/token_test.cpp
new file mode 100644
index 00000000000..fe66740feca
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Perf_Test/token_test.cpp
@@ -0,0 +1,46 @@
+// $Id$
+
+#define ACE_BUILD_SVC_DLL
+#include "ace/Token.h"
+#include "Performance_Test_Options.h"
+#include "Benchmark_Performance.h"
+
+ACE_RCSID(Synch_Benchmarks, token_test, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+class ACE_Svc_Export Token_Test : public Benchmark_Performance
+{
+public:
+ virtual int svc (void);
+
+private:
+ static ACE_Token token;
+};
+
+ACE_Token Token_Test::token;
+
+int
+Token_Test::svc (void)
+{
+ // Extract out the unique thread-specific value to be used as an
+ // index...
+ int ni = this->thr_id ();
+ synch_count = 2;
+
+ while (!this->done ())
+ {
+ token.acquire ();
+ performance_test_options.thr_work_count[ni]++;
+ buffer++;
+ token.release ();
+ }
+ /* NOTREACHED */
+ return 0;
+}
+
+ACE_SVC_FACTORY_DECLARE (Token_Test)
+ACE_SVC_FACTORY_DEFINE (Token_Test)
+
+// ACE_Service_Object_Type tok (&token_test, "Token_Test");
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/README b/ACE/performance-tests/Synch-Benchmarks/README
new file mode 100644
index 00000000000..c902ecab244
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/README
@@ -0,0 +1,46 @@
+This directory contains a program for benchmarking various
+synchronization and concurrent programming mechanisms in ACE.
+
+To build the program, do a make on the top level Makefile (or,
+on NT, open Synch_Tests.dsw and build evey project in it.)
+There are several modules which perform different benchmarking
+measurements in subdirectories. Here is a short description of all
+the subdirectories:
+
+ Synch_lib: This directory contains interface definitions required
+ by both main program (synch_driver) and other modules.
+ Base_Test: This directory contains a set of baseline tests. They
+ measure the time to obtain a lock without contension,
+ or trying to objtain a lock with contension.
+ Perf_Test: This directory contains a set of performance tests.
+ They measure the opeation performed by spawning a
+ bunch of threads and let these threads compete with
+ each other in obtaining a lock.
+
+There'll always be a "Method" object in each module subdirectory.
+They defines the method used in benchmarking and usually takes some
+options which can be defined in the 'svc.conf' file. Beside from this
+"Method" object, there are also a lot of "Test" objects that define
+the mechanism to be tested.
+
+Executing the program: the synch_driver performs various benchmarking
+according to the "script" defined in 'svc.conf' file. All command
+line options applicable to ACE's Service_Config class can be used.
+
+The entries in svc.conf file are always in groups. Each group
+consists of several svc.conf entries. The first entry in each group
+is the "Method" entry which defines the methodology used in the test.
+The rest of the entries are "Test" entries which define the mechanism
+to be test using the "Method".
+
+At this moment, you can not have entries with the same object (either
+"Method" object or "Test" object) in one svc.conf file. Therefore, at
+this moment, there can only be two groups in the svc.conf. Of them,
+each "Test" can only be performed once. Therefore, there's no way to
+benchmark using the same method with differnt configurations within
+the same svc.conf file. However, this can be easily overcome by
+defining multiple svc.conf files and invoking the synch_driver with
+different svc.conf file.
+
+There'll be more detailed description about how a "Method" object can
+be configured in respective subdirectory. \ No newline at end of file
diff --git a/ACE/performance-tests/Synch-Benchmarks/Synch_Benchmarks.mpc b/ACE/performance-tests/Synch-Benchmarks/Synch_Benchmarks.mpc
new file mode 100644
index 00000000000..92ad3685637
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Synch_Benchmarks.mpc
@@ -0,0 +1,12 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ exename = synch_driver
+ after += Synch_Lib
+ libs += Synch_Lib
+ libpaths += Synch_Lib
+ source_files {
+ synch_driver.cpp
+ }
+}
diff --git a/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Benchmark_Base.cpp b/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Benchmark_Base.cpp
new file mode 100644
index 00000000000..48c2ec20cd0
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Benchmark_Base.cpp
@@ -0,0 +1,95 @@
+// $Id$
+
+#if !defined (SYNCHLIB_BUILD_DLL)
+#define SYNCHLIB_BUILD_DLL
+#endif /* SYNCHLIB_BUILD_DLL */
+
+#include "ace/Log_Msg.h"
+#include "Benchmark_Base.h"
+
+ACE_RCSID(Synch_Benchmarks, Benchmark_Base, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+
+// Initialize the static variables.
+/* static */
+
+Benchmark_Base::Benchmark_Base (int type)
+ : benchmark_type_ (type)
+{
+}
+
+int
+Benchmark_Base::benchmark_type (void)
+{
+ return this->benchmark_type_;
+}
+
+int
+Benchmark_Base::thr_id (void)
+{
+#if defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_DCETHREADS) || defined (VXWORKS)
+ // This invokes the thread-specific storage smart pointer.
+ return this->id_->thr_id ();
+#else
+ return ACE_Thread::self ();
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_DCETHREADS || VXWORKS */
+}
+
+Benchmark_Method_Base::Benchmark_Method_Base (void)
+ : Benchmark_Base (Benchmark_Base::METHOD)
+{
+}
+
+int
+Benchmark_Method_Base::exec (ACE_Service_Repository_Iterator *sri)
+{
+ sri->advance ();
+ for (const ACE_Service_Type *sr;
+ sri->next (sr) != 0;
+ sri->advance ())
+ {
+ // This would greatly benefit from RTTI typesafe downcasting...
+ const ACE_Service_Type_Impl *type = sr->type ();
+ const void *obj = type->object ();
+ ACE_Service_Object *so = (ACE_Service_Object *) obj;
+ Benchmark_Base *bp = (Benchmark_Base *) so;
+
+ if (this->valid_test_object (bp))
+ {
+
+ ACE_DEBUG ((LM_DEBUG, "\nstarting up %s\n", sr->name ()));
+
+ int notused = this->pre_run_test (bp) == 0 && this->run_test () == 0 &&
+ this->post_run_test () == 0;
+ notused = notused;
+ }
+ else
+ return 0;
+ }
+ return 0;
+}
+
+#if defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_DCETHREADS) || defined (VXWORKS)
+/* static */
+MT_INT Thr_ID::thread_id_ (0);
+
+Thr_ID::Thr_ID (void)
+ : thr_id_ (++Thr_ID::thread_id_)
+{
+}
+
+int
+Thr_ID::thr_id (void)
+{
+ return this->thr_id_;
+}
+
+void
+Thr_ID::thr_id (int i)
+{
+ this->thr_id_ = i;
+}
+
+#endif /* ACE_HAS_PTHREADS || ACE_HAS_DCETHREADS || VXWORKS */
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Benchmark_Base.h b/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Benchmark_Base.h
new file mode 100644
index 00000000000..1737d45b36f
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Benchmark_Base.h
@@ -0,0 +1,114 @@
+/* -*- C++ -*- */
+// $Id$
+
+/* Defines the base class used to dynamically link in the benchmark tests */
+
+#ifndef ACE_BENCHMARK_BASE_H
+# define ACE_BENCHMARK_BASE_H
+
+# include "ace/Service_Config.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+# include "ace/Service_Repository.h"
+# include "ace/Service_Types.h"
+# include "ace/Atomic_Op.h"
+# include "export_mac.h"
+# include "ace/TSS_T.h"
+
+# if defined (ACE_HAS_THREADS)
+
+# if defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_DCETHREADS) || defined (VXWORKS)
+
+typedef ACE_Atomic_Op<ACE_Thread_Mutex, int> MT_INT;
+
+class Thr_ID
+ // TITLE
+ // A simple class that provides a thread-specific value in order
+ // to compensate for POSIX Pthreads.
+ //
+ // DESCRIPTION
+ // Pthreads are too lame to have a sensible scalar values for the
+ // thread id (unlike Solaris threads). Therefore, we have to
+ // emulate this ourselves with this class (gag).
+{
+public:
+ Thr_ID (void);
+ int thr_id (void);
+ void thr_id (int);
+
+private:
+ int thr_id_;
+ static MT_INT thread_id_;
+};
+# endif /* ACE_HAS_PTHREADS || ACE_HAS_DCETHREADS || VXWORKS */
+
+class SYNCHLIB_Export Benchmark_Base : public ACE_Service_Object
+{
+ // = TITLE
+ // Base class for all benchmarking objects.
+ //
+ // = DESCRIPTION
+ // This class is the base class for all benchmarking
+ // classes. Its major functionalities are to privide RTTI
+ // information and to define other common methods all
+ // benchmarking classes should support.
+public:
+ enum {
+ BENCHMARK_BASE,
+ METHOD,
+ BASELINE,
+ PERFORMANCE
+ };
+
+ int benchmark_type (void);
+ // RTTI information of this module.
+
+ int thr_id (void);
+ // Returns our thread id;
+
+protected:
+ Benchmark_Base (int type = BENCHMARK_BASE);
+ // Default ctor.
+
+ int benchmark_type_;
+ // Store the RTTI info of this module.
+
+# if defined (ACE_HAS_PTHREADS) || defined (ACE_HAS_DCETHREADS) || defined (VXWORKS)
+ ACE_TSS <Thr_ID> id_;
+ // Keeps track of our "virtual" thread id...
+# endif /* ACE_HAS_PTHREADS || ACE_HAS_DCETHREADS || VXWORKS */
+};
+
+class SYNCHLIB_Export Benchmark_Method_Base : public Benchmark_Base
+{
+ // = TITLE
+ // This class identifies itself as Benmarking Method class.
+ // It defines a method as of how the test is setup and measured.
+public:
+ int exec (ACE_Service_Repository_Iterator *sri);
+ // Run the test and advanced the service repository iterator
+
+ virtual int pre_run_test (Benchmark_Base *bp) = 0;
+ // Before running the real test. Subclasses implement this method
+ // to dictate how the test is performed.
+
+ virtual int run_test (void) = 0;
+ // Run the real test. Subclasses implement this method to
+ // dictate how the test is performed.
+
+ virtual int post_run_test (void) = 0;
+ // After running the real test. Subclasses implement this method to
+ // dictate how the test is performed.
+
+ virtual int valid_test_object (Benchmark_Base *) = 0;
+ // Check if we got a valid test to perform.
+
+protected:
+ Benchmark_Method_Base (void);
+};
+
+# endif /* ACE_HAS_THREADS */
+#endif /* ACE_BENCHMARK_BASE_H */
diff --git a/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Makefile.am b/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Makefile.am
new file mode 100644
index 00000000000..05c71adde0c
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Makefile.am
@@ -0,0 +1,36 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+## Makefile.Synch_Lib.am
+
+noinst_LTLIBRARIES = libSynch_Lib.la
+
+libSynch_Lib_la_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR) \
+ -DSYNCHLIB_BUILD_DLL
+
+libSynch_Lib_la_SOURCES = \
+ Benchmark_Base.cpp
+
+noinst_HEADERS = \
+ Benchmark_Base.h \
+ export_mac.h
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/README b/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/README
new file mode 100644
index 00000000000..f17fe39234a
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/README
@@ -0,0 +1,4 @@
+This subdirectory contains a library that defines the interface used
+by all benchmarking modules. The library is required by all modules
+and the synch_driver. If you want to develop your own benchmarking
+module, this directory provides a starting point.
diff --git a/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Synch_Benchmarks_Synch_Lib.mpc b/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Synch_Benchmarks_Synch_Lib.mpc
new file mode 100644
index 00000000000..34f382f3faa
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/Synch_Benchmarks_Synch_Lib.mpc
@@ -0,0 +1,7 @@
+// -*- MPC -*-
+// $Id$
+
+project(Synch_Lib) : acelib {
+ sharedname = Synch_Lib
+ dynamicflags += SYNCHLIB_BUILD_DLL
+}
diff --git a/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/export_mac.h b/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/export_mac.h
new file mode 100644
index 00000000000..e4e6be63334
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/Synch_Lib/export_mac.h
@@ -0,0 +1,40 @@
+// -*- C++ -*-
+// $Id$
+// Definition for Win32 Export directives.
+// This file is generated automatically by
+// ${ACE_ROOT}/GenExportH.BAT
+// ------------------------------
+#if !defined (SYNCHLIB_EXPORT_H)
+#define SYNCHLIB_EXPORT_H
+
+#include "ace/config-all.h"
+
+#if defined (ACE_AS_STATIC_LIBS) && !defined (SYNCHLIB_HAS_DLL)
+# define SYNCHLIB_HAS_DLL 0
+#endif /* ACE_AS_STATIC_LIBS && ! TEST_HAS_DLL */
+
+#if !defined (SYNCHLIB_HAS_DLL)
+#define SYNCHLIB_HAS_DLL 1
+#endif /* !SYNCHLIB_HAS_DLL */
+
+#if defined (SYNCHLIB_HAS_DLL)
+# if (SYNCHLIB_HAS_DLL == 1)
+# if defined (SYNCHLIB_BUILD_DLL)
+# define SYNCHLIB_Export ACE_Proper_Export_Flag
+# define SYNCHLIB_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T)
+# else
+# define SYNCHLIB_Export ACE_Proper_Import_Flag
+# define SYNCHLIB_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T)
+# endif /* SYNCHLIB_BUILD_DLL */
+# else
+# define SYNCHLIB_Export
+# define SYNCHLIB_SINGLETON_DECLARATION(T)
+# endif /* ! SYNCHLIB_HAS_DLL == 1 */
+#else
+# define SYNCHLIB_Export
+# define SYNCHLIB_SINGLETON_DECLARATION(T)
+#endif /* SYNCHLIB_HAS_DLL */
+
+#endif /* SYNCHLIB_EXPORT_H */
+// End of auto generated file.
+
diff --git a/ACE/performance-tests/Synch-Benchmarks/benchmarks b/ACE/performance-tests/Synch-Benchmarks/benchmarks
new file mode 100644
index 00000000000..5b3a6644bc5
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/benchmarks
@@ -0,0 +1,19 @@
+#!/bin/csh -f
+
+echo "Memory test = 512, 40M"
+./memory_test -i 80000 -M 512
+echo "Memory test = 1024, 40M"
+./memory_test -i 40000 -M 1024
+echo "Memory test = 2048, 40M"
+./memory_test -i 20000 -M 2048
+echo "Memory test = 4096, 40M"
+./memory_test -i 10000 -M 4096
+
+echo "Pipe test = 512, 40M"
+./pipe_test -i 80000 -M 512
+echo "Pipe test = 1024, 40M"
+./pipe_test -i 40000 -M 1024
+echo "Pipe test = 2048, 40M"
+./pipe_test -i 20000 -M 2048
+echo "Pipe test = 4096, 40M"
+./pipe_test -i 10000 -M 4096
diff --git a/ACE/performance-tests/Synch-Benchmarks/context.c b/ACE/performance-tests/Synch-Benchmarks/context.c
new file mode 100644
index 00000000000..a5a6e577b12
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/context.c
@@ -0,0 +1,73 @@
+/* $Id$ */
+#include <stdio.h>
+// @(#)context.c 1.1 10/18/96
+
+#include <stdlib.h>
+#include <thread.h>
+
+#define NSLEEP 100
+#define TMAX 2
+int count[TMAX];
+
+void *
+work (void *n)
+{
+ int ni = (int) n;
+
+ while (1)
+ {
+ thr_yield ();
+ count[ni]++;
+ }
+ return 0;
+}
+
+main (int argc, char *argv[])
+{
+ int ncorr, t1arg, t0arg, orig_ncorr;
+ thread_t tid1, tid0;
+ float rate;
+
+ if (argc != 6)
+ {
+ printf ("usage: %s t0_bound t0_new_lwp t1_bound t1_new_lwp ncorr\n", argv[0]);
+ exit (1);
+ }
+ t0arg = THR_DETACHED;
+ if (atoi (argv[1]))
+ t0arg |= THR_BOUND;
+ if (atoi (argv[2]))
+ t0arg |= THR_NEW_LWP;
+
+ t1arg = THR_DETACHED;
+ if (atoi (argv[3]))
+ t1arg |= THR_BOUND;
+ if (atoi (argv[4]))
+ t1arg |= THR_NEW_LWP;
+
+ ncorr = atoi (argv[5]);
+
+ if (thr_create (NULL, 0, work, 0, t0arg, &tid0) != 0)
+ perror ("couldn't create thread 0");
+ if (thr_create (NULL, 0, work, (void *) 1, t1arg, &tid1) != 0)
+ perror ("couldn't create thread 1");
+
+ orig_ncorr = thr_getconcurrency ();
+ if (ncorr)
+ thr_setconcurrency (ncorr);
+ sleep (NSLEEP);
+ rate = (count[0] + count[1]) / ((float) NSLEEP);
+ printf ("\n------------------------------------------------------------------------\n");
+ printf ("t0arg 0x%x (%s, %s, %s)\nt1arg 0x%x (%s, %s, %s)\ncount[0] %d count[1] %d\n\
+ncorr_orig %d ncorr_set %d ncorr_end %d rate %.3f per_cxt %.2f usec\n",
+ t0arg,
+ (t0arg & THR_DETACHED) ? "THR_DETACHED" : "Not Detached",
+ (t0arg & THR_BOUND) ? "THR_BOUND" : "Not Bound",
+ (t0arg & THR_NEW_LWP) ? "THR_NEW_LWP" : "No New_LWP",
+ t1arg,
+ (t1arg & THR_DETACHED) ? "THR_DETACHED" : "Not Detached",
+ (t1arg & THR_BOUND) ? "THR_BOUND" : "Not Bound",
+ (t1arg & THR_NEW_LWP) ? "THR_NEW_LWP" : "No New_LWP",
+ count[0], count[1],
+ orig_ncorr, ncorr, thr_getconcurrency (), rate, 1.0e6 / rate);
+}
diff --git a/ACE/performance-tests/Synch-Benchmarks/context.csh b/ACE/performance-tests/Synch-Benchmarks/context.csh
new file mode 100644
index 00000000000..867611f07e1
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/context.csh
@@ -0,0 +1,16 @@
+#/bin/csh -f
+time ./context 0 0 0 0 0
+time ./context 0 0 0 0 2
+time ./context 0 0 0 0 3
+
+time ./context 1 0 1 0 0
+time ./context 1 0 1 0 2
+time ./context 1 0 1 0 3
+
+time ./context 0 1 0 1 0
+time ./context 0 1 0 1 2
+time ./context 0 1 0 1 3
+
+time ./context 1 1 1 1 0
+time ./context 1 1 1 1 2
+time ./context 1 1 1 1 3
diff --git a/ACE/performance-tests/Synch-Benchmarks/orig-results b/ACE/performance-tests/Synch-Benchmarks/orig-results
new file mode 100644
index 00000000000..9d4389005f1
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/orig-results
@@ -0,0 +1,73 @@
+/*
+ --------------------- results -------------------------------------
+ t0arg 0x40 (THR_DETACHED, Not Bound, No New_LWP)
+ t1arg 0x40 (THR_DETACHED, Not Bound, No New_LWP)
+ count[0] 2222061 count[1] 2222061
+ ncorr_orig 1 ncorr_set 0 ncorr_end 2 rate 22070.520 per_cxt 45.31 usec
+
+ ------------------------------------------------------------------------
+ t0arg 0x40 (THR_DETACHED, Not Bound, No New_LWP)
+ t1arg 0x40 (THR_DETACHED, Not Bound, No New_LWP)
+ count[0] 3979311 count[1] 3824273
+ ncorr_orig 1 ncorr_set 2 ncorr_end 2 rate 38975.535 per_cxt 25.66 usec
+
+ ------------------------------------------------------------------------
+ t0arg 0x40 (THR_DETACHED, Not Bound, No New_LWP)
+ t1arg 0x40 (THR_DETACHED, Not Bound, No New_LWP)
+ count[0] 4173290 count[1] 3690153
+ ncorr_orig 1 ncorr_set 3 ncorr_end 3 rate 39134.219 per_cxt 25.55 usec
+
+ ------------------------------------------------------------------------
+ t0arg 0x41 (THR_DETACHED, THR_BOUND, No New_LWP)
+ t1arg 0x41 (THR_DETACHED, THR_BOUND, No New_LWP)
+ count[0] 1376594 count[1] 1404050
+ ncorr_orig 1 ncorr_set 0 ncorr_end 1 rate 13902.920 per_cxt 71.93 usec
+
+ ------------------------------------------------------------------------
+ t0arg 0x41 (THR_DETACHED, THR_BOUND, No New_LWP)
+ t1arg 0x41 (THR_DETACHED, THR_BOUND, No New_LWP)
+ count[0] 1522495 count[1] 1550889
+ ncorr_orig 1 ncorr_set 2 ncorr_end 2 rate 15366.580 per_cxt 65.08 usec
+
+ ------------------------------------------------------------------------
+ t0arg 0x41 (THR_DETACHED, THR_BOUND, No New_LWP)
+ t1arg 0x41 (THR_DETACHED, THR_BOUND, No New_LWP)
+ count[0] 1282030 count[1] 1265453
+ ncorr_orig 1 ncorr_set 3 ncorr_end 3 rate 12737.125 per_cxt 78.51 usec
+
+ ------------------------------------------------------------------------
+ t0arg 0x42 (THR_DETACHED, Not Bound, THR_NEW_LWP)
+ t1arg 0x42 (THR_DETACHED, Not Bound, THR_NEW_LWP)
+ count[0] 3892994 count[1] 3981143
+ ncorr_orig 3 ncorr_set 0 ncorr_end 3 rate 39273.352 per_cxt 25.46 usec
+
+ ------------------------------------------------------------------------
+ t0arg 0x42 (THR_DETACHED, Not Bound, THR_NEW_LWP)
+ t1arg 0x42 (THR_DETACHED, Not Bound, THR_NEW_LWP)
+ count[0] 4008638 count[1] 3882986
+ ncorr_orig 3 ncorr_set 2 ncorr_end 2 rate 39415.660 per_cxt 25.37 usec
+
+ ------------------------------------------------------------------------
+ t0arg 0x42 (THR_DETACHED, Not Bound, THR_NEW_LWP)
+ t1arg 0x42 (THR_DETACHED, Not Bound, THR_NEW_LWP)
+ count[0] 3859767 count[1] 3998157
+ ncorr_orig 3 ncorr_set 3 ncorr_end 3 rate 39145.160 per_cxt 25.55 usec
+
+ ------------------------------------------------------------------------
+ t0arg 0x43 (THR_DETACHED, THR_BOUND, THR_NEW_LWP)
+ t1arg 0x43 (THR_DETACHED, THR_BOUND, THR_NEW_LWP)
+ count[0] 1557142 count[1] 1588775
+ ncorr_orig 3 ncorr_set 0 ncorr_end 3 rate 15729.235 per_cxt 63.58 usec
+
+ ------------------------------------------------------------------------
+ t0arg 0x43 (THR_DETACHED, THR_BOUND, THR_NEW_LWP)
+ t1arg 0x43 (THR_DETACHED, THR_BOUND, THR_NEW_LWP)
+ count[0] 1570636 count[1] 1579111
+ ncorr_orig 3 ncorr_set 2 ncorr_end 3 rate 15748.395 per_cxt 63.50 usec
+
+ ------------------------------------------------------------------------
+ t0arg 0x43 (THR_DETACHED, THR_BOUND, THR_NEW_LWP)
+ t1arg 0x43 (THR_DETACHED, THR_BOUND, THR_NEW_LWP)
+ count[0] 1414198 count[1] 1371431
+ ncorr_orig 3 ncorr_set 3 ncorr_end 3 rate 13927.800 per_cxt 71.80 usec
+ */
diff --git a/ACE/performance-tests/Synch-Benchmarks/results/.no_prune b/ACE/performance-tests/Synch-Benchmarks/results/.no_prune
new file mode 100644
index 00000000000..b5bcdc481b9
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/results/.no_prune
@@ -0,0 +1 @@
+"Do not prune me."
diff --git a/ACE/performance-tests/Synch-Benchmarks/run_tests.pl b/ACE/performance-tests/Synch-Benchmarks/run_tests.pl
new file mode 100755
index 00000000000..1ef43e69298
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/run_tests.pl
@@ -0,0 +1,131 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+
+$EXE = "synch_driver";
+$Win32 = 0;
+if ($^O eq "MSWin32")
+{
+ $Win32 = 1;
+}
+
+$debug = 0;
+$name = "release";
+$result_dir = "results";
+$svcconf_dir = "svcconf";
+$conf_ext = ".conf";
+
+@Null_List = ();
+
+# This is called "baseline"
+@Baseline_List = ("base_acquire",
+ "base_tryacquire",
+ "base_acquire_read",
+ "base_tryacquire_read",
+ "base_acquire_write",
+ "base_tryacquire_write");
+
+# this is called "perf_thrno"
+@Perf_Thr_Number_List = ("perf_t1",
+ "perf_t2",
+ "perf_t4",
+ "perf_t8",
+ "perf_t16",
+ "perf_t32",
+ "perf_t64");
+
+@Target = @Null_List;
+
+while ( $#ARGV >= 0 && $ARGV[0] =~ /^-/ )
+{
+ if ($ARGV[0] eq '-d') # Run debug mode
+ {
+ $name = "debug";
+ }
+ elsif ($ARGV[0] eq '-p') # Debug perl script
+ {
+ $debug = 1;
+ print "debug perl scirpt\n";
+ }
+ elsif ($ARGV[0] eq '-D') # Subdir name to put the result
+ {
+ shift;
+ $result_dir = $ARGV[0];
+ }
+ elsif ($ARGV[0] eq '-S') # Subdir to svc.conf files.
+ {
+ shift;
+ $svcconf_dir = $ARGV[0];
+ }
+ elsif ($ARGV[0] eq '-N') # Specify test name.
+ {
+ shift;
+ if ($ARGV[0] eq "baseline")
+ {
+ @Target = @Baseline_List;
+ }
+ elsif ($ARGV[0] eq "perf_thrno")
+ {
+ @Target = @Perf_Thr_Number_List;
+ }
+ else
+ {
+ die "Unknown test \"$ARGV[0]\"\n";
+ }
+ }
+ else
+ {
+ warn "$0: unknown option $ARGV[0]\n";
+ die $usage;
+ }
+ shift;
+}
+
+die "You must specify a test to run\n" if (scalar (@Target) == 0);
+
+if ($Win32 != 0)
+{
+ $execname = "$name\\$EXE";
+ $DIR_SEPARATOR = '\\';
+}
+else
+{
+ $execname = "./$EXE"; # Notice that on UNIX, you much build
+ # Debug/Release program explicitly
+ # before running the script.
+ $DIR_SEPARATOR = '/';
+}
+
+for ($Cntr = 0; $Cntr < scalar (@Target); $Cntr++)
+{
+ $Redirect_Output = "$result_dir$DIR_SEPARATOR$Target[$Cntr].$name";
+ if ($debug != 0) # Only redirect output in actual run
+ {
+ print "Redirectling output to $Redirect_Output\n";
+ }
+ else
+ {
+ open STDOUT, "> $Redirect_Output";
+ open STDERR, ">&STDOUT";
+ }
+
+ @args = ("$execname",
+ "-f",
+ "$svcconf_dir$DIR_SEPARATOR$Target[$Cntr]$conf_ext");
+
+ if ($debug != 0)
+ {
+ print "Debug mode: Executing -- ";
+ for ($args_c = 0; $args_c < scalar (@args); $args_c ++)
+ {
+ print "$args[$args_c] ";
+ }
+ print "\n";
+ }
+ else
+ {
+ system (@args);
+ }
+}
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/base_acquire.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/base_acquire.conf
new file mode 100644
index 00000000000..2727bac4e73
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/base_acquire.conf
@@ -0,0 +1,20 @@
+# $Id$
+# Benchmark baseline acquire operation.
+
+dynamic Baseline_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Test() ""
+dynamic Baseline_Base_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Base_Test() "-i 10000000"
+dynamic Baseline_Null_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Null_Mutex_Test() "-i 10000000"
+dynamic Baseline_Adaptive_Null_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Null_Mutex_Test() "-i 10000000"
+dynamic Baseline_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Mutex_Test() "-i 10000000"
+dynamic Baseline_RW_Thread_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Thread_Mutex_Test() "-i 10000000"
+dynamic Baseline_RW_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Mutex_Test() "-i 10000000"
+dynamic Baseline_Process_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Process_Mutex_Test() "-i 10000000"
+dynamic Baseline_RW_Process_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Process_Mutex_Test() "-i 10000000"
+dynamic Baseline_Adaptive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Mutex_Test() "-i 10000000"
+dynamic Baseline_Adaptive_RW_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_RW_Mutex_Test() "-i 10000000"
+dynamic Baseline_Recursive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Recursive_Mutex_Test() "-i 10000000"
+dynamic Baseline_Adaptive_Recursive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Recursive_Mutex_Test() "-i 10000000"
+dynamic Baseline_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Semaphore_Test() "-i 10000000"
+dynamic Baseline_Process_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Process_Semaphore_Test() "-i 10000000"
+dynamic Baseline_Null_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Null_Semaphore_Test() "-i 10000000"
+dynamic Baseline_Token_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Token_Test() "-i 10000000"
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/base_acquire_read.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/base_acquire_read.conf
new file mode 100644
index 00000000000..9e25160b8d8
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/base_acquire_read.conf
@@ -0,0 +1,20 @@
+# $Id$
+# Benchmark baseline acquire operation.
+
+dynamic Baseline_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Test() ""
+dynamic Baseline_Base_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Base_Test() "-i 10000000 -r"
+dynamic Baseline_Null_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Null_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Adaptive_Null_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Null_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_RW_Thread_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Thread_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_RW_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Process_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Process_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_RW_Process_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Process_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Adaptive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Adaptive_RW_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_RW_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Recursive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Recursive_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Adaptive_Recursive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Recursive_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Semaphore_Test() "-i 10000000 -r"
+dynamic Baseline_Process_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Process_Semaphore_Test() "-i 10000000 -r"
+dynamic Baseline_Null_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Null_Semaphore_Test() "-i 10000000 -r"
+dynamic Baseline_Token_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Token_Test() "-i 10000000 -r"
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/base_acquire_write.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/base_acquire_write.conf
new file mode 100644
index 00000000000..147e04574ca
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/base_acquire_write.conf
@@ -0,0 +1,20 @@
+# $Id$
+# Benchmark baseline acquire operation.
+
+dynamic Baseline_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Test() ""
+dynamic Baseline_Base_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Base_Test() "-i 10000000 -w"
+dynamic Baseline_Null_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Null_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Adaptive_Null_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Null_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_RW_Thread_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Thread_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_RW_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Process_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Process_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_RW_Process_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Process_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Adaptive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Adaptive_RW_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_RW_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Recursive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Recursive_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Adaptive_Recursive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Recursive_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Semaphore_Test() "-i 10000000 -w"
+dynamic Baseline_Process_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Process_Semaphore_Test() "-i 10000000 -w"
+dynamic Baseline_Null_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Null_Semaphore_Test() "-i 10000000 -w"
+dynamic Baseline_Token_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Token_Test() "-i 10000000 -w"
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/base_tryacquire.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/base_tryacquire.conf
new file mode 100644
index 00000000000..91f78275ffa
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/base_tryacquire.conf
@@ -0,0 +1,20 @@
+# $Id$
+# Benchmark baseline tryacquire operation.
+
+dynamic Baseline_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Test() "-t -v"
+dynamic Baseline_Base_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Base_Test() "-i 10000000"
+dynamic Baseline_Null_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Null_Mutex_Test() "-i 10000000"
+dynamic Baseline_Adaptive_Null_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Null_Mutex_Test() "-i 10000000"
+dynamic Baseline_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Mutex_Test() "-i 10000000"
+dynamic Baseline_RW_Thread_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Thread_Mutex_Test() "-i 10000000"
+dynamic Baseline_RW_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Mutex_Test() "-i 10000000"
+dynamic Baseline_Process_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Process_Mutex_Test() "-i 10000000"
+dynamic Baseline_RW_Process_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Process_Mutex_Test() "-i 10000000"
+dynamic Baseline_Adaptive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Mutex_Test() "-i 10000000"
+dynamic Baseline_Adaptive_RW_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_RW_Mutex_Test() "-i 10000000"
+dynamic Baseline_Recursive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Recursive_Mutex_Test() "-i 10000000"
+dynamic Baseline_Adaptive_Recursive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Recursive_Mutex_Test() "-i 10000000"
+dynamic Baseline_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Semaphore_Test() "-i 10000000"
+dynamic Baseline_Process_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Process_Semaphore_Test() "-i 10000000"
+dynamic Baseline_Null_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Null_Semaphore_Test() "-i 10000000"
+dynamic Baseline_Token_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Token_Test() "-i 10000000"
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/base_tryacquire_read.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/base_tryacquire_read.conf
new file mode 100644
index 00000000000..d300b3b462f
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/base_tryacquire_read.conf
@@ -0,0 +1,20 @@
+# $Id$
+# Benchmark baseline tryacquire operation.
+
+dynamic Baseline_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Test() "-t -v"
+dynamic Baseline_Base_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Base_Test() "-i 10000000 -r"
+dynamic Baseline_Null_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Null_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Adaptive_Null_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Null_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_RW_Thread_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Thread_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_RW_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Process_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Process_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_RW_Process_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Process_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Adaptive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Adaptive_RW_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_RW_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Recursive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Recursive_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Adaptive_Recursive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Recursive_Mutex_Test() "-i 10000000 -r"
+dynamic Baseline_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Semaphore_Test() "-i 10000000 -r"
+dynamic Baseline_Process_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Process_Semaphore_Test() "-i 10000000 -r"
+dynamic Baseline_Null_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Null_Semaphore_Test() "-i 10000000 -r"
+dynamic Baseline_Token_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Token_Test() "-i 10000000 -r"
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/base_tryacquire_write.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/base_tryacquire_write.conf
new file mode 100644
index 00000000000..d220d4ecbd5
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/base_tryacquire_write.conf
@@ -0,0 +1,20 @@
+# $Id$
+# Benchmark baseline tryacquire operation.
+
+dynamic Baseline_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Test() "-t -v"
+dynamic Baseline_Base_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Base_Test() "-i 10000000 -w"
+dynamic Baseline_Null_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Null_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Adaptive_Null_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Null_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_RW_Thread_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Thread_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_RW_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Process_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Process_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_RW_Process_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_RW_Process_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Adaptive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Adaptive_RW_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_RW_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Recursive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Recursive_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Adaptive_Recursive_Mutex_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Adaptive_Recursive_Mutex_Test() "-i 10000000 -w"
+dynamic Baseline_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Semaphore_Test() "-i 10000000 -w"
+dynamic Baseline_Process_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Process_Semaphore_Test() "-i 10000000 -w"
+dynamic Baseline_Null_Semaphore_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Null_Semaphore_Test() "-i 10000000 -w"
+dynamic Baseline_Token_Test Service_Object * Base_Test/Base_Test:_make_Baseline_Token_Test() "-i 10000000 -w"
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t1.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t1.conf
new file mode 100644
index 00000000000..1c4c2ad2f01
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t1.conf
@@ -0,0 +1,32 @@
+# Dynamically configure all the tests
+
+dynamic Performance_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Performance_Test() "-s 60 -N -B -t 1"
+dynamic Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Mutex_Test()
+dynamic Adaptive_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Mutex_Test()
+dynamic Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Recursive_Lock_Test()
+dynamic Adaptive_Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Recursive_Lock_Test()
+dynamic Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Sema_Test()
+dynamic Adaptive_Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Sema_Test()
+dynamic RWRD_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWRD_Test()
+dynamic RWWR_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWWR_Test()
+dynamic Token_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Token_Test()
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t16.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t16.conf
new file mode 100644
index 00000000000..f50ae6f4544
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t16.conf
@@ -0,0 +1,32 @@
+# Dynamically configure all the tests
+
+dynamic Performance_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Performance_Test() "-s 60 -N -B -t 16"
+dynamic Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Mutex_Test()
+dynamic Adaptive_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Mutex_Test()
+dynamic Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Recursive_Lock_Test()
+dynamic Adaptive_Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Recursive_Lock_Test()
+dynamic Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Sema_Test()
+dynamic Adaptive_Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Sema_Test()
+dynamic RWRD_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWRD_Test()
+dynamic RWWR_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWWR_Test()
+dynamic Token_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Token_Test()
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t2.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t2.conf
new file mode 100644
index 00000000000..cc08f483a73
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t2.conf
@@ -0,0 +1,32 @@
+# Dynamically configure all the tests
+
+dynamic Performance_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Performance_Test() "-s 60 -N -B -t 2"
+dynamic Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Mutex_Test()
+dynamic Adaptive_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Mutex_Test()
+dynamic Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Recursive_Lock_Test()
+dynamic Adaptive_Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Recursive_Lock_Test()
+dynamic Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Sema_Test()
+dynamic Adaptive_Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Sema_Test()
+dynamic RWRD_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWRD_Test()
+dynamic RWWR_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWWR_Test()
+dynamic Token_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Token_Test()
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t32.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t32.conf
new file mode 100644
index 00000000000..c12d3dc752b
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t32.conf
@@ -0,0 +1,32 @@
+# Dynamically configure all the tests
+
+dynamic Performance_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Performance_Test() "-s 60 -N -B -t 32"
+dynamic Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Mutex_Test()
+dynamic Adaptive_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Mutex_Test()
+dynamic Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Recursive_Lock_Test()
+dynamic Adaptive_Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Recursive_Lock_Test()
+dynamic Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Sema_Test()
+dynamic Adaptive_Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Sema_Test()
+dynamic RWRD_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWRD_Test()
+dynamic RWWR_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWWR_Test()
+dynamic Token_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Token_Test()
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t4.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t4.conf
new file mode 100644
index 00000000000..2d6661d36e1
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t4.conf
@@ -0,0 +1,32 @@
+# Dynamically configure all the tests
+
+dynamic Performance_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Performance_Test() "-s 60 -N -B -t 4"
+dynamic Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Mutex_Test()
+dynamic Adaptive_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Mutex_Test()
+dynamic Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Recursive_Lock_Test()
+dynamic Adaptive_Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Recursive_Lock_Test()
+dynamic Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Sema_Test()
+dynamic Adaptive_Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Sema_Test()
+dynamic RWRD_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWRD_Test()
+dynamic RWWR_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWWR_Test()
+dynamic Token_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Token_Test()
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t64.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t64.conf
new file mode 100644
index 00000000000..0bf358d0191
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t64.conf
@@ -0,0 +1,32 @@
+# Dynamically configure all the tests
+
+dynamic Performance_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Performance_Test() "-s 60 -N -B -t 64"
+dynamic Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Mutex_Test()
+dynamic Adaptive_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Mutex_Test()
+dynamic Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Recursive_Lock_Test()
+dynamic Adaptive_Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Recursive_Lock_Test()
+dynamic Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Sema_Test()
+dynamic Adaptive_Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Sema_Test()
+dynamic RWRD_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWRD_Test()
+dynamic RWWR_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWWR_Test()
+dynamic Token_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Token_Test()
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t8.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t8.conf
new file mode 100644
index 00000000000..cbfe7062fa8
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/perf_t8.conf
@@ -0,0 +1,32 @@
+# Dynamically configure all the tests
+
+dynamic Performance_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Performance_Test() "-s 60 -N -B -t 8"
+dynamic Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Mutex_Test()
+dynamic Adaptive_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Mutex_Test()
+dynamic Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Recursive_Lock_Test()
+dynamic Adaptive_Recursive_Lock_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Recursive_Lock_Test()
+dynamic Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Sema_Test()
+dynamic Adaptive_Semaphore_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Adaptive_Sema_Test()
+dynamic RWRD_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWRD_Test()
+dynamic RWWR_Mutex_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_RWWR_Test()
+dynamic Token_Test
+ Service_Object *
+ Perf_Test/Perf_Test:_make_Token_Test()
diff --git a/ACE/performance-tests/Synch-Benchmarks/svcconf/svc.conf b/ACE/performance-tests/Synch-Benchmarks/svcconf/svc.conf
new file mode 100644
index 00000000000..ec2d85fbcbf
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/svcconf/svc.conf
@@ -0,0 +1,29 @@
+# Dynamically configure all the tests
+
+dynamic Performance_Test
+ Service_Object
+ *
+ Perf_Test/Perf_Test:_make_Performance_Test()
+ "-s 3 -t 4"
+dynamic Mutex_Test Service_Object
+ *
+ Perf_Test/Perf_Test:_make_Mutex_Test()
+#dynamic Guard_Test Service_Object * Perf_Test/Perf_Test:_make_Guard_Test() "-g"
+#dynamic SYSVSema_Test Service_Object * Perf_Test/Perf_Test:_make_SYSVSema_Test()
+#dynamic Adaptive_Mutex_Test Service_Object * Perf_Test/Perf_Test:_make_Adaptive_Mutex_Test()
+#dynamic Recursive_Lock_Test Service_Object * Perf_Test/Perf_Test:_make_Recursive_Lock_Test()
+#dynamic Adaptive_Recursive_Lock_Test Service_Object *
+# Perf_Test/Perf_Test:_make_Adaptive_Recursive_Lock_Test()
+#dynamic Semaphore_Test Service_Object * Perf_Test/Perf_Test:_make_Sema_Test()
+#dynamic Adaptive_Semaphore_Test Service_Object * Perf_Test/Perf_Test:_make_Adaptive_Sema_Test()
+#dynamic RWRD_Mutex_Test Service_Object * Perf_Test/Perf_Test:_make_RWRD_Test()
+#dynamic RWWR_Mutex_Test Service_Object * Perf_Test/Perf_Test:_make_RWWR_Test()
+#dynamic Token_Test Service_Object * Perf_Test/Perf_Test:_make_Token_Test()
+#dynamic SYSVSema_Test Service_Object * Perf_Test/Perf_Test:_make_SYSVSema_Test()
+#dynamic Context_Test Service_Object * Perf_Test/Perf_Test:_make_Context_Test()
+# dynamic Memory_Test Service_Object * Perf_Test/Perf_Test:_make_Memory_Test()
+#dynamic Pipe_Thr_Test Service_Object * Perf_Test/Perf_Test:_make_Pipe_Thr_Test()
+# dynamic Pipe_Proc_Test Service_Object * Perf_Test/Perf_Test:_make_Pipe_Proc_Test()
+# The following two tests don't work correctly yet...
+#dynamic Condition_Broadcast_Test Service_Object * Perf_Test/Perf_Test:_make_Cond_Brdcast_Test()
+#dynamic Condition_Signal_Test Service_Object * Perf_Test/Perf_Test:_make_Cond_Signal_Test()
diff --git a/ACE/performance-tests/Synch-Benchmarks/synch_driver.cpp b/ACE/performance-tests/Synch-Benchmarks/synch_driver.cpp
new file mode 100644
index 00000000000..eca2f6cecb0
--- /dev/null
+++ b/ACE/performance-tests/Synch-Benchmarks/synch_driver.cpp
@@ -0,0 +1,52 @@
+// $Id$
+
+// Driver program that measures the performance of synchronization
+// mechanisms provided by ACE and the underlying OS.
+
+#include "ace/Log_Msg.h"
+#include "ace/Service_Config.h"
+#include "ace/Service_Repository.h"
+#include "Synch_Lib/Benchmark_Base.h"
+
+ACE_RCSID(Synch_Benchmarks, synch_driver, "$Id$")
+
+#if defined (ACE_HAS_THREADS)
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ ACE_Service_Config::open (argc, argv);
+ ACE_Service_Repository_Iterator sri (*ACE_Service_Repository::instance ());
+
+ // Iteratively execute each service loaded in from the svc.conf
+ // file.
+
+ for (const ACE_Service_Type *sr;
+ sri.next (sr) != 0; )
+ {
+ // This would greatly benefit from RTTI typesafe downcasting...
+ const ACE_Service_Type_Impl *type = sr->type ();
+ const void *obj = type->object ();
+ ACE_Service_Object *so = (ACE_Service_Object *) obj;
+ Benchmark_Base *bb = (Benchmark_Base *) so;
+
+ if (bb->benchmark_type () == Benchmark_Base::METHOD)
+ {
+ Benchmark_Method_Base *bm = (Benchmark_Method_Base *) bb;
+
+ ACE_DEBUG ((LM_DEBUG, "\n\nExecuting %s\n", sr->name ()));
+
+ bm->exec (&sri);
+ }
+ else
+ sri.advance ();
+ }
+ return 0;
+}
+#else
+int
+ACE_TMAIN (int, ACE_TCHAR *[])
+{
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "This test requires the platform to have threads\n"), -1);
+}
+#endif /* ACE_HAS_THREADS */
diff --git a/ACE/performance-tests/TCP/Makefile.am b/ACE/performance-tests/TCP/Makefile.am
new file mode 100644
index 00000000000..3ebae23da8e
--- /dev/null
+++ b/ACE/performance-tests/TCP/Makefile.am
@@ -0,0 +1,38 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.TCP.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = tcp_test
+
+tcp_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+tcp_test_SOURCES = \
+ tcp_test.cpp
+
+tcp_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/performance-tests/TCP/README b/ACE/performance-tests/TCP/README
new file mode 100644
index 00000000000..ac486524c78
--- /dev/null
+++ b/ACE/performance-tests/TCP/README
@@ -0,0 +1,17 @@
+// $Id$
+
+udp_test sends TCP messages and records round-trip latency. The client
+records the latencies and provides nice summary statistics. The server
+simply echos packets back to the client.
+
+To run:
+ 1) On server host:
+ % ./tcp_test -s
+
+ 2) On client host:
+ % ./tcp_test -i 10000 <server host>
+
+The -i option specifies the number of samples (packets to send).
+Other command line options are available: ./tcp_test -? to
+list them.
+
diff --git a/ACE/performance-tests/TCP/TCP.mpc b/ACE/performance-tests/TCP/TCP.mpc
new file mode 100644
index 00000000000..09cb362e007
--- /dev/null
+++ b/ACE/performance-tests/TCP/TCP.mpc
@@ -0,0 +1,7 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ avoids += ace_for_tao
+ exename = tcp_test
+}
diff --git a/ACE/performance-tests/TCP/run_test.pl b/ACE/performance-tests/TCP/run_test.pl
new file mode 100755
index 00000000000..34c4f416c39
--- /dev/null
+++ b/ACE/performance-tests/TCP/run_test.pl
@@ -0,0 +1,34 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib '../../bin';
+use PerlACE::Run_Test;
+
+$SV = new PerlACE::Process ("tcp_test", "-s");
+$CL = new PerlACE::Process ("tcp_test", "-c localhost -i 50000 -b 64");
+
+$status = 0;
+
+$SV->Spawn ();
+
+sleep 5;
+
+$client = $CL->SpawnWaitKill (60);
+
+$server = $SV->WaitKill (5);
+
+if ($server != 0) {
+ print "ERROR: server returned $server\n";
+ $status = 1;
+}
+
+if ($client != 0) {
+ print "ERROR: client returned $client\n";
+ $status = 1;
+}
+
+exit $status;
diff --git a/ACE/performance-tests/TCP/tcp_test.cpp b/ACE/performance-tests/TCP/tcp_test.cpp
new file mode 100644
index 00000000000..182914e14b7
--- /dev/null
+++ b/ACE/performance-tests/TCP/tcp_test.cpp
@@ -0,0 +1,692 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// performance-tests/TCP
+//
+// = FILENAME
+// tcp_test.cpp
+//
+// = DESCRIPTION
+// Measures TCP round-trip performance.
+//
+// = AUTHORS
+// Based on udp_test by Fred Kuhns and David L. Levine
+// Modified by Carlos O'Ryan and Nanbor Wang.
+//
+// ============================================================================
+
+#include "ace/Reactor.h"
+#include "ace/Select_Reactor.h"
+#include "ace/TP_Reactor.h"
+#include "ace/SOCK_Stream.h"
+#include "ace/SOCK_Acceptor.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/INET_Addr.h"
+#include "ace/ACE.h"
+#include "ace/Get_Opt.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Thread_Manager.h"
+#include "ace/Sched_Params.h"
+#include "ace/Stats.h"
+#include "ace/Sample_History.h"
+#include "ace/OS_main.h"
+#include "ace/OS_NS_arpa_inet.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/OS_NS_errno.h"
+#include "ace/OS_NS_string.h"
+#include "ace/OS_NS_unistd.h"
+
+// FUZZ: disable check_for_math_include
+#include <math.h>
+
+ACE_RCSID(TCP, tcp_test, "$Id$")
+
+// Global variables (evil).
+static const u_short DEFPORT = 5050;
+static const int MAXPKTSZ = 65536;
+static const int DEFPKTSZ = 64;
+static const int DEFITERATIONS = 1000;
+static const int DEFINTERVAL = 0;
+static const int DEFAULT_THRNO = 10;
+
+static char sbuf[MAXPKTSZ];
+static char rbuf[MAXPKTSZ];
+
+static int usdelay = DEFINTERVAL;
+static int bufsz = DEFPKTSZ;
+static int VERBOSE = 0;
+static int dump_history = 0;
+static int svr_thrno = DEFAULT_THRNO;
+static int server = 0;
+static int client = 0;
+static int nsamples = DEFITERATIONS;
+static int so_bufsz = 0;
+static u_int use_reactor = 0;
+static int usecs = 0;
+
+enum {
+ SELECT = 1,
+ TP,
+ WFMO
+};
+
+
+static void
+usage (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ "tcp_test\n"
+ " [-v] (Verbose)\n"
+ " [-h] (dump all the samples)\n"
+ " [-m message size]\n"
+ " [-i iterations]\n"
+ " [-I usdelay]\n"
+ " [-b socket bufsz] \n"
+ " [-p port]\n"
+ " [-s]\n"
+ " [-c]\n"
+ // " [-x max_sample_allowed]\n"
+ " [-t number of threads]\n"
+ " [-a to use the ACE Select reactor]\n"
+ " [-x to use the ACE TP reactor]\n"
+ " [-w to use the ACE WFMO reactor]\n"
+ " targethost \n"));
+}
+
+// ****************************************************************
+
+class Client : public ACE_Event_Handler
+{
+public:
+ Client (const ACE_INET_Addr &remote_addr);
+
+ virtual ~Client (void);
+
+ // = Override <ACE_Event_Handler> methods.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+ int send (const char *buf, size_t len);
+ // Send the <buf> to the server.
+
+ int get_response (char *buf, size_t len);
+ // Wait for the response.
+
+ int run (void);
+ // Send messages to server and record statistics.
+
+ int shutdown (void);
+ // Send shutdown message to server.
+
+private:
+ ACE_SOCK_Stream endpoint_;
+ // To send messages and receive responses.
+
+ ACE_INET_Addr remote_addr_;
+ // The address to send messages to.
+
+ ACE_UNIMPLEMENTED_FUNC (Client (void))
+ ACE_UNIMPLEMENTED_FUNC (Client (const Client &))
+ ACE_UNIMPLEMENTED_FUNC (Client &operator= (const Client &))
+};
+
+Client::Client (const ACE_INET_Addr &remote_addr)
+ : remote_addr_ (remote_addr)
+{
+ ACE_SOCK_Connector connector;
+ if (connector.connect (this->endpoint_, remote_addr) == -1)
+ {
+ ACE_ERROR ((LM_ERROR, "Client - %p\n",
+ "connect failed"));
+ }
+
+ if (use_reactor)
+ {
+ if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "ACE_Reactor::register_handler: Client\n"));
+ }
+}
+
+Client::~Client (void)
+{
+}
+
+ACE_HANDLE
+Client::get_handle (void) const
+{
+ return this->endpoint_.get_handle ();
+}
+
+int
+Client::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+
+ ssize_t n = this->endpoint_.recv (buf, sizeof buf);
+
+ if (n == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "handle_input"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) buf of size %d = %*s\n",
+ n,
+ n,
+ buf));
+
+ return 0;
+}
+
+int
+Client::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ this->endpoint_.close ();
+ return 0;
+}
+
+int
+Client::send (const char *buf, size_t len)
+{
+ return this->endpoint_.send (buf, len);
+}
+
+int
+Client::get_response (char *buf, size_t len)
+{
+ return this->endpoint_.recv (buf, len);
+}
+
+int
+Client::run (void)
+{
+ ACE_OS::memset (sbuf, 0, bufsz);
+ ACE_OS::memset (rbuf, 0, bufsz);
+
+ for (int j = 0; j != 100; ++j)
+ {
+ if (this->send (sbuf, bufsz) <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "send"), -1);
+
+ // ssize_t n;
+ if ((this->get_response (rbuf, bufsz)) <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "get_response"), -1);
+ }
+
+ ACE_Sample_History history (nsamples);
+
+ ACE_hrtime_t test_start = ACE_OS::gethrtime ();
+ for (int i = 0; i != nsamples; ++i)
+ {
+ if (usecs != 0)
+ {
+ ACE_Time_Value tv (0, usecs);
+ ACE_OS::sleep (tv);
+ }
+
+ ACE_hrtime_t start = ACE_OS::gethrtime ();
+ if (this->send (sbuf, bufsz) <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "send"), -1);
+
+ // ssize_t n;
+ if ((this->get_response (rbuf, bufsz)) <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "get_response"), -1);
+
+ ACE_hrtime_t end = ACE_OS::gethrtime ();
+
+ history.sample (end - start);
+
+ if (VERBOSE && i % 500 == 0)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Send %d / %d events\n", i, nsamples));
+ }
+ }
+ ACE_hrtime_t test_end = ACE_OS::gethrtime ();
+
+ ACE_UINT32 gsf = ACE_High_Res_Timer::global_scale_factor ();
+
+ if (dump_history)
+ {
+ history.dump_samples (ACE_TEXT("HISTORY"), gsf);
+ }
+
+ ACE_Basic_Stats latency;
+ history.collect_basic_stats (latency);
+ latency.dump_results (ACE_TEXT("Client"), gsf);
+ ACE_Throughput_Stats::dump_throughput (ACE_TEXT("Client"),
+ gsf,
+ test_end - test_start,
+ latency.samples_count ());
+
+
+ return 0;
+}
+
+int
+Client::shutdown (void)
+{
+ const char buf = 'S';
+ int n = this->endpoint_.send (&buf, 1u);
+
+ if (use_reactor)
+ {
+ if (ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Reactor::remove_handler: Client\n"),
+ -1);
+ }
+
+ return n;
+}
+
+// ****************************************************************
+
+class Server : public ACE_Event_Handler
+{
+public:
+ Server (const ACE_INET_Addr &addr);
+
+ virtual ~Server (void);
+
+ // = Override <ACE_Event_Handler> methods.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+private:
+ ACE_SOCK_Stream endpoint_;
+ // Receives datagrams.
+
+ ACE_UNIMPLEMENTED_FUNC (Server (void))
+ ACE_UNIMPLEMENTED_FUNC (Server (const Server &))
+ ACE_UNIMPLEMENTED_FUNC (Server &operator= (const Server &))
+};
+
+Server::Server (const ACE_INET_Addr &addr)
+{
+ ACE_SOCK_Acceptor acceptor;
+
+ if (acceptor.open (addr, 1) == -1)
+ ACE_DEBUG ((LM_DEBUG, "%p\n", "open"));
+
+ ACE_DEBUG ((LM_DEBUG, "Listening on %s:%d\n",
+ addr.get_host_name (),
+ addr.get_port_number ()));
+ if (acceptor.accept (this->endpoint_) == -1)
+ ACE_ERROR ((LM_ERROR, "Server::Server %p\n",
+ "accept failed"));
+
+ if (use_reactor)
+ {
+ if (ACE_Reactor::instance ()->register_handler
+ (this,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "ACE_Reactor::register_handler: Server\n"));
+ }
+
+#if !defined (ACE_LACKS_SOCKET_BUFSIZ)
+ if (so_bufsz != 0)
+ {
+ if (this->endpoint_.set_option (SOL_SOCKET,
+ SO_SNDBUF,
+ (void *) &so_bufsz,
+ sizeof (so_bufsz)) == -1
+ && errno != ENOTSUP)
+ ACE_ERROR ((LM_ERROR, "Server::Server: SO_SNDBUF %p\n",
+ "set_option failed"));
+ else if (this->endpoint_.set_option (SOL_SOCKET,
+ SO_RCVBUF,
+ (void *) &so_bufsz,
+ sizeof (so_bufsz)) == -1
+ && errno != ENOTSUP)
+ ACE_ERROR ((LM_ERROR, "Server::Server: SO_RCVBUF %p\n",
+ "set_option failed"));
+ }
+#endif /* !ACE_LACKS_SOCKET_BUFSIZ */
+ if (acceptor.close () == -1)
+ ACE_ERROR ((LM_ERROR, "Server::Server %p\n",
+ "close failed"));
+}
+
+Server::~Server (void)
+{
+ this->endpoint_.close ();
+}
+
+ACE_HANDLE
+Server::get_handle (void) const
+{
+ return this->endpoint_.get_handle ();
+}
+
+int
+Server::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+
+ ssize_t n = this->endpoint_.recv (buf, bufsz);
+
+ if (n == -1)
+ ACE_DEBUG ((LM_ERROR,
+ "%p\n",
+ "handle_input: recv"));
+
+ // Send the message back as the response.
+ if (this->endpoint_.send (buf, n) == n)
+ {
+ if (n == 1 && buf[0] == 'S')
+ {
+ if (!use_reactor)
+ {
+ // Indicate done by returning 1.
+ return 1;
+ }
+
+ if (ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Reactor::remove_handler: server\n"),
+ -1);
+
+ ACE_Reactor::end_event_loop ();
+ }
+
+ return 0;
+ }
+
+ ACE_DEBUG ((LM_ERROR,
+ "%p\n",
+ "handle_input: send"));
+ return -1;
+}
+
+int
+Server::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ this->endpoint_.close ();
+
+ return 0;
+}
+
+static ACE_THR_FUNC_RETURN
+thread_pool_worker (void *)
+{
+ // Server thread function.
+
+ while (!ACE_Reactor::event_loop_done ())
+ {
+ if (ACE_Reactor::instance ()->handle_events () == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("(%t) %p\n"),
+ ACE_TEXT ("Error handling events")));
+ }
+
+ return 0;
+}
+
+int
+run_server (ACE_INET_Addr &addr)
+{
+ if (use_reactor)
+ {
+ ACE_Reactor *new_reactor = 0;
+
+ switch (use_reactor)
+ {
+ case SELECT:
+ {
+ ACE_Select_Reactor *sr = new ACE_Select_Reactor ();
+ new_reactor = new ACE_Reactor (sr, 1);
+ }
+ break;
+ case TP:
+ {
+ ACE_TP_Reactor *sr = new ACE_TP_Reactor ();
+ new_reactor = new ACE_Reactor (sr, 1);
+ }
+ break;
+ case WFMO:
+#if defined (ACE_WIN32)
+
+#else
+
+#endif /* ACE_WIN32 */
+ default:
+ ACE_ERROR_RETURN ((LM_ERROR, "Invalid reactor type selected\n"), -1);
+ }
+ ACE_Reactor::instance (new_reactor, 1);
+ }
+
+ Server server (addr);
+
+ if (!use_reactor)
+ {
+ // Handle input in the current thread.
+ // This is actually equivalent to thread-per-connection model.
+ while (server.handle_input (0) != 1)
+ continue;
+ }
+ else
+ {
+ switch (use_reactor)
+ {
+ case SELECT:
+ // Run the reactor event loop.
+ ACE_Reactor::run_event_loop ();
+ break;
+ case TP:
+ ACE_Thread_Manager::instance ()->spawn_n (svr_thrno,
+ thread_pool_worker);
+ ACE_Thread_Manager::instance ()->wait ();
+ break;
+ case WFMO:
+ break;
+ default:
+ break; // won't happen here.
+ }
+ }
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int c, dstport = DEFPORT;
+ int priority =
+ (ACE_Sched_Params::priority_min (ACE_SCHED_FIFO)
+ + ACE_Sched_Params::priority_max (ACE_SCHED_FIFO)) / 2;
+ priority = ACE_Sched_Params::next_priority (ACE_SCHED_FIFO,
+ priority);
+ // Enable FIFO scheduling, e.g., RT scheduling class on Solaris.
+
+ if (ACE_OS::sched_params (ACE_Sched_Params (ACE_SCHED_FIFO,
+ priority,
+ ACE_SCOPE_PROCESS)) != 0)
+ {
+ if (ACE_OS::last_error () == EPERM)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "server (%P|%t): user is not superuser, "
+ "test runs in time-shared class\n"));
+ }
+ else
+ ACE_ERROR ((LM_ERROR,
+ "server (%P|%t): sched_params failed\n"));
+ }
+
+
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT("hxwvb:I:p:sci:m:at:"));
+
+ while ((c = getopt ()) != -1)
+ {
+ switch ((char) c)
+ {
+ case 'v':
+ VERBOSE = 1;
+ break;
+
+ case 'h':
+ dump_history = 1;
+ break;
+
+ case 'm':
+ bufsz = ACE_OS::atoi (getopt.opt_arg ());
+
+ if (bufsz <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nMessage size must be greater than 0!\n\n"),
+ 1);
+ else if (bufsz > BUFSIZ)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nbufsz must be <= %d\n",
+ BUFSIZ),
+ 1);
+
+ case 'i':
+ nsamples = ACE_OS::atoi (getopt.opt_arg ());
+ if (nsamples <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nIterations must be greater than 0!\n\n"),
+ 1);
+ break;
+
+ case 'a':
+ use_reactor = SELECT;
+ break;
+
+ case 'x':
+ use_reactor = TP;
+ break;
+
+ case 'w':
+#if defined (ACE_WIN32)
+ use_reactor = WFMO;
+ break;
+#else
+ ACE_ERROR_RETURN ((LM_ERROR, "WFMO_Reactor is not supported\n"), -1);
+#endif /* ACE_WIN32 */
+
+ case 'b':
+ so_bufsz = ACE_OS::atoi (getopt.opt_arg ());
+
+ if (so_bufsz <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nInvalid socket buffer size!\n\n"),
+ 1);
+ break;
+
+ case 'I':
+ usdelay = ACE_OS::atoi (getopt.opt_arg ());
+
+ if (usdelay < 0)
+ {
+ usdelay = 0;
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%s: bad usdelay: %s\n",
+ argv[0],
+ getopt.opt_arg ()),
+ 1);
+ }
+ break;
+
+ case 'p':
+ dstport = ACE_OS::atoi (getopt.opt_arg ());
+ if (dstport <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nInvalid port number!\n\n"),
+ 1);
+ break;
+ case 't':
+ svr_thrno = ACE_OS::atoi (getopt.opt_arg ());
+
+ if (svr_thrno <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nInvalid server thread number!\n\n"),
+ 1);
+ break;
+
+ case 'c':
+ server = 0;
+ client = 1;
+ break;
+ case 's':
+ client = 0;
+ server = 1;
+ break;
+ default:
+ usage ();
+ return 1;
+ }
+ }
+
+ if (getopt.opt_ind () >= argc && client || argc == 1)
+ {
+ usage ();
+ return 1;
+ }
+
+ ACE_INET_Addr addr (dstport);
+
+ if (server)
+ return run_server (addr);
+
+ if ((u_int) bufsz < sizeof (ACE_hrtime_t))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nbufsz must be >= %d\n",
+ sizeof (ACE_hrtime_t)),
+ 1);
+
+ ACE_INET_Addr remote_addr;
+
+ if (ACE_OS::ace_isdigit(argv[getopt.opt_ind ()][0]))
+ {
+ if (remote_addr.set (dstport,
+ (ACE_UINT32) ACE_OS::inet_addr
+ (ACE_TEXT_ALWAYS_CHAR(argv[getopt.opt_ind ()]))) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "invalid IP address: %s\n",
+ argv[getopt.opt_ind ()]),
+ 1);
+ }
+ else
+ {
+ if (remote_addr.set (dstport, argv[getopt.opt_ind ()]) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "invalid IP address: %s\n",
+ argv[getopt.opt_ind ()]),
+ 1);
+ }
+ getopt.opt_ind ()++;
+
+ ACE_DEBUG ((LM_DEBUG, "Connecting to %s:%d\n",
+ remote_addr.get_host_name (),
+ remote_addr.get_port_number ()));
+
+ Client client (remote_addr);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nSending %d byte packets to %s:%d "
+ "with so_bufsz = %d\n\n",
+ bufsz,
+ addr.get_host_name (),
+ dstport,
+ so_bufsz));
+
+ client.run ();
+ client.shutdown ();
+
+ return 0;
+}
diff --git a/ACE/performance-tests/TTCP/ACE-C++/How_to_run_tests b/ACE/performance-tests/TTCP/ACE-C++/How_to_run_tests
new file mode 100644
index 00000000000..1346a745504
--- /dev/null
+++ b/ACE/performance-tests/TTCP/ACE-C++/How_to_run_tests
@@ -0,0 +1,29 @@
+// ACE version
+//
+//
+
+// HOSTNAMES:
+// for our tests, encip1-tango.cs.wustl.edu was the receiver hostname used for atm transfers
+// tango.cs.wustl.edu was the receiver hostname used for ethernet transfers
+// substitute the proper receiver hostname for your system.
+
+// Results:
+// These examples show the result files being stored in a /results directory off
+// the current path. This can be set to whatever you like.
+
+// ATM with 64k receiver buffers
+Receiver_Host: repeat 100 server -r -s -fm -p 10002 -b 65536
+Sender_Host: run_test 64 encip1-tango.cs.wustl.edu ./results/ace.atm.64 10002
+ or: client -fm -s -t -l 1048576 -n 100 -h encip1-tango.cs.wustl.edu -L ./results/ace.atm.64 -p 10002
+
+// ATM with 8k receiver buffers
+Receiver_Host: repeat 100 wrapper-new-ttcp -r -s -fm -p 10002
+Sender_Host: run_test 64 encip1-tango.cs.wustl.edu ./results/ace.atm.8 10002
+
+// ETHERNET with 64k receiver buffers
+Receiver_Host: repeat 100 wrapper-new-ttcp -r -s -fm -p 10002 -b 65536
+Sender_Host: run_test 64 tango.cs.wustl.edu ./results/ace.ethernet.64 10002
+
+// ETHERNET with 8k receiver buffers
+Receiver_Host: repeat 100 wrapper-new-ttcp -r -s -fm -p 10002
+Sender_Host: run_test 64 tango.cs.wustl.edu ./results/ace.ethernet.8 10002
diff --git a/ACE/performance-tests/TTCP/ACE-C++/run_test b/ACE/performance-tests/TTCP/ACE-C++/run_test
new file mode 100644
index 00000000000..e07e6ed0c80
--- /dev/null
+++ b/ACE/performance-tests/TTCP/ACE-C++/run_test
@@ -0,0 +1,35 @@
+# test_run 64 enatm0-kavita.cs.wustl.edu title 10002
+# repeat 100 wrapper-new-ttcp -r -s -fm -p 10002 -b 65536
+#!/bin/csh -f
+if ($#argv != 4) then
+ echo "Usage: sclt <Max msg size> <destination> <TitleOfThisTest> <port>" $4
+ exit 1
+endif
+#
+@ msize=1024
+@ limit= ($argv[1] * 1024)
+#echo $limit
+#echo $msize
+echo "Iteration#" 1 ": wrapper-new-ttcp -fm -s -t -l" $msize "-h" $2 "-L" $3 "-p" $4
+wrapper-new-ttcp -fm -s -t -l $msize -h $2 -x -L $3 -p $4
+sleep 1
+set flag=0
+while ($msize <= $limit)
+ if ($flag == 0) goto label
+ echo "Iteration#" 1 ": wrapper-new-ttcp -fm -s -t -l" $msize "-h" $2 "-x -L" $3 "-p" $4
+ wrapper-new-ttcp -fm -s -t -l $msize -h $2 -x -L $3 -p $4
+ sleep 1
+ label:
+ set flag=1
+ foreach i (2 3 4 5)
+ echo "Iteration#" $i ": wrapper-new-ttcp -fm -s -t -l" $msize "-h" $2 "-L " $3 "-p" $4
+ wrapper-new-ttcp -fm -s -t -l $msize -h $2 -L $3 -p $4
+ sleep 1
+ end
+ echo "---------------------------"
+ @ msize = ($msize * 2)
+end
+
+echo " "
+echo "Done at:"
+date
diff --git a/ACE/performance-tests/TTCP/ACE-C++/wrapper-new-ttcp.cpp b/ACE/performance-tests/TTCP/ACE-C++/wrapper-new-ttcp.cpp
new file mode 100644
index 00000000000..975048a4a7e
--- /dev/null
+++ b/ACE/performance-tests/TTCP/ACE-C++/wrapper-new-ttcp.cpp
@@ -0,0 +1,956 @@
+// $Id$
+
+/*
+ * T T C P . C
+ *
+ * Test TCP connection. Makes a connection on port 5001
+ * and transfers fabricated buffers or data copied from stdin.
+ *
+ * Usable on 4.2, 4.3, and 4.1a systems by defining one of
+ * BSD42 BSD43 (BSD41a)
+ * Machines using System V with BSD sockets should define SYSV.
+ *
+ * Modified for operation under 4.2BSD, 18 Dec 84
+ * T.C. Slattery, USNA
+ * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85.
+ * Modified in 1989 at Silicon Graphics, Inc.
+ * catch SIGPIPE to be able to print stats when receiver has died
+ * for tcp, don't look for sentinel during reads to allow small transfers
+ * increased default buffer size to 8K, nbuf to 2K to transfer 16MB
+ * moved default port to 5001, beyond IPPORT_USERRESERVED
+ * make sinkmode default because it is more popular,
+ * -s now means don't sink/source
+ * count number of read/write system calls to see effects of
+ * blocking from full socket buffers
+ * for tcp, -D option turns off buffered writes (sets TCP_NODELAY sockopt)
+ * buffer alignment options, -A and -O
+ * print stats in a format that's a bit easier to use with grep & awk
+ * for SYSV, mimic BSD routines to use most of the existing timing code
+ * Modified by Steve Miller of the University of Maryland, College Park
+ * -b sets the socket buffer size (SO_SNDBUF/SO_RCVBUF)
+ * Modified Sept. 1989 at Silicon Graphics, Inc.
+ * restored -s sense at request of tcs@brl
+ * Modified Oct. 1991 at Silicon Graphics, Inc.
+ * use getopt(3) for option processing, add -f and -T options.
+ * SGI IRIX 3.3 and 4.0 releases don't need #define SYSV.
+ * Modified Aug.1993 at University Paderborn, Germany
+ * some SVR4 changes and time functions changed to itimer() calls
+ * Modified by Douglas C. Schmidt September 28, 1994
+ * added support for testing UNIX domain socket performance
+ * Modified by Tim Harrison May, 1995
+ * added support for ACE wrappers
+ * Distribution Status -
+ * Public Domain. Distribution Unlimited.
+ */
+
+/* #define BSD43 */
+/* #define BSD42 */
+/* #define BSD41a */
+// #define SYSV /* required on SGI IRIX releases before 3.3 */
+
+#include "ace/Log_Msg.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Acceptor.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <malloc.h>
+#include <string.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/time.h> /* struct itimerval */
+#include <limits.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+ACE_SOCK_Connector connector_factory;
+ACE_SOCK_Acceptor acceptor_factory;
+ACE_INET_Addr address;
+
+#if defined(SYSV)
+#define bcopy(b1,b2,n) memcpy(b2,b1,n)
+#define bzero(b1,n) memset(b1,0,n)
+#include <sys/times.h>
+#include <sys/param.h>
+
+struct rusage
+ {
+ struct timeval ru_utime, ru_stime;
+ };
+#define RUSAGE_SELF 0
+
+#else
+#include <sys/resource.h>
+#endif
+
+struct sockaddr_in sinme;
+struct sockaddr_un sunme;
+struct sockaddr_in sinhim;
+struct sockaddr_un sunhim;
+struct sockaddr_in frominet;
+struct sockaddr_un fromunix;
+
+struct Session_Control_Message
+{
+ long nbuf_;
+ // number of buffers that will be sent this round.
+ long size_;
+ // size of the buffers that will be sent
+} session_control_buf;
+
+struct Data_Control_Message
+{
+ long size_;
+ char data_;
+} *message_buf;
+
+int fromlen;
+int domain = PF_INET; /* Default is to use Internet domain sockets. */
+char *domainname; /* Rendezvous address for UNIX domain sockets. */
+int fd; /* fd of network socket */
+
+int data_buf_len = 1024 * 1024 * 2; // length of data portion
+long total_msg_len; // length of entire message
+char *data_buf; // pointer to data portion
+int nbuf = 2 * 1024; /* number of buffers to send in sinkmode */
+
+int bufoffset = 0; /* align buffer to this */
+int bufalign = 16 * 1024; /* modulo this */
+
+int udp = 0; /* 0 = tcp, !0 = udp */
+int options = 0; /* socket options */
+int one = 1; /* for 4.3 BSD style setsockopt() */
+short port = 5001; /* TCP port number */
+char *host; /* ptr to name of host */
+int trans; /* 0=receive, !0=transmit mode */
+int sinkmode = 0; /* 0=normal I/O, !0=sink/source mode */
+int verbose = 0; /* 0=print basic info, 1=print cpu rate, proc
+ * resource usage. */
+int nodelay = 0; /* set TCP_NODELAY socket option */
+int b_flag = 0; /* use mread() */
+int sockbufsize = 0; /* socket buffer size to use */
+char fmt = 'K'; /* output format: k = kilobits, K = kilobytes,
+ * m = megabits, M = megabytes,
+ * g = gigabits, G = gigabytes */
+int touchdata = 0; /* access data after reading */
+
+struct hostent *addr;
+extern int errno;
+extern int optind;
+extern char *optarg;
+
+char Usage[] = "\
+Usage: ttcp -t [-options] host [ < in ]\n\
+ ttcp -r [-options > out]\n\
+Common options:\n\
+ -l ## length of bufs read from or written to network (default 8192)\n\
+ -u use UDP instead of TCP\n\
+ -U use UNIX domain sockets instead of Internet domain sockets\n\
+ -p ## port number to send to or listen at (default 5001)\n\
+ -s -t: source a pattern to network\n\
+ -r: sink (discard) all data from network\n\
+ -A align the start of buffers to this modulus (default 16384)\n\
+ -O start buffers at this offset from the modulus (default 0)\n\
+ -v verbose: print more statistics\n\
+ -d set SO_DEBUG socket option\n\
+ -b ## set socket buffer size (if supported)\n\
+ -f X format for rate: k,K = kilo{bit,byte}; m,M = mega; g,G = giga\n\
+Options specific to -t:\n\
+ -n## number of source bufs written to network (default 2048)\n\
+ -D don't buffer TCP writes (sets TCP_NODELAY socket option)\n\
+Options specific to -r:\n\
+ -B for -s, only output full blocks as specified by -l (for TAR)\n\
+ -T \"touch\": access each byte as it's read\n\
+";
+
+char stats[128];
+unsigned long nbytes; /* bytes on net */
+unsigned long numCalls = 0; /* # of I/O system calls */
+double cput, realt; /* user, real time (seconds) */
+
+void err (char *s);
+void mes (char *s);
+void pattern (register char *cp, register int cnt);
+char *outfmt (double b);
+void prep_timer (void);
+double read_timer (char *str, int len);
+static void prusage (register struct rusage *r0, struct rusage *r1, struct timeval *e, struct timeval *b, char *outp);
+static void tvadd (struct timeval *tsum, struct timeval *t0, struct timeval *t1);
+static void tvsub (struct timeval *tdiff, struct timeval *t1, struct timeval *t0);
+static void psecs (long l, register char *cp);
+void delay (int us);
+int mread (int fd, register char *bufp, unsigned n);
+int Nread (ACE_SOCK_Stream &s, void *buf, int count);
+int Nwrite (ACE_SOCK_Stream &s, void *buf, int count);
+
+#if !defined (__cplusplus)
+typedef void (*SIG_TYP)();
+#else
+typedef void (*SIG_TYP)(int);
+#endif
+
+#ifdef SVR4
+void
+sigpipe (int foo)
+#else
+void
+sigpipe ()
+#endif
+{
+}
+
+void sigpipe(int foo)
+{
+ printf("Caught signal %d\n", foo);
+}
+
+char *title = 0;
+int new_line = 0;
+
+int
+main (int argc, char *argv[])
+{
+ ACE_SOCK_Stream connection_stream;
+ int c;
+
+ printf("HZ = %d\n", HZ);
+ if (argc < 2)
+ goto usage;
+
+ while ((c = getopt (argc, argv, "drstU:uvBDTb:f:l:n:p:A:O:L:xh:")) != -1)
+ {
+ switch (c)
+ {
+
+ case 'h':
+ host = optarg;
+ break;
+ case 'x':
+ new_line = 1;
+ break;
+ case 'L':
+ title = optarg;
+ break;
+ case 'B':
+ b_flag = 1;
+ break;
+ case 't':
+ trans = 1;
+ break;
+ case 'r':
+ trans = 0;
+ break;
+ case 'd':
+ options |= SO_DEBUG;
+ break;
+ case 'D':
+#ifdef TCP_NODELAY
+ nodelay = 1;
+#else
+ fprintf (stderr,
+ "ttcp: -D option ignored: TCP_NODELAY socket option not supported\n");
+#endif
+ break;
+ case 'n':
+ nbuf = atoi (optarg);
+ break;
+ case 'l':
+ data_buf_len = atoi (optarg);
+ break;
+ case 's':
+ sinkmode = !sinkmode;
+ break;
+ case 'p':
+ port = atoi (optarg);
+ break;
+ case 'U':
+ domain = PF_UNIX;
+ domainname = optarg;
+ break;
+ case 'u':
+ udp = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'A':
+ bufalign = atoi (optarg);
+ break;
+ case 'O':
+ bufoffset = atoi (optarg);
+ break;
+ case 'b':
+#if defined(SO_SNDBUF) || defined(SO_RCVBUF)
+ sockbufsize = atoi (optarg);
+#else
+ fprintf (stderr, "ttcp: -b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported\n");
+#endif
+ break;
+ case 'f':
+ fmt = *optarg;
+ break;
+ case 'T':
+ touchdata = 1;
+ break;
+
+ default:
+ goto usage;
+ }
+ }
+
+ /* if transmitter, create remote address to transmit to. */
+
+ if (trans)
+ {
+ if (address.set (port, host) == -1)
+ perror ("address.set"), exit (1);
+ }
+
+ /* else, receiver create address to listen on */
+ else
+ {
+ address.set (port);
+ }
+
+ total_msg_len = sizeof (long) + data_buf_len;
+
+ // allocate the buffer
+ message_buf = (Data_Control_Message *) malloc (total_msg_len);
+ if (message_buf == 0)
+ err ("malloc");
+
+// if (bufalign != 0)
+// message_buf += (bufalign - ((int) message_buf % bufalign) + bufoffset) % bufalign;
+
+ // let's go ahead and set the control message for every send right now
+ message_buf->size_ = data_buf_len;
+
+ session_control_buf.nbuf_ = nbuf;
+ session_control_buf.size_ = data_buf_len;
+
+ //
+ // print out option values for trans and receiver
+ //
+
+ if (trans)
+ {
+ fprintf (stdout,
+ "ttcp-t: data_buf_len=%d, nbuf=%d, align=%d/%d, port=%d",
+ data_buf_len, nbuf, bufalign, bufoffset, port);
+ if (sockbufsize)
+ fprintf (stdout, ", sockbufsize=%d", sockbufsize);
+ fprintf (stdout, " %s -> %s\n",
+ domain == PF_INET ? (udp ? "udp" : "tcp") : "unix",
+ host == 0 ? domainname : host);
+ }
+ else // receiver
+ {
+ fprintf (stdout,
+ "ttcp-r: data_buf_len=%d, nbuf=%d, align=%d/%d, port=%d",
+ data_buf_len, nbuf, bufalign, bufoffset, port);
+ if (sockbufsize)
+ fprintf (stdout, ", sockbufsize=%d", sockbufsize);
+ fprintf (stdout, " %s\n", domain == PF_INET ? (udp ? "udp" : "tcp") : "unix");
+ }
+
+ mes ("socket");
+
+ //
+ // connect and accept
+ //
+
+ if (!udp)
+ {
+ signal (SIGPIPE, (SIG_TYP) sigpipe);
+
+ /* the transmitter will set options and connect to receiver */
+ if (trans)
+ {
+ // turn off weird ack things
+ if (nodelay)
+ {
+ struct protoent *p = getprotobyname ("tcp");
+
+ if (p && connection_stream.set_option (p->p_proto,
+ TCP_NODELAY,
+ (char *)& one,
+ sizeof (one)))
+ err ("setsockopt: nodelay");
+ mes ("nodelay");
+ }
+ if (connector_factory.connect (connection_stream, address) == -1)
+ perror ("connection failed"), exit (1);
+ fprintf (stdout,
+ "ttcp-t: data_buf_len=%d, nbuf=%d, align=%d/%d, port=%d",
+ data_buf_len, nbuf, bufalign, bufoffset, port);
+
+ if (sockbufsize)
+ {
+ if (connection_stream.set_option (SOL_SOCKET,
+ SO_SNDBUF,
+ (char *) &sockbufsize,
+ sizeof sockbufsize) == -1)
+ err ("acceptor_factory.set_option");
+ mes ("sndbuf");
+ }
+ }
+
+ /* receiver will listen for connections from the transmitter */
+ else
+ {
+ if (acceptor_factory.open (address, 1) == -1)
+ perror ("acceptor open"), exit (1);
+
+ if (sockbufsize)
+ {
+ if (connection_stream.set_option (SOL_SOCKET,
+ SO_RCVBUF,
+ (char *) &sockbufsize,
+ sizeof sockbufsize) == -1)
+ err ("acceptor_factory.set_option");
+ mes ("rcvbuf");
+ }
+
+ ACE_INET_Addr remote_address;
+
+ if (acceptor_factory.accept (connection_stream,
+ (ACE_Addr *) &remote_address) == -1)
+ perror ("acceptor accept"), exit (1);
+
+ // set the window size
+
+ fprintf (stderr, "ttcp-r: accept from %s\n", remote_address.get_host_name());
+ }
+ }
+
+ //
+ // start timer
+ //
+
+ errno = 0;
+ if (trans)
+ {
+ pattern (& (message_buf->data_), data_buf_len);
+ prep_timer ();
+
+ ACE_DEBUG ((LM_DEBUG, "Sending session control message"
+ " nbuf %d, size %d\n", session_control_buf.nbuf_,
+ session_control_buf.size_));
+ if (connection_stream.send_n ((char *) &session_control_buf,
+ sizeof (Session_Control_Message))
+ != sizeof (Session_Control_Message))
+ ACE_ERROR_RETURN ((LM_ERROR, "%p send session control failed\n",
+ "ttcp"), -1);
+
+ long ack;
+ int send_result;
+ while (nbuf--)
+ {
+ send_result = connection_stream.send_n ((char *) message_buf, total_msg_len);
+ if (send_result != total_msg_len)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p only sent %d of %d bytes on call %d\n",
+ "ttcp", send_result, total_msg_len, numCalls + 1), -1);
+ numCalls++;
+ nbytes += data_buf_len;
+
+ if (connection_stream.recv_n ((char *) &ack, sizeof ack)
+ != sizeof ack)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p recv of ack failed\n",
+ "ttcp"), -1);
+
+ if (ack != data_buf_len)
+ ACE_DEBUG ((LM_DEBUG, "received ack for only %d bytes\n", ack));
+ }
+ printf("Client finished. \n");
+ }
+ else
+ {
+ prep_timer ();
+
+ if (connection_stream.recv_n ((char *) &session_control_buf,
+ sizeof (Session_Control_Message))
+ != sizeof (Session_Control_Message))
+ ACE_ERROR_RETURN ((LM_ERROR, "%p recv session control failed\n",
+ "ttcp"), -1);
+
+ ACE_DEBUG ((LM_DEBUG, "received session control message"
+ " nbuf %d, size %d\n", session_control_buf.nbuf_,
+ session_control_buf.size_));
+
+ nbuf = session_control_buf.nbuf_;
+ // ignore session_control_buf.size_ for now
+
+ long cnt;
+
+ while (nbuf--)
+ {
+ if (connection_stream.recv_n ((char *) message_buf, sizeof (long))
+ != sizeof (long))
+ ACE_ERROR_RETURN ((LM_ERROR, "%p recv data control failed\n",
+ "ttcp"), -1);
+
+ cnt = connection_stream.recv_n (& (message_buf->data_), message_buf->size_);
+ if (cnt != message_buf->size_)
+ ACE_ERROR_RETURN ((LM_ERROR, "recv data failed\n"), -1);
+
+ numCalls++;
+ nbytes += cnt;
+
+ if (connection_stream.send_n ((char *) &cnt, sizeof cnt)
+ != sizeof cnt)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p send ack failed\n",
+ "ttcp"), -1);
+ }
+ printf("Server finished. \n");
+ }
+
+ /* if (errno)
+ err ("IO");
+ */
+ //
+ // stop the timer
+ //
+
+ (void) read_timer (stats, sizeof (stats));
+ if (udp && trans)
+ {
+ (void) Nwrite (connection_stream, message_buf, 4); /* rcvr end */
+ (void) Nwrite (connection_stream, message_buf, 4); /* rcvr end */
+ (void) Nwrite (connection_stream, message_buf, 4); /* rcvr end */
+ (void) Nwrite (connection_stream, message_buf, 4); /* rcvr end */
+ }
+ if (cput <= 0.0)
+ cput = 0.001;
+ if (realt <= 0.0)
+ realt = 0.001;
+
+#if defined (LM_RESULTS)
+ if (trans && (title != 0))
+ {
+ double tmp;
+ FILE *fd;
+ char filename[BUFSIZ];
+ ACE_OS::sprintf (filename, "%s.results", title);
+ fd = fopen(filename,"a+");
+ if (new_line)
+ fprintf(fd,"\n -l %ldk \t", data_buf_len/1024);
+ tmp = ((double) nbytes) / realt;
+ fprintf(fd,"%.2f ", tmp * 8.0 / 1024.0 / 1024.0);
+ fclose(fd);
+ }
+#endif
+
+ fprintf (stdout,
+ "ttcp%s: %ld bytes in %.2f real seconds = %s/sec +++\n",
+ trans ? "-t" : "-r",
+ nbytes, realt, outfmt (((double) nbytes) / realt));
+ if (verbose)
+ {
+ fprintf (stdout,
+ "ttcp%s: %ld bytes in %.2f CPU seconds = %s/cpu sec\n",
+ trans ? "-t" : "-r",
+ nbytes, cput, outfmt (((double) nbytes) / cput));
+ }
+ fprintf (stdout,
+ "ttcp%s: %d I/O calls, msec/call = %.2f, calls/sec = %.2f\n",
+ trans ? "-t" : "-r",
+ numCalls,
+ 1024.0 * realt / ((double) numCalls),
+ ((double) numCalls) / realt);
+ fprintf (stdout, "ttcp%s: %s\n", trans ? "-t" : "-r", stats);
+ if (verbose)
+ {
+ fprintf (stdout,
+ "ttcp%s: buffer address %#x\n",
+ trans ? "-t" : "-r",
+ message_buf);
+ }
+ exit (0);
+
+usage:
+ fprintf (stderr, Usage);
+ return 1;
+}
+
+void
+err (char *s)
+{
+ fprintf (stderr, "ttcp%s: ", trans ? "-t" : "-r");
+ perror (s);
+ fprintf (stderr, "errno=%d\n", errno);
+ exit (1);
+}
+
+void
+mes (char *s)
+{
+ fprintf (stderr, "ttcp%s: %s\n", trans ? "-t" : "-r", s);
+}
+
+void
+pattern (register char *cp, register int cnt)
+{
+ register char c;
+ c = 0;
+ while (cnt-- > 0)
+ {
+ while (!isprint ((c & 0x7F)))
+ c++;
+ *cp++ = (c++ & 0x7F);
+ }
+}
+
+char *
+outfmt (double b)
+{
+ static char obuf[50];
+ switch (fmt)
+ {
+ case 'G':
+ sprintf (obuf, "%.2f GB", b / 1024.0 / 1024.0 / 1024.0);
+ break;
+ default:
+ case 'K':
+ sprintf (obuf, "%.2f KB", b / 1024.0);
+ break;
+ case 'M':
+ sprintf (obuf, "%.2f MB", b / 1024.0 / 1024.0);
+ break;
+ case 'g':
+ sprintf (obuf, "%.2f Gbit", b * 8.0 / 1024.0 / 1024.0 / 1024.0);
+ break;
+ case 'k':
+ sprintf (obuf, "%.2f Kbit", b * 8.0 / 1024.0);
+ break;
+ case 'm':
+ sprintf (obuf, "%.2f Mbit", b * 8.0 / 1024.0 / 1024.0);
+ break;
+ }
+ return obuf;
+}
+
+static struct itimerval itime0; /* Time at which timing started */
+static struct rusage ru0; /* Resource utilization at the start */
+
+#if defined(SYSV)
+/*ARGSUSED */
+static void
+getrusage (int ignored, register struct rusage *ru)
+{
+ struct tms buf;
+
+ times (&buf);
+
+ /* Assumption: HZ <= 2147 (LONG_MAX/1000000) */
+ ru->ru_stime.tv_sec = buf.tms_stime / HZ;
+ ru->ru_stime.tv_usec = ((buf.tms_stime % HZ) * 1000000) / HZ;
+ ru->ru_utime.tv_sec = buf.tms_utime / HZ;
+ ru->ru_utime.tv_usec = ((buf.tms_utime % HZ) * 1000000) / HZ;
+}
+
+#endif /* SYSV */
+/*
+ * P R E P _ T I M E R
+ */
+void
+prep_timer ()
+{
+ itime0.it_interval.tv_sec = 0;
+ itime0.it_interval.tv_usec = 0;
+ // itime0.it_value.tv_sec = LONG_MAX / 22; /* greatest possible value , itimer() count backwards */
+ itime0.it_value.tv_sec = 3600;
+ itime0.it_value.tv_usec = 0;
+
+
+ getrusage (RUSAGE_SELF, &ru0);
+ fprintf(stdout, "\n");
+ fprintf(stdout, "beginning user time = %d sec and %d usec\n", ru0.ru_utime.tv_sec, ru0.ru_utime.tv_usec);
+ fprintf(stdout, "beginning sys time = %d sec and %d usec\n", ru0.ru_stime.tv_sec, ru0.ru_stime.tv_usec);
+
+ /* Init REAL Timer */
+ if (setitimer (ITIMER_REAL, &itime0, NULL))
+ {
+ perror ("Setting 'itimer' REAL failed");
+ return;
+ }
+ fprintf(stdout, "Beginning transaction time = %d sec and %d usec\n", itime0.it_value.tv_sec, itime0.it_value.tv_usec);
+}
+
+/*
+ * R E A D _ T I M E R
+ *
+ */
+double
+read_timer (char *str, int len)
+{
+ struct itimerval itimedol;
+ struct rusage ru1;
+ struct timeval td;
+ struct timeval tend, tstart;
+ char line[132];
+
+ getrusage (RUSAGE_SELF, &ru1);
+ fprintf(stdout, "final user time = %d sec and %d usec\n", ru1.ru_utime.tv_sec, ru1.ru_utime.tv_usec);
+ fprintf(stdout, "final sys time = %d sec and %d usec\n", ru1.ru_stime.tv_sec, ru1.ru_stime.tv_usec);
+
+ if (getitimer (ITIMER_REAL, &itimedol))
+ {
+ perror ("Getting 'itimer' REAL failed");
+ return (0.0);
+
+ }
+ fprintf(stdout, "End transaction time = %d sec and %d usec\n", itimedol.it_value.tv_sec, itimedol.it_value.tv_usec);
+ prusage (&ru0, &ru1, &itime0.it_value, &itimedol.it_value, line);
+ (void) strncpy (str, line, len);
+
+ /* Get real time */
+ tvsub (&td, &itime0.it_value, &itimedol.it_value);
+ realt = td.tv_sec + ((double) td.tv_usec) / 1000000;
+
+ /* Get CPU time (user+sys) */
+ tvadd (&tend, &ru1.ru_utime, &ru1.ru_stime);
+ tvadd (&tstart, &ru0.ru_utime, &ru0.ru_stime);
+ tvsub (&td, &tend, &tstart);
+ cput = td.tv_sec + ((double) td.tv_usec) / 1000000;
+ if (cput < 0.00001)
+ cput = 0.00001;
+ return (cput);
+}
+
+static void
+prusage (register struct rusage *r0, struct rusage *r1,
+ struct timeval *b, struct timeval *e, char *outp)
+{
+ struct timeval tdiff;
+ register time_t t;
+ register char *cp;
+ register int i;
+ int ms;
+
+ t = (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 1000 +
+ (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 100000 +
+ (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 1000 +
+ (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 100000;
+ ms = -((e->tv_sec - b->tv_sec) * 1000 + (e->tv_usec - b->tv_usec) / 1000);/* in milliseconds */
+
+#define END(x) {while(*x) x++;}
+#if defined(SYSV)
+ cp = "%Uuser %Ssys %Ereal %P";
+#else
+#if defined(sgi) /* IRIX 3.3 will show 0 for %M,%F,%R,%C */
+ cp = "%Uuser %Ssys %Ereal %P %Mmaxrss %F+%Rpf %Ccsw";
+#else
+ cp = "%Uutime %Sstime %Edtime %P cpu occupancy";
+ /* cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw";*/
+#endif
+#endif
+ for (; *cp; cp++)
+ {
+ if (*cp != '%')
+ *outp++ = *cp;
+ else if (cp[1])
+ switch (*++cp)
+ {
+
+ case 'U':
+ tvsub (&tdiff, &r1->ru_utime, &r0->ru_utime);
+ /* sprintf (outp, "%d.%01d", tdiff.tv_sec, tdiff.tv_usec);*/
+ sprintf (outp, "%f", (tdiff.tv_sec + tdiff.tv_usec/1000000.0));
+ END (outp);
+ break;
+
+ case 'S':
+ tvsub (&tdiff, &r1->ru_stime, &r0->ru_stime);
+ /* sprintf (outp, "%d.%01d", tdiff.tv_sec, tdiff.tv_usec);*/
+ sprintf (outp, "%f", (tdiff.tv_sec + tdiff.tv_usec/1000000.0));
+ END (outp);
+ break;
+
+ case 'E':
+ psecs (ms / 1000, outp);
+ END (outp);
+ break;
+
+ case 'P':
+ sprintf (outp, "%f%%", (t * 100.0 / ((ms ? ms : 1))));
+ END (outp);
+ break;
+
+#if !defined(SYSV)
+ case 'W':
+ i = r1->ru_nswap - r0->ru_nswap;
+ sprintf (outp, "%d", i);
+ END (outp);
+ break;
+
+ case 'X':
+ sprintf (outp, "%d", t == 0 ? 0 : (r1->ru_ixrss - r0->ru_ixrss) / t);
+ END (outp);
+ break;
+
+ case 'D':
+ sprintf (outp, "%d", t == 0 ? 0 :
+ (r1->ru_idrss + r1->ru_isrss - (r0->ru_idrss + r0->ru_isrss)) / t);
+ END (outp);
+ break;
+
+ case 'K':
+ sprintf (outp, "%d", t == 0 ? 0 :
+ ((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) -
+ (r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t);
+ END (outp);
+ break;
+
+ case 'M':
+ sprintf (outp, "%d", r1->ru_maxrss / 2);
+ END (outp);
+ break;
+
+ case 'F':
+ sprintf (outp, "%d", r1->ru_majflt - r0->ru_majflt);
+ END (outp);
+ break;
+
+ case 'R':
+ sprintf (outp, "%d", r1->ru_minflt - r0->ru_minflt);
+ END (outp);
+ break;
+
+ case 'I':
+ sprintf (outp, "%d", r1->ru_inblock - r0->ru_inblock);
+ END (outp);
+ break;
+
+ case 'O':
+ sprintf (outp, "%d", r1->ru_oublock - r0->ru_oublock);
+ END (outp);
+ break;
+ case 'C':
+ sprintf (outp, "%d+%d", r1->ru_nvcsw - r0->ru_nvcsw,
+ r1->ru_nivcsw - r0->ru_nivcsw);
+ END (outp);
+ break;
+#endif /* !SYSV */
+ }
+ }
+ *outp = '\0';
+}
+
+static void
+tvadd (struct timeval *tsum, struct timeval *t0, struct timeval *t1)
+{
+
+ tsum->tv_sec = t0->tv_sec + t1->tv_sec;
+ tsum->tv_usec = t0->tv_usec + t1->tv_usec;
+ if (tsum->tv_usec > 1000000)
+ tsum->tv_sec++, tsum->tv_usec -= 1000000;
+}
+
+static void
+tvsub (struct timeval *tdiff, struct timeval *t1, struct timeval *t0)
+{
+
+ tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
+ tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
+ if (tdiff->tv_usec < 0)
+ tdiff->tv_sec--, tdiff->tv_usec += 1000000;
+}
+
+static void
+psecs (long l, register char *cp)
+{
+ register int i;
+
+ i = l / 3600;
+ if (i)
+ {
+ sprintf (cp, "%d hours", i);
+ END (cp);
+ i = l % 3600;
+ sprintf (cp, "%d minutes ", (i / 60));
+ sprintf (cp, "%d seconds ", (i % 60));
+ END (cp);
+ }
+ else
+ {
+ i = l;
+ sprintf (cp, "%d minutes ", i / 60);
+ END (cp);
+ }
+ i %= 60;
+ *cp++ = ':';
+ sprintf (cp, "%d seconds ", i);
+}
+
+/*
+ * N R E A D
+ */
+int
+Nread (ACE_SOCK_Stream &s, void *buf, int count)
+{
+ numCalls++;
+ return (s.recv (buf, count));
+}
+
+/*
+ * N W R I T E
+ */
+int
+Nwrite (ACE_SOCK_Stream &s, void *buf, int count)
+{
+ numCalls++;
+ return s.send (buf, count);
+}
+
+void
+delay (int us)
+{
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = us;
+ (void) select (1, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &tv);
+}
+
+/*
+ * M R E A D
+ *
+ * This function performs the function of a read(II) but will
+ * call read(II) multiple times in order to get the requested
+ * number of characters. This can be necessary because
+ * network connections don't deliver data with the same
+ * grouping as it is written with. Written by Robert S. Miles, BRL.
+ */
+int
+mread (int fd, register char *bufp, unsigned n)
+{
+ register unsigned count = 0;
+ register int nread;
+
+ do
+ {
+ nread = read (fd, bufp, n - count);
+ numCalls++;
+ if (nread < 0)
+ {
+ perror ("ttcp_mread");
+ return (-1);
+ }
+ if (nread == 0)
+ return ((int) count);
+ count += (unsigned) nread;
+ bufp += nread;
+ }
+ while (count < n);
+
+ return ((int) count);
+}
+
diff --git a/ACE/performance-tests/TTCP/C/How_to_run_tests b/ACE/performance-tests/TTCP/C/How_to_run_tests
new file mode 100644
index 00000000000..c08a515a5af
--- /dev/null
+++ b/ACE/performance-tests/TTCP/C/How_to_run_tests
@@ -0,0 +1,30 @@
+// C version
+//
+//
+
+// HOSTNAMES:
+// for our tests, enatm0-tango.cs.wustl.edu was the receiver hostname used for atm transfers
+// tango.cs.wustl.edu was the receiver hostname used for ethernet transfers
+// substitute the proper receiver hostname for your system.
+
+// Results:
+// These examples show the result files being stored in a /results directory off
+// the current path. This can be set to whatever you like.
+
+// ATM with 32k receiver buffers
+Receiver_Host: repeat 100 server -r -s -fm -p 10002 -b 65536
+Sender_Host: run_test 64 encip1-tango.cs.wustl.edu ./results/ace.atm.64 10002
+ or: client -fm -s -t -l 1048576 -n 100 -h encip1-tango.cs.wustl.edu -L ./results/ace.atm.64 -p 10002
+
+// ATM with 8k receiver buffers
+Receiver_Host: repeat 100 new-ttcp -r -s -fm -p 10002
+Sender_Host: run_test 64 enatm0-tango.cs.wustl.edu ./results/c.atm.8 10002
+
+// ETHERNET with 64k receiver buffers
+Receiver_Host: repeat 100 new-ttcp -r -s -fm -p 10002 -b 65536
+Sender_Host: run_test 64 tango.cs.wustl.edu ./results/c.ethernet.64 10002
+
+// ETHERNET with 8k receiver buffers
+Receiver_Host: repeat 100 new-ttcp -r -s -fm -p 10002
+Sender_Host: run_test 64 tango.cs.wustl.edu ./results/c.ethernet.8 10002
+
diff --git a/ACE/performance-tests/TTCP/C/README b/ACE/performance-tests/TTCP/C/README
new file mode 100644
index 00000000000..0da8b3d8010
--- /dev/null
+++ b/ACE/performance-tests/TTCP/C/README
@@ -0,0 +1,35 @@
+
+ TTCP for c_version and ACE-wrappers
+ ----------------------------------------------------
+
+This is the super-readme file for the "ttcp" code. This directory
+contains the C and ACE-wrappers versions of ttcp code. To compile the
+code, you have to do the following:
+
+1. You should have ACE installed in your system and configured
+ correctly. (see the reference manual for installation and
+ configuration procedure)
+
+2. Copy this directory (ttcp) in the same directory structure to your
+ disk space.
+
+3. setup the following environment parameters (before compilation stage):
+ ACE_ROOT, LD_LIBRARY_PATH.
+
+For example:
+ACE_ROOT=/project/adaptive/ACE_wrappers
+LD_LIBRARY_PATH=/project/adaptive/ACE_wrappers/build/SunOS5.4/ace
+
+4. Do make (using GNU make) in this directory level. This will create
+ the executable ttcp target code for each ttcp version.
+
+5. Read the README or How_to_run_tests file existing in each directory
+ to know how to use the executable.
+
+6. Have fun.
+
+Ehab S. Al-Shaer
+6/30/1995
+
+
+
diff --git a/ACE/performance-tests/TTCP/C/new-ttcp.cpp b/ACE/performance-tests/TTCP/C/new-ttcp.cpp
new file mode 100644
index 00000000000..a897f5b39a3
--- /dev/null
+++ b/ACE/performance-tests/TTCP/C/new-ttcp.cpp
@@ -0,0 +1,970 @@
+// $Id$
+
+/*
+ * T T C P . C
+ *
+ * Test TCP connection. Makes a connection on port 5001
+ * and transfers fabricated buffers or data copied from stdin.
+ *
+ * Usable on 4.2, 4.3, and 4.1a systems by defining one of
+ * BSD42 BSD43 (BSD41a)
+ * Machines using System V with BSD sockets should define SYSV.
+ *
+ * Modified for operation under 4.2BSD, 18 Dec 84
+ * T.C. Slattery, USNA
+ * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85.
+ * Modified in 1989 at Silicon Graphics, Inc.
+ * catch SIGPIPE to be able to print stats when receiver has died
+ * for tcp, don't look for sentinel during reads to allow small transfers
+ * increased default buffer size to 8K, nbuf to 2K to transfer 16MB
+ * moved default port to 5001, beyond IPPORT_USERRESERVED
+ * make sinkmode default because it is more popular,
+ * -s now means don't sink/source
+ * count number of read/write system calls to see effects of
+ * blocking from full socket buffers
+ * for tcp, -D option turns off buffered writes (sets TCP_NODELAY sockopt)
+ * buffer alignment options, -A and -O
+ * print stats in a format that's a bit easier to use with grep & awk
+ * for SYSV, mimic BSD routines to use most of the existing timing code
+ * Modified by Steve Miller of the University of Maryland, College Park
+ * -b sets the socket buffer size (SO_SNDBUF/SO_RCVBUF)
+ * Modified Sept. 1989 at Silicon Graphics, Inc.
+ * restored -s sense at request of tcs@brl
+ * Modified Oct. 1991 at Silicon Graphics, Inc.
+ * use getopt(3) for option processing, add -f and -T options.
+ * SGI IRIX 3.3 and 4.0 releases don't need #define SYSV.
+ * Modified Aug.1993 at University Paderborn, Germany
+ * some SVR4 changes and time functions changed to itimer() calls
+ * Modified by Douglas C. Schmidt September 28, 1994
+ * added support for testing UNIX domain socket performance
+ * Modified by Tim Harrison May, 1995
+ * added support for ACE wrappers
+ * Distribution Status -
+ * Public Domain. Distribution Unlimited.
+ */
+
+/* #define BSD43 */
+/* #define BSD42 */
+/* #define BSD41a */
+#define SYSV /* required on SGI IRIX releases before 3.3 */
+
+#include "ace/Log_Msg.h"
+#include "ace/SOCK_Connector.h"
+#include "ace/SOCK_Acceptor.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <malloc.h>
+#include <string.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/time.h> /* struct itimerval */
+#include <limits.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+ACE_SOCK_Connector connector_factory;
+ACE_SOCK_Acceptor acceptor_factory;
+ACE_INET_Addr address;
+
+#if defined(SYSV)
+#define bcopy(b1,b2,n) memcpy(b2,b1,n)
+#define bzero(b1,n) memset(b1,0,n)
+#include <sys/times.h>
+#include <sys/param.h>
+struct rusage
+ {
+ struct timeval ru_utime, ru_stime;
+ };
+#define RUSAGE_SELF 0
+
+#else
+#include <sys/resource.h>
+#endif
+
+ACE_RCSID(C, new_ttcp, "$Id$")
+
+struct sockaddr_in sinme;
+struct sockaddr_un sunme;
+struct sockaddr_in sinhim;
+struct sockaddr_un sunhim;
+struct sockaddr_in frominet;
+struct sockaddr_un fromunix;
+
+int send_n (const void *buf, int len);
+int recv_n (void *buf, int len);
+int connection_descriptor;
+
+struct Session_Control_Message
+{
+ long nbuf_;
+ // number of buffers that will be sent this round.
+ long size_;
+ // size of the buffers that will be sent
+} session_control_buf;
+
+struct Data_Control_Message
+{
+ long size_;
+ char data_;
+} *message_buf;
+
+int fromlen;
+int domain = PF_INET; /* Default is to use Internet domain sockets. */
+char *domainname; /* Rendezvous address for UNIX domain sockets. */
+int fd; /* fd of network socket */
+
+int data_buf_len = 1024 * 1024 * 2; // length of data portion
+long total_msg_len; // length of entire message
+char *data_buf; // pointer to data portion
+int nbuf = 2 * 1024; /* number of buffers to send in sinkmode */
+
+int bufoffset = 0; /* align buffer to this */
+int bufalign = 16 * 1024; /* modulo this */
+
+int udp = 0; /* 0 = tcp, !0 = udp */
+int options = 0; /* socket options */
+int one = 1; /* for 4.3 BSD style setsockopt() */
+short port = 5001; /* TCP port number */
+char *host; /* ptr to name of host */
+int trans; /* 0=receive, !0=transmit mode */
+int sinkmode = 0; /* 0=normal I/O, !0=sink/source mode */
+int verbose = 0; /* 0=print basic info, 1=print cpu rate, proc
+ * resource usage. */
+int nodelay = 0; /* set TCP_NODELAY socket option */
+int b_flag = 0; /* use mread() */
+int sockbufsize = 0; /* socket buffer size to use */
+char fmt = 'K'; /* output format: k = kilobits, K = kilobytes,
+ * m = megabits, M = megabytes,
+ * g = gigabits, G = gigabytes */
+int touchdata = 0; /* access data after reading */
+
+struct hostent *addr;
+extern int errno;
+extern int optind;
+extern char *optarg;
+
+char Usage[] = "\
+Usage: ttcp -t [-options] host [ < in ]\n\
+ ttcp -r [-options > out]\n\
+Common options:\n\
+ -l ## length of bufs read from or written to network (default 8192)\n\
+ -u use UDP instead of TCP\n\
+ -U use UNIX domain sockets instead of Internet domain sockets\n\
+ -p ## port number to send to or listen at (default 5001)\n\
+ -s -t: source a pattern to network\n\
+ -r: sink (discard) all data from network\n\
+ -A align the start of buffers to this modulus (default 16384)\n\
+ -O start buffers at this offset from the modulus (default 0)\n\
+ -v verbose: print more statistics\n\
+ -d set SO_DEBUG socket option\n\
+ -b ## set socket buffer size (if supported)\n\
+ -f X format for rate: k,K = kilo{bit,byte}; m,M = mega; g,G = giga\n\
+Options specific to -t:\n\
+ -n## number of source bufs written to network (default 2048)\n\
+ -D don't buffer TCP writes (sets TCP_NODELAY socket option)\n\
+Options specific to -r:\n\
+ -B for -s, only output full blocks as specified by -l (for TAR)\n\
+ -T \"touch\": access each byte as it's read\n\
+";
+
+char stats[128];
+unsigned long nbytes; /* bytes on net */
+unsigned long numCalls = 0; /* # of I/O system calls */
+double cput, realt; /* user, real time (seconds) */
+
+void err (char *s);
+void mes (char *s);
+void pattern (register char *cp, register int cnt);
+char *outfmt (double b);
+static void getrusage (int ignored, register struct rusage *ru);
+void prep_timer (void);
+double read_timer (char *str, int len);
+static void prusage (register struct rusage *r0, struct rusage *r1, struct timeval *e, struct timeval *b, char *outp);
+static void tvadd (struct timeval *tsum, struct timeval *t0, struct timeval *t1);
+static void tvsub (struct timeval *tdiff, struct timeval *t1, struct timeval *t0);
+static void psecs (long l, register char *cp);
+void delay (int us);
+int mread (int fd, register char *bufp, unsigned n);
+int Nread (ACE_SOCK_Stream &s, void *buf, int count);
+int Nwrite (ACE_SOCK_Stream &s, void *buf, int count);
+
+#if !defined (__cplusplus)
+typedef void (*SIG_TYP)();
+#endif
+
+#ifdef SVR4
+void
+sigpipe (int foo)
+#else
+void
+sigpipe ()
+#endif
+{
+}
+
+char *title = 0;
+int new_line = 0;
+
+int
+main (int argc, char *argv[])
+{
+ ACE_SOCK_Stream connection_stream;
+ unsigned long addr_tmp;
+ int c;
+
+ if (argc < 2)
+ goto usage;
+
+ while ((c = getopt (argc, argv, "drstU:uvBDTb:f:l:n:p:A:O:L:xh:")) != -1)
+ {
+ switch (c)
+ {
+
+ case 'h':
+ host = optarg;
+ break;
+ case 'x':
+ new_line = 1;
+ break;
+ case 'L':
+ title = optarg;
+ break;
+ case 'B':
+ b_flag = 1;
+ break;
+ case 't':
+ trans = 1;
+ break;
+ case 'r':
+ trans = 0;
+ break;
+ case 'd':
+ options |= SO_DEBUG;
+ break;
+ case 'D':
+#ifdef TCP_NODELAY
+ nodelay = 1;
+#else
+ fprintf (stderr,
+ "ttcp: -D option ignored: TCP_NODELAY socket option not supported\n");
+#endif
+ break;
+ case 'n':
+ nbuf = atoi (optarg);
+ break;
+ case 'l':
+ data_buf_len = atoi (optarg);
+ break;
+ case 's':
+ sinkmode = !sinkmode;
+ break;
+ case 'p':
+ port = atoi (optarg);
+ break;
+ case 'U':
+ domain = PF_UNIX;
+ domainname = optarg;
+ break;
+ case 'u':
+ udp = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 'A':
+ bufalign = atoi (optarg);
+ break;
+ case 'O':
+ bufoffset = atoi (optarg);
+ break;
+ case 'b':
+#if defined(SO_SNDBUF) || defined(SO_RCVBUF)
+ sockbufsize = atoi (optarg);
+#else
+ fprintf (stderr, "ttcp: -b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported\n");
+#endif
+ break;
+ case 'f':
+ fmt = *optarg;
+ break;
+ case 'T':
+ touchdata = 1;
+ break;
+
+ default:
+ goto usage;
+ }
+ }
+
+ /* if transmitter, create remote address to transmit to. */
+
+ if (trans)
+ {
+ if (address.set (port, host) == -1)
+ perror ("address.set"), exit (1);
+ }
+
+ /* else, receiver create address to listen on */
+ else
+ {
+ address.set (port);
+ }
+
+ total_msg_len = sizeof (long) + data_buf_len;
+
+ // allocate the buffer
+ message_buf = (Data_Control_Message *) malloc (total_msg_len);
+ if (message_buf == 0)
+ err ("malloc");
+
+// if (bufalign != 0)
+// message_buf += (bufalign - ((int) message_buf % bufalign) + bufoffset) % bufalign;
+
+ // let's go ahead and set the control message for every send right now
+ message_buf->size_ = data_buf_len;
+
+ session_control_buf.nbuf_ = nbuf;
+ session_control_buf.size_ = data_buf_len;
+
+ //
+ // print out option values for trans and receiver
+ //
+
+ if (trans)
+ {
+ fprintf (stdout,
+ "ttcp-t: data_buf_len=%d, nbuf=%d, align=%d/%d, port=%d",
+ data_buf_len, nbuf, bufalign, bufoffset, port);
+ if (sockbufsize)
+ fprintf (stdout, ", sockbufsize=%d", sockbufsize);
+ fprintf (stdout, " %s -> %s\n",
+ domain == PF_INET ? (udp ? "udp" : "tcp") : "unix",
+ host == 0 ? domainname : host);
+ }
+ else // receiver
+ {
+ fprintf (stdout,
+ "ttcp-r: data_buf_len=%d, nbuf=%d, align=%d/%d, port=%d",
+ data_buf_len, nbuf, bufalign, bufoffset, port);
+ if (sockbufsize)
+ fprintf (stdout, ", sockbufsize=%d", sockbufsize);
+ fprintf (stdout, " %s\n", domain == PF_INET ? (udp ? "udp" : "tcp") : "unix");
+ }
+
+ mes ("socket");
+
+ //
+ // connect and accept
+ //
+
+ if (!udp)
+ {
+ signal (SIGPIPE, (SIG_TYP) sigpipe);
+
+ /* the transmitter will set options and connect to receiver */
+ if (trans)
+ {
+ if (connector_factory.connect (connection_stream, address) == -1)
+ perror ("connection failed"), exit (1);
+ fprintf (stdout,
+ "ttcp-t: data_buf_len=%d, nbuf=%d, align=%d/%d, port=%d",
+ data_buf_len, nbuf, bufalign, bufoffset, port);
+
+ // turn off weird ack things
+ if (nodelay)
+ {
+ struct protoent *p = getprotobyname ("tcp");
+
+ if (p && connection_stream.set_option (p->p_proto,
+ TCP_NODELAY,
+ (char *)& one,
+ sizeof (one)))
+ err ("setsockopt: nodelay");
+ mes ("nodelay");
+ }
+ if (sockbufsize)
+ {
+ if (connection_stream.set_option (SOL_SOCKET,
+ SO_SNDBUF,
+ (char *) &sockbufsize,
+ sizeof sockbufsize) == -1)
+ err ("acceptor_factory.set_option");
+ mes ("sndbuf");
+ }
+ }
+
+ /* receiver will listen for connections from the transmitter */
+ else
+ {
+ if (acceptor_factory.open (address, 1) == -1)
+ perror ("acceptor open"), exit (1);
+
+ ACE_INET_Addr remote_address;
+
+ if (acceptor_factory.accept (connection_stream,
+ (ACE_Addr *) &remote_address) == -1)
+ perror ("acceptor accept"), exit (1);
+
+ // set the window size
+ if (sockbufsize)
+ {
+ if (connection_stream.set_option (SOL_SOCKET,
+ SO_RCVBUF,
+ (char *) &sockbufsize,
+ sizeof sockbufsize) == -1)
+ err ("acceptor_factory.set_option");
+ mes ("rcvbuf");
+ }
+
+ fprintf (stderr, "ttcp-r: accept from %s\n", remote_address.get_host_name());
+ }
+ }
+
+ //
+ // start timer
+ //
+
+ errno = 0;
+
+ // used in send_n and recv_n
+ connection_descriptor = connection_stream.get_handle ();
+
+ if (trans)
+ {
+ pattern (& (message_buf->data_), data_buf_len);
+ prep_timer ();
+
+ ACE_DEBUG ((LM_DEBUG, "Sending session control message"
+ " nbuf %d, size %d\n", session_control_buf.nbuf_,
+ session_control_buf.size_));
+ if (send_n ((char *) &session_control_buf,
+ sizeof (Session_Control_Message))
+ != sizeof (Session_Control_Message))
+ ACE_ERROR_RETURN ((LM_ERROR, "%p send session control failed\n",
+ "ttcp"), -1);
+
+ long ack;
+ int send_result;
+ while (nbuf--)
+ {
+ send_result = send_n ((char *) message_buf, total_msg_len);
+ if (send_result != total_msg_len)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p only sent %d of %d bytes on call %d\n",
+ "ttcp", send_result, total_msg_len, numCalls + 1), -1);
+ numCalls++;
+ nbytes += data_buf_len;
+
+ if (recv_n ((char *) &ack, sizeof ack) != sizeof ack)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p recv of ack failed\n",
+ "ttcp"), -1);
+
+ if (ack != data_buf_len)
+ ACE_DEBUG ((LM_DEBUG, "received ack for only %d bytes\n", ack));
+ }
+ }
+ else
+ {
+ prep_timer ();
+
+ if (recv_n ((char *) &session_control_buf,
+ sizeof (Session_Control_Message)) != sizeof (Session_Control_Message))
+ ACE_ERROR_RETURN ((LM_ERROR, "%p recv session control failed\n",
+ "ttcp"), -1);
+
+ ACE_DEBUG ((LM_DEBUG, "received session control message"
+ " nbuf %d, size %d\n", session_control_buf.nbuf_,
+ session_control_buf.size_));
+
+ nbuf = session_control_buf.nbuf_;
+ // ignore session_control_buf.size_ for now
+
+ long cnt;
+
+ while (nbuf--)
+ {
+ if (recv_n ((char *) message_buf, sizeof (long)) != sizeof (long))
+ ACE_ERROR_RETURN ((LM_ERROR, "%p recv data control failed\n",
+ "ttcp"), -1);
+
+ cnt = recv_n (& (message_buf->data_), message_buf->size_);
+ if (cnt != message_buf->size_)
+ ACE_ERROR_RETURN ((LM_ERROR, "recv data failed\n"), -1);
+
+ numCalls++;
+ nbytes += cnt;
+
+ if (send_n ((char *) &cnt, sizeof cnt) != sizeof cnt)
+ ACE_ERROR_RETURN ((LM_ERROR, "%p send ack failed\n",
+ "ttcp"), -1);
+ }
+ }
+
+ if (errno)
+ err ("IO");
+
+ //
+ // stop the timer
+ //
+
+ (void) read_timer (stats, sizeof (stats));
+ if (udp && trans)
+ {
+ (void) Nwrite (connection_stream, message_buf, 4); /* rcvr end */
+ (void) Nwrite (connection_stream, message_buf, 4); /* rcvr end */
+ (void) Nwrite (connection_stream, message_buf, 4); /* rcvr end */
+ (void) Nwrite (connection_stream, message_buf, 4); /* rcvr end */
+ }
+ if (cput <= 0.0)
+ cput = 0.001;
+ if (realt <= 0.0)
+ realt = 0.001;
+
+#if defined (LM_RESULTS)
+ if (trans && (title != 0))
+ {
+ double tmp;
+ FILE *fd;
+ char filename[BUFSIZ];
+ ACE_OS::sprintf (filename, "%s.results", title);
+ fd = fopen(filename,"a+");
+ if (new_line)
+ fprintf(fd,"\n -l %ldk \t", data_buf_len/1024);
+ tmp = ((double) nbytes) / realt;
+ fprintf(fd,"%.2f ", tmp * 8.0 / 1024.0 / 1024.0);
+ fclose(fd);
+ }
+#endif
+
+ fprintf (stdout,
+ "ttcp%s: %ld bytes in %.2f real seconds = %s/sec +++\n",
+ trans ? "-t" : "-r",
+ nbytes, realt, outfmt (((double) nbytes) / realt));
+ if (verbose)
+ {
+ fprintf (stdout,
+ "ttcp%s: %ld bytes in %.2f CPU seconds = %s/cpu sec\n",
+ trans ? "-t" : "-r",
+ nbytes, cput, outfmt (((double) nbytes) / cput));
+ }
+ fprintf (stdout,
+ "ttcp%s: %d I/O calls, msec/call = %.2f, calls/sec = %.2f\n",
+ trans ? "-t" : "-r",
+ numCalls,
+ 1024.0 * realt / ((double) numCalls),
+ ((double) numCalls) / realt);
+ fprintf (stdout, "ttcp%s: %s\n", trans ? "-t" : "-r", stats);
+ if (verbose)
+ {
+ fprintf (stdout,
+ "ttcp%s: buffer address %#x\n",
+ trans ? "-t" : "-r",
+ message_buf);
+ }
+ exit (0);
+
+usage:
+ fprintf (stderr, Usage);
+ return 1;
+}
+
+int
+send_n (const void *buf, int len)
+{
+ size_t bytes_written;
+ int n;
+
+ for (bytes_written = 0; bytes_written < len; bytes_written += n)
+ if ((n = write (connection_descriptor, (const char *) buf + bytes_written,
+ len - bytes_written)) == -1)
+ return -1;
+
+ return bytes_written;
+}
+
+int
+recv_n (void *buf, int len)
+{
+ size_t bytes_read;
+ int n;
+
+ for (bytes_read = 0; bytes_read < len; bytes_read += n)
+ if ((n = read (connection_descriptor, (char *) buf + bytes_read,
+ len - bytes_read)) == -1)
+ return -1;
+ else if (n == 0)
+ break;
+
+ return bytes_read;
+}
+
+void
+err (char *s)
+{
+ fprintf (stderr, "ttcp%s: ", trans ? "-t" : "-r");
+ perror (s);
+ fprintf (stderr, "errno=%d\n", errno);
+ exit (1);
+}
+
+void
+mes (char *s)
+{
+ fprintf (stderr, "ttcp%s: %s\n", trans ? "-t" : "-r", s);
+}
+
+void
+pattern (register char *cp, register int cnt)
+{
+ register char c;
+ c = 0;
+ while (cnt-- > 0)
+ {
+ while (!isprint ((c & 0x7F)))
+ c++;
+ *cp++ = (c++ & 0x7F);
+ }
+}
+
+char *
+outfmt (double b)
+{
+ static char obuf[50];
+ switch (fmt)
+ {
+ case 'G':
+ sprintf (obuf, "%.2f GB", b / 1024.0 / 1024.0 / 1024.0);
+ break;
+ default:
+ case 'K':
+ sprintf (obuf, "%.2f KB", b / 1024.0);
+ break;
+ case 'M':
+ sprintf (obuf, "%.2f MB", b / 1024.0 / 1024.0);
+ break;
+ case 'g':
+ sprintf (obuf, "%.2f Gbit", b * 8.0 / 1024.0 / 1024.0 / 1024.0);
+ break;
+ case 'k':
+ sprintf (obuf, "%.2f Kbit", b * 8.0 / 1024.0);
+ break;
+ case 'm':
+ sprintf (obuf, "%.2f Mbit", b * 8.0 / 1024.0 / 1024.0);
+ break;
+ }
+ return obuf;
+}
+
+static struct itimerval itime0; /* Time at which timing started */
+static struct rusage ru0; /* Resource utilization at the start */
+
+#if defined(SYSV)
+/*ARGSUSED */
+static void
+getrusage (int ignored, register struct rusage *ru)
+{
+ struct tms buf;
+
+ times (&buf);
+
+ /* Assumption: HZ <= 2147 (LONG_MAX/1000000) */
+ ru->ru_stime.tv_sec = buf.tms_stime / HZ;
+ ru->ru_stime.tv_usec = ((buf.tms_stime % HZ) * 1000000) / HZ;
+ ru->ru_utime.tv_sec = buf.tms_utime / HZ;
+ ru->ru_utime.tv_usec = ((buf.tms_utime % HZ) * 1000000) / HZ;
+}
+
+#endif /* SYSV */
+/*
+ * P R E P _ T I M E R
+ */
+void
+prep_timer ()
+{
+ itime0.it_interval.tv_sec = 0;
+ itime0.it_interval.tv_usec = 0;
+ itime0.it_value.tv_sec = LONG_MAX / 22; /* greatest possible value , itimer() count backwards */
+ itime0.it_value.tv_usec = 0;
+
+
+ getrusage (RUSAGE_SELF, &ru0);
+
+ /* Init REAL Timer */
+ if (setitimer (ITIMER_REAL, &itime0, NULL))
+ {
+ perror ("Setting 'itimer' REAL failed");
+ return;
+ }
+
+}
+
+/*
+ * R E A D _ T I M E R
+ *
+ */
+double
+read_timer (char *str, int len)
+{
+ struct itimerval itimedol;
+ struct rusage ru1;
+ struct timeval td;
+ struct timeval tend, tstart;
+ char line[132];
+
+ getrusage (RUSAGE_SELF, &ru1);
+
+ if (getitimer (ITIMER_REAL, &itimedol))
+ {
+ perror ("Getting 'itimer' REAL failed");
+ return (0.0);
+ }
+
+ prusage (&ru0, &ru1, &itime0.it_value, &itimedol.it_value, line);
+ (void) strncpy (str, line, len);
+
+ /* Get real time */
+ tvsub (&td, &itime0.it_value, &itimedol.it_value);
+ realt = td.tv_sec + ((double) td.tv_usec) / 1000000;
+
+ /* Get CPU time (user+sys) */
+ tvadd (&tend, &ru1.ru_utime, &ru1.ru_stime);
+ tvadd (&tstart, &ru0.ru_utime, &ru0.ru_stime);
+ tvsub (&td, &tend, &tstart);
+ cput = td.tv_sec + ((double) td.tv_usec) / 1000000;
+ if (cput < 0.00001)
+ cput = 0.00001;
+ return (cput);
+}
+
+static void
+prusage (register struct rusage *r0, struct rusage *r1,
+ struct timeval *e, struct timeval *b, char *outp)
+{
+ struct timeval tdiff;
+ register time_t t;
+ register char *cp;
+ register int i;
+ int ms;
+
+ t = (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 +
+ (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
+ (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 +
+ (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
+ ms = (e->tv_sec - b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000;
+
+#define END(x) {while(*x) x++;}
+#if defined(SYSV)
+ cp = "%Uuser %Ssys %Ereal %P";
+#else
+#if defined(sgi) /* IRIX 3.3 will show 0 for %M,%F,%R,%C */
+ cp = "%Uuser %Ssys %Ereal %P %Mmaxrss %F+%Rpf %Ccsw";
+#else
+ cp = "%Uuser %Ssys %Ereal %P %Xi+%Dd %Mmaxrss %F+%Rpf %Ccsw";
+#endif
+#endif
+ for (; *cp; cp++)
+ {
+ if (*cp != '%')
+ *outp++ = *cp;
+ else if (cp[1])
+ switch (*++cp)
+ {
+
+ case 'U':
+ tvsub (&tdiff, &r1->ru_utime, &r0->ru_utime);
+ sprintf (outp, "%d.%01d", tdiff.tv_sec, tdiff.tv_usec / 100000);
+ END (outp);
+ break;
+
+ case 'S':
+ tvsub (&tdiff, &r1->ru_stime, &r0->ru_stime);
+ sprintf (outp, "%d.%01d", tdiff.tv_sec, tdiff.tv_usec / 100000);
+ END (outp);
+ break;
+
+ case 'E':
+ psecs (ms / 100, outp);
+ END (outp);
+ break;
+
+ case 'P':
+ sprintf (outp, "%d%%", (int) (t * 100 / ((ms ? ms : 1))));
+ END (outp);
+ break;
+
+#if !defined(SYSV)
+ case 'W':
+ i = r1->ru_nswap - r0->ru_nswap;
+ sprintf (outp, "%d", i);
+ END (outp);
+ break;
+
+ case 'X':
+ sprintf (outp, "%d", t == 0 ? 0 : (r1->ru_ixrss - r0->ru_ixrss) / t);
+ END (outp);
+ break;
+
+ case 'D':
+ sprintf (outp, "%d", t == 0 ? 0 :
+ (r1->ru_idrss + r1->ru_isrss - (r0->ru_idrss + r0->ru_isrss)) / t);
+ END (outp);
+ break;
+
+ case 'K':
+ sprintf (outp, "%d", t == 0 ? 0 :
+ ((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) -
+ (r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t);
+ END (outp);
+ break;
+
+ case 'M':
+ sprintf (outp, "%d", r1->ru_maxrss / 2);
+ END (outp);
+ break;
+
+ case 'F':
+ sprintf (outp, "%d", r1->ru_majflt - r0->ru_majflt);
+ END (outp);
+ break;
+
+ case 'R':
+ sprintf (outp, "%d", r1->ru_minflt - r0->ru_minflt);
+ END (outp);
+ break;
+
+ case 'I':
+ sprintf (outp, "%d", r1->ru_inblock - r0->ru_inblock);
+ END (outp);
+ break;
+
+ case 'O':
+ sprintf (outp, "%d", r1->ru_oublock - r0->ru_oublock);
+ END (outp);
+ break;
+ case 'C':
+ sprintf (outp, "%d+%d", r1->ru_nvcsw - r0->ru_nvcsw,
+ r1->ru_nivcsw - r0->ru_nivcsw);
+ END (outp);
+ break;
+#endif /* !SYSV */
+ }
+ }
+ *outp = '\0';
+}
+
+static void
+tvadd (struct timeval *tsum, struct timeval *t0, struct timeval *t1)
+{
+
+ tsum->tv_sec = t0->tv_sec + t1->tv_sec;
+ tsum->tv_usec = t0->tv_usec + t1->tv_usec;
+ if (tsum->tv_usec > 1000000)
+ tsum->tv_sec++, tsum->tv_usec -= 1000000;
+}
+
+static void
+tvsub (struct timeval *tdiff, struct timeval *t1, struct timeval *t0)
+{
+
+ tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
+ tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
+ if (tdiff->tv_usec < 0)
+ tdiff->tv_sec--, tdiff->tv_usec += 1000000;
+}
+
+static void
+psecs (long l, register char *cp)
+{
+ register int i;
+
+ i = l / 3600;
+ if (i)
+ {
+ sprintf (cp, "%d:", i);
+ END (cp);
+ i = l % 3600;
+ sprintf (cp, "%d%d", (i / 60) / 10, (i / 60) % 10);
+ END (cp);
+ }
+ else
+ {
+ i = l;
+ sprintf (cp, "%d", i / 60);
+ END (cp);
+ }
+ i %= 60;
+ *cp++ = ':';
+ sprintf (cp, "%d%d", i / 10, i % 10);
+}
+
+/*
+ * N R E A D
+ */
+int
+Nread (ACE_SOCK_Stream &s, void *buf, int count)
+{
+ numCalls++;
+ return (s.recv (buf, count));
+}
+
+/*
+ * N W R I T E
+ */
+int
+Nwrite (ACE_SOCK_Stream &s, void *buf, int count)
+{
+ numCalls++;
+ return s.send (buf, count);
+}
+
+void
+delay (int us)
+{
+ struct timeval tv;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = us;
+ (void) select (1, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &tv);
+}
+
+/*
+ * M R E A D
+ *
+ * This function performs the function of a read(II) but will
+ * call read(II) multiple times in order to get the requested
+ * number of characters. This can be necessary because
+ * network connections don't deliver data with the same
+ * grouping as it is written with. Written by Robert S. Miles, BRL.
+ */
+int
+mread (int fd, register char *bufp, unsigned n)
+{
+ register unsigned count = 0;
+ register int nread;
+
+ do
+ {
+ nread = read (fd, bufp, n - count);
+ numCalls++;
+ if (nread < 0)
+ {
+ perror ("ttcp_mread");
+ return (-1);
+ }
+ if (nread == 0)
+ return ((int) count);
+ count += (unsigned) nread;
+ bufp += nread;
+ }
+ while (count < n);
+
+ return ((int) count);
+}
diff --git a/ACE/performance-tests/TTCP/C/run_test b/ACE/performance-tests/TTCP/C/run_test
new file mode 100644
index 00000000000..9a4fa346ad3
--- /dev/null
+++ b/ACE/performance-tests/TTCP/C/run_test
@@ -0,0 +1,35 @@
+# test_run 64 enatm0-kavita.cs.wustl.edu title 10002
+# repeat 100 new-ttcp -r -s -fm -p 10002 -b 65536
+#!/bin/csh -f
+if ($#argv != 4) then
+ echo "Usage: sclt <Max msg size> <destination> <TitleOfThisTest> <port>" $4
+ exit 1
+endif
+#
+@ msize=1024
+@ limit= ($argv[1] * 1024)
+#echo $limit
+#echo $msize
+echo "Iteration#" 1 ": new-ttcp -fm -s -t -l" $msize "-h" $2 "-x -L" $3 "-p" $4
+new-ttcp -fm -s -t -l $msize -h $2 -x -L $3 -p $4
+sleep 1
+set flag=0
+while ($msize <= $limit)
+ if ($flag == 0) goto label
+ echo "Iteration#" 1 ": new-ttcp -fm -s -t -l" $msize "-h" $2 "-x -L" $3 "-p" $4
+ new-ttcp -fm -s -t -l $msize -h $2 -x -L $3 -p $4
+ sleep 1
+ label:
+ set flag=1
+ foreach i (2 3 4 5)
+ echo "Iteration#" $i ": new-ttcp -fm -s -t -l" $msize "-h" $2 "-L" $3 "-p" $4
+ new-ttcp -fm -s -t -l $msize -h $2 -L $3 -p $4
+ sleep 1
+ end
+ echo "---------------------------"
+ @ msize = ($msize * 2)
+end
+
+echo " "
+echo "Done at:"
+date
diff --git a/ACE/performance-tests/UDP/Makefile.am b/ACE/performance-tests/UDP/Makefile.am
new file mode 100644
index 00000000000..e9dc7db03f2
--- /dev/null
+++ b/ACE/performance-tests/UDP/Makefile.am
@@ -0,0 +1,38 @@
+## Process this file with automake to create Makefile.in
+##
+## $Id$
+##
+## This file was generated by MPC. Any changes made directly to
+## this file will be lost the next time it is generated.
+##
+## MPC Command:
+## /acebuilds/ACE_wrappers-repository/bin/mwc.pl -include /acebuilds/MPC/config -include /acebuilds/MPC/templates -feature_file /acebuilds/ACE_wrappers-repository/local.features -noreldefs -type automake -exclude build,Kokyu
+
+ACE_BUILDDIR = $(top_builddir)
+ACE_ROOT = $(top_srcdir)
+
+
+## Makefile.UDP.am
+
+if !BUILD_ACE_FOR_TAO
+noinst_PROGRAMS = udp_test
+
+udp_test_CPPFLAGS = \
+ -I$(ACE_ROOT) \
+ -I$(ACE_BUILDDIR)
+
+udp_test_SOURCES = \
+ udp_test.cpp
+
+udp_test_LDADD = \
+ $(ACE_BUILDDIR)/ace/libACE.la
+
+endif !BUILD_ACE_FOR_TAO
+
+## Clean up template repositories, etc.
+clean-local:
+ -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.*
+ -rm -f gcctemp.c gcctemp so_locations *.ics
+ -rm -rf cxx_repository ptrepository ti_files
+ -rm -rf templateregistry ir.out
+ -rm -rf ptrepository SunWS_cache Templates.DB
diff --git a/ACE/performance-tests/UDP/README b/ACE/performance-tests/UDP/README
new file mode 100644
index 00000000000..f2eb3308e1e
--- /dev/null
+++ b/ACE/performance-tests/UDP/README
@@ -0,0 +1,17 @@
+// $Id$
+
+udp_test sends UDP packets and records round-trip latency. The client
+records the latencies and provides nice summary statistics. The server
+simply echos packets back to the client.
+
+To run:
+ 1) On server host:
+ % ./udp_test -r
+
+ 2) On client host:
+ % ./udp_test -t -n 1000 <server host>
+
+The -n option specifies the number of samples (packets to send).
+Other command line options are available: ./udp_test -? to
+list them.
+
diff --git a/ACE/performance-tests/UDP/UDP.mpc b/ACE/performance-tests/UDP/UDP.mpc
new file mode 100644
index 00000000000..19928979e7b
--- /dev/null
+++ b/ACE/performance-tests/UDP/UDP.mpc
@@ -0,0 +1,10 @@
+// -*- MPC -*-
+// $Id$
+
+project : aceexe {
+ avoids += ace_for_tao
+ exename = udp_test
+ verbatim(gnuace, local) {
+ LDLIBS += $(MATHLIB)
+ }
+}
diff --git a/ACE/performance-tests/UDP/run_test.pl b/ACE/performance-tests/UDP/run_test.pl
new file mode 100755
index 00000000000..638b8c18c99
--- /dev/null
+++ b/ACE/performance-tests/UDP/run_test.pl
@@ -0,0 +1,34 @@
+eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
+ & eval 'exec perl -S $0 $argv:q'
+ if 0;
+
+# $Id$
+# -*- perl -*-
+
+use lib '../../bin';
+use PerlACE::Run_Test;
+
+$SV = new PerlACE::Process ("udp_test", "-r");
+$CL = new PerlACE::Process ("udp_test", "-t -n 10000 localhost");
+
+$status = 0;
+
+$SV->Spawn ();
+
+sleep 5;
+
+$client = $CL->SpawnWaitKill (60);
+
+$server = $SV->WaitKill (5);
+
+if ($server != 0) {
+ print "ERROR: server returned $server\n";
+ $status = 1;
+}
+
+if ($client != 0) {
+ print "ERROR: client returned $client\n";
+ $status = 1;
+}
+
+exit $status;
diff --git a/ACE/performance-tests/UDP/udp_test.cpp b/ACE/performance-tests/UDP/udp_test.cpp
new file mode 100644
index 00000000000..449c998f3ae
--- /dev/null
+++ b/ACE/performance-tests/UDP/udp_test.cpp
@@ -0,0 +1,759 @@
+// $Id$
+
+// ============================================================================
+//
+// = LIBRARY
+// performance-tests/UDP
+//
+// = FILENAME
+// udp_test.cpp
+//
+// = DESCRIPTION
+// Measures UDP round-trip performance.
+//
+// = AUTHORS
+// Fred Kuhns and David L. Levine
+//
+// ============================================================================
+
+#include "ace/OS_main.h"
+#include "ace/Reactor.h"
+#include "ace/SOCK_Dgram.h"
+#include "ace/INET_Addr.h"
+#include "ace/ACE.h"
+#include "ace/Get_Opt.h"
+#include "ace/High_Res_Timer.h"
+#include "ace/Log_Msg.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/OS_NS_ctype.h"
+#include "ace/OS_NS_arpa_inet.h"
+#include "ace/OS_NS_string.h"
+#include "ace/os_include/os_netdb.h"
+#include "ace/OS_NS_unistd.h"
+
+// FUZZ: disable check_for_math_include
+#include <math.h>
+
+ACE_RCSID(UDP, udp_test, "$Id$")
+
+// Global variables (evil).
+static const u_short DEFPORT = 5050;
+static const int MAXPKTSZ = 65536;
+static const int DEFPKTSZ = 64;
+static const int DEFITERATIONS = 1000;
+static const int DEFINTERVAL = 1000; // 1000 usecs.
+static const int DEFWINDOWSZ = 10; // 10 microsecond.
+static char SendBuf[MAXPKTSZ];
+static char RxBuf[MAXPKTSZ];
+static ACE_TCHAR **cmd;
+static ACE_TCHAR datafile[MAXHOSTNAMELEN];
+
+static ACE_UINT32 nsamples = DEFITERATIONS;
+static int usdelay = DEFINTERVAL;
+static int bufsz = DEFPKTSZ;
+static int window = DEFWINDOWSZ;
+static int VERBOSE = 0;
+static int logfile = 0;
+static int server = 0;
+static int client = 0;
+static u_int use_reactor = 0;
+ACE_hrtime_t max_allow = 0;
+ACE_hrtime_t total_ltime;
+ACE_hrtime_t ltime;
+
+static void
+usage (void)
+{
+ ACE_ERROR ((LM_ERROR,
+ "%s\n"
+ "[-w window_size]\n"
+ " [-f datafile] (creates datafile.samp and datafile.dist)\n"
+ " [-v] (Verbose)\n"
+ " [-b send_bufsz]\n"
+ " [-n nsamples]\n"
+ " [-I usdelay]\n"
+ " [-s so_bufsz] \n"
+ " [-p port]\n"
+ " [-t]\n"
+ " [-r]\n"
+ " [-x max_sample_allowed]\n"
+ " [-a to use the ACE reactor]\n"
+ " targethost \n",
+ *cmd));
+}
+
+static ACE_hrtime_t *Samples;
+static u_int *Dist;
+static ACE_TCHAR sumfile[30];
+static ACE_TCHAR distfile[30];
+static ACE_TCHAR sampfile[30];
+
+class Client : public ACE_Event_Handler
+{
+public:
+ Client (const ACE_INET_Addr &addr,
+ const ACE_INET_Addr &remote_addr);
+
+ virtual ~Client (void);
+
+ // = Override <ACE_Event_Handler> methods.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+ int send (const char *buf, size_t len);
+ // Send the <buf> to the server.
+
+ int get_response (char *buf, size_t len);
+ // Wait for the response.
+
+ int run (void);
+ // Send messages to server and record statistics.
+
+ int shutdown (void);
+ // Send shutdown message to server.
+
+private:
+ ACE_SOCK_Dgram endpoint_;
+ // To send messages and receive responses.
+
+ ACE_INET_Addr remote_addr_;
+ // The address to send messages to.
+
+ ACE_UNIMPLEMENTED_FUNC (Client (void))
+ ACE_UNIMPLEMENTED_FUNC (Client (const Client &))
+ ACE_UNIMPLEMENTED_FUNC (Client &operator= (const Client &))
+};
+
+Client::Client (const ACE_INET_Addr &addr,
+ const ACE_INET_Addr &remote_addr)
+ : endpoint_ (addr),
+ remote_addr_ (remote_addr)
+{
+ if (use_reactor)
+ {
+ if (ACE_Reactor::instance ()->register_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "ACE_Reactor::register_handler: Client\n"));
+ }
+}
+
+Client::~Client (void)
+{
+}
+
+ACE_HANDLE
+Client::get_handle (void) const
+{
+ return endpoint_.get_handle ();
+}
+
+int
+Client::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+ ACE_INET_Addr from_addr;
+
+ ssize_t n = endpoint_.recv (buf, sizeof buf, from_addr);
+
+ if (n == -1)
+ ACE_ERROR ((LM_ERROR,
+ "%p\n",
+ "handle_input"));
+ else
+ ACE_DEBUG ((LM_DEBUG,
+ "(%P|%t) buf of size %d = %*s\n",
+ n,
+ n,
+ buf));
+
+ return 0;
+}
+
+int
+Client::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ this->endpoint_.close ();
+ return 0;
+}
+
+int
+Client::send (const char *buf, size_t len)
+{
+ return this->endpoint_.send (buf, len, remote_addr_);
+}
+
+int
+Client::get_response (char *buf, size_t len)
+{
+ ACE_INET_Addr addr;
+ return this->endpoint_.recv (buf, len, addr);
+}
+
+int
+Client::run (void)
+{
+ int ndist = 0;
+ int i;
+ int j;
+ int n;
+ int maxindx = 0;
+ int minindx = 0;
+ char *sbuf = SendBuf;
+ char *rbuf = RxBuf;
+
+ ACE_High_Res_Timer timer;
+ ACE_hrtime_t sample;
+
+#if defined (ACE_LACKS_FLOATING_POINT)
+ ACE_hrtime_t sample_mean;
+#else /* ! ACE_LACKS_FLOATING_POINT */
+ int d;
+ double std_dev = 0.0;
+ double std_err = 0.0;
+ double sample_mean = 0.0;
+#endif /* ! ACE_LACKS_FLOATING_POINT */
+
+ int tracking_last_over = 0;
+ ACE_High_Res_Timer since_over;
+ ACE_hrtime_t psum = 0;
+ ACE_hrtime_t sum = 0;
+ ACE_hrtime_t max = 0;
+ ACE_hrtime_t min = (ACE_hrtime_t) (u_int) -1;
+ FILE *sumfp = 0;
+ FILE *distfp = 0;
+ FILE *sampfp = 0;
+ pid_t *pid = (pid_t *) sbuf;
+ int *seq = (int *) (sbuf + sizeof (int));
+
+ ACE_OS::memset (sbuf, 0, bufsz);
+ ACE_OS::memset (rbuf, 0, bufsz);
+
+ *pid = ACE_OS::getpid ();
+ *seq = 0;
+
+ ACE_DEBUG ((LM_DEBUG,
+ "PID = %d, Starting SEQ = %d\n",
+ *pid,
+ *seq));
+
+ // Allocate memory to hold samples.
+ Samples = (ACE_hrtime_t *) ACE_OS::calloc (nsamples,
+ sizeof (ACE_hrtime_t));
+
+ for (i = -1, *seq = 0, j = 0;
+ i < (ACE_INT32) nsamples;
+ (*seq)++, i++, j++, timer.reset ())
+ {
+ timer.start ();
+ if (send (sbuf, bufsz) <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "send"), -1);
+
+ if ((n = get_response (rbuf, bufsz)) <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR, "(%P) %p\n", "get_response"), -1);
+
+ timer.stop ();
+
+ if (n <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nTrouble receiving from socket!\n\n"),
+ -1);
+
+ timer.elapsed_time (sample); // in nanoseconds.
+
+ if (i < 0 )
+ {
+#ifndef ACE_LACKS_LONGLONG_T
+ ACE_DEBUG ((LM_DEBUG,
+ "Ignoring first sample of %u usecs\n",
+ (ACE_UINT32) (sample)));
+#else
+ ACE_DEBUG ((LM_DEBUG,
+ "Ignoring first sample of %u usecs\n",
+ (ACE_UINT32) (sample.lo())));
+#endif
+ continue;
+ }
+ else if (max_allow > 0 && sample > max_allow)
+ {
+ ACE_DEBUG ((LM_DEBUG, "Sample # %i = "
+ "%u msec is over the limit (%u)!\n",
+ i,
+ (ACE_UINT32) (sample / (ACE_UINT32) 1000000),
+ (ACE_UINT32) (max_allow / (ACE_UINT32) 1000000)));
+
+ if (tracking_last_over)
+ {
+ since_over.stop ();
+ ACE_Time_Value over_time;
+ since_over.elapsed_time (over_time);
+ ACE_DEBUG ((LM_DEBUG,
+ "\tTime since last over = %u msec!\n",
+ over_time.msec ()));
+ since_over.reset ();
+ }
+
+ tracking_last_over = 1;
+ since_over.start ();
+ i--;
+ continue;
+ }
+
+ Samples[i] = sample;
+ sum += sample;
+
+ if (min == (ACE_hrtime_t) (u_int) -1)
+ {
+ min = sample;
+ minindx = i;
+ }
+ if (sample > max)
+ {
+ max = sample;
+ maxindx = i;
+ }
+ if (sample < min)
+ {
+ min = sample;
+ minindx = i;
+ }
+
+ if (VERBOSE)
+ {
+ psum += sample;
+ if (j == 500)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "(%i) Partial (running) mean %u usecs\n",
+ i + 1,
+ (ACE_UINT32) (psum / (ACE_UINT32) (1000 * 500))));
+ j = 0;
+ psum = 0;
+ }
+ }
+ }
+
+#if defined (ACE_LACKS_FLOATING_POINT)
+ sample_mean = sum / nsamples;
+#else /* ! ACE_LACKS_FLOATING_POINT */
+ sample_mean = ((double) ACE_U64_TO_U32 (sum)) / (double) nsamples;
+#endif /* ! ACE_LACKS_FLOATING_POINT */
+
+ if (logfile)
+ {
+ ACE_OS::sprintf (sumfile, ACE_TEXT("%s.sum"), datafile);
+ ACE_OS::sprintf (distfile, ACE_TEXT("%s.dist"), datafile);
+ ACE_OS::sprintf (sampfile, ACE_TEXT("%s.samp"), datafile);
+
+ distfp = ACE_OS::fopen(distfile, ACE_TEXT("w"));
+
+ if (distfp == NULL)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "Unable to open dist file!\n\n"));
+ logfile = 0;
+ }
+ if (logfile && (sampfp = ACE_OS::fopen (sampfile, ACE_TEXT("w"))) == NULL)
+ {
+ ACE_OS::fclose (distfp);
+ ACE_DEBUG ((LM_DEBUG,
+ "Unable to open sample file!\n\n"));
+ logfile = 0;
+ }
+ if (logfile && (sumfp = ACE_OS::fopen (sumfile, ACE_TEXT("w"))) == NULL)
+ {
+ ACE_OS::fclose (distfp);
+ ACE_OS::fclose (sampfp);
+ ACE_DEBUG ((LM_DEBUG,
+ "Unable to open sample file!\n\n"));
+ logfile = 0;
+ }
+ }
+
+ if (window)
+ {
+ window = window * 1000; // convert to nsec.
+ ndist = (int)((max-min) / window) + 1;
+ Dist = (u_int *) ACE_OS::calloc (ndist,
+ sizeof (u_int));
+ }
+
+#if ! defined (ACE_LACKS_FLOATING_POINT)
+ for (i = 0; i < (ACE_INT32) nsamples; i++)
+ {
+ std_dev += ((double) ACE_U64_TO_U32 (Samples[i]) - sample_mean) *
+ ((double) ACE_U64_TO_U32 (Samples[i]) - sample_mean);
+ d = (int)((Samples[i] - min)/window);
+
+ if (d < 0 || d > ndist)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "\nError indexing into dist array %d (%d)\n\n",
+ d,
+ ndist));
+ ACE_OS::exit (1);
+ }
+ Dist[d] += 1;
+ if (logfile)
+ ACE_OS::fprintf (sampfp,
+ "%u\n",
+ ACE_U64_TO_U32 (Samples[i]));
+ }
+#endif /* ACE_LACKS_FLOATING_POINT */
+
+ if (logfile)
+ {
+ ACE_hrtime_t tmp;
+ tmp = min + (window / 2);
+
+ for (i = 0; i < ndist; i++)
+ {
+ ACE_OS::fprintf (distfp,
+ "%u %d\n",
+ (ACE_UINT32) (tmp / (ACE_UINT32) 1000),
+ Dist[i]);
+ tmp += window;
+ }
+ }
+
+#if defined (ACE_LACKS_FLOATING_POINT)
+ ACE_DEBUG ((LM_DEBUG,
+ "\nResults for %i samples (usec):\n"
+ "\tSample Mean = %u,\n"
+ "\tSample Max = %u, Max index = %u,\n"
+ "\tSample Min = %u, Min index = %u,\n",
+ nsamples,
+ (ACE_UINT32) (sample_mean / (ACE_UINT32) 1000),
+ (ACE_UINT32) (max / (ACE_UINT32) 1000),
+ maxindx,
+ (ACE_UINT32) (min / (ACE_UINT32) 1000),
+ minindx));
+#else /* ! ACE_LACKS_FLOATING_POINT */
+ std_dev = (double) sqrt (std_dev / (double) (nsamples - 1.0));
+ std_err = (double) std_dev / sqrt ((double) nsamples);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nResults for %i samples (usec):\n"
+ "\tSample Mean = %f,\n"
+ "\tSample Max = %u, Max index = %d,\n"
+ "\tSample Min = %u, Min index = %d,\n"
+ "\tStandard Deviation = %f,\n"
+ "\tStandard Error = %f\n",
+ nsamples,
+ sample_mean / 1000.0,
+ (u_int) (max / (ACE_UINT32) 1000),
+ maxindx,
+ (u_int) (min / (ACE_UINT32) 1000),
+ minindx,
+ std_dev / 1000.0,
+ std_err / 1000.0));
+
+ if (logfile)
+ {
+ ACE_OS::fprintf (sumfp,
+ "Command executed: \n");
+ for (; *cmd; cmd++)
+ ACE_OS::fprintf (sumfp,
+ "%s ",
+ *cmd);
+ ACE_OS::fprintf (sumfp,
+ "\n");
+
+ ACE_OS::fprintf (sumfp,
+ "\nResults for %i samples (usec):"
+ "\tSample Mean = %f,\n"
+ "\tSample Max = %u, Max index = %d,\n"
+ "\tSample Min = %u, Min index = %d,\n"
+ "\tStandard Deviation = %f,\n"
+ "\tStandard Error = %f\n",
+ nsamples,
+ sample_mean / 1000.0,
+ (ACE_UINT32) (max / (ACE_UINT32) 1000),
+ maxindx,
+ (ACE_UINT32) (min / (ACE_UINT32) 1000),
+ minindx,
+ std_dev / 1000.0,
+ std_err / 1000.0);
+ }
+#endif /* ! ACE_LACKS_FLOATING_POINT */
+
+ return 0;
+}
+
+int
+Client::shutdown (void)
+{
+ const char buf = 'S';
+ const int n = endpoint_.send (&buf, 1u, remote_addr_);
+
+ if (use_reactor)
+ {
+ if (ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Reactor::remove_handler: Client\n"),
+ -1);
+ }
+
+ return n;
+}
+
+class Server : public ACE_Event_Handler
+{
+public:
+ Server (const ACE_INET_Addr &addr);
+
+ virtual ~Server (void);
+
+ // = Override <ACE_Event_Handler> methods.
+ virtual ACE_HANDLE get_handle (void) const;
+ virtual int handle_input (ACE_HANDLE);
+ virtual int handle_close (ACE_HANDLE handle,
+ ACE_Reactor_Mask close_mask);
+
+private:
+ ACE_SOCK_Dgram endpoint_;
+ // Receives datagrams.
+
+ ACE_UNIMPLEMENTED_FUNC (Server (void))
+ ACE_UNIMPLEMENTED_FUNC (Server (const Server &))
+ ACE_UNIMPLEMENTED_FUNC (Server &operator= (const Server &))
+};
+
+Server::Server (const ACE_INET_Addr &addr)
+ : endpoint_ (addr)
+{
+ if (use_reactor)
+ {
+ if (ACE_Reactor::instance ()->register_handler
+ (this,
+ ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR ((LM_ERROR,
+ "ACE_Reactor::register_handler: Server\n"));
+ }
+}
+
+Server::~Server (void)
+{
+}
+
+ACE_HANDLE
+Server::get_handle (void) const
+{
+ return endpoint_.get_handle ();
+}
+
+int
+Server::handle_input (ACE_HANDLE)
+{
+ char buf[BUFSIZ];
+ ACE_INET_Addr from_addr;
+
+ ssize_t n = endpoint_.recv (buf, sizeof buf, from_addr);
+
+ if (n == -1)
+ ACE_DEBUG ((LM_ERROR,
+ "%p\n",
+ "handle_input: recv"));
+
+ // Send the message back as the response.
+ if (endpoint_.send (buf, n, from_addr) == n)
+ {
+ if (n == 1 && buf[0] == 'S')
+ {
+ if (use_reactor)
+ {
+ if (ACE_Reactor::instance ()->remove_handler
+ (this, ACE_Event_Handler::READ_MASK) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ACE_Reactor::remove_handler: server\n"),
+ -1);
+
+ ACE_Reactor::end_event_loop ();
+ }
+ else
+ {
+ // Indicate done by returning 1.
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+ else
+ {
+ ACE_DEBUG ((LM_ERROR,
+ "%p\n",
+ "handle_input: send"));
+ return -1;
+ }
+}
+
+int
+Server::handle_close (ACE_HANDLE,
+ ACE_Reactor_Mask)
+{
+ endpoint_.close ();
+
+ return 0;
+}
+
+int
+ACE_TMAIN (int argc, ACE_TCHAR *argv[])
+{
+ int c, dstport = DEFPORT;
+ int so_bufsz = 0;
+
+ cmd = argv;
+
+ ACE_Get_Opt getopt (argc, argv, ACE_TEXT("x:w:f:vs:I:p:rtn:b:a"));
+
+ while ((c = getopt ()) != -1)
+ {
+ switch ((char) c)
+ {
+ case 'x':
+ max_allow = ACE_OS::atoi (getopt.opt_arg ());
+ break;
+ case 'w':
+ window = ACE_OS::atoi (getopt.opt_arg ());
+ if (window < 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "Invalid window!\n\n"),
+ 1);
+ break;
+ case 'f':
+ ACE_OS::strcpy (datafile, getopt.opt_arg ());
+ logfile = 1;
+ break;
+ case 'v':
+ VERBOSE = 1;
+ break;
+ case 'b':
+ bufsz = ACE_OS::atoi (getopt.opt_arg ());
+
+ if (bufsz <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nBuffer size must be greater than 0!\n\n"),
+ 1);
+
+ case 'n':
+ nsamples = ACE_OS::atoi (getopt.opt_arg ());
+ if (nsamples <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nIterations must be greater than 0!\n\n"),
+ 1);
+ break;
+ case 'a':
+ use_reactor = 1;
+ break;
+ case 's':
+ so_bufsz = ACE_OS::atoi (getopt.opt_arg ());
+
+ if (so_bufsz <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nInvalid socket buffer size!\n\n"),
+ 1);
+ break;
+ case 'I':
+ usdelay = ACE_OS::atoi (getopt.opt_arg ());
+
+ if (usdelay == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "%s: bad usdelay: %s\n",
+ argv[0],
+ getopt.opt_arg ()),
+ 1);
+ break;
+ case 'p':
+ dstport = ACE_OS::atoi (getopt.opt_arg ());
+ if (dstport <= 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nInvalid port number!\n\n"),
+ 1);
+ break;
+ case 't':
+ server = 0;
+ client = 1;
+ break;
+ case 'r':
+ client = 0;
+ server = 1;
+ break;
+ default:
+ usage ();
+ return 1;
+ }
+ }
+
+ if (getopt.opt_ind () >= argc && client || argc == 1)
+ {
+ usage ();
+ return 1;
+ }
+
+ ACE_INET_Addr addr (server ? dstport : dstport + 1);
+
+ if (server)
+ {
+ Server server (addr);
+
+ if (use_reactor)
+ {
+ ACE_Reactor::run_event_loop ();
+ }
+ else
+ {
+ // Handle input in the current thread.
+ while (server.handle_input (0) != 1)
+ continue;
+ }
+ }
+ else
+ {
+ if ((u_int) bufsz < sizeof (ACE_hrtime_t))
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "\nbufsz must be >= %d\n",
+ sizeof (ACE_hrtime_t)),
+ 1);
+ ACE_INET_Addr remote_addr;
+
+ if (ACE_OS::ace_isdigit(argv[getopt.opt_ind ()][0]))
+ {
+ if (remote_addr.set (dstport,
+ (ACE_UINT32) ACE_OS::inet_addr
+ (ACE_TEXT_ALWAYS_CHAR(argv[getopt.opt_ind ()]))) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "invalid IP address: %s\n",
+ argv[getopt.opt_ind ()]),
+ 1);
+ }
+ else
+ {
+ if (remote_addr.set (dstport, argv[getopt.opt_ind ()]) == -1)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "invalid IP address: %s\n",
+ argv[getopt.opt_ind ()]),
+ 1);
+ }
+ getopt.opt_ind ()++;
+
+ Client client (addr, remote_addr);
+
+ ACE_DEBUG ((LM_DEBUG,
+ "\nSending %d byte packets to %s:%d "
+ "with so_bufsz = %d\n\n",
+ bufsz,
+ addr.get_host_name (),
+ dstport,
+ so_bufsz));
+
+ client.run ();
+ client.shutdown ();
+ }
+
+ return 0;
+}
diff --git a/ACE/performance-tests/perf.mwc b/ACE/performance-tests/perf.mwc
new file mode 100644
index 00000000000..dd297256b34
--- /dev/null
+++ b/ACE/performance-tests/perf.mwc
@@ -0,0 +1,5 @@
+// -*- MPC -*-
+// $Id$
+
+workspace {
+}