summaryrefslogtreecommitdiff
path: root/src/socket_base.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/socket_base.cpp')
-rw-r--r--src/socket_base.cpp38
1 files changed, 10 insertions, 28 deletions
diff --git a/src/socket_base.cpp b/src/socket_base.cpp
index 682062c..8ff2a6a 100644
--- a/src/socket_base.cpp
+++ b/src/socket_base.cpp
@@ -40,6 +40,7 @@
#include "io_thread.hpp"
#include "connect_session.hpp"
#include "config.hpp"
+#include "clock.hpp"
#include "pipe.hpp"
#include "err.hpp"
#include "ctx.hpp"
@@ -56,14 +57,6 @@
#include "xrep.hpp"
#include "uuid.hpp"
-// If the RDTSC is available we use it to prevent excessive
-// polling for commands. The nice thing here is that it will work on any
-// system with x86 architecture and gcc or MSVC compiler.
-#if (defined __GNUC__ && (defined __i386__ || defined __x86_64__)) ||\
- (defined _MSC_VER && (defined _M_IX86 || defined _M_X64))
-#define ZMQ_DELAY_COMMANDS
-#endif
-
zmq::socket_base_t *zmq::socket_base_t::create (int type_, class ctx_t *parent_,
uint32_t slot_)
{
@@ -109,7 +102,7 @@ zmq::socket_base_t::socket_base_t (ctx_t *parent_, uint32_t slot_) :
own_t (parent_, slot_),
ctx_terminated (false),
destroyed (false),
- last_processing_time (0),
+ last_tsc (0),
ticks (0),
rcvmore (false)
{
@@ -486,7 +479,7 @@ int zmq::socket_base_t::recv (::zmq_msg_t *msg_, int flags_)
//
// Note that 'recv' uses different command throttling algorithm (the one
// described above) from the one used by 'send'. This is because counting
- // ticks is more efficient than doing rdtsc all the time.
+ // ticks is more efficient than doing RDTSC all the time.
if (++ticks == inbound_poll_rate) {
if (unlikely (process_commands (false, false) != 0))
return -1;
@@ -627,35 +620,24 @@ int zmq::socket_base_t::process_commands (bool block_, bool throttle_)
}
else {
-#if defined ZMQ_DELAY_COMMANDS
+ // Get the CPU's tick counter. If 0, the counter is not available.
+ uint64_t tsc = zmq::clock_t::rdtsc ();
+
// Optimised version of command processing - it doesn't have to check
// for incoming commands each time. It does so only if certain time
// elapsed since last command processing. Command delay varies
// depending on CPU speed: It's ~1ms on 3GHz CPU, ~2ms on 1.5GHz CPU
// etc. The optimisation makes sense only on platforms where getting
// a timestamp is a very cheap operation (tens of nanoseconds).
- if (throttle_) {
-
- // Get timestamp counter.
-#if defined __GNUC__
- uint32_t low;
- uint32_t high;
- __asm__ volatile ("rdtsc" : "=a" (low), "=d" (high));
- uint64_t current_time = (uint64_t) high << 32 | low;
-#elif defined _MSC_VER
- uint64_t current_time = __rdtsc ();
-#else
-#error
-#endif
+ if (tsc && throttle_) {
+
// Check whether TSC haven't jumped backwards (in case of migration
// between CPU cores) and whether certain time have elapsed since
// last command processing. If it didn't do nothing.
- if (current_time >= last_processing_time &&
- current_time - last_processing_time <= max_command_delay)
+ if (tsc >= last_tsc && tsc - last_tsc <= max_command_delay)
return 0;
- last_processing_time = current_time;
+ last_tsc = tsc;
}
-#endif
// Check whether there are any commands pending for this thread.
rc = signaler.recv (&cmd, false);