Infrastructure for adding custom polling engines

pull/16298/head
Vijay Pai 7 years ago
parent cb87dd9fef
commit 17e3611c0d
  1. 1
      build.yaml
  2. 41
      src/core/lib/iomgr/ev_posix.cc
  3. 10
      src/core/lib/iomgr/ev_posix.h
  4. 28
      test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
  5. 2
      tools/run_tests/generated/tests.json

@ -4106,6 +4106,7 @@ targets:
- mac
- linux
- posix
uses_polling: false
- name: bm_error
build: test
language: c++

@ -101,10 +101,15 @@ const grpc_event_engine_vtable* init_non_polling(bool explicit_request) {
}
} // namespace
static const event_engine_factory g_factories[] = {
#define ENGINE_HEAD_CUSTOM "head_custom"
#define ENGINE_TAIL_CUSTOM "tail_custom"
static event_engine_factory g_factories[] = {
{ENGINE_HEAD_CUSTOM, nullptr}, {ENGINE_HEAD_CUSTOM, nullptr},
{"epollex", grpc_init_epollex_linux}, {"epoll1", grpc_init_epoll1_linux},
{"epollsig", grpc_init_epollsig_linux}, {"poll", grpc_init_poll_posix},
{"poll-cv", grpc_init_poll_cv_posix}, {"none", init_non_polling},
{ENGINE_TAIL_CUSTOM, nullptr}, {ENGINE_TAIL_CUSTOM, nullptr},
};
static void add(const char* beg, const char* end, char*** ss, size_t* ns) {
@ -138,7 +143,7 @@ static bool is(const char* want, const char* have) {
static void try_engine(const char* engine) {
for (size_t i = 0; i < GPR_ARRAY_SIZE(g_factories); i++) {
if (is(engine, g_factories[i].name)) {
if (g_factories[i].factory != nullptr && is(engine, g_factories[i].name)) {
if ((g_event_engine = g_factories[i].factory(
0 == strcmp(engine, g_factories[i].name)))) {
g_poll_strategy_name = g_factories[i].name;
@ -149,14 +154,32 @@ static void try_engine(const char* engine) {
}
}
/* This should be used for testing purposes ONLY */
void grpc_set_event_engine_test_only(
const grpc_event_engine_vtable* ev_engine) {
g_event_engine = ev_engine;
}
/* Call this before calling grpc_event_engine_init() */
void grpc_register_event_engine_factory(const char* name,
event_engine_factory_fn factory,
bool add_at_head) {
const char* custom_match =
add_at_head ? ENGINE_HEAD_CUSTOM : ENGINE_TAIL_CUSTOM;
// Overwrite an existing registration if already registered
for (size_t i = 0; i < GPR_ARRAY_SIZE(g_factories); i++) {
if (0 == strcmp(name, g_factories[i].name)) {
g_factories[i].factory = factory;
return;
}
}
// Otherwise fill in an available custom slot
for (size_t i = 0; i < GPR_ARRAY_SIZE(g_factories); i++) {
if (0 == strcmp(g_factories[i].name, custom_match)) {
g_factories[i].name = name;
g_factories[i].factory = factory;
return;
}
}
const grpc_event_engine_vtable* grpc_get_event_engine_test_only() {
return g_event_engine;
// Otherwise fail
GPR_ASSERT(false);
}
/* Call this only after calling grpc_event_engine_init() */

@ -82,6 +82,11 @@ typedef struct grpc_event_engine_vtable {
void (*shutdown_engine)(void);
} grpc_event_engine_vtable;
/* register a new event engine factory */
void grpc_register_event_engine_factory(
const char* name, const grpc_event_engine_vtable* (*factory)(bool),
bool add_at_head);
void grpc_event_engine_init(void);
void grpc_event_engine_shutdown(void);
@ -173,9 +178,4 @@ void grpc_pollset_set_del_fd(grpc_pollset_set* pollset_set, grpc_fd* fd);
typedef int (*grpc_poll_function_type)(struct pollfd*, nfds_t, int);
extern grpc_poll_function_type grpc_poll_function;
/* WARNING: The following two functions should be used for testing purposes
* ONLY */
void grpc_set_event_engine_test_only(const grpc_event_engine_vtable*);
const grpc_event_engine_vtable* grpc_get_event_engine_test_only();
#endif /* GRPC_CORE_LIB_IOMGR_EV_POSIX_H */

@ -37,12 +37,9 @@ struct grpc_pollset {
namespace grpc {
namespace testing {
auto& force_library_initialization = Library::get();
static void* g_tag = (void*)static_cast<intptr_t>(10); // Some random number
static grpc_completion_queue* g_cq;
static grpc_event_engine_vtable g_vtable;
static const grpc_event_engine_vtable* g_old_vtable;
static void pollset_shutdown(grpc_pollset* ps, grpc_closure* closure) {
GRPC_CLOSURE_SCHED(closure, GRPC_ERROR_NONE);
@ -83,7 +80,7 @@ static grpc_error* pollset_work(grpc_pollset* ps, grpc_pollset_worker** worker,
return GRPC_ERROR_NONE;
}
static void init_engine_vtable() {
static const grpc_event_engine_vtable* init_engine_vtable(bool) {
memset(&g_vtable, 0, sizeof(g_vtable));
g_vtable.pollset_size = sizeof(grpc_pollset);
@ -92,17 +89,23 @@ static void init_engine_vtable() {
g_vtable.pollset_destroy = pollset_destroy;
g_vtable.pollset_work = pollset_work;
g_vtable.pollset_kick = pollset_kick;
g_vtable.shutdown_engine = [] {};
return &g_vtable;
}
static void setup() {
grpc_init();
// This test should only ever be run with a non or any polling engine
// Override the polling engine for the non-polling engine
// and add a custom polling engine
grpc_register_event_engine_factory("none", init_engine_vtable, false);
grpc_register_event_engine_factory("bm_cq_multiple_threads",
init_engine_vtable, true);
/* Override the event engine with our test event engine (g_vtable); but before
* that, save the current event engine in g_old_vtable. We will have to set
* g_old_vtable back before calling grpc_shutdown() */
init_engine_vtable();
g_old_vtable = grpc_get_event_engine_test_only();
grpc_set_event_engine_test_only(&g_vtable);
grpc_init();
GPR_ASSERT(strcmp(grpc_get_poll_strategy_name(), "none") == 0 ||
strcmp(grpc_get_poll_strategy_name(), "bm_cq_multiple_threads") ==
0);
g_cq = grpc_completion_queue_create_for_next(nullptr);
}
@ -118,9 +121,6 @@ static void teardown() {
}
grpc_completion_queue_destroy(g_cq);
/* Restore the old event engine before calling grpc_shutdown */
grpc_set_event_engine_test_only(g_old_vtable);
grpc_shutdown();
}

@ -3483,7 +3483,7 @@
"mac",
"posix"
],
"uses_polling": true
"uses_polling": false
},
{
"args": [],

Loading…
Cancel
Save