Browse Source
unix implementation of uv_async_t has been wasting cpu cycles for nothing since 1.29.0 release implement efficient callback scheduling for linuxpull/1889/head
![chat.freenode.net/cohcho](/assets/img/avatar_default.png)
5 changed files with 110 additions and 0 deletions
@ -0,0 +1,78 @@ |
|||
#include "base/io/Async.h" |
|||
|
|||
|
|||
#if defined(XMRIG_UV_PERFORMANCE_BUG) |
|||
#include <sys/eventfd.h> |
|||
#include <sys/poll.h> |
|||
#include <unistd.h> |
|||
#include <cstdlib> |
|||
|
|||
|
|||
namespace xmrig { |
|||
|
|||
|
|||
uv_async_t::~uv_async_t() |
|||
{ |
|||
close(m_fd); |
|||
} |
|||
|
|||
|
|||
static void on_schedule(uv_poll_t *handle, int status, int events) |
|||
{ |
|||
static uint64_t val; |
|||
uv_async_t *async = reinterpret_cast<uv_async_t *>(handle); |
|||
for (;;) { |
|||
int r = read(async->m_fd, &val, sizeof(val)); |
|||
|
|||
if (r == sizeof(val)) |
|||
continue; |
|||
|
|||
if (r != -1) |
|||
break; |
|||
|
|||
if (errno == EAGAIN || errno == EWOULDBLOCK) |
|||
break; |
|||
|
|||
if (errno == EINTR) |
|||
continue; |
|||
|
|||
abort(); |
|||
} |
|||
if (async->m_cb) { |
|||
(*async->m_cb)(async); |
|||
} |
|||
} |
|||
|
|||
|
|||
int uv_async_init(uv_loop_t *loop, uv_async_t *async, uv_async_cb cb) |
|||
{ |
|||
int fd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); |
|||
if (fd < 0) { |
|||
return uv_translate_sys_error(errno); |
|||
} |
|||
uv_poll_init(loop, (uv_poll_t *)async, fd); |
|||
uv_poll_start((uv_poll_t *)async, POLLIN, on_schedule); |
|||
async->m_cb = cb; |
|||
async->m_fd = fd; |
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int uv_async_send(uv_async_t *async) |
|||
{ |
|||
static const uint64_t val = 1; |
|||
int r; |
|||
do { |
|||
r = write(async->m_fd, &val, sizeof(val)); |
|||
} |
|||
while (r == -1 && errno == EINTR); |
|||
if (r == sizeof(val) || (r == 1 && (errno == EAGAIN || errno == EWOULDBLOCK))) { |
|||
return 0; |
|||
} |
|||
abort(); |
|||
} |
|||
|
|||
|
|||
|
|||
} // namespace xmrig
|
|||
#endif |
@ -0,0 +1,27 @@ |
|||
#pragma once |
|||
|
|||
#include <uv.h> |
|||
|
|||
|
|||
// since 2019.05.16, Version 1.29.0 (Stable)
|
|||
#if (UV_VERSION_MAJOR >= 1) && (UV_VERSION_MINOR >= 29) && defined(__linux__) |
|||
#define XMRIG_UV_PERFORMANCE_BUG |
|||
namespace xmrig { |
|||
|
|||
|
|||
struct uv_async_t: uv_poll_t |
|||
{ |
|||
typedef void (*uv_async_cb)(uv_async_t* handle); |
|||
~uv_async_t(); |
|||
int m_fd = -1; |
|||
uv_async_cb m_cb = nullptr; |
|||
}; |
|||
|
|||
|
|||
using uv_async_cb = uv_async_t::uv_async_cb; |
|||
extern int uv_async_init(uv_loop_t *loop, uv_async_t *async, uv_async_cb cb); |
|||
extern int uv_async_send(uv_async_t *async); |
|||
|
|||
|
|||
} // namespace xmrig
|
|||
#endif |
Loading…
Reference in new issue