From b1d020279b4027a797231ae05f0b1b8f5cfd755d Mon Sep 17 00:00:00 2001 From: Dmitriy Musatkin <63878209+DmitriyMusatkin@users.noreply.github.com> Date: Mon, 2 Dec 2024 14:24:32 -0800 Subject: [PATCH 1/6] Switch CI to use roles (#698) --- .github/workflows/ci.yml | 188 +++++++++++++++++++++--------- .github/workflows/proof-alarm.yml | 4 +- 2 files changed, 133 insertions(+), 59 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9774c160..b89f046ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,19 +6,21 @@ on: - 'main' env: - BUILDER_VERSION: v0.9.62 + BUILDER_VERSION: v0.9.72 BUILDER_SOURCE: releases BUILDER_HOST: https://d19elf31gohf1l.cloudfront.net PACKAGE_NAME: aws-c-io LINUX_BASE_IMAGE: ubuntu-18-x64 RUN: ${{ github.run_id }}-${{ github.run_number }} - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - AWS_REGION: us-east-1 + CRT_CI_ROLE: ${{ secrets.CRT_CI_ROLE_ARN }} + AWS_DEFAULT_REGION: us-east-1 + +permissions: + id-token: write # This is required for requesting the JWT jobs: linux-compat: - runs-on: ubuntu-22.04 # latest + runs-on: ubuntu-24.04 # latest strategy: fail-fast: false matrix: @@ -32,22 +34,30 @@ jobs: - rhel8-x64 - al2-x64 steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} run: | aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ matrix.image }} build -p ${{ env.PACKAGE_NAME }} linux-byo-crypto: - runs-on: ubuntu-22.04 # latest + runs-on: ubuntu-24.04 # latest steps: - # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} + # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-al2-x64 build -p ${{ env.PACKAGE_NAME }} --cmake-extra=-DBYO_CRYPTO=ON linux-compiler-compat: - runs-on: ubuntu-22.04 # latest + runs-on: ubuntu-24.04 # latest strategy: matrix: compiler: @@ -57,13 +67,21 @@ jobs: - clang-9 - clang-10 - clang-11 + - clang-15 + - clang-17 - gcc-4.8 - gcc-5 - gcc-6 - gcc-7 - gcc-8 + - gcc-11 + # - gcc-13 TODO: figure out why its not passing steps: - # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} + # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages - name: Build ${{ env.PACKAGE_NAME }} run: | aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh @@ -72,28 +90,40 @@ jobs: linux-debug: runs-on: ubuntu-24.04 # latest steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} run: | aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --config Debug clang-sanitizers: - runs-on: ubuntu-22.04 # latest + runs-on: ubuntu-24.04 # latest strategy: fail-fast: false matrix: sanitizers: [",thread", ",address,undefined"] steps: - # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages - - name: Build ${{ env.PACKAGE_NAME }} - run: | - aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh - ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --compiler=clang-11 --cmake-extra=-DENABLE_SANITIZERS=ON --cmake-extra=-DSANITIZERS="${{ matrix.sanitizers }}" + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} + # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages + - name: Build ${{ env.PACKAGE_NAME }} + run: | + aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh + ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build -p ${{ env.PACKAGE_NAME }} --compiler=clang-11 --cmake-extra=-DENABLE_SANITIZERS=ON --cmake-extra=-DSANITIZERS="${{ matrix.sanitizers }}" linux-shared-libs: - runs-on: ubuntu-22.04 # latest + runs-on: ubuntu-24.04 # latest steps: - # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} + # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages - name: Build ${{ env.PACKAGE_NAME }} run: | aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh @@ -102,17 +132,25 @@ jobs: # Test downstream repos. # This should not be required because we can run into a chicken and egg problem if there is a change that needs some fix in a downstream repo. downstream: - runs-on: ubuntu-22.04 # latest + runs-on: ubuntu-24.04 # latest steps: - # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages - - name: Build ${{ env.PACKAGE_NAME }} - run: | - aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh - ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build downstream -p ${{ env.PACKAGE_NAME }} + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} + # We can't use the `uses: docker://image` version yet, GitHub lacks authentication for actions -> packages + - name: Build ${{ env.PACKAGE_NAME }} + run: | + aws s3 cp s3://aws-crt-test-stuff/ci/${{ env.BUILDER_VERSION }}/linux-container-ci.sh ./linux-container-ci.sh && chmod a+x ./linux-container-ci.sh + ./linux-container-ci.sh ${{ env.BUILDER_VERSION }} aws-crt-${{ env.LINUX_BASE_IMAGE }} build downstream -p ${{ env.PACKAGE_NAME }} windows: runs-on: windows-2022 # latest steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" @@ -121,6 +159,10 @@ jobs: windows-debug: runs-on: windows-2022 # latest steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" @@ -132,6 +174,10 @@ jobs: matrix: arch: [x86, x64] steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" @@ -140,6 +186,10 @@ jobs: windows-shared-libs: runs-on: windows-2022 # latest steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" @@ -148,6 +198,10 @@ jobs: windows-app-verifier: runs-on: windows-2022 # latest steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | python -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder.pyz')" @@ -159,6 +213,10 @@ jobs: macos: runs-on: macos-14 # latest steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" @@ -168,6 +226,10 @@ jobs: macos-x64: runs-on: macos-14-large # latest steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" @@ -177,6 +239,10 @@ jobs: macos-debug: runs-on: macos-14 # latest steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} - name: Build ${{ env.PACKAGE_NAME }} + consumers run: | python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" @@ -184,39 +250,47 @@ jobs: ./builder build -p ${{ env.PACKAGE_NAME }} --config Debug freebsd: - runs-on: ubuntu-22.04 # latest - steps: - - uses: actions/checkout@v4 - - name: Build ${{ env.PACKAGE_NAME }} + consumers - id: test - uses: cross-platform-actions/action@v0.23.0 - with: - operating_system: freebsd - architecture: x86-64 - version: '14.0' - cpu_count: 4 - shell: bash - run: | - sudo pkg install -y python3 net/py-urllib3 - python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" - chmod a+x builder - ./builder build -p ${{ env.PACKAGE_NAME }} + runs-on: ubuntu-24.04 # latest + steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} + - uses: actions/checkout@v4 + - name: Build ${{ env.PACKAGE_NAME }} + consumers + id: test + uses: cross-platform-actions/action@v0.23.0 + with: + operating_system: freebsd + architecture: x86-64 + version: '14.0' + cpu_count: 4 + shell: bash + run: | + sudo pkg install -y python3 net/py-urllib3 + python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" + chmod a+x builder + ./builder build -p ${{ env.PACKAGE_NAME }} openbsd: - runs-on: ubuntu-22.04 # latest - steps: - - uses: actions/checkout@v4 - - name: Build ${{ env.PACKAGE_NAME }} + consumers - id: test - uses: cross-platform-actions/action@v0.23.0 - with: - operating_system: openbsd - architecture: x86-64 - version: '7.4' - cpu_count: 4 - shell: bash - run: | - sudo pkg_add py3-urllib3 - python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" - chmod a+x builder - ./builder build -p ${{ env.PACKAGE_NAME }} + runs-on: ubuntu-24.04 # latest + steps: + - uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ env.CRT_CI_ROLE }} + aws-region: ${{ env.AWS_DEFAULT_REGION }} + - uses: actions/checkout@v4 + - name: Build ${{ env.PACKAGE_NAME }} + consumers + id: test + uses: cross-platform-actions/action@v0.23.0 + with: + operating_system: openbsd + architecture: x86-64 + version: '7.4' + cpu_count: 4 + shell: bash + run: | + sudo pkg_add py3-urllib3 + python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" + chmod a+x builder + ./builder build -p ${{ env.PACKAGE_NAME }} diff --git a/.github/workflows/proof-alarm.yml b/.github/workflows/proof-alarm.yml index 4e33d77f7..50e94db77 100644 --- a/.github/workflows/proof-alarm.yml +++ b/.github/workflows/proof-alarm.yml @@ -7,11 +7,11 @@ on: [push] jobs: check-for-changes: - runs-on: ubuntu-20.04 # latest + runs-on: ubuntu-24.04 # latest steps: - name: Checkout Sources - uses: actions/checkout@v1 + uses: actions/checkout@v4 - name: Check run: | From 85bf6cefb2b536d0a3423ec920bbbd06178afada Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 3 Dec 2024 09:22:07 -0800 Subject: [PATCH 2/6] move aws_io_handle --- include/aws/io/io.h | 14 -------------- include/aws/io/private/event_loop_impl.h | 14 ++++++++++++++ include/aws/io/socket.h | 1 + 3 files changed, 15 insertions(+), 14 deletions(-) diff --git a/include/aws/io/io.h b/include/aws/io/io.h index a9cc2618b..097e79a78 100644 --- a/include/aws/io/io.h +++ b/include/aws/io/io.h @@ -16,20 +16,6 @@ AWS_PUSH_SANE_WARNING_LEVEL struct aws_io_handle; -typedef void aws_io_set_queue_on_handle_fn(struct aws_io_handle *handle, void *queue); -typedef void aws_io_clear_queue_on_handle_fn(struct aws_io_handle *handle); - -struct aws_io_handle { - union { - int fd; - /* on Apple systems, handle is of type nw_connection_t. On Windows, it's a SOCKET handle. */ - void *handle; - } data; - void *additional_data; - aws_io_set_queue_on_handle_fn *set_queue; - aws_io_clear_queue_on_handle_fn *clear_queue; -}; - enum aws_io_message_type { AWS_IO_MESSAGE_APPLICATION_DATA, }; diff --git a/include/aws/io/private/event_loop_impl.h b/include/aws/io/private/event_loop_impl.h index 0a855d757..9001dc738 100644 --- a/include/aws/io/private/event_loop_impl.h +++ b/include/aws/io/private/event_loop_impl.h @@ -18,6 +18,20 @@ AWS_PUSH_SANE_WARNING_LEVEL struct aws_event_loop; struct aws_overlapped; +typedef void aws_io_set_queue_on_handle_fn(struct aws_io_handle *handle, void *queue); +typedef void aws_io_clear_queue_on_handle_fn(struct aws_io_handle *handle); + +struct aws_io_handle { + union { + int fd; + /* on Apple systems, handle is of type nw_connection_t. On Windows, it's a SOCKET handle. */ + void *handle; + } data; + void *additional_data; + aws_io_set_queue_on_handle_fn *set_queue; + aws_io_clear_queue_on_handle_fn *clear_queue; +}; + typedef void(aws_event_loop_on_completion_fn)( struct aws_event_loop *event_loop, struct aws_overlapped *overlapped, diff --git a/include/aws/io/socket.h b/include/aws/io/socket.h index 3506f7f1b..2442f0c06 100644 --- a/include/aws/io/socket.h +++ b/include/aws/io/socket.h @@ -8,6 +8,7 @@ #include #include #include +#include AWS_PUSH_SANE_WARNING_LEVEL From ef012d349ca04b3144d363d9d0952fb46d283cde Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 3 Dec 2024 11:11:47 -0800 Subject: [PATCH 3/6] schedule service entry on dispatch queue resume --- source/darwin/dispatch_queue_event_loop.c | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/source/darwin/dispatch_queue_event_loop.c b/source/darwin/dispatch_queue_event_loop.c index 7b4671316..25c44e05f 100644 --- a/source/darwin/dispatch_queue_event_loop.c +++ b/source/darwin/dispatch_queue_event_loop.c @@ -48,6 +48,35 @@ static struct aws_event_loop_vtable s_vtable = { .is_on_callers_thread = s_is_on_callers_thread, }; +/** + * DISPATCH QUEUE + * + * Event loop is responsible for processing events and tasks by launching an execution loop on a single thread. Each + * iteration of this loop performs three primary jobs: + * 1. Process I/O events. + * 2. Process cross-thread tasks. + * 3. Execute all runnable tasks. + * + * Apple Dispatch queues are FIFO queues to which the application can submit tasks in the form of block objects, and the + * block objects will be executed on a system defined thread pool. Instead of executing the loop on a single thread, we + * tried to recurrently run a single iteration of the execution loop as a dispatch queue block object. + * aws-c-io library use a sequential dispatch queue to make sure the tasks scheduled on the same dispatch queue are + * executed in a strict execution order, though the tasks might be distributed on different threads in the thread pool. + * + * Data Structures ****** + * `dispatch_loop_context`: Context for each execution iteration + * `scheduled_service_entry`: Each entry maps to each iteration we scheduled on system dispatch queue. As we lost + * control of the submitted block on the system dispatch queue, the entry is what we used to track the context and user + * data. + * `dispatch_loop`: Implementation of the event loop for dispatch queue. + * + * Functions ************ + * `s_run_iteration`: The function execute on each single iteration + * `begin_iteration`: Decide if we should run the iteration + * `end_iteration`: Clean up the related resource and decide if we should schedule next iteration + * + */ + /* Internal ref-counted dispatch loop context to processing Apple Dispatch Queue Resources */ struct dispatch_loop_context { struct aws_mutex lock; @@ -288,6 +317,7 @@ static int s_run(struct aws_event_loop *event_loop) { AWS_LOGF_INFO(AWS_LS_IO_EVENT_LOOP, "id=%p: Starting event-loop thread.", (void *)event_loop); dispatch_resume(dispatch_loop->dispatch_queue); dispatch_loop->synced_task_data.suspended = false; + s_try_schedule_new_iteration(dispatch_loop->synced_task_data.context, 0) } aws_mutex_unlock(&dispatch_loop->synced_task_data.context->lock); From 31a9a95b06d6403d6890bbeca67214dc570aaa11 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Wed, 4 Dec 2024 12:50:46 -0800 Subject: [PATCH 4/6] update cr --- include/aws/io/socket.h | 3 --- source/event_loop.c | 10 +++++----- source/socket.c | 19 +++++++++---------- source/windows/iocp/socket.c | 4 ++-- 4 files changed, 16 insertions(+), 20 deletions(-) diff --git a/include/aws/io/socket.h b/include/aws/io/socket.h index 3506f7f1b..d4e38afb8 100644 --- a/include/aws/io/socket.h +++ b/include/aws/io/socket.h @@ -6,7 +6,6 @@ */ #include -#include #include AWS_PUSH_SANE_WARNING_LEVEL @@ -138,8 +137,6 @@ struct aws_socket_endpoint { uint32_t port; }; -struct aws_socket; - struct aws_socket { struct aws_socket_vtable *vtable; struct aws_allocator *allocator; diff --git a/source/event_loop.c b/source/event_loop.c index 946fcd9a8..d10c5fe78 100644 --- a/source/event_loop.c +++ b/source/event_loop.c @@ -656,30 +656,30 @@ static int aws_event_loop_type_validate_platform(enum aws_event_loop_type type) switch (type) { case AWS_EVENT_LOOP_EPOLL: #ifndef AWS_ENABLE_EPOLL - AWS_LOGF_DEBUG(AWS_LS_IO_EVENT_LOOP, "Event loop type EPOLL is not supported on the platform."); + AWS_LOGF_ERROR(AWS_LS_IO_EVENT_LOOP, "Event loop type EPOLL is not supported on the platform."); return aws_raise_error(AWS_ERROR_PLATFORM_NOT_SUPPORTED); #endif // AWS_ENABLE_EPOLL break; case AWS_EVENT_LOOP_IOCP: #ifndef AWS_ENABLE_IO_COMPLETION_PORTS - AWS_LOGF_DEBUG(AWS_LS_IO_EVENT_LOOP, "Event loop type IOCP is not supported on the platform."); + AWS_LOGF_ERROR(AWS_LS_IO_EVENT_LOOP, "Event loop type IOCP is not supported on the platform."); return aws_raise_error(AWS_ERROR_PLATFORM_NOT_SUPPORTED); #endif // AWS_ENABLE_IO_COMPLETION_PORTS break; case AWS_EVENT_LOOP_KQUEUE: #ifndef AWS_ENABLE_KQUEUE - AWS_LOGF_DEBUG(AWS_LS_IO_EVENT_LOOP, "Event loop type KQUEUE is not supported on the platform."); + AWS_LOGF_ERROR(AWS_LS_IO_EVENT_LOOP, "Event loop type KQUEUE is not supported on the platform."); return aws_raise_error(AWS_ERROR_PLATFORM_NOT_SUPPORTED); #endif // AWS_ENABLE_KQUEUE break; case AWS_EVENT_LOOP_DISPATCH_QUEUE: #ifndef AWS_ENABLE_DISPATCH_QUEUE - AWS_LOGF_DEBUG(AWS_LS_IO_EVENT_LOOP, "Event loop type Dispatch Queue is not supported on the platform."); + AWS_LOGF_ERROR(AWS_LS_IO_EVENT_LOOP, "Event loop type Dispatch Queue is not supported on the platform."); return aws_raise_error(AWS_ERROR_PLATFORM_NOT_SUPPORTED); #endif // AWS_ENABLE_DISPATCH_QUEUE break; default: - AWS_LOGF_DEBUG(AWS_LS_IO_EVENT_LOOP, "Invalid event loop type."); + AWS_LOGF_ERROR(AWS_LS_IO_EVENT_LOOP, "Invalid event loop type."); return aws_raise_error(AWS_ERROR_UNSUPPORTED_OPERATION); break; } diff --git a/source/socket.c b/source/socket.c index 4eda7d002..88e085677 100644 --- a/source/socket.c +++ b/source/socket.c @@ -110,26 +110,25 @@ bool aws_socket_is_open(struct aws_socket *socket) { * function failed to retrieve the default type value. */ static enum aws_socket_impl_type aws_socket_get_default_impl_type(void) { - enum aws_socket_impl_type type = AWS_SOCKET_IMPL_PLATFORM_DEFAULT; // override default socket #ifdef AWS_USE_APPLE_NETWORK_FRAMEWORK - type = AWS_SOCKET_IMPL_APPLE_NETWORK_FRAMEWORK; -#endif // AWS_USE_APPLE_NETWORK_FRAMEWORK - if (type != AWS_SOCKET_IMPL_PLATFORM_DEFAULT) { - return type; - } + return AWS_SOCKET_IMPL_APPLE_NETWORK_FRAMEWORK; +#else // ! AWS_USE_APPLE_NETWORK_FRAMEWORK /** * Ideally we should use the platform definition (e.x.: AWS_OS_APPLE) here, however the platform * definition was declared in aws-c-common. We probably do not want to introduce extra dependency here. */ -#if defined(AWS_ENABLE_KQUEUE) || defined(AWS_ENABLE_EPOLL) +# if defined(AWS_ENABLE_KQUEUE) || defined(AWS_ENABLE_EPOLL) return AWS_SOCKET_IMPL_POSIX; -#elif AWS_ENABLE_DISPATCH_QUEUE +# elif defined(AWS_ENABLE_DISPATCH_QUEUE) return AWS_SOCKET_IMPL_APPLE_NETWORK_FRAMEWORK; -#elif AWS_ENABLE_IO_COMPLETION_PORTS +# elif defined(AWS_ENABLE_IO_COMPLETION_PORTS) return AWS_SOCKET_IMPL_WINSOCK; -#else +# else + AWS_FATAL_ASSERT( + true && "Invalid default socket impl type. Please check make sure the library is compiled the correct "); return AWS_SOCKET_IMPL_PLATFORM_DEFAULT; +# endif #endif } diff --git a/source/windows/iocp/socket.c b/source/windows/iocp/socket.c index b2d8ad16a..d672719c8 100644 --- a/source/windows/iocp/socket.c +++ b/source/windows/iocp/socket.c @@ -398,8 +398,8 @@ static int s_socket_init( struct aws_allocator *alloc, const struct aws_socket_options *options, bool create_underlying_socket) { - AWS_ASSERT(options->domain <= AWS_SOCKET_LOCAL); - AWS_ASSERT(options->type <= AWS_SOCKET_DGRAM); + AWS_FATAL_ASSERT(options->domain <= AWS_SOCKET_LOCAL); + AWS_FATAL_ASSERT(options->type <= AWS_SOCKET_DGRAM); AWS_ZERO_STRUCT(*socket); struct iocp_socket *impl = aws_mem_calloc(alloc, 1, sizeof(struct iocp_socket)); From 7cdd319dbb6f5db543b7e84fcd8ec107bccae5ae Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Thu, 5 Dec 2024 09:13:16 -0800 Subject: [PATCH 5/6] WIP code review update --- source/darwin/dispatch_queue.h | 4 --- source/darwin/dispatch_queue_event_loop.c | 36 +++++++++++++++-------- source/event_loop.c | 1 + 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/source/darwin/dispatch_queue.h b/source/darwin/dispatch_queue.h index 6b0b68f31..cfc6b0a9e 100644 --- a/source/darwin/dispatch_queue.h +++ b/source/darwin/dispatch_queue.h @@ -47,9 +47,6 @@ struct dispatch_loop { struct aws_linked_list local_cross_thread_tasks; struct aws_event_loop *base_loop; - /* Apple dispatch queue uses the id string to identify the dispatch queue */ - struct aws_string *dispatch_queue_id; - /* Synced data handle cross thread tasks and events, and event loop operations*/ struct { struct aws_linked_list cross_thread_tasks; @@ -62,7 +59,6 @@ struct dispatch_loop { * aws_event_loop *event_loop)` for details. */ struct { - struct aws_mutex thread_data_lock; bool is_executing; aws_thread_id_t current_thread_id; diff --git a/source/darwin/dispatch_queue_event_loop.c b/source/darwin/dispatch_queue_event_loop.c index 25c44e05f..5081378e2 100644 --- a/source/darwin/dispatch_queue_event_loop.c +++ b/source/darwin/dispatch_queue_event_loop.c @@ -93,6 +93,14 @@ struct scheduled_service_entry { struct dispatch_loop_context *dispatch_queue_context; }; +static void s_acquire_dispatch_loop_context(struct dispatch_loop_context *contxt){ + aws_ref_count_acquire(&contxt->ref_count); +} + +static void s_release_dispatch_loop_context(struct dispatch_loop_context *contxt){ + aws_ref_count_release(&contxt->ref_count); +} + static struct scheduled_service_entry *s_scheduled_service_entry_new( struct dispatch_loop_context *context, uint64_t timestamp) { @@ -102,7 +110,7 @@ static struct scheduled_service_entry *s_scheduled_service_entry_new( entry->allocator = context->allocator; entry->timestamp = timestamp; entry->dispatch_queue_context = context; - aws_ref_count_acquire(&context->ref_count); + s_acquire_dispatch_loop_context(context); return entry; } @@ -112,7 +120,7 @@ static void s_scheduled_service_entry_destroy(struct scheduled_service_entry *en aws_linked_list_remove(&entry->node); } struct dispatch_loop_context *dispatch_queue_context = entry->dispatch_queue_context; - aws_ref_count_release(&dispatch_queue_context->ref_count); + s_release_dispatch_loop_context(dispatch_queue_context); aws_mem_release(entry->allocator, entry); } @@ -150,9 +158,8 @@ static void s_dispatch_event_loop_destroy(void *context) { aws_mutex_lock(&dispatch_loop->synced_task_data.context->lock); dispatch_loop->synced_task_data.context->io_dispatch_loop = NULL; aws_mutex_unlock(&dispatch_loop->synced_task_data.context->lock); - aws_ref_count_release(&dispatch_loop->synced_task_data.context->ref_count); + s_release_dispatch_loop_context(dispatch_loop->synced_task_data.context); - aws_string_destroy(dispatch_loop->dispatch_queue_id); aws_mem_release(dispatch_loop->allocator, dispatch_loop); aws_event_loop_clean_up_base(event_loop); aws_mem_release(event_loop->alloc, event_loop); @@ -191,6 +198,7 @@ struct aws_event_loop *aws_event_loop_new_with_dispatch_queue( struct aws_event_loop *loop = aws_mem_calloc(alloc, 1, sizeof(struct aws_event_loop)); struct dispatch_loop *dispatch_loop = NULL; + dispatch_loop->allocator = alloc; AWS_LOGF_DEBUG(AWS_LS_IO_EVENT_LOOP, "id=%p: Initializing dispatch_queue event-loop", (void *)loop); if (aws_event_loop_init_base(loop, alloc, options->clock)) { @@ -199,23 +207,27 @@ struct aws_event_loop *aws_event_loop_new_with_dispatch_queue( dispatch_loop = aws_mem_calloc(alloc, 1, sizeof(struct dispatch_loop)); - dispatch_loop->dispatch_queue_id = s_get_unique_dispatch_queue_id(alloc); + struct aws_string *dispatch_queue_id = s_get_unique_dispatch_queue_id(alloc); - dispatch_loop->dispatch_queue = - dispatch_queue_create((char *)dispatch_loop->dispatch_queue_id->bytes, DISPATCH_QUEUE_SERIAL); + dispatch_loop->dispatch_queue = dispatch_queue_create((char *)dispatch_queue_id->bytes, DISPATCH_QUEUE_SERIAL); if (!dispatch_loop->dispatch_queue) { AWS_LOGF_FATAL(AWS_LS_IO_EVENT_LOOP, "id=%p: Failed to create dispatch queue.", (void *)loop); aws_raise_error(AWS_ERROR_SYS_CALL_FAILURE); goto clean_up; } + AWS_LOGF_INFO( + AWS_LS_IO_EVENT_LOOP, + "id=%p: Apple dispatch queue created with id:" PRInSTR, + (void *)loop, + AWS_BYTE_CURSOR_PRI(aws_byte_cursor_from_string(dispatch_queue_id))); + int err = aws_task_scheduler_init(&dispatch_loop->scheduler, alloc); if (err) { AWS_LOGF_ERROR(AWS_LS_IO_EVENT_LOOP, "id=%p: Initializing task scheduler failed", (void *)loop); goto clean_up; } - dispatch_loop->allocator = alloc; dispatch_loop->base_loop = loop; aws_linked_list_init(&dispatch_loop->local_cross_thread_tasks); @@ -309,6 +321,8 @@ static int s_wait_for_stop_completion(struct aws_event_loop *event_loop) { return AWS_OP_SUCCESS; } +static void s_try_schedule_new_iteration(struct dispatch_loop_context *loop, uint64_t timestamp); + static int s_run(struct aws_event_loop *event_loop) { struct dispatch_loop *dispatch_loop = event_loop->impl_data; @@ -317,7 +331,7 @@ static int s_run(struct aws_event_loop *event_loop) { AWS_LOGF_INFO(AWS_LS_IO_EVENT_LOOP, "id=%p: Starting event-loop thread.", (void *)event_loop); dispatch_resume(dispatch_loop->dispatch_queue); dispatch_loop->synced_task_data.suspended = false; - s_try_schedule_new_iteration(dispatch_loop->synced_task_data.context, 0) + s_try_schedule_new_iteration(dispatch_loop->synced_task_data.context, 0); } aws_mutex_unlock(&dispatch_loop->synced_task_data.context->lock); @@ -340,8 +354,6 @@ static int s_stop(struct aws_event_loop *event_loop) { return AWS_OP_SUCCESS; } -static void s_try_schedule_new_iteration(struct dispatch_loop_context *loop, uint64_t timestamp); - // returns true if we should execute an iteration, false otherwise static bool begin_iteration(struct scheduled_service_entry *entry) { bool should_execute_iteration = false; @@ -462,7 +474,7 @@ static void s_run_iteration(void *context) { * * If timestamp==0, the function will always schedule a new iteration as long as the event loop is not suspended. * - * The function should be wrapped with dispatch_loop->synced_task_data->lock + * The function should be wrapped with dispatch_loop->synced_task_data->context->lock */ static void s_try_schedule_new_iteration(struct dispatch_loop_context *dispatch_loop_context, uint64_t timestamp) { struct dispatch_loop *dispatch_loop = dispatch_loop_context->io_dispatch_loop; diff --git a/source/event_loop.c b/source/event_loop.c index 1bc237385..c5e0ea54c 100644 --- a/source/event_loop.c +++ b/source/event_loop.c @@ -107,6 +107,7 @@ enum aws_event_loop_type aws_event_loop_get_default_type(void) { AWS_LOGF_ERROR( AWS_LS_IO_EVENT_LOOP, "Failed to get default event loop type. The library is not built correctly on the platform."); + return AWS_EVENT_LOOP_PLATFORM_DEFAULT; #endif } From d45eb98d9e32de127a3a93f88a75ca23609c5e56 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 10 Dec 2024 13:25:00 -0800 Subject: [PATCH 6/6] wip update cr --- source/darwin/dispatch_queue.h | 1 - source/darwin/dispatch_queue_event_loop.c | 144 ++++++++++++---------- 2 files changed, 76 insertions(+), 69 deletions(-) diff --git a/source/darwin/dispatch_queue.h b/source/darwin/dispatch_queue.h index cfc6b0a9e..85f8592a4 100644 --- a/source/darwin/dispatch_queue.h +++ b/source/darwin/dispatch_queue.h @@ -44,7 +44,6 @@ struct dispatch_loop { struct aws_allocator *allocator; dispatch_queue_t dispatch_queue; struct aws_task_scheduler scheduler; - struct aws_linked_list local_cross_thread_tasks; struct aws_event_loop *base_loop; /* Synced data handle cross thread tasks and events, and event loop operations*/ diff --git a/source/darwin/dispatch_queue_event_loop.c b/source/darwin/dispatch_queue_event_loop.c index 5081378e2..6b00cee58 100644 --- a/source/darwin/dispatch_queue_event_loop.c +++ b/source/darwin/dispatch_queue_event_loop.c @@ -93,14 +93,22 @@ struct scheduled_service_entry { struct dispatch_loop_context *dispatch_queue_context; }; -static void s_acquire_dispatch_loop_context(struct dispatch_loop_context *contxt){ +static void s_acquire_dispatch_loop_context(struct dispatch_loop_context *contxt) { aws_ref_count_acquire(&contxt->ref_count); } -static void s_release_dispatch_loop_context(struct dispatch_loop_context *contxt){ +static void s_release_dispatch_loop_context(struct dispatch_loop_context *contxt) { aws_ref_count_release(&contxt->ref_count); } +static void s_lock_dispatch_loop_context(struct dispatch_loop_context *contxt) { + aws_mutex_lock(&contxt->lock); +} + +static void s_unlock_dispatch_loop_context(struct dispatch_loop_context *contxt) { + aws_mutex_unlock(&contxt->lock); +} + static struct scheduled_service_entry *s_scheduled_service_entry_new( struct dispatch_loop_context *context, uint64_t timestamp) { @@ -154,11 +162,21 @@ static void s_dispatch_event_loop_destroy(void *context) { struct aws_event_loop *event_loop = context; struct dispatch_loop *dispatch_loop = event_loop->impl_data; - // Null out the dispatch queue loop context - aws_mutex_lock(&dispatch_loop->synced_task_data.context->lock); - dispatch_loop->synced_task_data.context->io_dispatch_loop = NULL; - aws_mutex_unlock(&dispatch_loop->synced_task_data.context->lock); - s_release_dispatch_loop_context(dispatch_loop->synced_task_data.context); + if (dispatch_loop->synced_task_data.context) { + // Null out the dispatch queue loop context + s_lock_dispatch_loop_context(dispatch_loop->synced_task_data.context); + dispatch_loop->synced_task_data.context->io_dispatch_loop = NULL; + s_unlock_dispatch_loop_context(dispatch_loop->synced_task_data.context); + s_release_dispatch_loop_context(dispatch_loop->synced_task_data.context); + } + + // The scheduler should be cleaned up and zero out in event loop destroy task. Double check here in case the destroy + // function is not called or initialize was failed. + if (aws_task_scheduler_is_valid(&dispatch_loop->scheduler)) { + aws_task_scheduler_clean_up(&dispatch_loop->scheduler); + } + + aws_mutex_clean_up(&dispatch_loop->synced_thread_data.thread_data_lock); aws_mem_release(dispatch_loop->allocator, dispatch_loop); aws_event_loop_clean_up_base(event_loop); @@ -169,24 +187,22 @@ static void s_dispatch_event_loop_destroy(void *context) { /** Return a aws_string* with unique dispatch queue id string. The id is In format of * "com.amazonaws.commonruntime.eventloop."*/ -static struct aws_string *s_get_unique_dispatch_queue_id(struct aws_allocator *alloc) { +static struct aws_byte_cursor AWS_LITERAL_APPLE_DISPATCH_QUEUE_ID_PREFIX = + AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("com.amazonaws.commonruntime.eventloop."); +static const size_t AWS_IO_APPLE_DISPATCH_QUEUE_ID_PREFIX_LENGTH = 37; +static const size_t AWS_IO_APPLE_DISPATCH_QUEUE_ID_LENGTH = + AWS_IO_APPLE_DISPATCH_QUEUE_ID_PREFIX_LENGTH + AWS_UUID_STR_LEN; + +static void s_get_unique_dispatch_queue_id(char result[AWS_IO_APPLE_DISPATCH_QUEUE_ID_LENGTH]) { struct aws_uuid uuid; AWS_FATAL_ASSERT(aws_uuid_init(&uuid) == AWS_OP_SUCCESS); char uuid_str[AWS_UUID_STR_LEN] = {0}; struct aws_byte_buf uuid_buf = aws_byte_buf_from_array(uuid_str, sizeof(uuid_str)); uuid_buf.len = 0; aws_uuid_to_str(&uuid, &uuid_buf); - struct aws_byte_cursor uuid_cursor = aws_byte_cursor_from_buf(&uuid_buf); - - struct aws_byte_buf dispatch_queue_id_buf; - aws_byte_buf_init_copy_from_cursor( - &dispatch_queue_id_buf, alloc, aws_byte_cursor_from_c_str("com.amazonaws.commonruntime.eventloop.")); - aws_byte_buf_append_dynamic(&dispatch_queue_id_buf, &uuid_cursor); - - struct aws_string *result = aws_string_new_from_buf(alloc, &dispatch_queue_id_buf); - aws_byte_buf_clean_up(&dispatch_queue_id_buf); - return result; + memcpy(result, AWS_LITERAL_APPLE_DISPATCH_QUEUE_ID_PREFIX.ptr, AWS_IO_APPLE_DISPATCH_QUEUE_ID_PREFIX_LENGTH); + memcpy(result + AWS_IO_APPLE_DISPATCH_QUEUE_ID_PREFIX_LENGTH, uuid_buf.buffer, uuid_buf.len); } /* Setup a dispatch_queue with a scheduler. */ @@ -207,9 +223,10 @@ struct aws_event_loop *aws_event_loop_new_with_dispatch_queue( dispatch_loop = aws_mem_calloc(alloc, 1, sizeof(struct dispatch_loop)); - struct aws_string *dispatch_queue_id = s_get_unique_dispatch_queue_id(alloc); + char dispatch_queue_id[AWS_IO_APPLE_DISPATCH_QUEUE_ID_LENGTH] = {0}; + s_get_unique_dispatch_queue_id(dispatch_queue_id); - dispatch_loop->dispatch_queue = dispatch_queue_create((char *)dispatch_queue_id->bytes, DISPATCH_QUEUE_SERIAL); + dispatch_loop->dispatch_queue = dispatch_queue_create(dispatch_queue_id, DISPATCH_QUEUE_SERIAL); if (!dispatch_loop->dispatch_queue) { AWS_LOGF_FATAL(AWS_LS_IO_EVENT_LOOP, "id=%p: Failed to create dispatch queue.", (void *)loop); aws_raise_error(AWS_ERROR_SYS_CALL_FAILURE); @@ -217,10 +234,10 @@ struct aws_event_loop *aws_event_loop_new_with_dispatch_queue( } AWS_LOGF_INFO( - AWS_LS_IO_EVENT_LOOP, - "id=%p: Apple dispatch queue created with id:" PRInSTR, - (void *)loop, - AWS_BYTE_CURSOR_PRI(aws_byte_cursor_from_string(dispatch_queue_id))); + AWS_LS_IO_EVENT_LOOP, "id=%p: Apple dispatch queue created with id: %s", (void *)loop, dispatch_queue_id); + + aws_mutex_init(&dispatch_loop->synced_thread_data.thread_data_lock); + dispatch_loop->synced_thread_data.is_executing = false; int err = aws_task_scheduler_init(&dispatch_loop->scheduler, alloc); if (err) { @@ -230,19 +247,15 @@ struct aws_event_loop *aws_event_loop_new_with_dispatch_queue( dispatch_loop->base_loop = loop; - aws_linked_list_init(&dispatch_loop->local_cross_thread_tasks); aws_linked_list_init(&dispatch_loop->synced_task_data.cross_thread_tasks); - aws_mutex_init(&dispatch_loop->synced_thread_data.thread_data_lock); - dispatch_loop->synced_thread_data.is_executing = false; - struct dispatch_loop_context *context = aws_mem_calloc(alloc, 1, sizeof(struct dispatch_loop_context)); aws_ref_count_init(&context->ref_count, context, s_dispatch_loop_context_destroy); + context->allocator = alloc; context->scheduling_state.will_schedule = false; aws_linked_list_init(&context->scheduling_state.scheduled_services); aws_mutex_init(&context->lock); context->io_dispatch_loop = dispatch_loop; - context->allocator = alloc; dispatch_loop->synced_task_data.context = context; loop->impl_data = dispatch_loop; @@ -256,10 +269,9 @@ struct aws_event_loop *aws_event_loop_new_with_dispatch_queue( dispatch_release(dispatch_loop->dispatch_queue); } s_dispatch_event_loop_destroy(loop); + } else { + aws_mem_release(alloc, loop); } - - aws_mem_release(alloc, loop); - return NULL; } @@ -272,25 +284,21 @@ static void s_dispatch_queue_destroy_task(void *context) { aws_mutex_unlock(&dispatch_loop->synced_thread_data.thread_data_lock); aws_task_scheduler_clean_up(&dispatch_loop->scheduler); - aws_mutex_lock(&dispatch_loop->synced_task_data.context->lock); - - while (!aws_linked_list_empty(&dispatch_loop->synced_task_data.cross_thread_tasks)) { - struct aws_linked_list_node *node = - aws_linked_list_pop_front(&dispatch_loop->synced_task_data.cross_thread_tasks); + s_lock_dispatch_loop_context(dispatch_loop->synced_task_data.context); - struct aws_task *task = AWS_CONTAINER_OF(node, struct aws_task, node); - task->fn(task, task->arg, AWS_TASK_STATUS_CANCELED); - } + // swap the cross-thread tasks into task-local data + struct aws_linked_list local_cross_thread_tasks; + aws_linked_list_init(&local_cross_thread_tasks); + aws_linked_list_swap_contents(&dispatch_loop->synced_task_data.cross_thread_tasks, &local_cross_thread_tasks); + dispatch_loop->synced_task_data.suspended = true; + s_unlock_dispatch_loop_context(dispatch_loop->synced_task_data.context); - while (!aws_linked_list_empty(&dispatch_loop->local_cross_thread_tasks)) { - struct aws_linked_list_node *node = aws_linked_list_pop_front(&dispatch_loop->local_cross_thread_tasks); + while (!aws_linked_list_empty(&local_cross_thread_tasks)) { + struct aws_linked_list_node *node = aws_linked_list_pop_front(&local_cross_thread_tasks); struct aws_task *task = AWS_CONTAINER_OF(node, struct aws_task, node); task->fn(task, task->arg, AWS_TASK_STATUS_CANCELED); } - dispatch_loop->synced_task_data.suspended = true; - aws_mutex_unlock(&dispatch_loop->synced_task_data.context->lock); - aws_mutex_lock(&dispatch_loop->synced_thread_data.thread_data_lock); dispatch_loop->synced_thread_data.is_executing = false; aws_mutex_unlock(&dispatch_loop->synced_thread_data.thread_data_lock); @@ -333,7 +341,7 @@ static int s_run(struct aws_event_loop *event_loop) { dispatch_loop->synced_task_data.suspended = false; s_try_schedule_new_iteration(dispatch_loop->synced_task_data.context, 0); } - aws_mutex_unlock(&dispatch_loop->synced_task_data.context->lock); + s_unlock_dispatch_loop_context(dispatch_loop->synced_task_data.context); return AWS_OP_SUCCESS; } @@ -349,7 +357,7 @@ static int s_stop(struct aws_event_loop *event_loop) { * releasing the dispatch queue. */ dispatch_suspend(dispatch_loop->dispatch_queue); } - aws_mutex_unlock(&dispatch_loop->synced_task_data.context->lock); + s_unlock_dispatch_loop_context(dispatch_loop->synced_task_data.context); return AWS_OP_SUCCESS; } @@ -358,25 +366,20 @@ static int s_stop(struct aws_event_loop *event_loop) { static bool begin_iteration(struct scheduled_service_entry *entry) { bool should_execute_iteration = false; struct dispatch_loop_context *contxt = entry->dispatch_queue_context; - aws_mutex_lock(&contxt->lock); + s_lock_dispatch_loop_context(contxt); struct dispatch_loop *dispatch_loop = entry->dispatch_queue_context->io_dispatch_loop; if (!dispatch_loop) { - aws_mutex_unlock(&contxt->lock); - return should_execute_iteration; + goto begin_iteration_done; } - // swap the cross-thread tasks into task-local data - AWS_FATAL_ASSERT(aws_linked_list_empty(&dispatch_loop->local_cross_thread_tasks)); - aws_linked_list_swap_contents( - &dispatch_loop->synced_task_data.cross_thread_tasks, &dispatch_loop->local_cross_thread_tasks); - // mark us as running an iteration and remove from the pending list dispatch_loop->synced_task_data.context->scheduling_state.will_schedule = true; aws_linked_list_remove(&entry->node); - aws_mutex_unlock(&contxt->lock); - should_execute_iteration = true; + +begin_iteration_done: + s_unlock_dispatch_loop_context(contxt); return should_execute_iteration; } @@ -384,11 +387,10 @@ static bool begin_iteration(struct scheduled_service_entry *entry) { static void end_iteration(struct scheduled_service_entry *entry) { struct dispatch_loop_context *contxt = entry->dispatch_queue_context; - aws_mutex_lock(&contxt->lock); + s_lock_dispatch_loop_context(contxt); struct dispatch_loop *dispatch_loop = entry->dispatch_queue_context->io_dispatch_loop; if (!dispatch_loop) { - aws_mutex_unlock(&contxt->lock); - return; + goto end_iteration_done; } dispatch_loop->synced_task_data.context->scheduling_state.will_schedule = false; @@ -413,8 +415,9 @@ static void end_iteration(struct scheduled_service_entry *entry) { } } - aws_mutex_unlock(&contxt->lock); s_scheduled_service_entry_destroy(entry); +end_iteration_done: + s_unlock_dispatch_loop_context(contxt); } // Iteration function that scheduled and executed by the Dispatch Queue API @@ -422,9 +425,9 @@ static void s_run_iteration(void *context) { struct scheduled_service_entry *entry = context; struct dispatch_loop_context *dispatch_queue_context = entry->dispatch_queue_context; - aws_mutex_lock(&dispatch_queue_context->lock); + s_lock_dispatch_loop_context(dispatch_queue_context); struct dispatch_loop *dispatch_loop = entry->dispatch_queue_context->io_dispatch_loop; - aws_mutex_unlock(&dispatch_queue_context->lock); + s_unlock_dispatch_loop_context(dispatch_queue_context); if (!dispatch_loop) { s_scheduled_service_entry_destroy(entry); return; @@ -435,11 +438,16 @@ static void s_run_iteration(void *context) { return; } + // swap the cross-thread tasks into task-local data + struct aws_linked_list local_cross_thread_tasks; + aws_linked_list_init(&local_cross_thread_tasks); + aws_linked_list_swap_contents(&dispatch_loop->synced_task_data.cross_thread_tasks, &local_cross_thread_tasks); + aws_event_loop_register_tick_start(dispatch_loop->base_loop); - // run the full iteration here: local cross-thread tasks - while (!aws_linked_list_empty(&dispatch_loop->local_cross_thread_tasks)) { - struct aws_linked_list_node *node = aws_linked_list_pop_front(&dispatch_loop->local_cross_thread_tasks); + // run the full iteration here: local cross-thread tasks + while (!aws_linked_list_empty(&local_cross_thread_tasks)) { + struct aws_linked_list_node *node = aws_linked_list_pop_front(&local_cross_thread_tasks); struct aws_task *task = AWS_CONTAINER_OF(node, struct aws_task, node); /* Timestamp 0 is used to denote "now" tasks */ @@ -493,7 +501,7 @@ static void s_try_schedule_new_iteration(struct dispatch_loop_context *dispatch_ static void s_schedule_task_common(struct aws_event_loop *event_loop, struct aws_task *task, uint64_t run_at_nanos) { struct dispatch_loop *dispatch_loop = event_loop->impl_data; - aws_mutex_lock(&dispatch_loop->synced_task_data.context->lock); + s_lock_dispatch_loop_context(dispatch_loop->synced_task_data.context); bool should_schedule = false; bool was_empty = aws_linked_list_empty(&dispatch_loop->synced_task_data.cross_thread_tasks); @@ -524,7 +532,7 @@ static void s_schedule_task_common(struct aws_event_loop *event_loop, struct aws s_try_schedule_new_iteration(dispatch_loop->synced_task_data.context, 0); } - aws_mutex_unlock(&dispatch_loop->synced_task_data.context->lock); + s_unlock_dispatch_loop_context(dispatch_loop->synced_task_data.context); } static void s_schedule_task_now(struct aws_event_loop *event_loop, struct aws_task *task) {