2 * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include <openssl/macros.h>
11 #include "quic_local.h"
12 #include "internal/time.h"
13 #include "internal/thread.h"
14 #include "internal/thread_arch.h"
15 #include "internal/quic_thread_assist.h"
17 #if !defined(OPENSSL_NO_QUIC_THREAD_ASSIST)
19 /* Main loop for the QUIC assist thread. */
20 static unsigned int assist_thread_main(void *arg
)
22 QUIC_THREAD_ASSIST
*qta
= arg
;
23 CRYPTO_MUTEX
*m
= ossl_quic_channel_get_mutex(qta
->ch
);
26 ossl_crypto_mutex_lock(m
);
28 rtor
= ossl_quic_channel_get_reactor(qta
->ch
);
36 deadline
= ossl_quic_reactor_get_tick_deadline(rtor
);
37 if (qta
->now_cb
!= NULL
38 && !ossl_time_is_zero(deadline
)
39 && !ossl_time_is_infinite(deadline
)) {
41 * ossl_crypto_condvar_wait_timeout needs to use real time for the
44 deadline
= ossl_time_add(ossl_time_subtract(deadline
,
45 qta
->now_cb(qta
->now_cb_arg
)),
48 ossl_crypto_condvar_wait_timeout(qta
->cv
, m
, deadline
);
51 * We have now been woken up. This can be for one of the following
54 * - We have been asked to teardown (qta->teardown is set);
55 * - The tick deadline has passed.
56 * - The tick deadline has changed.
58 * For robustness, this loop also handles spurious wakeups correctly
59 * (which does not require any extra code).
64 ossl_quic_reactor_tick(rtor
, QUIC_REACTOR_TICK_FLAG_CHANNEL_ONLY
);
67 ossl_crypto_mutex_unlock(m
);
71 int ossl_quic_thread_assist_init_start(QUIC_THREAD_ASSIST
*qta
,
73 OSSL_TIME (*now_cb
)(void *arg
),
76 CRYPTO_MUTEX
*mutex
= ossl_quic_channel_get_mutex(ch
);
85 qta
->now_cb_arg
= now_cb_arg
;
87 qta
->cv
= ossl_crypto_condvar_new();
91 qta
->t
= ossl_crypto_thread_native_start(assist_thread_main
,
94 ossl_crypto_condvar_free(&qta
->cv
);
101 int ossl_quic_thread_assist_stop_async(QUIC_THREAD_ASSIST
*qta
)
103 if (!qta
->teardown
) {
105 ossl_crypto_condvar_signal(qta
->cv
);
111 int ossl_quic_thread_assist_wait_stopped(QUIC_THREAD_ASSIST
*qta
)
113 CRYPTO_THREAD_RETVAL rv
;
114 CRYPTO_MUTEX
*m
= ossl_quic_channel_get_mutex(qta
->ch
);
119 if (!ossl_quic_thread_assist_stop_async(qta
))
122 ossl_crypto_mutex_unlock(m
);
124 if (!ossl_crypto_thread_native_join(qta
->t
, &rv
)) {
125 ossl_crypto_mutex_lock(m
);
131 ossl_crypto_mutex_lock(m
);
135 int ossl_quic_thread_assist_cleanup(QUIC_THREAD_ASSIST
*qta
)
137 if (!ossl_assert(qta
->joined
))
140 ossl_crypto_condvar_free(&qta
->cv
);
141 ossl_crypto_thread_native_clean(qta
->t
);
148 int ossl_quic_thread_assist_notify_deadline_changed(QUIC_THREAD_ASSIST
*qta
)
153 ossl_crypto_condvar_signal(qta
->cv
);