1 /* 2 * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the Apache License 2.0 (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 #include "internal/quic_reactor_wait_ctx.h" 10 #include "internal/common.h" 11 #include "internal/thread_arch.h" 12 #include <assert.h> 13 14 struct quic_reactor_wait_slot_st { 15 OSSL_LIST_MEMBER(quic_reactor_wait_slot, QUIC_REACTOR_WAIT_SLOT); 16 QUIC_REACTOR *rtor; /* primary key */ 17 size_t blocking_count; /* datum */ 18 }; 19 20 DEFINE_LIST_OF_IMPL(quic_reactor_wait_slot, QUIC_REACTOR_WAIT_SLOT); 21 22 void ossl_quic_reactor_wait_ctx_init(QUIC_REACTOR_WAIT_CTX *ctx) 23 { 24 ossl_list_quic_reactor_wait_slot_init(&ctx->slots); 25 } 26 27 static void slot_activate(QUIC_REACTOR_WAIT_SLOT *slot) 28 { 29 if (++slot->blocking_count == 1) 30 ossl_quic_reactor_enter_blocking_section(slot->rtor); 31 } 32 33 static void slot_deactivate(QUIC_REACTOR_WAIT_SLOT *slot) 34 { 35 assert(slot->blocking_count > 0); 36 37 if (--slot->blocking_count > 0) 38 return; 39 40 ossl_quic_reactor_leave_blocking_section(slot->rtor); 41 } 42 43 int ossl_quic_reactor_wait_ctx_enter(QUIC_REACTOR_WAIT_CTX *ctx, 44 QUIC_REACTOR *rtor) 45 { 46 QUIC_REACTOR_WAIT_SLOT *slot; 47 48 OSSL_LIST_FOREACH(slot, quic_reactor_wait_slot, &ctx->slots) 49 if (slot->rtor == rtor) 50 break; 51 52 if (slot == NULL) { 53 if ((slot = OPENSSL_zalloc(sizeof(QUIC_REACTOR_WAIT_SLOT))) == NULL) 54 return 0; 55 56 slot->rtor = rtor; 57 ossl_list_quic_reactor_wait_slot_insert_tail(&ctx->slots, slot); 58 } 59 60 slot_activate(slot); 61 return 1; 62 } 63 64 void ossl_quic_reactor_wait_ctx_leave(QUIC_REACTOR_WAIT_CTX *ctx, 65 QUIC_REACTOR *rtor) 66 { 67 QUIC_REACTOR_WAIT_SLOT *slot; 68 69 OSSL_LIST_FOREACH(slot, quic_reactor_wait_slot, &ctx->slots) 70 if (slot->rtor == rtor) 71 break; 72 73 assert(slot != NULL); 74 slot_deactivate(slot); 75 } 76 77 void ossl_quic_reactor_wait_ctx_cleanup(QUIC_REACTOR_WAIT_CTX *ctx) 78 { 79 QUIC_REACTOR_WAIT_SLOT *slot, *nslot; 80 81 OSSL_LIST_FOREACH_DELSAFE(slot, nslot, quic_reactor_wait_slot, &ctx->slots) { 82 assert(slot->blocking_count == 0); 83 OPENSSL_free(slot); 84 } 85 } 86