From 70bbc093f14eabab36ce466527fc7bce49bbaf04 Mon Sep 17 00:00:00 2001 From: Trevor Norris Date: Wed, 18 Mar 2020 11:29:10 -0600 Subject: [PATCH] include: add internal fields struct to uv_loop_t Add struct `uv__loop_internal_fields_t` as a location for future additions to `uv_loop_t` while also maintaining v1.x compatibility. Currently `uv__loop_internal_fields_t` only contains the `flags` field. The reason for adding the `flags` field is because the same field was never added to `UV_LOOP_PRIVATE_FIELDS` in Windows as it was in Unix. The idea for creating a struct and attaching it to `uv_loop_t` for future API enhancements was taken from a comment by bnoordhuis in: https://github.com/libuv/libuv/issues/2506#issuecomment-540050665 Also add `internal_fields` to `uv_loop_t` to store the pointer to `uv__loop_internal_fields_t`. This naming makes more sense than just using `active_reqs.unused[1]`. To maintain ABI compatibility, shrink the `unused` array. PR-URL: https://github.com/libuv/libuv/pull/2725 Reviewed-By: Fedor Indutny Reviewed-By: Santiago Gimeno Reviewed-By: Jameson Nash --- include/uv.h | 4 +++- src/unix/loop.c | 14 ++++++++++++++ src/uv-common.h | 9 +++++++++ src/win/core.c | 11 +++++++++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/include/uv.h b/include/uv.h index 1eaeb4f6..8dfa5ee3 100644 --- a/include/uv.h +++ b/include/uv.h @@ -1775,9 +1775,11 @@ struct uv_loop_s { unsigned int active_handles; void* handle_queue[2]; union { - void* unused[2]; + void* unused; unsigned int count; } active_reqs; + /* Internal storage for future extensions. */ + void* internal_fields; /* Internal flag to signal loop stop. */ unsigned int stop_flag; UV_LOOP_PRIVATE_FIELDS diff --git a/src/unix/loop.c b/src/unix/loop.c index e5b28895..9f5c9a38 100644 --- a/src/unix/loop.c +++ b/src/unix/loop.c @@ -28,6 +28,7 @@ #include int uv_loop_init(uv_loop_t* loop) { + uv__loop_internal_fields_t* lfields; void* saved_data; int err; @@ -36,6 +37,11 @@ int uv_loop_init(uv_loop_t* loop) { memset(loop, 0, sizeof(*loop)); loop->data = saved_data; + lfields = (uv__loop_internal_fields_t*) uv__calloc(1, sizeof(*lfields)); + if (lfields == NULL) + return UV_ENOMEM; + loop->internal_fields = lfields; + heap_init((struct heap*) &loop->timer_heap); QUEUE_INIT(&loop->wq); QUEUE_INIT(&loop->idle_handles); @@ -105,6 +111,8 @@ fail_rwlock_init: fail_signal_init: uv__platform_loop_delete(loop); + uv__free(lfields); + loop->internal_fields = NULL; uv__free(loop->watchers); loop->nwatchers = 0; @@ -146,6 +154,8 @@ int uv_loop_fork(uv_loop_t* loop) { void uv__loop_close(uv_loop_t* loop) { + uv__loop_internal_fields_t* lfields; + uv__signal_loop_cleanup(loop); uv__platform_loop_delete(loop); uv__async_stop(loop); @@ -181,6 +191,10 @@ void uv__loop_close(uv_loop_t* loop) { uv__free(loop->watchers); loop->watchers = NULL; loop->nwatchers = 0; + + lfields = uv__get_internal_fields(loop); + uv__free(lfields); + loop->internal_fields = NULL; } diff --git a/src/uv-common.h b/src/uv-common.h index 063588ea..d60c17e8 100644 --- a/src/uv-common.h +++ b/src/uv-common.h @@ -333,6 +333,9 @@ void uv__threadpool_cleanup(void); } \ while (0) +#define uv__get_internal_fields(loop) \ + ((uv__loop_internal_fields_t*) loop->internal_fields) + /* Allocator prototypes */ void *uv__calloc(size_t count, size_t size); char *uv__strdup(const char* s); @@ -342,4 +345,10 @@ void uv__free(void* ptr); void* uv__realloc(void* ptr, size_t size); void* uv__reallocf(void* ptr, size_t size); +typedef struct uv__loop_internal_fields_s uv__loop_internal_fields_t; + +struct uv__loop_internal_fields_s { + unsigned int flags; +}; + #endif /* UV_COMMON_H_ */ diff --git a/src/win/core.c b/src/win/core.c index 9974a115..47de7ce9 100644 --- a/src/win/core.c +++ b/src/win/core.c @@ -233,6 +233,11 @@ int uv_loop_init(uv_loop_t* loop) { if (loop->iocp == NULL) return uv_translate_sys_error(GetLastError()); + lfields = (uv__loop_internal_fields_t*) uv__calloc(1, sizeof(*lfields)); + if (lfields == NULL) + return UV_ENOMEM; + loop->internal_fields = lfields; + /* To prevent uninitialized memory access, loop->time must be initialized * to zero before calling uv_update_time for the first time. */ @@ -297,6 +302,8 @@ fail_mutex_init: loop->timer_heap = NULL; fail_timers_alloc: + uv__free(lfields); + loop->internal_fields = NULL; CloseHandle(loop->iocp); loop->iocp = INVALID_HANDLE_VALUE; @@ -347,6 +354,10 @@ void uv__loop_close(uv_loop_t* loop) { uv__free(loop->timer_heap); loop->timer_heap = NULL; + lfields = uv__get_internal_fields(loop); + uv__free(lfields); + loop->internal_fields = NULL; + CloseHandle(loop->iocp); }