mirror of
https://github.com/cuberite/libevent.git
synced 2025-09-10 04:50:37 -04:00
Merge branch 'osx-clock'
Moves the thread into real-time scheduling class, as recommended in [1], it
fixes the separate test provided by @ygj6 [2] everywhere (github actions,
travis-ci, appveyor) under osx.
[1]: https://developer.apple.com/library/archive/technotes/tn2169/_index.html
[2]: dde1a6e4d0
Although even after this changes the following time-related tests failed
on travis-ci:
- no_events
- del_wait
But anyway I guess #940 can be closed, since this fixes the issue in common.
* osx-clock:
test: Use THREAD_* wrappers in del_notify/del_wait
test: move threads created with THREAD_START() to realtime scheduling class too
test: put thread into real time scheduling class on osx for better latencies
Closes: #940
(cherry picked from commit a6f81aa45455c8afb69980f7026a0e706f4f9387)
This commit is contained in:
parent
677378ea42
commit
e85afbe3d5
@ -440,6 +440,7 @@ endif()
|
|||||||
CHECK_INCLUDE_FILE(sys/uio.h EVENT__HAVE_SYS_UIO_H)
|
CHECK_INCLUDE_FILE(sys/uio.h EVENT__HAVE_SYS_UIO_H)
|
||||||
CHECK_INCLUDE_FILES("sys/types.h;ifaddrs.h" EVENT__HAVE_IFADDRS_H)
|
CHECK_INCLUDE_FILES("sys/types.h;ifaddrs.h" EVENT__HAVE_IFADDRS_H)
|
||||||
CHECK_INCLUDE_FILE(mach/mach_time.h EVENT__HAVE_MACH_MACH_TIME_H)
|
CHECK_INCLUDE_FILE(mach/mach_time.h EVENT__HAVE_MACH_MACH_TIME_H)
|
||||||
|
CHECK_INCLUDE_FILE(mach/mach.h EVENT__HAVE_MACH_MACH_H)
|
||||||
CHECK_INCLUDE_FILE(netinet/tcp.h EVENT__HAVE_NETINET_TCP_H)
|
CHECK_INCLUDE_FILE(netinet/tcp.h EVENT__HAVE_NETINET_TCP_H)
|
||||||
CHECK_INCLUDE_FILE(sys/wait.h EVENT__HAVE_SYS_WAIT_H)
|
CHECK_INCLUDE_FILE(sys/wait.h EVENT__HAVE_SYS_WAIT_H)
|
||||||
CHECK_INCLUDE_FILE(sys/resource.h EVENT__HAVE_SYS_RESOURCE_H)
|
CHECK_INCLUDE_FILE(sys/resource.h EVENT__HAVE_SYS_RESOURCE_H)
|
||||||
|
@ -222,6 +222,7 @@ AC_CHECK_HEADERS([ \
|
|||||||
fcntl.h \
|
fcntl.h \
|
||||||
ifaddrs.h \
|
ifaddrs.h \
|
||||||
mach/mach_time.h \
|
mach/mach_time.h \
|
||||||
|
mach/mach.h \
|
||||||
netdb.h \
|
netdb.h \
|
||||||
netinet/in.h \
|
netinet/in.h \
|
||||||
netinet/in6.h \
|
netinet/in6.h \
|
||||||
|
@ -178,6 +178,9 @@
|
|||||||
/* Define to 1 if you have the <mach/mach_time.h> header file. */
|
/* Define to 1 if you have the <mach/mach_time.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_MACH_MACH_TIME_H 1
|
#cmakedefine EVENT__HAVE_MACH_MACH_TIME_H 1
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <mach/mach.h> header file. */
|
||||||
|
#cmakedefine EVENT__HAVE_MACH_MACH_H 1
|
||||||
|
|
||||||
/* Define to 1 if you have the <memory.h> header file. */
|
/* Define to 1 if you have the <memory.h> header file. */
|
||||||
#cmakedefine EVENT__HAVE_MEMORY_H 1
|
#cmakedefine EVENT__HAVE_MEMORY_H 1
|
||||||
|
|
||||||
|
@ -31,10 +31,6 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EVENT__HAVE_PTHREADS
|
|
||||||
#include <pthread.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "event2/event-config.h"
|
#include "event2/event-config.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
@ -73,6 +69,7 @@
|
|||||||
#include "time-internal.h"
|
#include "time-internal.h"
|
||||||
|
|
||||||
#include "regress.h"
|
#include "regress.h"
|
||||||
|
#include "regress_thread.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include "regress.gen.h"
|
#include "regress.gen.h"
|
||||||
@ -979,7 +976,7 @@ test_fork(void)
|
|||||||
evutil_closesocket(child_pair[1]);
|
evutil_closesocket(child_pair[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EVENT__HAVE_PTHREADS
|
#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
|
||||||
static void* del_wait_thread(void *arg)
|
static void* del_wait_thread(void *arg)
|
||||||
{
|
{
|
||||||
struct timeval tv_start, tv_end;
|
struct timeval tv_start, tv_end;
|
||||||
@ -1007,14 +1004,14 @@ static void
|
|||||||
test_del_wait(void)
|
test_del_wait(void)
|
||||||
{
|
{
|
||||||
struct event ev;
|
struct event ev;
|
||||||
pthread_t thread;
|
THREAD_T thread;
|
||||||
|
|
||||||
setup_test("event_del will wait: ");
|
setup_test("event_del will wait: ");
|
||||||
|
|
||||||
event_set(&ev, pair[1], EV_READ|EV_PERSIST, del_wait_cb, &ev);
|
event_set(&ev, pair[1], EV_READ|EV_PERSIST, del_wait_cb, &ev);
|
||||||
event_add(&ev, NULL);
|
event_add(&ev, NULL);
|
||||||
|
|
||||||
pthread_create(&thread, NULL, del_wait_thread, NULL);
|
THREAD_START(thread, del_wait_thread, NULL);
|
||||||
|
|
||||||
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
|
if (write(pair[0], TEST1, strlen(TEST1)+1) < 0) {
|
||||||
tt_fail_perror("write");
|
tt_fail_perror("write");
|
||||||
@ -1033,7 +1030,7 @@ test_del_wait(void)
|
|||||||
test_timeval_diff_eq(&tv_start, &tv_end, 270);
|
test_timeval_diff_eq(&tv_start, &tv_end, 270);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_join(thread, NULL);
|
THREAD_JOIN(thread);
|
||||||
|
|
||||||
tt_int_op(test_ok, ==, 1);
|
tt_int_op(test_ok, ==, 1);
|
||||||
|
|
||||||
@ -3505,8 +3502,8 @@ struct testcase_t main_testcases[] = {
|
|||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
LEGACY(fork, TT_ISOLATED),
|
LEGACY(fork, TT_ISOLATED),
|
||||||
#endif
|
#endif
|
||||||
#ifdef EVENT__HAVE_PTHREADS
|
|
||||||
/** TODO: support win32 */
|
#ifdef EVTHREAD_USE_PTHREADS_IMPLEMENTED
|
||||||
LEGACY(del_wait, TT_ISOLATED|TT_NEED_THREADS|TT_RETRIABLE),
|
LEGACY(del_wait, TT_ISOLATED|TT_NEED_THREADS|TT_RETRIABLE),
|
||||||
LEGACY(del_notify, TT_ISOLATED|TT_NEED_THREADS),
|
LEGACY(del_notify, TT_ISOLATED|TT_NEED_THREADS),
|
||||||
#endif
|
#endif
|
||||||
|
@ -139,6 +139,7 @@ SSL_CTX *get_ssl_ctx(void);
|
|||||||
void init_ssl(void);
|
void init_ssl(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void thread_setup(pthread_t pthread);
|
||||||
void * basic_test_setup(const struct testcase_t *testcase);
|
void * basic_test_setup(const struct testcase_t *testcase);
|
||||||
int basic_test_cleanup(const struct testcase_t *testcase, void *ptr);
|
int basic_test_cleanup(const struct testcase_t *testcase, void *ptr);
|
||||||
|
|
||||||
|
@ -186,6 +186,52 @@ ignore_log_cb(int s, const char *msg)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
|
||||||
|
#ifdef EVENT__HAVE_MACH_MACH_H
|
||||||
|
#include <mach/mach.h>
|
||||||
|
#endif
|
||||||
|
#ifdef EVENT__HAVE_MACH_MACH_TIME_H
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
#endif
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put into the real time scheduling class for better timers latency.
|
||||||
|
* https://developer.apple.com/library/archive/technotes/tn2169/_index.html#//apple_ref/doc/uid/DTS40013172-CH1-TNTAG6000
|
||||||
|
*/
|
||||||
|
void move_pthread_to_realtime_scheduling_class(pthread_t pthread)
|
||||||
|
{
|
||||||
|
mach_timebase_info_data_t timebase_info;
|
||||||
|
mach_timebase_info(&timebase_info);
|
||||||
|
|
||||||
|
const uint64_t NANOS_PER_MSEC = 1000000ULL;
|
||||||
|
double clock2abs = ((double)timebase_info.denom / (double)timebase_info.numer) * NANOS_PER_MSEC;
|
||||||
|
|
||||||
|
thread_time_constraint_policy_data_t policy;
|
||||||
|
policy.period = 0;
|
||||||
|
policy.computation = (uint32_t)(5 * clock2abs); // 5 ms of work
|
||||||
|
policy.constraint = (uint32_t)(10 * clock2abs);
|
||||||
|
policy.preemptible = FALSE;
|
||||||
|
|
||||||
|
int kr = thread_policy_set(pthread_mach_thread_np(pthread_self()),
|
||||||
|
THREAD_TIME_CONSTRAINT_POLICY,
|
||||||
|
(thread_policy_t)&policy,
|
||||||
|
THREAD_TIME_CONSTRAINT_POLICY_COUNT);
|
||||||
|
if (kr != KERN_SUCCESS) {
|
||||||
|
mach_error("thread_policy_set:", kr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void thread_setup(pthread_t pthread)
|
||||||
|
{
|
||||||
|
move_pthread_to_realtime_scheduling_class(pthread);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void thread_setup(pthread_t pthread) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
void *
|
void *
|
||||||
basic_test_setup(const struct testcase_t *testcase)
|
basic_test_setup(const struct testcase_t *testcase)
|
||||||
{
|
{
|
||||||
@ -193,6 +239,8 @@ basic_test_setup(const struct testcase_t *testcase)
|
|||||||
evutil_socket_t spair[2] = { -1, -1 };
|
evutil_socket_t spair[2] = { -1, -1 };
|
||||||
struct basic_test_data *data = NULL;
|
struct basic_test_data *data = NULL;
|
||||||
|
|
||||||
|
thread_setup(pthread_self());
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
if (testcase->flags & TT_ENABLE_IOCP_FLAG)
|
if (testcase->flags & TT_ENABLE_IOCP_FLAG)
|
||||||
return (void*)TT_SKIP;
|
return (void*)TT_SKIP;
|
||||||
|
@ -27,13 +27,17 @@
|
|||||||
#ifndef REGRESS_THREAD_H_INCLUDED_
|
#ifndef REGRESS_THREAD_H_INCLUDED_
|
||||||
#define REGRESS_THREAD_H_INCLUDED_
|
#define REGRESS_THREAD_H_INCLUDED_
|
||||||
|
|
||||||
|
#include "regress.h"
|
||||||
|
|
||||||
#ifdef EVENT__HAVE_PTHREADS
|
#ifdef EVENT__HAVE_PTHREADS
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#define THREAD_T pthread_t
|
#define THREAD_T pthread_t
|
||||||
#define THREAD_FN void *
|
#define THREAD_FN void *
|
||||||
#define THREAD_RETURN() return (NULL)
|
#define THREAD_RETURN() return (NULL)
|
||||||
#define THREAD_START(threadvar, fn, arg) \
|
#define THREAD_START(threadvar, fn, arg) do { \
|
||||||
pthread_create(&(threadvar), NULL, fn, arg)
|
if (!pthread_create(&(threadvar), NULL, fn, arg)) \
|
||||||
|
thread_setup(threadvar); \
|
||||||
|
} while (0)
|
||||||
#define THREAD_JOIN(th) pthread_join(th, NULL)
|
#define THREAD_JOIN(th) pthread_join(th, NULL)
|
||||||
#else
|
#else
|
||||||
#define THREAD_T HANDLE
|
#define THREAD_T HANDLE
|
||||||
@ -42,7 +46,7 @@
|
|||||||
#define THREAD_START(threadvar, fn, arg) do { \
|
#define THREAD_START(threadvar, fn, arg) do { \
|
||||||
uintptr_t threadhandle = _beginthreadex(NULL,0,fn,(arg),0,NULL); \
|
uintptr_t threadhandle = _beginthreadex(NULL,0,fn,(arg),0,NULL); \
|
||||||
(threadvar) = (HANDLE) threadhandle; \
|
(threadvar) = (HANDLE) threadhandle; \
|
||||||
} while (0)
|
} while (0)
|
||||||
#define THREAD_JOIN(th) WaitForSingleObject(th, INFINITE)
|
#define THREAD_JOIN(th) WaitForSingleObject(th, INFINITE)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user