From 4727adafb7718651e08d54b5a729c135626cf865 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Fri, 17 May 2019 12:39:54 -0700 Subject: [PATCH 01/21] src: reformat with clang-format 8.0 --- src/reflock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reflock.c b/src/reflock.c index fe5ac12..773e97d 100644 --- a/src/reflock.c +++ b/src/reflock.c @@ -19,8 +19,8 @@ static const long REFLOCK__POISON = (long) 0x300dead0; static HANDLE reflock__keyed_event = NULL; int reflock_global_init(void) { - NTSTATUS status = - NtCreateKeyedEvent(&reflock__keyed_event, KEYEDEVENT_ALL_ACCESS, NULL, 0); + NTSTATUS status = NtCreateKeyedEvent( + &reflock__keyed_event, KEYEDEVENT_ALL_ACCESS, NULL, 0); if (status != STATUS_SUCCESS) return_set_error(-1, RtlNtStatusToDosError(status)); return 0; From 0088a1f263452eda5b82fb04dbb31dd072171060 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Fri, 17 May 2019 12:37:08 -0700 Subject: [PATCH 02/21] sock: put functions in a more logical order --- src/sock.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sock.c b/src/sock.c index 79cef2d..050295b 100644 --- a/src/sock.c +++ b/src/sock.c @@ -319,6 +319,10 @@ int sock_feed_event(port_state_t* port_state, return 1; } +sock_state_t* sock_state_from_queue_node(queue_node_t* queue_node) { + return container_of(queue_node, sock_state_t, queue_node); +} + queue_node_t* sock_state_to_queue_node(sock_state_t* sock_state) { return &sock_state->queue_node; } @@ -330,7 +334,3 @@ sock_state_t* sock_state_from_tree_node(tree_node_t* tree_node) { tree_node_t* sock_state_to_tree_node(sock_state_t* sock_state) { return &sock_state->tree_node; } - -sock_state_t* sock_state_from_queue_node(queue_node_t* queue_node) { - return container_of(queue_node, sock_state_t, queue_node); -} From cf4530307fc30b9eaa3f86519133b0356eb798c1 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Fri, 17 May 2019 13:32:01 -0700 Subject: [PATCH 03/21] port: make the definition of 'struct port_state' private --- src/api.c | 17 ++++++----------- src/poll-group.c | 21 +++++++++++++-------- src/port.c | 28 ++++++++++++++++++++++++++++ src/port.h | 19 ++++++++----------- 4 files changed, 55 insertions(+), 30 deletions(-) diff --git a/src/api.c b/src/api.c index 10cb3ea..7482f5e 100644 --- a/src/api.c +++ b/src/api.c @@ -11,11 +11,6 @@ static ts_tree_t epoll__handle_tree; -static inline port_state_t* epoll__handle_tree_node_to_port( - ts_tree_node_t* tree_node) { - return container_of(tree_node, port_state_t, handle_tree_node); -} - int epoll_global_init(void) { ts_tree_init(&epoll__handle_tree); return 0; @@ -24,6 +19,7 @@ int epoll_global_init(void) { static HANDLE epoll__create(void) { port_state_t* port_state; HANDLE ephnd; + ts_tree_node_t* tree_node; if (init() < 0) return NULL; @@ -32,9 +28,8 @@ static HANDLE epoll__create(void) { if (port_state == NULL) return NULL; - if (ts_tree_add(&epoll__handle_tree, - &port_state->handle_tree_node, - (uintptr_t) ephnd) < 0) { + tree_node = port_state_to_handle_tree_node(port_state); + if (ts_tree_add(&epoll__handle_tree, tree_node, (uintptr_t) ephnd) < 0) { /* This should never happen. */ port_delete(port_state); return_set_error(NULL, ERROR_ALREADY_EXISTS); @@ -70,7 +65,7 @@ int epoll_close(HANDLE ephnd) { goto err; } - port_state = epoll__handle_tree_node_to_port(tree_node); + port_state = port_state_from_handle_tree_node(tree_node); port_close(port_state); ts_tree_node_unref_and_destroy(tree_node); @@ -96,7 +91,7 @@ int epoll_ctl(HANDLE ephnd, int op, SOCKET sock, struct epoll_event* ev) { goto err; } - port_state = epoll__handle_tree_node_to_port(tree_node); + port_state = port_state_from_handle_tree_node(tree_node); r = port_ctl(port_state, op, sock, ev); ts_tree_node_unref(tree_node); @@ -134,7 +129,7 @@ int epoll_wait(HANDLE ephnd, goto err; } - port_state = epoll__handle_tree_node_to_port(tree_node); + port_state = port_state_from_handle_tree_node(tree_node); num_events = port_wait(port_state, events, maxevents, timeout); ts_tree_node_unref(tree_node); diff --git a/src/poll-group.c b/src/poll-group.c index 53b9ca2..bf700f4 100644 --- a/src/poll-group.c +++ b/src/poll-group.c @@ -5,6 +5,7 @@ #include "error.h" #include "poll-group.h" #include "port.h" +#include "queue.h" #include "util.h" #include "win.h" @@ -18,6 +19,9 @@ typedef struct poll_group { } poll_group_t; static poll_group_t* poll_group__new(port_state_t* port_state) { + HANDLE iocp = port_get_iocp(port_state); + queue_t* poll_group_queue = port_get_poll_group_queue(port_state); + poll_group_t* poll_group = malloc(sizeof *poll_group); if (poll_group == NULL) return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); @@ -27,13 +31,12 @@ static poll_group_t* poll_group__new(port_state_t* port_state) { queue_node_init(&poll_group->queue_node); poll_group->port_state = port_state; - if (afd_create_helper_handle(port_state->iocp, - &poll_group->afd_helper_handle) < 0) { + if (afd_create_helper_handle(iocp, &poll_group->afd_helper_handle) < 0) { free(poll_group); return NULL; } - queue_append(&port_state->poll_group_queue, &poll_group->queue_node); + queue_append(poll_group_queue, &poll_group->queue_node); return poll_group; } @@ -54,10 +57,11 @@ HANDLE poll_group_get_afd_helper_handle(poll_group_t* poll_group) { } poll_group_t* poll_group_acquire(port_state_t* port_state) { - queue_t* queue = &port_state->poll_group_queue; + queue_t* poll_group_queue = port_get_poll_group_queue(port_state); poll_group_t* poll_group = - !queue_empty(queue) - ? container_of(queue_last(queue), poll_group_t, queue_node) + !queue_empty(poll_group_queue) + ? container_of( + queue_last(poll_group_queue), poll_group_t, queue_node) : NULL; if (poll_group == NULL || @@ -67,18 +71,19 @@ poll_group_t* poll_group_acquire(port_state_t* port_state) { return NULL; if (++poll_group->group_size == POLL_GROUP__MAX_GROUP_SIZE) - queue_move_first(&port_state->poll_group_queue, &poll_group->queue_node); + queue_move_first(poll_group_queue, &poll_group->queue_node); return poll_group; } void poll_group_release(poll_group_t* poll_group) { port_state_t* port_state = poll_group->port_state; + queue_t* poll_group_queue = port_get_poll_group_queue(port_state); poll_group->group_size--; assert(poll_group->group_size < POLL_GROUP__MAX_GROUP_SIZE); - queue_move_last(&port_state->poll_group_queue, &poll_group->queue_node); + queue_move_last(poll_group_queue, &poll_group->queue_node); /* Poll groups are currently only freed when the epoll port is closed. */ } diff --git a/src/port.c b/src/port.c index 602d813..02ed36b 100644 --- a/src/port.c +++ b/src/port.c @@ -16,6 +16,17 @@ #define PORT__MAX_ON_STACK_COMPLETIONS 256 +typedef struct port_state { + HANDLE iocp; + tree_t sock_tree; + queue_t sock_update_queue; + queue_t sock_deleted_queue; + queue_t poll_group_queue; + ts_tree_node_t handle_tree_node; + CRITICAL_SECTION lock; + size_t active_poll_count; +} port_state_t; + static port_state_t* port__alloc(void) { port_state_t* port_state = malloc(sizeof *port_state); if (port_state == NULL) @@ -393,3 +404,20 @@ void port_remove_deleted_socket(port_state_t* port_state, return; queue_remove(sock_state_to_queue_node(sock_state)); } + +HANDLE port_get_iocp(port_state_t* port_state) { + assert(port_state->iocp != NULL); + return port_state->iocp; +} + +queue_t* port_get_poll_group_queue(port_state_t* port_state) { + return &port_state->poll_group_queue; +} + +port_state_t* port_state_from_handle_tree_node(ts_tree_node_t* tree_node) { + return container_of(tree_node, port_state_t, handle_tree_node); +} + +ts_tree_node_t* port_state_to_handle_tree_node(port_state_t* port_state) { + return &port_state->handle_tree_node; +} diff --git a/src/port.h b/src/port.h index f9e5ecc..bed89b0 100644 --- a/src/port.h +++ b/src/port.h @@ -14,17 +14,6 @@ typedef struct port_state port_state_t; typedef struct sock_state sock_state_t; -typedef struct port_state { - HANDLE iocp; - tree_t sock_tree; - queue_t sock_update_queue; - queue_t sock_deleted_queue; - queue_t poll_group_queue; - ts_tree_node_t handle_tree_node; - CRITICAL_SECTION lock; - size_t active_poll_count; -} port_state_t; - WEPOLL_INTERNAL port_state_t* port_new(HANDLE* iocp_out); WEPOLL_INTERNAL int port_close(port_state_t* port_state); WEPOLL_INTERNAL int port_delete(port_state_t* port_state); @@ -57,4 +46,12 @@ WEPOLL_INTERNAL void port_add_deleted_socket(port_state_t* port_state, WEPOLL_INTERNAL void port_remove_deleted_socket(port_state_t* port_state, sock_state_t* sock_state); +WEPOLL_INTERNAL HANDLE port_get_iocp(port_state_t* port_state); +WEPOLL_INTERNAL queue_t* port_get_poll_group_queue(port_state_t* port_state); + +WEPOLL_INTERNAL port_state_t* port_state_from_handle_tree_node( + ts_tree_node_t* tree_node); +WEPOLL_INTERNAL ts_tree_node_t* port_state_to_handle_tree_node( + port_state_t* port_state); + #endif /* WEPOLL_PORT_H_ */ From 20af8d02c7f63f563c2972d3ef4b69cee455570f Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Fri, 17 May 2019 13:41:00 -0700 Subject: [PATCH 04/21] port: rename 'iocp' to 'iocp_handle' where appropriate --- src/afd.c | 5 +++-- src/afd.h | 2 +- src/poll-group.c | 5 +++-- src/port.c | 37 +++++++++++++++++++------------------ src/port.h | 4 ++-- 5 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/afd.c b/src/afd.c index 886fd22..8d533e7 100644 --- a/src/afd.c +++ b/src/afd.c @@ -16,7 +16,8 @@ static UNICODE_STRING afd__helper_name = static OBJECT_ATTRIBUTES afd__helper_attributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&afd__helper_name, 0); -int afd_create_helper_handle(HANDLE iocp, HANDLE* afd_helper_handle_out) { +int afd_create_helper_handle(HANDLE iocp_handle, + HANDLE* afd_helper_handle_out) { HANDLE afd_helper_handle; IO_STATUS_BLOCK iosb; NTSTATUS status; @@ -38,7 +39,7 @@ int afd_create_helper_handle(HANDLE iocp, HANDLE* afd_helper_handle_out) { if (status != STATUS_SUCCESS) return_set_error(-1, RtlNtStatusToDosError(status)); - if (CreateIoCompletionPort(afd_helper_handle, iocp, 0, 0) == NULL) + if (CreateIoCompletionPort(afd_helper_handle, iocp_handle, 0, 0) == NULL) goto error; if (!SetFileCompletionNotificationModes(afd_helper_handle, diff --git a/src/afd.h b/src/afd.h index d7869cd..c26cb8f 100644 --- a/src/afd.h +++ b/src/afd.h @@ -30,7 +30,7 @@ typedef struct _AFD_POLL_INFO { AFD_POLL_HANDLE_INFO Handles[1]; } AFD_POLL_INFO, *PAFD_POLL_INFO; -WEPOLL_INTERNAL int afd_create_helper_handle(HANDLE iocp, +WEPOLL_INTERNAL int afd_create_helper_handle(HANDLE iocp_handle, HANDLE* afd_helper_handle_out); WEPOLL_INTERNAL int afd_poll(HANDLE afd_helper_handle, diff --git a/src/poll-group.c b/src/poll-group.c index bf700f4..442c73a 100644 --- a/src/poll-group.c +++ b/src/poll-group.c @@ -19,7 +19,7 @@ typedef struct poll_group { } poll_group_t; static poll_group_t* poll_group__new(port_state_t* port_state) { - HANDLE iocp = port_get_iocp(port_state); + HANDLE iocp_handle = port_get_iocp_handle(port_state); queue_t* poll_group_queue = port_get_poll_group_queue(port_state); poll_group_t* poll_group = malloc(sizeof *poll_group); @@ -31,7 +31,8 @@ static poll_group_t* poll_group__new(port_state_t* port_state) { queue_node_init(&poll_group->queue_node); poll_group->port_state = port_state; - if (afd_create_helper_handle(iocp, &poll_group->afd_helper_handle) < 0) { + if (afd_create_helper_handle(iocp_handle, &poll_group->afd_helper_handle) < + 0) { free(poll_group); return NULL; } diff --git a/src/port.c b/src/port.c index 02ed36b..6c8727d 100644 --- a/src/port.c +++ b/src/port.c @@ -17,7 +17,7 @@ #define PORT__MAX_ON_STACK_COMPLETIONS 256 typedef struct port_state { - HANDLE iocp; + HANDLE iocp_handle; tree_t sock_tree; queue_t sock_update_queue; queue_t sock_deleted_queue; @@ -41,28 +41,29 @@ static void port__free(port_state_t* port) { } static HANDLE port__create_iocp(void) { - HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); - if (iocp == NULL) + HANDLE iocp_handle = + CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); + if (iocp_handle == NULL) return_map_error(NULL); - return iocp; + return iocp_handle; } -port_state_t* port_new(HANDLE* iocp_out) { +port_state_t* port_new(HANDLE* iocp_handle_out) { port_state_t* port_state; - HANDLE iocp; + HANDLE iocp_handle; port_state = port__alloc(); if (port_state == NULL) goto err1; - iocp = port__create_iocp(); - if (iocp == NULL) + iocp_handle = port__create_iocp(); + if (iocp_handle == NULL) goto err2; memset(port_state, 0, sizeof *port_state); - port_state->iocp = iocp; + port_state->iocp_handle = iocp_handle; tree_init(&port_state->sock_tree); queue_init(&port_state->sock_update_queue); queue_init(&port_state->sock_deleted_queue); @@ -70,7 +71,7 @@ port_state_t* port_new(HANDLE* iocp_out) { ts_tree_node_init(&port_state->handle_tree_node); InitializeCriticalSection(&port_state->lock); - *iocp_out = iocp; + *iocp_handle_out = iocp_handle; return port_state; err2: @@ -80,10 +81,10 @@ err1: } static int port__close_iocp(port_state_t* port_state) { - HANDLE iocp = port_state->iocp; - port_state->iocp = NULL; + HANDLE iocp_handle = port_state->iocp_handle; + port_state->iocp_handle = NULL; - if (!CloseHandle(iocp)) + if (!CloseHandle(iocp_handle)) return_map_error(-1); return 0; @@ -104,7 +105,7 @@ int port_delete(port_state_t* port_state) { queue_node_t* queue_node; /* At this point the IOCP port should have been closed. */ - assert(port_state->iocp == NULL); + assert(port_state->iocp_handle == NULL); while ((tree_node = tree_root(&port_state->sock_tree)) != NULL) { sock_state_t* sock_state = sock_state_from_tree_node(tree_node); @@ -184,7 +185,7 @@ static int port__poll(port_state_t* port_state, LeaveCriticalSection(&port_state->lock); - BOOL r = GetQueuedCompletionStatusEx(port_state->iocp, + BOOL r = GetQueuedCompletionStatusEx(port_state->iocp_handle, iocp_events, maxevents, &completion_count, @@ -405,9 +406,9 @@ void port_remove_deleted_socket(port_state_t* port_state, queue_remove(sock_state_to_queue_node(sock_state)); } -HANDLE port_get_iocp(port_state_t* port_state) { - assert(port_state->iocp != NULL); - return port_state->iocp; +HANDLE port_get_iocp_handle(port_state_t* port_state) { + assert(port_state->iocp_handle != NULL); + return port_state->iocp_handle; } queue_t* port_get_poll_group_queue(port_state_t* port_state) { diff --git a/src/port.h b/src/port.h index bed89b0..d7b9215 100644 --- a/src/port.h +++ b/src/port.h @@ -14,7 +14,7 @@ typedef struct port_state port_state_t; typedef struct sock_state sock_state_t; -WEPOLL_INTERNAL port_state_t* port_new(HANDLE* iocp_out); +WEPOLL_INTERNAL port_state_t* port_new(HANDLE* iocp_handle_out); WEPOLL_INTERNAL int port_close(port_state_t* port_state); WEPOLL_INTERNAL int port_delete(port_state_t* port_state); @@ -46,7 +46,7 @@ WEPOLL_INTERNAL void port_add_deleted_socket(port_state_t* port_state, WEPOLL_INTERNAL void port_remove_deleted_socket(port_state_t* port_state, sock_state_t* sock_state); -WEPOLL_INTERNAL HANDLE port_get_iocp(port_state_t* port_state); +WEPOLL_INTERNAL HANDLE port_get_iocp_handle(port_state_t* port_state); WEPOLL_INTERNAL queue_t* port_get_poll_group_queue(port_state_t* port_state); WEPOLL_INTERNAL port_state_t* port_state_from_handle_tree_node( From 06dd355e33424c11acda92b449204eb8628cbd49 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Wed, 12 Jun 2019 19:09:06 +0200 Subject: [PATCH 05/21] tools: use prettier to format javascript files --- .eslintrc.json | 27 ------------------------ .prettierrc.json | 5 +++++ tools/combine.js | 52 ++++++++++++++++++++++++++-------------------- tools/release.js | 3 +++ tools/run-tests.js | 13 ++++++------ 5 files changed, 43 insertions(+), 57 deletions(-) delete mode 100644 .eslintrc.json create mode 100644 .prettierrc.json diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 9c7a144..0000000 --- a/.eslintrc.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "env": { - "es6": true, - "node": true - }, - "extends": "eslint:recommended", - "parserOptions": { - "ecmaVersion": 7, - "ecmaFeatures": { "experimentalObjectRestSpread": true } - }, - "rules": { - "linebreak-style": [ "error", "unix" ], - "no-console": "off", - "no-trailing-spaces": "error", - "no-var": "error", - "prefer-const": "error", - "quotes": [ "error", "single" ], - "semi": [ "error", "always" ], - "indent": [ "error", 2, { - "ArrayExpression": "first", - "ObjectExpression": "first", - "FunctionExpression": { "parameters": "first" }, - "FunctionDeclaration": { "parameters": "first" }, - "CallExpression": { "arguments": "first" } - }] - } -} diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..b2d49bd --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,5 @@ +{ + "endOfLine": "lf", + "proseWrap": "always", + "singleQuote": true +} diff --git a/tools/combine.js b/tools/combine.js index 762b4a9..83a1348 100644 --- a/tools/combine.js +++ b/tools/combine.js @@ -9,23 +9,23 @@ const files = []; const includeDirs = []; let stripGuardsEnabled = false; -process.argv - .slice(2) - .forEach(arg => { - let match; - if ((match = /^-I(.*)$/.exec(arg))) - includeDirs.push(match[1]); - else if (arg === '--strip-guards') - stripGuardsEnabled = true; - else - files.push(arg); - }); +process.argv.slice(2).forEach(arg => { + let match; + if ((match = /^-I(.*)$/.exec(arg))) { + includeDirs.push(match[1]); + } else if (arg === '--strip-guards') { + stripGuardsEnabled = true; + } else { + files.push(arg); + } +}); const included = {}; function readFileWithPath(fileName, dirs) { - if (/[/\\]/.test(fileName)) + if (/[/\\]/.test(fileName)) { return fs.readFileSync(fileName, 'utf8'); + } for (let i = 0; i < dirs.length; i++) { const filePath = path.resolve(dirs[i], fileName); @@ -70,14 +70,17 @@ function strip_guards(filename, source) { function lines(filename, strip) { let source = readFileWithPath(filename, ['.'].concat(includeDirs)); - if (strip) source = strip_guards(filename, source); + if (strip) { + source = strip_guards(filename, source); + } return source.split(/\r?\n/g); } function include(line, filename) { const key = path.basename(filename).toLowerCase(); - if (included[key]) + if (included[key]) { return ''; // Included earlier. + } console.error('Including: ' + key); included[key] = true; return lines(filename, true); @@ -93,20 +96,23 @@ function add(filename) { const sys_included = {}; function include_sys(line, filename) { const key = path.basename(filename).toLowerCase(); - if (sys_included[key]) + if (sys_included[key]) { return ''; // Included earlier. - + } sys_included[key] = true; } let source = []; -source = source.concat('/*') - .concat(fs.readFileSync('LICENSE', 'utf8') - .replace(/^\s+|\s+$/g, '') - .split(/\r?\n/g) - .map(line => ' * ' + line) - .map(line => line.replace(/\s+$/, '')) +source = source + .concat('/*') + .concat( + fs + .readFileSync('LICENSE', 'utf8') + .replace(/^\s+|\s+$/g, '') + .split(/\r?\n/g) + .map(line => ' * ' + line) + .map(line => line.replace(/\s+$/, '')) ) .concat(' */') .concat(''); @@ -121,7 +127,7 @@ const patterns = [ { re: /^\s*#include\s*<([^"]*)>.*$/, fn: include_sys } ]; -restart: for (let lno = 0; lno < source.length;) { +restart: for (let lno = 0; lno < source.length; ) { for (const i in patterns) { const line = source[lno]; const pattern = patterns[i]; diff --git a/tools/release.js b/tools/release.js index 1f2c98b..22f0763 100644 --- a/tools/release.js +++ b/tools/release.js @@ -42,12 +42,14 @@ const distTree = getSHA(stdout); exec('git reset'); +// prettier-ignore stdout = exec(`git commit-tree -S ${distTree} ` + `-p ${previousTagCommit} ` + `-p ${sourceCommit} ` + `-m "version ${version}"`, utf8); const distCommit = getSHA(stdout); +// prettier-ignore stdout = exec(`git commit-tree -S ${sourceTree} ` + `-p ${sourceCommit} ` + `-p ${distCommit} ` + @@ -60,6 +62,7 @@ console.log(''); console.log(`Previous release tag: ${previousTag}`); console.log(`New release tag ${distTag}`); +// prettier-ignore exec(`git tag ${distTag} ${distCommit} ` + `-sm "version ${version}"`, inherit); diff --git a/tools/run-tests.js b/tools/run-tests.js index 33d69de..7263383 100644 --- a/tools/run-tests.js +++ b/tools/run-tests.js @@ -1,4 +1,3 @@ - const spawn = require('child_process').spawn; const basename = require('path').basename; @@ -6,21 +5,22 @@ const test_exes = process.argv.slice(2); run_tests(test_exes); function run_tests(test_exes, num = 0, fail_count = 0) { - if (test_exes.length <= num) + if (test_exes.length <= num) { return done(test_exes, fail_count); + } const test_exe = test_exes[num]; const test_name = basename(test_exe, '.exe'); - console.log('(%d/%d) %s...', (num + 1), test_exes.length, test_name); + console.log('(%d/%d) %s...', num + 1, test_exes.length, test_name); const child = spawn(test_exe, [], { encoding: 'utf8' }); let out = ''; - child.stdout.on('data', (data) => out += data); - child.stderr.on('data', (data) => out += data); + child.stdout.on('data', data => (out += data)); + child.stderr.on('data', data => (out += data)); - child.on('exit', (code) => { + child.on('exit', code => { if (code === 0) { console.log(' PASS'); } else { @@ -38,4 +38,3 @@ function done(test_exes, fail_count) { process.exit(fail_count == 0 ? 0 : 1); } - From 017fa62aac683998eb80a71c87964a3c4a93ee3f Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Wed, 12 Jun 2019 19:12:49 +0200 Subject: [PATCH 06/21] tools/combine: fold identical 'typedef struct' declarations --- tools/combine.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/combine.js b/tools/combine.js index 83a1348..f828995 100644 --- a/tools/combine.js +++ b/tools/combine.js @@ -102,6 +102,15 @@ function include_sys(line, filename) { sys_included[key] = true; } +const declarations = {}; +function declare(line) { + const key = line.replace(/\s+/g, ' ').trim(); + if (declarations[key]) { + return ''; // Declared earlier. + } + declarations[key] = true; +} + let source = []; source = source @@ -124,7 +133,8 @@ for (let i = 0; i < files.length; i++) { const patterns = [ { re: /^\s*#include\s*"([^"]*)".*$/, fn: include }, - { re: /^\s*#include\s*<([^"]*)>.*$/, fn: include_sys } + { re: /^\s*#include\s*<([^"]*)>.*$/, fn: include_sys }, + { re: /^\s*typedef\s+struct\s+\w+\s+\w+\s*;\s*$/, fn: declare } ]; restart: for (let lno = 0; lno < source.length; ) { From 7080d540e21ebd8d5df78fa6abd686c7e0c261f3 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Wed, 12 Jun 2019 15:57:58 +0200 Subject: [PATCH 07/21] build: do not force-include wepoll.h using a command line switch --- CMakeLists.txt | 3 +-- src/api.c | 1 + src/sock.c | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 133136f..1b082d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,10 +69,9 @@ set(DLL_TARGET "${HEADER_NAME}.dll") add_library(${DLL_TARGET} SHARED ${SOURCES_HEADER} ${SOURCES_SRC} ${SOURCES_SRC_REGULAR}) target_include_directories(${DLL_TARGET} PUBLIC include src/regular) if(MSVC) - target_compile_options(${DLL_TARGET} PUBLIC "-FI${SOURCES_HEADER}") target_compile_definitions(${DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__declspec(dllexport)" ) else() - target_compile_options(${DLL_TARGET} PUBLIC -include ${SOURCES_HEADER} -fvisibility=hidden) + target_compile_options(${DLL_TARGET} PUBLIC -fvisibility=hidden) target_compile_definitions(${DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__attribute__((visibility(\"default\")))") endif() set_target_properties(${DLL_TARGET} PROPERTIES OUTPUT_NAME ${DLL_NAME}) diff --git a/src/api.c b/src/api.c index 7482f5e..f330181 100644 --- a/src/api.c +++ b/src/api.c @@ -7,6 +7,7 @@ #include "port.h" #include "thread-safe-tree.h" #include "util.h" +#include "wepoll.h" #include "win.h" static ts_tree_t epoll__handle_tree; diff --git a/src/sock.c b/src/sock.c index 050295b..3fd0cad 100644 --- a/src/sock.c +++ b/src/sock.c @@ -9,6 +9,7 @@ #include "poll-group.h" #include "port.h" #include "sock.h" +#include "wepoll.h" #include "ws.h" static const uint32_t SOCK__KNOWN_EPOLL_EVENTS = From 027fb4a419991fa72c113a35824fafa2b10552ee Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Wed, 12 Jun 2019 16:32:01 +0200 Subject: [PATCH 08/21] util,test: remove definition and usage of type 'ssize_t' --- src/util.h | 4 ---- test/test-tree.c | 9 ++++----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/util.h b/src/util.h index 41cb35d..d767bdb 100644 --- a/src/util.h +++ b/src/util.h @@ -7,10 +7,6 @@ #include "internal.h" -#ifndef _SSIZE_T_DEFINED -typedef intptr_t ssize_t; -#endif - #define array_count(a) (sizeof(a) / (sizeof((a)[0]))) /* clang-format off */ diff --git a/test/test-tree.c b/test/test-tree.c index a2cd956..de1842a 100644 --- a/test/test-tree.c +++ b/test/test-tree.c @@ -6,7 +6,6 @@ #include "test-util.h" #include "tree.h" -#include "util.h" #define NODE_COUNT 1000 static_assert(NODE_COUNT <= RAND_MAX, "NODE_COUNT too high"); @@ -54,21 +53,21 @@ static void check_tree_count(const tree_t* tree, size_t expected_count) { } static void keys_increasing(tree_t* tree, test_op_t op) { - size_t i; + uintptr_t i; for (i = 0; i < NODE_COUNT; i++) op(tree, i); } static void keys_decreasing(tree_t* tree, test_op_t op) { - ssize_t i; + intptr_t i; for (i = NODE_COUNT - 1; i >= 0; i--) - op(tree, (size_t) i); + op(tree, (uintptr_t) i); } static void keys_random(tree_t* tree, test_op_t op) { uintptr_t keys[NODE_COUNT]; uintptr_t index, key; - ssize_t left; + intptr_t left; for (index = 0; index < NODE_COUNT; index++) keys[index] = index; From a627f365fd784c29df90172d255ec712a578e30a Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Wed, 12 Jun 2019 16:56:31 +0200 Subject: [PATCH 09/21] src,test: clean up #include directives --- src/afd.c | 5 ++--- src/afd.h | 1 - src/api.c | 1 - src/init.c | 3 ++- src/poll-group.c | 3 ++- src/poll-group.h | 5 ++--- src/port.c | 2 +- src/port.h | 10 +++------- src/reflock.c | 1 - src/reflock.h | 2 -- src/sock.c | 5 ++++- src/sock.h | 7 ++----- src/tree.c | 1 + src/tree.h | 1 - src/util.h | 3 --- src/ws.c | 2 -- src/ws.h | 1 - test/test-auto-drop-on-close.c | 1 + test/test-connect-fail-events.c | 1 - test/test-connect-success-events.c | 1 + test/test-ctl-fuzz.c | 1 - test/test-leak-1.c | 4 ---- test/test-mixed-socket-types.c | 2 -- test/test-multi-poll.c | 1 - test/test-oneshot-and-hangup.c | 1 - test/test-reflock.c | 1 + test/test-tree.c | 3 --- test/test-udp-pings.c | 2 +- 28 files changed, 23 insertions(+), 48 deletions(-) diff --git a/src/afd.c b/src/afd.c index 8d533e7..abc3336 100644 --- a/src/afd.c +++ b/src/afd.c @@ -1,12 +1,11 @@ -#include +#include +#include #include #include "afd.h" #include "error.h" #include "nt.h" -#include "util.h" #include "win.h" -#include "ws.h" #define IOCTL_AFD_POLL 0x00012024 diff --git a/src/afd.h b/src/afd.h index c26cb8f..cc49a44 100644 --- a/src/afd.h +++ b/src/afd.h @@ -3,7 +3,6 @@ #include "internal.h" #include "nt.h" -#include "util.h" #include "win.h" /* clang-format off */ diff --git a/src/api.c b/src/api.c index f330181..38513c9 100644 --- a/src/api.c +++ b/src/api.c @@ -6,7 +6,6 @@ #include "init.h" #include "port.h" #include "thread-safe-tree.h" -#include "util.h" #include "wepoll.h" #include "win.h" diff --git a/src/init.c b/src/init.c index db237d4..04f72bc 100644 --- a/src/init.c +++ b/src/init.c @@ -1,11 +1,12 @@ #include +#include -#include "afd.h" #include "api.h" #include "init.h" #include "nt.h" #include "reflock.h" #include "util.h" +#include "win.h" #include "ws.h" static bool init__done = false; diff --git a/src/poll-group.c b/src/poll-group.c index 442c73a..e3ded8d 100644 --- a/src/poll-group.c +++ b/src/poll-group.c @@ -1,7 +1,8 @@ #include -#include +#include #include +#include "afd.h" #include "error.h" #include "poll-group.h" #include "port.h" diff --git a/src/poll-group.h b/src/poll-group.h index 2e5cd09..2dd100d 100644 --- a/src/poll-group.h +++ b/src/poll-group.h @@ -1,13 +1,12 @@ #ifndef WEPOLL_POLL_GROUP_H_ #define WEPOLL_POLL_GROUP_H_ -#include "error.h" #include "internal.h" -#include "queue.h" #include "win.h" -typedef struct port_state port_state_t; typedef struct poll_group poll_group_t; +typedef struct port_state port_state_t; +typedef struct queue_node queue_node_t; WEPOLL_INTERNAL poll_group_t* poll_group_acquire(port_state_t* port); WEPOLL_INTERNAL void poll_group_release(poll_group_t* poll_group); diff --git a/src/port.c b/src/port.c index 6c8727d..c4c9241 100644 --- a/src/port.c +++ b/src/port.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/src/port.h b/src/port.h index d7b9215..bedfaf3 100644 --- a/src/port.h +++ b/src/port.h @@ -1,18 +1,14 @@ #ifndef WEPOLL_PORT_H_ #define WEPOLL_PORT_H_ -#include "afd.h" #include "internal.h" -#include "poll-group.h" -#include "queue.h" -#include "sock.h" -#include "thread-safe-tree.h" -#include "tree.h" -#include "util.h" +#include "wepoll.h" #include "win.h" typedef struct port_state port_state_t; +typedef struct queue queue_t; typedef struct sock_state sock_state_t; +typedef struct ts_tree_node ts_tree_node_t; WEPOLL_INTERNAL port_state_t* port_new(HANDLE* iocp_handle_out); WEPOLL_INTERNAL int port_close(port_state_t* port_state); diff --git a/src/reflock.c b/src/reflock.c index 773e97d..98c73ca 100644 --- a/src/reflock.c +++ b/src/reflock.c @@ -1,5 +1,4 @@ #include -#include #include #include "error.h" diff --git a/src/reflock.h b/src/reflock.h index 473c5f0..c4525ca 100644 --- a/src/reflock.h +++ b/src/reflock.h @@ -19,8 +19,6 @@ * should use another lock to guarantee that this can't happen. */ -#include - #include "internal.h" typedef struct reflock { diff --git a/src/sock.c b/src/sock.c index 3fd0cad..bad7d5c 100644 --- a/src/sock.c +++ b/src/sock.c @@ -1,14 +1,17 @@ #include -#include #include #include +#include #include #include "afd.h" #include "error.h" #include "poll-group.h" #include "port.h" +#include "queue.h" #include "sock.h" +#include "tree.h" +#include "util.h" #include "wepoll.h" #include "ws.h" diff --git a/src/sock.h b/src/sock.h index ea531ed..c316ccd 100644 --- a/src/sock.h +++ b/src/sock.h @@ -1,17 +1,14 @@ #ifndef WEPOLL_SOCK_H_ #define WEPOLL_SOCK_H_ -#include - #include "internal.h" -#include "queue.h" -#include "tree.h" -#include "util.h" #include "wepoll.h" #include "win.h" typedef struct port_state port_state_t; +typedef struct queue_node queue_node_t; typedef struct sock_state sock_state_t; +typedef struct tree_node tree_node_t; WEPOLL_INTERNAL sock_state_t* sock_new(port_state_t* port_state, SOCKET socket); diff --git a/src/tree.c b/src/tree.c index 76dfa00..b6750a3 100644 --- a/src/tree.c +++ b/src/tree.c @@ -4,6 +4,7 @@ #include #include "tree.h" +#include "util.h" void tree_init(tree_t* tree) { memset(tree, 0, sizeof *tree); diff --git a/src/tree.h b/src/tree.h index 139e13f..1e01257 100644 --- a/src/tree.h +++ b/src/tree.h @@ -5,7 +5,6 @@ #include #include "internal.h" -#include "util.h" /* N.b.: the tree functions do not set errno or LastError when they fail. Each * of the API functions has at most one failure mode. It is up to the caller to diff --git a/src/util.h b/src/util.h index d767bdb..0bd90d5 100644 --- a/src/util.h +++ b/src/util.h @@ -1,12 +1,9 @@ #ifndef WEPOLL_UTIL_H_ #define WEPOLL_UTIL_H_ -#include #include #include -#include "internal.h" - #define array_count(a) (sizeof(a) / (sizeof((a)[0]))) /* clang-format off */ diff --git a/src/ws.c b/src/ws.c index 74b6bdf..83de065 100644 --- a/src/ws.c +++ b/src/ws.c @@ -1,8 +1,6 @@ -#include #include #include "error.h" -#include "util.h" #include "win.h" #include "ws.h" diff --git a/src/ws.h b/src/ws.h index d688d27..34ce5bb 100644 --- a/src/ws.h +++ b/src/ws.h @@ -2,7 +2,6 @@ #define WEPOLL_WS_H_ #include "internal.h" -#include "util.h" #include "win.h" WEPOLL_INTERNAL int ws_global_init(void); diff --git a/test/test-auto-drop-on-close.c b/test/test-auto-drop-on-close.c index dd82778..2cdaf7e 100644 --- a/test/test-auto-drop-on-close.c +++ b/test/test-auto-drop-on-close.c @@ -10,6 +10,7 @@ */ #include +#include #include #include "test-util.h" diff --git a/test/test-connect-fail-events.c b/test/test-connect-fail-events.c index 1c28183..457d2e4 100644 --- a/test/test-connect-fail-events.c +++ b/test/test-connect-fail-events.c @@ -2,7 +2,6 @@ #include #include "test-util.h" -#include "util.h" #include "wepoll.h" #include "win.h" diff --git a/test/test-connect-success-events.c b/test/test-connect-success-events.c index 525fb71..ebc0fda 100644 --- a/test/test-connect-success-events.c +++ b/test/test-connect-success-events.c @@ -8,6 +8,7 @@ #include #include +#include #include "test-util.h" #include "util.h" diff --git a/test/test-ctl-fuzz.c b/test/test-ctl-fuzz.c index 72bf47e..85e57ab 100644 --- a/test/test-ctl-fuzz.c +++ b/test/test-ctl-fuzz.c @@ -1,4 +1,3 @@ -#include #include #include #include diff --git a/test/test-leak-1.c b/test/test-leak-1.c index 6364dfc..efca1b5 100644 --- a/test/test-leak-1.c +++ b/test/test-leak-1.c @@ -1,10 +1,6 @@ -#include -#include -#include #include #include "test-util.h" -#include "util.h" #include "wepoll.h" #include "win.h" diff --git a/test/test-mixed-socket-types.c b/test/test-mixed-socket-types.c index bf36c51..90bb534 100644 --- a/test/test-mixed-socket-types.c +++ b/test/test-mixed-socket-types.c @@ -1,7 +1,5 @@ -#include #include -#include "error.h" #include "test-util.h" #include "wepoll.h" #include "win.h" diff --git a/test/test-multi-poll.c b/test/test-multi-poll.c index 894d3ca..80f869b 100644 --- a/test/test-multi-poll.c +++ b/test/test-multi-poll.c @@ -4,7 +4,6 @@ #include #include -#include "init.h" #include "test-util.h" #include "util.h" #include "wepoll.h" diff --git a/test/test-oneshot-and-hangup.c b/test/test-oneshot-and-hangup.c index 7016fc9..7aaf207 100644 --- a/test/test-oneshot-and-hangup.c +++ b/test/test-oneshot-and-hangup.c @@ -1,6 +1,5 @@ #include #include -#include #include #include diff --git a/test/test-reflock.c b/test/test-reflock.c index e342518..727d80a 100644 --- a/test/test-reflock.c +++ b/test/test-reflock.c @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/test/test-tree.c b/test/test-tree.c index de1842a..d6f1a0d 100644 --- a/test/test-tree.c +++ b/test/test-tree.c @@ -1,8 +1,5 @@ -#include -#include #include #include -#include #include "test-util.h" #include "tree.h" diff --git a/test/test-udp-pings.c b/test/test-udp-pings.c index bc6dacc..0f92643 100644 --- a/test/test-udp-pings.c +++ b/test/test-udp-pings.c @@ -1,7 +1,7 @@ +#include #include #include -#include "error.h" #include "test-util.h" #include "wepoll.h" #include "win.h" From d5f8f5f1b1be1a4ba8adb51eb4ee4de7a305a9c8 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Wed, 12 Jun 2019 20:33:56 +0200 Subject: [PATCH 10/21] afd: use IO_STATUS_BLOCK instead of OVERLAPPED to track async poll ops This reduces per-socket memory usage, as the OVERLAPPED structure contains some fields that are never used. --- src/afd.c | 48 +++++++++++++++++++++++++++--------------------- src/afd.h | 4 +++- src/nt.h | 11 +++++++++++ src/port.c | 6 ++++-- src/sock.c | 25 +++++++++---------------- src/sock.h | 3 ++- 6 files changed, 56 insertions(+), 41 deletions(-) diff --git a/src/afd.c b/src/afd.c index abc3336..7373938 100644 --- a/src/afd.c +++ b/src/afd.c @@ -55,33 +55,18 @@ error: int afd_poll(HANDLE afd_helper_handle, AFD_POLL_INFO* poll_info, - OVERLAPPED* overlapped) { - IO_STATUS_BLOCK* iosb; - HANDLE event; - void* apc_context; + IO_STATUS_BLOCK* io_status_block) { NTSTATUS status; /* Blocking operation is not supported. */ - assert(overlapped != NULL); + assert(io_status_block != NULL); - iosb = (IO_STATUS_BLOCK*) &overlapped->Internal; - event = overlapped->hEvent; - - /* Do what other windows APIs would do: if hEvent has it's lowest bit set, - * don't post a completion to the completion port. */ - if ((uintptr_t) event & 1) { - event = (HANDLE)((uintptr_t) event & ~(uintptr_t) 1); - apc_context = NULL; - } else { - apc_context = overlapped; - } - - iosb->Status = STATUS_PENDING; + io_status_block->Status = STATUS_PENDING; status = NtDeviceIoControlFile(afd_helper_handle, - event, NULL, - apc_context, - iosb, + NULL, + io_status_block, + io_status_block, IOCTL_AFD_POLL, poll_info, sizeof *poll_info, @@ -95,3 +80,24 @@ int afd_poll(HANDLE afd_helper_handle, else return_set_error(-1, RtlNtStatusToDosError(status)); } + +int afd_cancel_poll(HANDLE afd_helper_handle, + IO_STATUS_BLOCK* io_status_block) { + NTSTATUS cancel_status; + IO_STATUS_BLOCK cancel_iosb; + + /* If the poll operation has already completed or has been cancelled earlier, + * there's nothing left for us to do. */ + if (io_status_block->Status != STATUS_PENDING) + return 0; + + cancel_status = + NtCancelIoFileEx(afd_helper_handle, io_status_block, &cancel_iosb); + + /* NtCancelIoFileEx() may return STATUS_NOT_FOUND if the operation completed + * just before calling NtCancelIoFileEx(). This is not an error. */ + if (cancel_status == STATUS_SUCCESS || cancel_status == STATUS_NOT_FOUND) + return 0; + else + return_set_error(-1, RtlNtStatusToDosError(cancel_status)); +} diff --git a/src/afd.h b/src/afd.h index cc49a44..844a09e 100644 --- a/src/afd.h +++ b/src/afd.h @@ -34,6 +34,8 @@ WEPOLL_INTERNAL int afd_create_helper_handle(HANDLE iocp_handle, WEPOLL_INTERNAL int afd_poll(HANDLE afd_helper_handle, AFD_POLL_INFO* poll_info, - OVERLAPPED* overlapped); + IO_STATUS_BLOCK* io_status_block); +WEPOLL_INTERNAL int afd_cancel_poll(HANDLE afd_helper_handle, + IO_STATUS_BLOCK* io_status_block); #endif /* WEPOLL_AFD_H_ */ diff --git a/src/nt.h b/src/nt.h index 07a9eb6..10a98d8 100644 --- a/src/nt.h +++ b/src/nt.h @@ -25,6 +25,10 @@ typedef NTSTATUS* PNTSTATUS; #define STATUS_CANCELLED ((NTSTATUS) 0xC0000120L) #endif +#ifndef STATUS_NOT_FOUND +#define STATUS_NOT_FOUND ((NTSTATUS) 0xC0000225L) +#endif + typedef struct _IO_STATUS_BLOCK { NTSTATUS Status; ULONG_PTR Information; @@ -65,6 +69,13 @@ typedef struct _OBJECT_ATTRIBUTES { (STANDARD_RIGHTS_REQUIRED | KEYEDEVENT_WAIT | KEYEDEVENT_WAKE) #define NT_NTDLL_IMPORT_LIST(X) \ + X(NTSTATUS, \ + NTAPI, \ + NtCancelIoFileEx, \ + (HANDLE FileHandle, \ + PIO_STATUS_BLOCK IoRequestToCancel, \ + PIO_STATUS_BLOCK IoStatusBlock)) \ + \ X(NTSTATUS, \ NTAPI, \ NtCreateFile, \ diff --git a/src/port.c b/src/port.c index c4c9241..afad1c8 100644 --- a/src/port.c +++ b/src/port.c @@ -4,6 +4,7 @@ #include #include "error.h" +#include "nt.h" #include "poll-group.h" #include "port.h" #include "queue.h" @@ -162,10 +163,11 @@ static int port__feed_events(port_state_t* port_state, DWORD i; for (i = 0; i < iocp_event_count; i++) { - OVERLAPPED* overlapped = iocp_events[i].lpOverlapped; + IO_STATUS_BLOCK* io_status_block = + (IO_STATUS_BLOCK*) iocp_events[i].lpOverlapped; struct epoll_event* ev = &epoll_events[epoll_event_count]; - epoll_event_count += sock_feed_event(port_state, overlapped, ev); + epoll_event_count += sock_feed_event(port_state, io_status_block, ev); } return epoll_event_count; diff --git a/src/sock.c b/src/sock.c index bad7d5c..e4539c3 100644 --- a/src/sock.c +++ b/src/sock.c @@ -26,7 +26,7 @@ typedef enum sock__poll_status { } sock__poll_status_t; typedef struct sock_state { - OVERLAPPED overlapped; + IO_STATUS_BLOCK io_status_block; AFD_POLL_INFO poll_info; queue_node_t queue_node; tree_node_t tree_node; @@ -51,16 +51,11 @@ static inline void sock__free(sock_state_t* sock_state) { } static int sock__cancel_poll(sock_state_t* sock_state) { - HANDLE afd_helper_handle = - poll_group_get_afd_helper_handle(sock_state->poll_group); assert(sock_state->poll_status == SOCK__POLL_PENDING); - /* CancelIoEx() may fail with ERROR_NOT_FOUND if the overlapped operation has - * already completed. This is not a problem and we proceed normally. */ - if (!HasOverlappedIoCompleted(&sock_state->overlapped) && - !CancelIoEx(afd_helper_handle, &sock_state->overlapped) && - GetLastError() != ERROR_NOT_FOUND) - return_map_error(-1); + if (afd_cancel_poll(poll_group_get_afd_helper_handle(sock_state->poll_group), + &sock_state->io_status_block) < 0) + return -1; sock_state->poll_status = SOCK__POLL_CANCELLED; sock_state->pending_events = 0; @@ -237,11 +232,9 @@ int sock_update(port_state_t* port_state, sock_state_t* sock_state) { sock_state->poll_info.Handles[0].Events = sock__epoll_events_to_afd_events(sock_state->user_events); - memset(&sock_state->overlapped, 0, sizeof sock_state->overlapped); - if (afd_poll(poll_group_get_afd_helper_handle(sock_state->poll_group), &sock_state->poll_info, - &sock_state->overlapped) < 0) { + &sock_state->io_status_block) < 0) { switch (GetLastError()) { case ERROR_IO_PENDING: /* Overlapped poll operation in progress; this is expected. */ @@ -269,10 +262,10 @@ int sock_update(port_state_t* port_state, sock_state_t* sock_state) { } int sock_feed_event(port_state_t* port_state, - OVERLAPPED* overlapped, + IO_STATUS_BLOCK* io_status_block, struct epoll_event* ev) { sock_state_t* sock_state = - container_of(overlapped, sock_state_t, overlapped); + container_of(io_status_block, sock_state_t, io_status_block); AFD_POLL_INFO* poll_info = &sock_state->poll_info; uint32_t epoll_events = 0; @@ -283,10 +276,10 @@ int sock_feed_event(port_state_t* port_state, /* Socket has been deleted earlier and can now be freed. */ return sock__delete(port_state, sock_state, false); - } else if ((NTSTATUS) overlapped->Internal == STATUS_CANCELLED) { + } else if (io_status_block->Status == STATUS_CANCELLED) { /* The poll request was cancelled by CancelIoEx. */ - } else if (!NT_SUCCESS(overlapped->Internal)) { + } else if (!NT_SUCCESS(io_status_block->Status)) { /* The overlapped request itself failed in an unexpected way. */ epoll_events = EPOLLERR; diff --git a/src/sock.h b/src/sock.h index c316ccd..e22f14e 100644 --- a/src/sock.h +++ b/src/sock.h @@ -2,6 +2,7 @@ #define WEPOLL_SOCK_H_ #include "internal.h" +#include "nt.h" #include "wepoll.h" #include "win.h" @@ -24,7 +25,7 @@ WEPOLL_INTERNAL int sock_set_event(port_state_t* port_state, WEPOLL_INTERNAL int sock_update(port_state_t* port_state, sock_state_t* sock_state); WEPOLL_INTERNAL int sock_feed_event(port_state_t* port_state, - OVERLAPPED* overlapped, + IO_STATUS_BLOCK* io_status_block, struct epoll_event* ev); WEPOLL_INTERNAL sock_state_t* sock_state_from_queue_node( From 8c98df30da51811a78b32cc387ea982311da9169 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Mon, 24 Jun 2019 17:44:56 +0200 Subject: [PATCH 11/21] gitignore: sort patterns --- .gitignore | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 303923c..e23086c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ -*_BASE_* *_BACKUP_* -*_REMOTE_* +*_BASE_* *_LOCAL_* +*_REMOTE_* *.a *.dll @@ -10,9 +10,9 @@ *.ilk *.lib *.manifest -*.pdb *.opensdf *.orig +*.pdb *.sdf *.sln *.suo @@ -43,9 +43,9 @@ /out/ /Release/ /RelWithDebInfo/ -/x64/ /Win32/ +/x64/ -/CMakeCache.txt /cmake_install.cmake +/CMakeCache.txt /Makefile From a11398b1c5a8723fdad1131b4a889cb7d189db51 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Mon, 24 Jun 2019 12:47:58 +0200 Subject: [PATCH 12/21] api: fix typo in comment --- src/api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api.c b/src/api.c index 38513c9..3c7c498 100644 --- a/src/api.c +++ b/src/api.c @@ -102,7 +102,7 @@ int epoll_ctl(HANDLE ephnd, int op, SOCKET sock, struct epoll_event* ev) { return 0; err: - /* On Linux, in the case of epoll_ctl_mod(), EBADF takes priority over other + /* On Linux, in the case of epoll_ctl(), EBADF takes priority over other * errors. Wepoll mimics this behavior. */ err_check_handle(ephnd); err_check_handle((HANDLE) sock); From d87deefada8d61a59164b4c032b04f22c8480707 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Sun, 12 Jan 2020 21:23:36 +0100 Subject: [PATCH 13/21] doc: update copyright years --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 6c8b1c8..d7fc4b1 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ wepoll - epoll for Windows https://github.com/piscisaureus/wepoll -Copyright 2012-2019, Bert Belder +Copyright 2012-2020, Bert Belder All rights reserved. Redistribution and use in source and binary forms, with or without From 8cd6e896cd517b59aef86a33bc3c14c4da04d427 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Sun, 12 Jan 2020 21:21:54 +0100 Subject: [PATCH 14/21] test: fix clang warning caused by 'static_assert' polyfill --- test/shared/test-util.h | 1 + 1 file changed, 1 insertion(+) diff --git a/test/shared/test-util.h b/test/shared/test-util.h index 0d24e15..4acb5c5 100644 --- a/test/shared/test-util.h +++ b/test/shared/test-util.h @@ -7,6 +7,7 @@ #pragma clang diagnostic ignored "-Wbad-function-cast" #pragma clang diagnostic ignored "-Wcast-qual" #pragma clang diagnostic ignored "-Wformat-non-iso" +#pragma clang diagnostic ignored "-Wkeyword-macro" #endif #ifdef _MSC_VER From c57eb84863ac0ce35fd91e1171fc010916cc886c Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Sun, 12 Jan 2020 22:55:23 +0100 Subject: [PATCH 15/21] build: work around bug in in Windows SDK 10.0.17763.0 and maybe other versions --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b082d4..8b8c5e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,9 @@ else() add_compile_options(-Wall -Wextra -Werror) endif() +# Work around bug in in Windows SDK 10.0.17763.0 and maybe other versions. +add_definitions(-D_CRT_HAS_CXX17=0) + set(DIST_DIR "dist") set(TEST_RUNNER "tools/run-tests.js") From dd7dd6fcd971d667d152eaf0b5148dff6de46703 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Mon, 24 Jun 2019 12:59:56 +0200 Subject: [PATCH 16/21] build: rename configuration 'combined' to 'bundle' --- .appveyor.yml | 2 +- CMakeLists.txt | 34 ++++++++++++++--------------- src/{combined => bundle}/internal.h | 0 3 files changed, 18 insertions(+), 18 deletions(-) rename src/{combined => bundle}/internal.h (100%) diff --git a/.appveyor.yml b/.appveyor.yml index 982490c..1d4550d 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -140,7 +140,7 @@ before_build: build_script: - cmd: cmake --build . --config "%configuration%" --target wepoll.dll - - cmd: cmake --build . --config "%configuration%" --target wepoll-combined.dll + - cmd: cmake --build . --config "%configuration%" --target wepoll-bundle.dll test_script: - cmd: cmake --build . --config "%configuration%" --target test-all diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b8c5e6..0f31cf2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ file(GLOB SOURCES_HEADER include/*.h) file(GLOB SOURCES_SRC src/*.c src/*.h) file(GLOB SOURCES_SRC_C src/*.c) file(GLOB SOURCES_SRC_REGULAR src/regular/*.c src/regular/*.h) -file(GLOB SOURCES_SRC_COMBINED src/combined/*.c src/combined/*.h) +file(GLOB SOURCES_SRC_BUNDLE src/bundle/*.c src/bundle/*.h) file(GLOB SOURCES_TEST test/*.c) file(GLOB SOURCES_TEST_SHARED test/shared/*.c test/shared/*.h) file(GLOB SOURCES_DOC LICENSE *.md) @@ -30,36 +30,36 @@ file(GLOB SOURCES_DOC LICENSE *.md) get_filename_component(HEADER_NAME ${SOURCES_HEADER} NAME_WE) string(TOUPPER ${HEADER_NAME} HEADER_NAME_UC) -set(COMBINED_HEADER "${DIST_DIR}/${HEADER_NAME}.h") -set(COMBINED_SRC "${DIST_DIR}/${HEADER_NAME}.c") +set(BUNDLE_HEADER "${DIST_DIR}/${HEADER_NAME}.h") +set(BUNDLE_SRC "${DIST_DIR}/${HEADER_NAME}.c") set(DLL_NAME "${HEADER_NAME}") -set(COMBINED_DLL_NAME "${HEADER_NAME}-combined") +set(BUNDLE_DLL_NAME "${HEADER_NAME}-bundle") set_property(GLOBAL PROPERTY USE_FOLDERS ON) source_group("" FILES ${SOURCES_HEADER}) source_group(src FILES ${SOURCES_SRC}) source_group(src FILES ${SOURCES_SRC_REGULAR}) -source_group(src FILES ${SOURCES_SRC_COMBINED}) +source_group(src FILES ${SOURCES_SRC_BUNDLE}) source_group("" FILES ${SOURCES_TEST}) source_group(test/shared FILES ${SOURCES_TEST_SHARED}) source_group(doc FILES ${SOURCES_DOC}) -source_group(${DIST_DIR} FILES ${COMBINED_HEADER} ${COMBINED_SRC}) +source_group(${DIST_DIR} FILES ${BUNDLE_HEADER} ${BUNDLE_SRC}) add_custom_command( - OUTPUT ${COMBINED_HEADER} - COMMAND node tools/combine.js ${SOURCES_HEADER} > ${COMBINED_HEADER} + OUTPUT ${BUNDLE_HEADER} + COMMAND node tools/combine.js ${SOURCES_HEADER} > ${BUNDLE_HEADER} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPLICIT_DEPENDS c ${SOURCES_HEADER} ) add_custom_command( - OUTPUT ${COMBINED_SRC} - COMMAND node tools/combine.js -Iinclude -Isrc -Isrc/combined --strip-guards ${SOURCES_HEADER} ${SOURCES_SRC_C} > ${COMBINED_SRC} + OUTPUT ${BUNDLE_SRC} + COMMAND node tools/combine.js -Iinclude -Isrc -Isrc/bundle --strip-guards ${SOURCES_HEADER} ${SOURCES_SRC_C} > ${BUNDLE_SRC} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - IMPLICIT_DEPENDS c ${SOURCES_HEADER} ${SOURCES_SRC} ${SOURCES_SRC_COMBINED} + IMPLICIT_DEPENDS c ${SOURCES_HEADER} ${SOURCES_SRC} ${SOURCES_SRC_BUNDLE} ) -add_custom_target(dist DEPENDS ${COMBINED_SRC} ${COMBINED_HEADER}) +add_custom_target(dist DEPENDS ${BUNDLE_SRC} ${BUNDLE_HEADER}) file(MAKE_DIRECTORY ${DIST_DIR}) add_custom_command( TARGET dist POST_BUILD @@ -79,14 +79,14 @@ else() endif() set_target_properties(${DLL_TARGET} PROPERTIES OUTPUT_NAME ${DLL_NAME}) -set(COMBINED_DLL_TARGET "${COMBINED_DLL_NAME}.dll") -add_library(${COMBINED_DLL_TARGET} SHARED ${COMBINED_HEADER} ${COMBINED_SRC}) +set(BUNDLE_DLL_TARGET "${BUNDLE_DLL_NAME}.dll") +add_library(${BUNDLE_DLL_TARGET} SHARED ${BUNDLE_HEADER} ${BUNDLE_SRC}) if(MSVC) - target_compile_definitions(${COMBINED_DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__declspec(dllexport)" ) + target_compile_definitions(${BUNDLE_DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__declspec(dllexport)" ) else() - target_compile_definitions(${COMBINED_DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__attribute__((visibility(\"default\")))") + target_compile_definitions(${BUNDLE_DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__attribute__((visibility(\"default\")))") endif() -set_target_properties(${COMBINED_DLL_TARGET} PROPERTIES OUTPUT_NAME ${COMBINED_DLL_NAME}) +set_target_properties(${BUNDLE_DLL_TARGET} PROPERTIES OUTPUT_NAME ${BUNDLE_DLL_NAME}) foreach(TEST_SOURCE ${SOURCES_TEST}) get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE) diff --git a/src/combined/internal.h b/src/bundle/internal.h similarity index 100% rename from src/combined/internal.h rename to src/bundle/internal.h From d272c5188d4a8e973548a916f5782cd501d29d7e Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Mon, 24 Jun 2019 13:19:08 +0200 Subject: [PATCH 17/21] tools/bundle: rename 'combine.js' to 'bundle.js' --- CMakeLists.txt | 4 ++-- tools/{combine.js => bundle.js} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename tools/{combine.js => bundle.js} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f31cf2..b1d6031 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,14 +47,14 @@ source_group(${DIST_DIR} FILES ${BUNDLE_HEADER} ${BUNDLE_SRC}) add_custom_command( OUTPUT ${BUNDLE_HEADER} - COMMAND node tools/combine.js ${SOURCES_HEADER} > ${BUNDLE_HEADER} + COMMAND node tools/bundle.js ${SOURCES_HEADER} > ${BUNDLE_HEADER} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPLICIT_DEPENDS c ${SOURCES_HEADER} ) add_custom_command( OUTPUT ${BUNDLE_SRC} - COMMAND node tools/combine.js -Iinclude -Isrc -Isrc/bundle --strip-guards ${SOURCES_HEADER} ${SOURCES_SRC_C} > ${BUNDLE_SRC} + COMMAND node tools/bundle.js -Iinclude -Isrc -Isrc/bundle --strip-guards ${SOURCES_HEADER} ${SOURCES_SRC_C} > ${BUNDLE_SRC} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} IMPLICIT_DEPENDS c ${SOURCES_HEADER} ${SOURCES_SRC} ${SOURCES_SRC_BUNDLE} ) diff --git a/tools/combine.js b/tools/bundle.js similarity index 100% rename from tools/combine.js rename to tools/bundle.js From bb6c522d8f23fc334e77f79823ce68390ad722da Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Mon, 24 Jun 2019 15:49:06 +0200 Subject: [PATCH 18/21] tools/bundle: require include guards to end with '_H_' --- tools/bundle.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/bundle.js b/tools/bundle.js index f828995..d1b76ab 100644 --- a/tools/bundle.js +++ b/tools/bundle.js @@ -44,7 +44,7 @@ function readFileWithPath(fileName, dirs) { function strip_guards(filename, source) { const lead_comments_re = /^(\s*\/\*((?!\*\/)[\s\S])*\*\/)*\s*/; const trail_comments_re = /(\s*\/\*((?!\*\/)[\s\S])*\*\/)*\s*$/; - const lead_guards_re = /^#ifndef\s+(\w+)\s+#define\s+(\w+)\s+/; + const lead_guards_re = /^#ifndef\s+(\w+_H_)\s+#define\s+(\w+_H_)\s+/; const trail_guards_re = /#endif$/; // Strip leading and trailing comments and whitespace. From 4536518f8a00bf8960547b7b5615a86f4ce1d05e Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Mon, 24 Jun 2019 15:50:17 +0200 Subject: [PATCH 19/21] tools/bundle: log files in which no include guards were found --- tools/bundle.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/bundle.js b/tools/bundle.js index d1b76ab..25e577b 100644 --- a/tools/bundle.js +++ b/tools/bundle.js @@ -57,9 +57,11 @@ function strip_guards(filename, source) { // Remove include guards, if found. if (lead_guards && trail_guards && lead_guards[1] == lead_guards[2]) { - console.error('Stripping include guards: ' + filename); + console.error('Stripping include guards from ' + filename); source = source.replace(lead_guards_re, ''); source = source.replace(trail_guards_re, ''); + } else { + console.error('No include guards found in ' + filename); } // Add back a trailing newline. From 3ad20d71ffd6828d7b3596361f56f74a2b35a281 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Sun, 12 Jan 2020 23:45:03 +0100 Subject: [PATCH 20/21] build: refactor config infrastructure and test build setup * Configuration is now done with files, instead of through command line switches specified in CMakeLists.txt. * Link tests with a static library instead of compiling individual wepoll source files as part of the test executable. This should make the CI run significantly faster. --- .gitignore | 1 + CMakeLists.txt | 173 +++++++++++++------- config/external/dllexport/config-external.h | 5 + config/external/static/config-external.h | 1 + config/internal/bundle/config-internal.h | 2 + config/internal/default/config-internal.h | 2 + include/wepoll.h | 4 +- src/afd.h | 2 +- src/api.h | 2 +- src/bundle/internal.h | 7 - src/config.h | 6 + src/error.h | 2 +- src/init.h | 2 +- src/nt.h | 2 +- src/poll-group.h | 2 +- src/port.h | 2 +- src/queue.h | 2 +- src/reflock.h | 2 +- src/regular/internal.h | 7 - src/sock.h | 2 +- src/thread-safe-tree.h | 2 +- src/tree.h | 2 +- src/ws.h | 2 +- test/shared/test-util.h | 4 +- 24 files changed, 149 insertions(+), 89 deletions(-) create mode 100644 config/external/dllexport/config-external.h create mode 100644 config/external/static/config-external.h create mode 100644 config/internal/bundle/config-internal.h create mode 100644 config/internal/default/config-internal.h delete mode 100644 src/bundle/internal.h create mode 100644 src/config.h delete mode 100644 src/regular/internal.h diff --git a/.gitignore b/.gitignore index e23086c..ef5cae9 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ /CMakeScripts/ /Debug/ /dist/ +/gen/ /ipch/ /lib/ /MinSizeRel/ diff --git a/CMakeLists.txt b/CMakeLists.txt index b1d6031..86cb6ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required(VERSION 3.0.0) project(wepoll) +include(CMakeParseArguments) + link_libraries(ws2_32) if(MSVC) @@ -15,91 +17,148 @@ endif() # Work around bug in in Windows SDK 10.0.17763.0 and maybe other versions. add_definitions(-D_CRT_HAS_CXX17=0) -set(DIST_DIR "dist") -set(TEST_RUNNER "tools/run-tests.js") - -file(GLOB SOURCES_HEADER include/*.h) +file(GLOB SOURCES_DOC LICENSE *.md) +file(GLOB_RECURSE SOURCES_CONFIG config/*.h) +file(GLOB SOURCES_CONFIG_EXTERNAL_DLLEXPORT config/external/dllexport/*.h) +file(GLOB SOURCES_CONFIG_EXTERNAL_STATIC config/external/static/*.h) +file(GLOB SOURCES_CONFIG_INTERNAL_BUNDLE config/internal/bundle/*.h) +file(GLOB SOURCES_CONFIG_INTERNAL_DEFAULT config/internal/default/*.h) +file(GLOB SOURCES_INCLUDE include/*.h) file(GLOB SOURCES_SRC src/*.c src/*.h) file(GLOB SOURCES_SRC_C src/*.c) -file(GLOB SOURCES_SRC_REGULAR src/regular/*.c src/regular/*.h) -file(GLOB SOURCES_SRC_BUNDLE src/bundle/*.c src/bundle/*.h) file(GLOB SOURCES_TEST test/*.c) file(GLOB SOURCES_TEST_SHARED test/shared/*.c test/shared/*.h) -file(GLOB SOURCES_DOC LICENSE *.md) - -get_filename_component(HEADER_NAME ${SOURCES_HEADER} NAME_WE) -string(TOUPPER ${HEADER_NAME} HEADER_NAME_UC) - -set(BUNDLE_HEADER "${DIST_DIR}/${HEADER_NAME}.h") -set(BUNDLE_SRC "${DIST_DIR}/${HEADER_NAME}.c") -set(DLL_NAME "${HEADER_NAME}") -set(BUNDLE_DLL_NAME "${HEADER_NAME}-bundle") set_property(GLOBAL PROPERTY USE_FOLDERS ON) -source_group("" FILES ${SOURCES_HEADER}) +source_group(doc FILES ${SOURCES_DOC}) +source_group(config FILES ${SOURCES_CONFIG}) +source_group(include FILES ${SOURCES_INCLUDE}) source_group(src FILES ${SOURCES_SRC}) -source_group(src FILES ${SOURCES_SRC_REGULAR}) -source_group(src FILES ${SOURCES_SRC_BUNDLE}) source_group("" FILES ${SOURCES_TEST}) source_group(test/shared FILES ${SOURCES_TEST_SHARED}) -source_group(doc FILES ${SOURCES_DOC}) -source_group(${DIST_DIR} FILES ${BUNDLE_HEADER} ${BUNDLE_SRC}) -add_custom_command( - OUTPUT ${BUNDLE_HEADER} - COMMAND node tools/bundle.js ${SOURCES_HEADER} > ${BUNDLE_HEADER} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - IMPLICIT_DEPENDS c ${SOURCES_HEADER} -) +get_filename_component(LIB_NAME ${SOURCES_INCLUDE} NAME_WE) -add_custom_command( - OUTPUT ${BUNDLE_SRC} - COMMAND node tools/bundle.js -Iinclude -Isrc -Isrc/bundle --strip-guards ${SOURCES_HEADER} ${SOURCES_SRC_C} > ${BUNDLE_SRC} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - IMPLICIT_DEPENDS c ${SOURCES_HEADER} ${SOURCES_SRC} ${SOURCES_SRC_BUNDLE} -) +set(TOOL_RUN_TESTS "tools/run-tests.js") +set(TOOL_BUNDLE "tools/bundle.js") + +set(DIST_DIR "${PROJECT_BINARY_DIR}/dist") +set(GEN_DIR "${PROJECT_BINARY_DIR}/gen") -add_custom_target(dist DEPENDS ${BUNDLE_SRC} ${BUNDLE_HEADER}) file(MAKE_DIRECTORY ${DIST_DIR}) +file(MAKE_DIRECTORY ${GEN_DIR}) + +function(bundle_header) + cmake_parse_arguments(BUNDLE "" "OUTPUT;EXTERNAL_CONFIG" "" ${ARGN}) + set(CONFIG_EXTERNAL_DIR "config/external/${BUNDLE_EXTERNAL_CONFIG}") + file(GLOB SOURCES_CONFIG_EXTERNAL "${CONFIG_EXTERNAL_DIR}/*.h") + add_custom_command( + OUTPUT ${BUNDLE_OUTPUT} + COMMAND node ${TOOL_BUNDLE} + -I${CONFIG_EXTERNAL_DIR} + ${SOURCES_INCLUDE} + > ${BUNDLE_OUTPUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${TOOL_BUNDLE} ${SOURCES_CONFIG_EXTERNAL} ${SOURCES_INCLUDE} + ) +endfunction() + +function(bundle_source) + cmake_parse_arguments(BUNDLE "" "OUTPUT;EXTERNAL_CONFIG" "" ${ARGN}) + set(CONFIG_EXTERNAL_DIR "config/external/${BUNDLE_EXTERNAL_CONFIG}") + file(GLOB SOURCES_CONFIG_EXTERNAL "${CONFIG_EXTERNAL_DIR}/*.h") + add_custom_command( + OUTPUT ${BUNDLE_OUTPUT} + COMMAND node ${TOOL_BUNDLE} --strip-guards + -I${CONFIG_EXTERNAL_DIR} -Iconfig/internal/bundle -Iinclude -Isrc + ${SOURCES_INCLUDE} ${SOURCES_SRC_C} + > ${BUNDLE_OUTPUT} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${TOOL_BUNDLE} + ${SOURCES_CONFIG_EXTERNAL} ${SOURCES_CONFIG_INTERNAL_BUNDLE} + ${SOURCES_INCLUDE} ${SOURCES_SRC} + ) +endfunction() + +set(BUNDLE_DIST_TARGET "dist") +set(BUNDLE_DIST_HEADER "${DIST_DIR}/${LIB_NAME}.h") +set(BUNDLE_DIST_SOURCE "${DIST_DIR}/${LIB_NAME}.c") +bundle_header(OUTPUT ${BUNDLE_DIST_HEADER} EXTERNAL_CONFIG static) +bundle_source(OUTPUT ${BUNDLE_DIST_SOURCE} EXTERNAL_CONFIG static) +set_source_files_properties( + ${BUNDLE_DIST_HEADER} ${BUNDLE_DIST_SOURCE} + PROPERTIES GENERATED TRUE +) +add_custom_target( + ${BUNDLE_DIST_TARGET} + DEPENDS ${BUNDLE_DIST_SOURCE} ${BUNDLE_DIST_HEADER} + SOURCES ${SOURCES_CONFIG_EXTERNAL_STATIC} ${SOURCES_CONFIG_INTERNAL_BUNDLE} + ${SOURCES_INCLUDE} ${SOURCES_SRC} ${SOURCES_DOC} +) add_custom_command( - TARGET dist POST_BUILD + TARGET ${BUNDLE_DIST_TARGET} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${SOURCES_DOC} ${DIST_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ${SOURCES_DOC} ) -set(DLL_TARGET "${HEADER_NAME}.dll") -add_library(${DLL_TARGET} SHARED ${SOURCES_HEADER} ${SOURCES_SRC} ${SOURCES_SRC_REGULAR}) -target_include_directories(${DLL_TARGET} PUBLIC include src/regular) -if(MSVC) - target_compile_definitions(${DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__declspec(dllexport)" ) -else() - target_compile_options(${DLL_TARGET} PUBLIC -fvisibility=hidden) - target_compile_definitions(${DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__attribute__((visibility(\"default\")))") -endif() -set_target_properties(${DLL_TARGET} PROPERTIES OUTPUT_NAME ${DLL_NAME}) +set(DLL_TARGET "${LIB_NAME}.dll") +add_library( + ${DLL_TARGET} SHARED + ${SOURCES_CONFIG_EXTERNAL_DLLEXPORT} ${SOURCES_CONFIG_INTERNAL_DEFAULT} + ${SOURCES_INCLUDE} ${SOURCES_SRC} +) +target_include_directories( + ${DLL_TARGET} PUBLIC + config/external/dllexport config/internal/default include src +) +set_target_properties(${DLL_TARGET} PROPERTIES OUTPUT_NAME ${DLL_TARGET}) -set(BUNDLE_DLL_TARGET "${BUNDLE_DLL_NAME}.dll") -add_library(${BUNDLE_DLL_TARGET} SHARED ${BUNDLE_HEADER} ${BUNDLE_SRC}) -if(MSVC) - target_compile_definitions(${BUNDLE_DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__declspec(dllexport)" ) -else() - target_compile_definitions(${BUNDLE_DLL_TARGET} PUBLIC "-D${HEADER_NAME_UC}_EXPORT=__attribute__((visibility(\"default\")))") -endif() -set_target_properties(${BUNDLE_DLL_TARGET} PROPERTIES OUTPUT_NAME ${BUNDLE_DLL_NAME}) +set(BUNDLE_DLL_TARGET "${LIB_NAME}-bundle.dll") +set(BUNDLE_DLL_SOURCE "${GEN_DIR}/${LIB_NAME}-bundle-dll.c") +bundle_source(OUTPUT ${BUNDLE_DLL_SOURCE} EXTERNAL_CONFIG dllexport) +set_source_files_properties(${BUNDLE_DLL_SOURCE} PROPERTIES GENERATED TRUE) +add_library( + ${BUNDLE_DLL_TARGET} SHARED + ${SOURCES_CONFIG_EXTERNAL_DLLEXPORT} ${SOURCES_CONFIG_INTERNAL_DEFAULT} + ${BUNDLE_DLL_SOURCE} +) +set_target_properties( + ${BUNDLE_DLL_TARGET} + PROPERTIES OUTPUT_NAME "${LIB_NAME}-bundle" +) + +set(TESTING_LIB_TARGET "${LIB_NAME}-testing.lib") +add_library( + ${TESTING_LIB_TARGET} STATIC + ${SOURCES_CONFIG_EXTERNAL_STATIC} ${SOURCES_CONFIG_INTERNAL_DEFAULT} + ${SOURCES_INCLUDE} ${SOURCES_SRC} ${SOURCES_TEST_SHARED} +) +target_include_directories( + ${TESTING_LIB_TARGET} PUBLIC + config/external/static config/internal/default include src +) +set_target_properties( + ${TESTING_LIB_TARGET} PROPERTIES + OUTPUT_NAME "${LIB_NAME}-testing" +) foreach(TEST_SOURCE ${SOURCES_TEST}) get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE) - add_executable(${TEST_NAME} ${TEST_SOURCE} ${SOURCES_SRC} ${SOURCES_SRC_REGULAR} ${SOURCES_TEST_SHARED}) + add_executable(${TEST_NAME} ${TEST_SOURCE}) + target_include_directories( + ${TEST_NAME} PUBLIC + config/external/static config/internal/default include src test/shared + ) + target_link_libraries(${TEST_NAME} ${TESTING_LIB_TARGET}) set_target_properties(${TEST_NAME} PROPERTIES FOLDER Tests) - target_include_directories(${TEST_NAME} PUBLIC include src src/regular test/shared) list(APPEND TEST_TARGETS ${TEST_NAME}) list(APPEND TEST_OUTPUTS $) -endforeach(TEST_SOURCE ${SOURCES_TEST}) +endforeach() add_custom_target( test-all - COMMAND node ${TEST_RUNNER} ${TEST_OUTPUTS} + COMMAND node ${TOOL_RUN_TESTS} ${TEST_OUTPUTS} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS ${TEST_RUNNER} ${TEST_TARGETS} + DEPENDS ${TOOL_RUN_TESTS} ${TEST_TARGETS} ) diff --git a/config/external/dllexport/config-external.h b/config/external/dllexport/config-external.h new file mode 100644 index 0000000..039e07a --- /dev/null +++ b/config/external/dllexport/config-external.h @@ -0,0 +1,5 @@ +#ifdef _MSC_VER +#define WEPOLL_EXPORT __declspec(dllexport) +#else /* GCC/Clang */ +#define WEPOLL_EXPORT __attribute__((dllexport)) +#endif diff --git a/config/external/static/config-external.h b/config/external/static/config-external.h new file mode 100644 index 0000000..28a7045 --- /dev/null +++ b/config/external/static/config-external.h @@ -0,0 +1 @@ +#define WEPOLL_EXPORT diff --git a/config/internal/bundle/config-internal.h b/config/internal/bundle/config-internal.h new file mode 100644 index 0000000..d14707d --- /dev/null +++ b/config/internal/bundle/config-internal.h @@ -0,0 +1,2 @@ +#define WEPOLL_INTERNAL static +#define WEPOLL_INTERNAL_VAR static diff --git a/config/internal/default/config-internal.h b/config/internal/default/config-internal.h new file mode 100644 index 0000000..8d58100 --- /dev/null +++ b/config/internal/default/config-internal.h @@ -0,0 +1,2 @@ +#define WEPOLL_INTERNAL +#define WEPOLL_INTERNAL_VAR extern diff --git a/include/wepoll.h b/include/wepoll.h index c6f12e2..416e30b 100644 --- a/include/wepoll.h +++ b/include/wepoll.h @@ -1,9 +1,7 @@ #ifndef WEPOLL_H_ #define WEPOLL_H_ -#ifndef WEPOLL_EXPORT -#define WEPOLL_EXPORT -#endif +#include "config-external.h" #include diff --git a/src/afd.h b/src/afd.h index 844a09e..93dde65 100644 --- a/src/afd.h +++ b/src/afd.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_AFD_H_ #define WEPOLL_AFD_H_ -#include "internal.h" +#include "config.h" #include "nt.h" #include "win.h" diff --git a/src/api.h b/src/api.h index a4e9540..9bda65e 100644 --- a/src/api.h +++ b/src/api.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_API_H_ #define WEPOLL_API_H_ -#include "internal.h" +#include "config.h" WEPOLL_INTERNAL int epoll_global_init(void); diff --git a/src/bundle/internal.h b/src/bundle/internal.h deleted file mode 100644 index 7d36eff..0000000 --- a/src/bundle/internal.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef WEPOLL_INTERNAL_H_ -#define WEPOLL_INTERNAL_H_ - -#define WEPOLL_INTERNAL static -#define WEPOLL_INTERNAL_VAR static - -#endif /* WEPOLL_INTERNAL_H_ */ diff --git a/src/config.h b/src/config.h new file mode 100644 index 0000000..c469e5c --- /dev/null +++ b/src/config.h @@ -0,0 +1,6 @@ +#ifndef WEPOLL_CONFIG_H_ +#define WEPOLL_CONFIG_H_ + +#include "config-internal.h" + +#endif /* WEPOLL_CONFIG_H_ */ diff --git a/src/error.h b/src/error.h index 6efc258..3d4f9d6 100644 --- a/src/error.h +++ b/src/error.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_ERROR_H_ #define WEPOLL_ERROR_H_ -#include "internal.h" +#include "config.h" #include "win.h" #define return_map_error(value) \ diff --git a/src/init.h b/src/init.h index ae7a050..1278489 100644 --- a/src/init.h +++ b/src/init.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_INIT_H_ #define WEPOLL_INIT_H_ -#include "internal.h" +#include "config.h" WEPOLL_INTERNAL int init(void); diff --git a/src/nt.h b/src/nt.h index 10a98d8..8c31882 100644 --- a/src/nt.h +++ b/src/nt.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_NT_H_ #define WEPOLL_NT_H_ -#include "internal.h" +#include "config.h" #include "win.h" WEPOLL_INTERNAL int nt_global_init(void); diff --git a/src/poll-group.h b/src/poll-group.h index 2dd100d..9aa97f8 100644 --- a/src/poll-group.h +++ b/src/poll-group.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_POLL_GROUP_H_ #define WEPOLL_POLL_GROUP_H_ -#include "internal.h" +#include "config.h" #include "win.h" typedef struct poll_group poll_group_t; diff --git a/src/port.h b/src/port.h index bedfaf3..93f45d8 100644 --- a/src/port.h +++ b/src/port.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_PORT_H_ #define WEPOLL_PORT_H_ -#include "internal.h" +#include "config.h" #include "wepoll.h" #include "win.h" diff --git a/src/queue.h b/src/queue.h index 49a603d..dc7aad9 100644 --- a/src/queue.h +++ b/src/queue.h @@ -3,7 +3,7 @@ #include -#include "internal.h" +#include "config.h" typedef struct queue_node queue_node_t; diff --git a/src/reflock.h b/src/reflock.h index c4525ca..155eb7c 100644 --- a/src/reflock.h +++ b/src/reflock.h @@ -19,7 +19,7 @@ * should use another lock to guarantee that this can't happen. */ -#include "internal.h" +#include "config.h" typedef struct reflock { volatile long state; /* 32-bit Interlocked APIs operate on `long` values. */ diff --git a/src/regular/internal.h b/src/regular/internal.h deleted file mode 100644 index 95d51b6..0000000 --- a/src/regular/internal.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef WEPOLL_INTERNAL_H_ -#define WEPOLL_INTERNAL_H_ - -#define WEPOLL_INTERNAL -#define WEPOLL_INTERNAL_VAR extern - -#endif /* WEPOLL_INTERNAL_H_ */ diff --git a/src/sock.h b/src/sock.h index e22f14e..f55f5f4 100644 --- a/src/sock.h +++ b/src/sock.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_SOCK_H_ #define WEPOLL_SOCK_H_ -#include "internal.h" +#include "config.h" #include "nt.h" #include "wepoll.h" #include "win.h" diff --git a/src/thread-safe-tree.h b/src/thread-safe-tree.h index 8b4235d..41f3222 100644 --- a/src/thread-safe-tree.h +++ b/src/thread-safe-tree.h @@ -3,7 +3,7 @@ #include -#include "internal.h" +#include "config.h" #include "reflock.h" #include "tree.h" #include "win.h" diff --git a/src/tree.h b/src/tree.h index 1e01257..95f42f7 100644 --- a/src/tree.h +++ b/src/tree.h @@ -4,7 +4,7 @@ #include #include -#include "internal.h" +#include "config.h" /* N.b.: the tree functions do not set errno or LastError when they fail. Each * of the API functions has at most one failure mode. It is up to the caller to diff --git a/src/ws.h b/src/ws.h index 34ce5bb..6fd1fa0 100644 --- a/src/ws.h +++ b/src/ws.h @@ -1,7 +1,7 @@ #ifndef WEPOLL_WS_H_ #define WEPOLL_WS_H_ -#include "internal.h" +#include "config.h" #include "win.h" WEPOLL_INTERNAL int ws_global_init(void); diff --git a/test/shared/test-util.h b/test/shared/test-util.h index 4acb5c5..1859483 100644 --- a/test/shared/test-util.h +++ b/test/shared/test-util.h @@ -12,13 +12,13 @@ #ifdef _MSC_VER #define no_return __declspec(noreturn) -#else /* GCC/clang */ +#else /* GCC/Clang */ #define no_return __attribute__((noreturn)) #endif #ifdef _MSC_VER #define no_inline __declspec(noinline) -#else /* GCC/clang */ +#else /* GCC/Clang */ #define no_inline __attribute__((noinline)) #endif From efa35adbc59492ab79afaa1d6038d172ab88d2f7 Mon Sep 17 00:00:00 2001 From: Bert Belder Date: Mon, 13 Jan 2020 00:15:16 +0100 Subject: [PATCH 21/21] tree: rename 'FIXUP' macros to 'REBALANCE' --- src/tree.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/tree.c b/src/tree.c index b6750a3..ffabe50 100644 --- a/src/tree.c +++ b/src/tree.c @@ -51,23 +51,23 @@ static inline void tree__rotate_right(tree_t* tree, tree_node_t* node) { break; \ } -#define TREE__FIXUP_AFTER_INSERT(cis, trans) \ - tree_node_t* grandparent = parent->parent; \ - tree_node_t* uncle = grandparent->trans; \ - \ - if (uncle && uncle->red) { \ - parent->red = uncle->red = false; \ - grandparent->red = true; \ - node = grandparent; \ - } else { \ - if (node == parent->trans) { \ - tree__rotate_##cis(tree, parent); \ - node = parent; \ - parent = node->parent; \ - } \ - parent->red = false; \ - grandparent->red = true; \ - tree__rotate_##trans(tree, grandparent); \ +#define TREE__REBALANCE_AFTER_INSERT(cis, trans) \ + tree_node_t* grandparent = parent->parent; \ + tree_node_t* uncle = grandparent->trans; \ + \ + if (uncle && uncle->red) { \ + parent->red = uncle->red = false; \ + grandparent->red = true; \ + node = grandparent; \ + } else { \ + if (node == parent->trans) { \ + tree__rotate_##cis(tree, parent); \ + node = parent; \ + parent = node->parent; \ + } \ + parent->red = false; \ + grandparent->red = true; \ + tree__rotate_##trans(tree, grandparent); \ } int tree_add(tree_t* tree, tree_node_t* node, uintptr_t key) { @@ -95,9 +95,9 @@ int tree_add(tree_t* tree, tree_node_t* node, uintptr_t key) { for (; parent && parent->red; parent = node->parent) { if (parent == parent->parent->left) { - TREE__FIXUP_AFTER_INSERT(left, right) + TREE__REBALANCE_AFTER_INSERT(left, right) } else { - TREE__FIXUP_AFTER_INSERT(right, left) + TREE__REBALANCE_AFTER_INSERT(right, left) } } tree->root->red = false; @@ -105,7 +105,7 @@ int tree_add(tree_t* tree, tree_node_t* node, uintptr_t key) { return 0; } -#define TREE__FIXUP_AFTER_REMOVE(cis, trans) \ +#define TREE__REBALANCE_AFTER_REMOVE(cis, trans) \ tree_node_t* sibling = parent->trans; \ \ if (sibling->red) { \ @@ -191,9 +191,9 @@ void tree_del(tree_t* tree, tree_node_t* node) { if (node == tree->root) break; if (node == parent->left) { - TREE__FIXUP_AFTER_REMOVE(left, right) + TREE__REBALANCE_AFTER_REMOVE(left, right) } else { - TREE__FIXUP_AFTER_REMOVE(right, left) + TREE__REBALANCE_AFTER_REMOVE(right, left) } node = parent; parent = parent->parent;