Skip to content

Commit

Permalink
Merge branch 'EventLoopPublicApi' of github.com:awslabs/aws-c-io into…
Browse files Browse the repository at this point in the history
… runtime_select_event_loop
  • Loading branch information
xiazhvera committed Nov 7, 2024
2 parents 470164b + 9e6d574 commit d8f5fdd
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 56 deletions.
54 changes: 41 additions & 13 deletions include/aws/io/event_loop.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,6 @@ enum aws_event_loop_type {
AWS_ELT_DISPATCH_QUEUE,
};

/**
* Configuration to pin an event loop group to a particular CPU group
*/
struct aws_event_loop_group_pin_options {

/**
* CPU group id that threads in this event loop group should be bound to
*/
uint16_t cpu_group;
};

/**
* Event loop group configuration options
*/
Expand All @@ -65,12 +54,20 @@ struct aws_event_loop_group_options {
/**
* Optional callback to invoke when the event loop group finishes destruction.
*/
struct aws_shutdown_callback_options *shutdown_options;
const struct aws_shutdown_callback_options *shutdown_options;

/**
* Optional configuration to control how the event loop group's threads bind to CPU groups
*/
struct aws_event_loop_group_pin_options *pin_options;
uint16_t *cpu_group;

/**
* Override for the clock function that event loops should use. Defaults to the system's high resolution
* timer.
*
* Do not bind this value to managed code; it is only used in timing-sensitive tests.
*/
aws_io_clock_fn *clock_override;
};

AWS_EXTERN_C_BEGIN
Expand Down Expand Up @@ -163,6 +160,37 @@ size_t aws_event_loop_group_get_loop_count(struct aws_event_loop_group *el_group
AWS_IO_API
struct aws_event_loop *aws_event_loop_group_get_next_loop(struct aws_event_loop_group *el_group);

/**
* Initializes an event loop group with platform defaults. If max_threads == 0, then the
* loop count will be the number of available processors on the machine / 2 (to exclude hyper-threads).
* Otherwise, max_threads will be the number of event loops in the group.
*
* @deprecated - use aws_event_loop_group_new() instead
*/
AWS_IO_API
struct aws_event_loop_group *aws_event_loop_group_new_default(
struct aws_allocator *alloc,
uint16_t max_threads,
const struct aws_shutdown_callback_options *shutdown_options);

/** Creates an event loop group, with clock, number of loops to manage, the function to call for creating a new
* event loop, and also pins all loops to hw threads on the same cpu_group (e.g. NUMA nodes). Note:
* If el_count exceeds the number of hw threads in the cpu_group it will be clamped to the number of hw threads
* on the assumption that if you care about NUMA, you don't want hyper-threads doing your IO and you especially
* don't want IO on a different node.
*
* If max_threads == 0, then the
* loop count will be the number of available processors in the cpu_group / 2 (to exclude hyper-threads)
*
* @deprecated - use aws_event_loop_group_new() instead
*/
AWS_IO_API
struct aws_event_loop_group *aws_event_loop_group_new_default_pinned_to_cpu_group(
struct aws_allocator *alloc,
uint16_t max_threads,
uint16_t cpu_group,
const struct aws_shutdown_callback_options *shutdown_options);

AWS_EXTERN_C_END

AWS_POP_SANE_WARNING_LEVEL
Expand Down
1 change: 0 additions & 1 deletion include/aws/io/private/event_loop_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,6 @@ AWS_IO_API
struct aws_event_loop_group *aws_event_loop_group_new_internal(
struct aws_allocator *allocator,
const struct aws_event_loop_group_options *options,
aws_io_clock_fn *clock_override,
aws_new_event_loop_fn *new_loop_fn,
void *new_loop_user_data);

Expand Down
38 changes: 32 additions & 6 deletions source/event_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,22 +130,21 @@ static void s_aws_event_loop_group_shutdown_async(struct aws_event_loop_group *e
struct aws_event_loop_group *aws_event_loop_group_new_internal(
struct aws_allocator *allocator,
const struct aws_event_loop_group_options *options,
aws_io_clock_fn *clock_override,
aws_new_event_loop_fn *new_loop_fn,
void *new_loop_user_data) {
AWS_FATAL_ASSERT(new_loop_fn);

aws_io_clock_fn *clock = clock_override;
aws_io_clock_fn *clock = options->clock_override;
if (!clock) {
clock = aws_high_res_clock_get_ticks;
}

size_t group_cpu_count = 0;
struct aws_cpu_info *usable_cpus = NULL;

bool pin_threads = options->pin_options != NULL;
bool pin_threads = options->cpu_group != NULL;
if (pin_threads) {
uint16_t cpu_group = options->pin_options->cpu_group;
uint16_t cpu_group = *options->cpu_group;
group_cpu_count = aws_get_cpu_count_for_group(cpu_group);
if (!group_cpu_count) {
// LOG THIS
Expand Down Expand Up @@ -253,8 +252,7 @@ struct aws_event_loop_group *aws_event_loop_group_new(
struct aws_allocator *allocator,
const struct aws_event_loop_group_options *options) {

return aws_event_loop_group_new_internal(
allocator, options, aws_high_res_clock_get_ticks, s_default_new_event_loop, NULL);
return aws_event_loop_group_new_internal(allocator, options, s_default_new_event_loop, NULL);
}

struct aws_event_loop_group *aws_event_loop_group_acquire(struct aws_event_loop_group *el_group) {
Expand Down Expand Up @@ -644,3 +642,31 @@ struct aws_event_loop *aws_event_loop_new_epoll_with_options(
return NULL;
}
#endif // AWS_ENABLE_KQUEUE

struct aws_event_loop_group *aws_event_loop_group_new_default(
struct aws_allocator *alloc,
uint16_t max_threads,
const struct aws_shutdown_callback_options *shutdown_options) {

struct aws_event_loop_group_options elg_options = {
.loop_count = max_threads,
.shutdown_options = shutdown_options,
};

return aws_event_loop_group_new(alloc, &elg_options);
}

struct aws_event_loop_group *aws_event_loop_group_new_default_pinned_to_cpu_group(
struct aws_allocator *alloc,
uint16_t max_threads,
uint16_t cpu_group,
const struct aws_shutdown_callback_options *shutdown_options) {

struct aws_event_loop_group_options elg_options = {
.loop_count = max_threads,
.shutdown_options = shutdown_options,
.cpu_group = &cpu_group,
};

return aws_event_loop_group_new(alloc, &elg_options);
}
4 changes: 3 additions & 1 deletion tests/channel_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,9 @@ static int s_test_channel_connect_some_hosts_timeout(struct aws_allocator *alloc
.shutdown = false,
};

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *event_loop_group = aws_event_loop_group_new(allocator, &elg_options);

/* resolve our s3 test bucket and an EC2 host with an ACL that blackholes the connection */
Expand Down
48 changes: 36 additions & 12 deletions tests/default_host_resolver_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ static int s_test_default_with_ipv6_lookup_fn(struct aws_allocator *allocator, v

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);

struct aws_host_resolver_default_options resolver_options = {
Expand Down Expand Up @@ -190,7 +192,9 @@ static int s_test_default_host_resolver_ipv6_address_variations_fn(struct aws_al

};

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);

struct aws_host_resolver_default_options resolver_options = {
Expand Down Expand Up @@ -265,7 +269,9 @@ static int s_test_default_with_ipv4_only_lookup_fn(struct aws_allocator *allocat

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);

struct aws_host_resolver_default_options resolver_options = {
Expand Down Expand Up @@ -336,7 +342,9 @@ static int s_test_default_with_multiple_lookups_fn(struct aws_allocator *allocat

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);

struct aws_host_resolver_default_options resolver_options = {
Expand Down Expand Up @@ -464,7 +472,9 @@ static int s_test_resolver_ttls_fn(struct aws_allocator *allocator, void *ctx) {

s_set_time(0);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);

struct aws_host_resolver_default_options resolver_options = {
Expand Down Expand Up @@ -677,7 +687,9 @@ static int s_test_resolver_connect_failure_recording_fn(struct aws_allocator *al

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);

struct aws_host_resolver_default_options resolver_options = {
Expand Down Expand Up @@ -870,7 +882,9 @@ static int s_test_resolver_ttl_refreshes_on_resolve_fn(struct aws_allocator *all

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);

struct aws_host_resolver_default_options resolver_options = {
Expand Down Expand Up @@ -1051,7 +1065,9 @@ static int s_test_resolver_ipv4_address_lookup_fn(struct aws_allocator *allocato

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);

struct aws_host_resolver_default_options resolver_options = {
Expand Down Expand Up @@ -1113,7 +1129,9 @@ static int s_test_resolver_purge_host_cache(struct aws_allocator *allocator, voi
(void)ctx;
aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);

struct aws_host_resolver_default_options resolver_options = {
Expand Down Expand Up @@ -1229,7 +1247,9 @@ static int s_test_resolver_purge_cache(struct aws_allocator *allocator, void *ct
(void)ctx;
aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);

struct aws_host_resolver_default_options resolver_options = {
Expand Down Expand Up @@ -1379,7 +1399,9 @@ static int s_test_resolver_ipv6_address_lookup_fn(struct aws_allocator *allocato

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);

struct aws_host_resolver_default_options resolver_options = {
Expand Down Expand Up @@ -1442,7 +1464,9 @@ static int s_test_resolver_low_frequency_starvation_fn(struct aws_allocator *all

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);

struct aws_host_resolver_default_options resolver_options = {
Expand Down
11 changes: 5 additions & 6 deletions tests/event_loop_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,9 @@ static int test_event_loop_group_setup_and_shutdown(struct aws_allocator *alloca
(void)ctx;
aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 0};
struct aws_event_loop_group_options elg_options = {
.loop_count = 0,
};
struct aws_event_loop_group *event_loop_group = aws_event_loop_group_new(allocator, &elg_options);

size_t cpu_count = aws_system_info_processor_count();
Expand Down Expand Up @@ -1077,13 +1079,10 @@ static int test_numa_aware_event_loop_group_setup_and_shutdown(struct aws_alloca

/* pass UINT16_MAX here to check the boundary conditions on numa cpu detection. It should never create more threads
* than hw cpus available */
struct aws_event_loop_group_pin_options pin_options = {
.cpu_group = 0,
};

uint16_t cpu_group = 0;
struct aws_event_loop_group_options elg_options = {
.loop_count = UINT16_MAX,
.pin_options = &pin_options,
.cpu_group = &cpu_group,
};
struct aws_event_loop_group *event_loop_group = aws_event_loop_group_new(allocator, &elg_options);

Expand Down
20 changes: 15 additions & 5 deletions tests/exponential_backoff_retry_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ static int s_test_exponential_backoff_retry_too_many_retries_for_jitter_mode(

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);
struct aws_exponential_backoff_retry_options config = {
.max_retries = 3,
Expand Down Expand Up @@ -158,7 +160,9 @@ static int s_test_exponential_backoff_retry_client_errors_do_not_count_fn(struct

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);
struct aws_exponential_backoff_retry_options config = {
.el_group = el_group,
Expand Down Expand Up @@ -203,7 +207,9 @@ static int s_test_exponential_backoff_retry_no_jitter_time_taken_fn(struct aws_a

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);
struct aws_exponential_backoff_retry_options config = {
.max_retries = 3,
Expand Down Expand Up @@ -256,7 +262,9 @@ static int s_test_exponential_max_backoff_retry_no_jitter_fn(struct aws_allocato

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);
struct aws_exponential_backoff_retry_options config = {
.max_retries = 3,
Expand Down Expand Up @@ -314,7 +322,9 @@ static int s_test_exponential_backoff_retry_invalid_options_fn(struct aws_alloca

aws_io_library_init(allocator);

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *el_group = aws_event_loop_group_new(allocator, &elg_options);
struct aws_exponential_backoff_retry_options config = {
.max_retries = 64,
Expand Down
4 changes: 3 additions & 1 deletion tests/pkcs11_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1653,7 +1653,9 @@ static int s_test_pkcs11_tls_negotiation_succeeds_common(
ASSERT_SUCCESS(aws_mutex_init(&s_tls_tester.synced.mutex));
ASSERT_SUCCESS(aws_condition_variable_init(&s_tls_tester.synced.cvar));

struct aws_event_loop_group_options elg_options = {.loop_count = 1};
struct aws_event_loop_group_options elg_options = {
.loop_count = 1,
};
struct aws_event_loop_group *event_loop_group = aws_event_loop_group_new(allocator, &elg_options);
ASSERT_NOT_NULL(event_loop_group);

Expand Down
Loading

0 comments on commit d8f5fdd

Please sign in to comment.