1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* 11e1051a39Sopenharmony_ci * Without this we start getting longjmp crashes because it thinks we're jumping 12e1051a39Sopenharmony_ci * up the stack when in fact we are jumping to an entirely different stack. The 13e1051a39Sopenharmony_ci * cost of this is not having certain buffer overrun/underrun checks etc for 14e1051a39Sopenharmony_ci * this source file :-( 15e1051a39Sopenharmony_ci */ 16e1051a39Sopenharmony_ci#undef _FORTIFY_SOURCE 17e1051a39Sopenharmony_ci 18e1051a39Sopenharmony_ci/* This must be the first #include file */ 19e1051a39Sopenharmony_ci#include "async_local.h" 20e1051a39Sopenharmony_ci 21e1051a39Sopenharmony_ci#include <openssl/err.h> 22e1051a39Sopenharmony_ci#include "crypto/cryptlib.h" 23e1051a39Sopenharmony_ci#include <string.h> 24e1051a39Sopenharmony_ci 25e1051a39Sopenharmony_ci#define ASYNC_JOB_RUNNING 0 26e1051a39Sopenharmony_ci#define ASYNC_JOB_PAUSING 1 27e1051a39Sopenharmony_ci#define ASYNC_JOB_PAUSED 2 28e1051a39Sopenharmony_ci#define ASYNC_JOB_STOPPING 3 29e1051a39Sopenharmony_ci 30e1051a39Sopenharmony_cistatic CRYPTO_THREAD_LOCAL ctxkey; 31e1051a39Sopenharmony_cistatic CRYPTO_THREAD_LOCAL poolkey; 32e1051a39Sopenharmony_ci 33e1051a39Sopenharmony_cistatic void async_delete_thread_state(void *arg); 34e1051a39Sopenharmony_ci 35e1051a39Sopenharmony_cistatic async_ctx *async_ctx_new(void) 36e1051a39Sopenharmony_ci{ 37e1051a39Sopenharmony_ci async_ctx *nctx; 38e1051a39Sopenharmony_ci 39e1051a39Sopenharmony_ci if (!ossl_init_thread_start(NULL, NULL, async_delete_thread_state)) 40e1051a39Sopenharmony_ci return NULL; 41e1051a39Sopenharmony_ci 42e1051a39Sopenharmony_ci nctx = OPENSSL_malloc(sizeof(*nctx)); 43e1051a39Sopenharmony_ci if (nctx == NULL) { 44e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); 45e1051a39Sopenharmony_ci goto err; 46e1051a39Sopenharmony_ci } 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci async_fibre_init_dispatcher(&nctx->dispatcher); 49e1051a39Sopenharmony_ci nctx->currjob = NULL; 50e1051a39Sopenharmony_ci nctx->blocked = 0; 51e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_set_local(&ctxkey, nctx)) 52e1051a39Sopenharmony_ci goto err; 53e1051a39Sopenharmony_ci 54e1051a39Sopenharmony_ci return nctx; 55e1051a39Sopenharmony_cierr: 56e1051a39Sopenharmony_ci OPENSSL_free(nctx); 57e1051a39Sopenharmony_ci 58e1051a39Sopenharmony_ci return NULL; 59e1051a39Sopenharmony_ci} 60e1051a39Sopenharmony_ci 61e1051a39Sopenharmony_ciasync_ctx *async_get_ctx(void) 62e1051a39Sopenharmony_ci{ 63e1051a39Sopenharmony_ci return (async_ctx *)CRYPTO_THREAD_get_local(&ctxkey); 64e1051a39Sopenharmony_ci} 65e1051a39Sopenharmony_ci 66e1051a39Sopenharmony_cistatic int async_ctx_free(void) 67e1051a39Sopenharmony_ci{ 68e1051a39Sopenharmony_ci async_ctx *ctx; 69e1051a39Sopenharmony_ci 70e1051a39Sopenharmony_ci ctx = async_get_ctx(); 71e1051a39Sopenharmony_ci 72e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_set_local(&ctxkey, NULL)) 73e1051a39Sopenharmony_ci return 0; 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_ci OPENSSL_free(ctx); 76e1051a39Sopenharmony_ci 77e1051a39Sopenharmony_ci return 1; 78e1051a39Sopenharmony_ci} 79e1051a39Sopenharmony_ci 80e1051a39Sopenharmony_cistatic ASYNC_JOB *async_job_new(void) 81e1051a39Sopenharmony_ci{ 82e1051a39Sopenharmony_ci ASYNC_JOB *job = NULL; 83e1051a39Sopenharmony_ci 84e1051a39Sopenharmony_ci job = OPENSSL_zalloc(sizeof(*job)); 85e1051a39Sopenharmony_ci if (job == NULL) { 86e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); 87e1051a39Sopenharmony_ci return NULL; 88e1051a39Sopenharmony_ci } 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci job->status = ASYNC_JOB_RUNNING; 91e1051a39Sopenharmony_ci 92e1051a39Sopenharmony_ci return job; 93e1051a39Sopenharmony_ci} 94e1051a39Sopenharmony_ci 95e1051a39Sopenharmony_cistatic void async_job_free(ASYNC_JOB *job) 96e1051a39Sopenharmony_ci{ 97e1051a39Sopenharmony_ci if (job != NULL) { 98e1051a39Sopenharmony_ci OPENSSL_free(job->funcargs); 99e1051a39Sopenharmony_ci async_fibre_free(&job->fibrectx); 100e1051a39Sopenharmony_ci OPENSSL_free(job); 101e1051a39Sopenharmony_ci } 102e1051a39Sopenharmony_ci} 103e1051a39Sopenharmony_ci 104e1051a39Sopenharmony_cistatic ASYNC_JOB *async_get_pool_job(void) { 105e1051a39Sopenharmony_ci ASYNC_JOB *job; 106e1051a39Sopenharmony_ci async_pool *pool; 107e1051a39Sopenharmony_ci 108e1051a39Sopenharmony_ci pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey); 109e1051a39Sopenharmony_ci if (pool == NULL) { 110e1051a39Sopenharmony_ci /* 111e1051a39Sopenharmony_ci * Pool has not been initialised, so init with the defaults, i.e. 112e1051a39Sopenharmony_ci * no max size and no pre-created jobs 113e1051a39Sopenharmony_ci */ 114e1051a39Sopenharmony_ci if (ASYNC_init_thread(0, 0) == 0) 115e1051a39Sopenharmony_ci return NULL; 116e1051a39Sopenharmony_ci pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey); 117e1051a39Sopenharmony_ci } 118e1051a39Sopenharmony_ci 119e1051a39Sopenharmony_ci job = sk_ASYNC_JOB_pop(pool->jobs); 120e1051a39Sopenharmony_ci if (job == NULL) { 121e1051a39Sopenharmony_ci /* Pool is empty */ 122e1051a39Sopenharmony_ci if ((pool->max_size != 0) && (pool->curr_size >= pool->max_size)) 123e1051a39Sopenharmony_ci return NULL; 124e1051a39Sopenharmony_ci 125e1051a39Sopenharmony_ci job = async_job_new(); 126e1051a39Sopenharmony_ci if (job != NULL) { 127e1051a39Sopenharmony_ci if (! async_fibre_makecontext(&job->fibrectx)) { 128e1051a39Sopenharmony_ci async_job_free(job); 129e1051a39Sopenharmony_ci return NULL; 130e1051a39Sopenharmony_ci } 131e1051a39Sopenharmony_ci pool->curr_size++; 132e1051a39Sopenharmony_ci } 133e1051a39Sopenharmony_ci } 134e1051a39Sopenharmony_ci return job; 135e1051a39Sopenharmony_ci} 136e1051a39Sopenharmony_ci 137e1051a39Sopenharmony_cistatic void async_release_job(ASYNC_JOB *job) { 138e1051a39Sopenharmony_ci async_pool *pool; 139e1051a39Sopenharmony_ci 140e1051a39Sopenharmony_ci pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey); 141e1051a39Sopenharmony_ci if (pool == NULL) { 142e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR); 143e1051a39Sopenharmony_ci return; 144e1051a39Sopenharmony_ci } 145e1051a39Sopenharmony_ci OPENSSL_free(job->funcargs); 146e1051a39Sopenharmony_ci job->funcargs = NULL; 147e1051a39Sopenharmony_ci sk_ASYNC_JOB_push(pool->jobs, job); 148e1051a39Sopenharmony_ci} 149e1051a39Sopenharmony_ci 150e1051a39Sopenharmony_civoid async_start_func(void) 151e1051a39Sopenharmony_ci{ 152e1051a39Sopenharmony_ci ASYNC_JOB *job; 153e1051a39Sopenharmony_ci async_ctx *ctx = async_get_ctx(); 154e1051a39Sopenharmony_ci 155e1051a39Sopenharmony_ci if (ctx == NULL) { 156e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR); 157e1051a39Sopenharmony_ci return; 158e1051a39Sopenharmony_ci } 159e1051a39Sopenharmony_ci while (1) { 160e1051a39Sopenharmony_ci /* Run the job */ 161e1051a39Sopenharmony_ci job = ctx->currjob; 162e1051a39Sopenharmony_ci job->ret = job->func(job->funcargs); 163e1051a39Sopenharmony_ci 164e1051a39Sopenharmony_ci /* Stop the job */ 165e1051a39Sopenharmony_ci job->status = ASYNC_JOB_STOPPING; 166e1051a39Sopenharmony_ci if (!async_fibre_swapcontext(&job->fibrectx, 167e1051a39Sopenharmony_ci &ctx->dispatcher, 1)) { 168e1051a39Sopenharmony_ci /* 169e1051a39Sopenharmony_ci * Should not happen. Getting here will close the thread...can't do 170e1051a39Sopenharmony_ci * much about it 171e1051a39Sopenharmony_ci */ 172e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT); 173e1051a39Sopenharmony_ci } 174e1051a39Sopenharmony_ci } 175e1051a39Sopenharmony_ci} 176e1051a39Sopenharmony_ci 177e1051a39Sopenharmony_ciint ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret, 178e1051a39Sopenharmony_ci int (*func)(void *), void *args, size_t size) 179e1051a39Sopenharmony_ci{ 180e1051a39Sopenharmony_ci async_ctx *ctx; 181e1051a39Sopenharmony_ci OSSL_LIB_CTX *libctx; 182e1051a39Sopenharmony_ci 183e1051a39Sopenharmony_ci if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) 184e1051a39Sopenharmony_ci return ASYNC_ERR; 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_ci ctx = async_get_ctx(); 187e1051a39Sopenharmony_ci if (ctx == NULL) 188e1051a39Sopenharmony_ci ctx = async_ctx_new(); 189e1051a39Sopenharmony_ci if (ctx == NULL) 190e1051a39Sopenharmony_ci return ASYNC_ERR; 191e1051a39Sopenharmony_ci 192e1051a39Sopenharmony_ci if (*job != NULL) 193e1051a39Sopenharmony_ci ctx->currjob = *job; 194e1051a39Sopenharmony_ci 195e1051a39Sopenharmony_ci for (;;) { 196e1051a39Sopenharmony_ci if (ctx->currjob != NULL) { 197e1051a39Sopenharmony_ci if (ctx->currjob->status == ASYNC_JOB_STOPPING) { 198e1051a39Sopenharmony_ci *ret = ctx->currjob->ret; 199e1051a39Sopenharmony_ci ctx->currjob->waitctx = NULL; 200e1051a39Sopenharmony_ci async_release_job(ctx->currjob); 201e1051a39Sopenharmony_ci ctx->currjob = NULL; 202e1051a39Sopenharmony_ci *job = NULL; 203e1051a39Sopenharmony_ci return ASYNC_FINISH; 204e1051a39Sopenharmony_ci } 205e1051a39Sopenharmony_ci 206e1051a39Sopenharmony_ci if (ctx->currjob->status == ASYNC_JOB_PAUSING) { 207e1051a39Sopenharmony_ci *job = ctx->currjob; 208e1051a39Sopenharmony_ci ctx->currjob->status = ASYNC_JOB_PAUSED; 209e1051a39Sopenharmony_ci ctx->currjob = NULL; 210e1051a39Sopenharmony_ci return ASYNC_PAUSE; 211e1051a39Sopenharmony_ci } 212e1051a39Sopenharmony_ci 213e1051a39Sopenharmony_ci if (ctx->currjob->status == ASYNC_JOB_PAUSED) { 214e1051a39Sopenharmony_ci if (*job == NULL) 215e1051a39Sopenharmony_ci return ASYNC_ERR; 216e1051a39Sopenharmony_ci ctx->currjob = *job; 217e1051a39Sopenharmony_ci 218e1051a39Sopenharmony_ci /* 219e1051a39Sopenharmony_ci * Restore the default libctx to what it was the last time the 220e1051a39Sopenharmony_ci * fibre ran 221e1051a39Sopenharmony_ci */ 222e1051a39Sopenharmony_ci libctx = OSSL_LIB_CTX_set0_default(ctx->currjob->libctx); 223e1051a39Sopenharmony_ci if (libctx == NULL) { 224e1051a39Sopenharmony_ci /* Failed to set the default context */ 225e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR); 226e1051a39Sopenharmony_ci goto err; 227e1051a39Sopenharmony_ci } 228e1051a39Sopenharmony_ci /* Resume previous job */ 229e1051a39Sopenharmony_ci if (!async_fibre_swapcontext(&ctx->dispatcher, 230e1051a39Sopenharmony_ci &ctx->currjob->fibrectx, 1)) { 231e1051a39Sopenharmony_ci ctx->currjob->libctx = OSSL_LIB_CTX_set0_default(libctx); 232e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT); 233e1051a39Sopenharmony_ci goto err; 234e1051a39Sopenharmony_ci } 235e1051a39Sopenharmony_ci /* 236e1051a39Sopenharmony_ci * In case the fibre changed the default libctx we set it back 237e1051a39Sopenharmony_ci * again to what it was originally, and remember what it had 238e1051a39Sopenharmony_ci * been changed to. 239e1051a39Sopenharmony_ci */ 240e1051a39Sopenharmony_ci ctx->currjob->libctx = OSSL_LIB_CTX_set0_default(libctx); 241e1051a39Sopenharmony_ci continue; 242e1051a39Sopenharmony_ci } 243e1051a39Sopenharmony_ci 244e1051a39Sopenharmony_ci /* Should not happen */ 245e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ERR_R_INTERNAL_ERROR); 246e1051a39Sopenharmony_ci async_release_job(ctx->currjob); 247e1051a39Sopenharmony_ci ctx->currjob = NULL; 248e1051a39Sopenharmony_ci *job = NULL; 249e1051a39Sopenharmony_ci return ASYNC_ERR; 250e1051a39Sopenharmony_ci } 251e1051a39Sopenharmony_ci 252e1051a39Sopenharmony_ci /* Start a new job */ 253e1051a39Sopenharmony_ci if ((ctx->currjob = async_get_pool_job()) == NULL) 254e1051a39Sopenharmony_ci return ASYNC_NO_JOBS; 255e1051a39Sopenharmony_ci 256e1051a39Sopenharmony_ci if (args != NULL) { 257e1051a39Sopenharmony_ci ctx->currjob->funcargs = OPENSSL_malloc(size); 258e1051a39Sopenharmony_ci if (ctx->currjob->funcargs == NULL) { 259e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); 260e1051a39Sopenharmony_ci async_release_job(ctx->currjob); 261e1051a39Sopenharmony_ci ctx->currjob = NULL; 262e1051a39Sopenharmony_ci return ASYNC_ERR; 263e1051a39Sopenharmony_ci } 264e1051a39Sopenharmony_ci memcpy(ctx->currjob->funcargs, args, size); 265e1051a39Sopenharmony_ci } else { 266e1051a39Sopenharmony_ci ctx->currjob->funcargs = NULL; 267e1051a39Sopenharmony_ci } 268e1051a39Sopenharmony_ci 269e1051a39Sopenharmony_ci ctx->currjob->func = func; 270e1051a39Sopenharmony_ci ctx->currjob->waitctx = wctx; 271e1051a39Sopenharmony_ci libctx = ossl_lib_ctx_get_concrete(NULL); 272e1051a39Sopenharmony_ci if (!async_fibre_swapcontext(&ctx->dispatcher, 273e1051a39Sopenharmony_ci &ctx->currjob->fibrectx, 1)) { 274e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT); 275e1051a39Sopenharmony_ci goto err; 276e1051a39Sopenharmony_ci } 277e1051a39Sopenharmony_ci /* 278e1051a39Sopenharmony_ci * In case the fibre changed the default libctx we set it back again 279e1051a39Sopenharmony_ci * to what it was, and remember what it had been changed to. 280e1051a39Sopenharmony_ci */ 281e1051a39Sopenharmony_ci ctx->currjob->libctx = OSSL_LIB_CTX_set0_default(libctx); 282e1051a39Sopenharmony_ci } 283e1051a39Sopenharmony_ci 284e1051a39Sopenharmony_cierr: 285e1051a39Sopenharmony_ci async_release_job(ctx->currjob); 286e1051a39Sopenharmony_ci ctx->currjob = NULL; 287e1051a39Sopenharmony_ci *job = NULL; 288e1051a39Sopenharmony_ci return ASYNC_ERR; 289e1051a39Sopenharmony_ci} 290e1051a39Sopenharmony_ci 291e1051a39Sopenharmony_ciint ASYNC_pause_job(void) 292e1051a39Sopenharmony_ci{ 293e1051a39Sopenharmony_ci ASYNC_JOB *job; 294e1051a39Sopenharmony_ci async_ctx *ctx = async_get_ctx(); 295e1051a39Sopenharmony_ci 296e1051a39Sopenharmony_ci if (ctx == NULL 297e1051a39Sopenharmony_ci || ctx->currjob == NULL 298e1051a39Sopenharmony_ci || ctx->blocked) { 299e1051a39Sopenharmony_ci /* 300e1051a39Sopenharmony_ci * Could be we've deliberately not been started within a job so this is 301e1051a39Sopenharmony_ci * counted as success. 302e1051a39Sopenharmony_ci */ 303e1051a39Sopenharmony_ci return 1; 304e1051a39Sopenharmony_ci } 305e1051a39Sopenharmony_ci 306e1051a39Sopenharmony_ci job = ctx->currjob; 307e1051a39Sopenharmony_ci job->status = ASYNC_JOB_PAUSING; 308e1051a39Sopenharmony_ci 309e1051a39Sopenharmony_ci if (!async_fibre_swapcontext(&job->fibrectx, 310e1051a39Sopenharmony_ci &ctx->dispatcher, 1)) { 311e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT); 312e1051a39Sopenharmony_ci return 0; 313e1051a39Sopenharmony_ci } 314e1051a39Sopenharmony_ci /* Reset counts of added and deleted fds */ 315e1051a39Sopenharmony_ci async_wait_ctx_reset_counts(job->waitctx); 316e1051a39Sopenharmony_ci 317e1051a39Sopenharmony_ci return 1; 318e1051a39Sopenharmony_ci} 319e1051a39Sopenharmony_ci 320e1051a39Sopenharmony_cistatic void async_empty_pool(async_pool *pool) 321e1051a39Sopenharmony_ci{ 322e1051a39Sopenharmony_ci ASYNC_JOB *job; 323e1051a39Sopenharmony_ci 324e1051a39Sopenharmony_ci if (pool == NULL || pool->jobs == NULL) 325e1051a39Sopenharmony_ci return; 326e1051a39Sopenharmony_ci 327e1051a39Sopenharmony_ci do { 328e1051a39Sopenharmony_ci job = sk_ASYNC_JOB_pop(pool->jobs); 329e1051a39Sopenharmony_ci async_job_free(job); 330e1051a39Sopenharmony_ci } while (job); 331e1051a39Sopenharmony_ci} 332e1051a39Sopenharmony_ci 333e1051a39Sopenharmony_ciint async_init(void) 334e1051a39Sopenharmony_ci{ 335e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_init_local(&ctxkey, NULL)) 336e1051a39Sopenharmony_ci return 0; 337e1051a39Sopenharmony_ci 338e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_init_local(&poolkey, NULL)) { 339e1051a39Sopenharmony_ci CRYPTO_THREAD_cleanup_local(&ctxkey); 340e1051a39Sopenharmony_ci return 0; 341e1051a39Sopenharmony_ci } 342e1051a39Sopenharmony_ci 343e1051a39Sopenharmony_ci return 1; 344e1051a39Sopenharmony_ci} 345e1051a39Sopenharmony_ci 346e1051a39Sopenharmony_civoid async_deinit(void) 347e1051a39Sopenharmony_ci{ 348e1051a39Sopenharmony_ci CRYPTO_THREAD_cleanup_local(&ctxkey); 349e1051a39Sopenharmony_ci CRYPTO_THREAD_cleanup_local(&poolkey); 350e1051a39Sopenharmony_ci} 351e1051a39Sopenharmony_ci 352e1051a39Sopenharmony_ciint ASYNC_init_thread(size_t max_size, size_t init_size) 353e1051a39Sopenharmony_ci{ 354e1051a39Sopenharmony_ci async_pool *pool; 355e1051a39Sopenharmony_ci size_t curr_size = 0; 356e1051a39Sopenharmony_ci 357e1051a39Sopenharmony_ci if (init_size > max_size) { 358e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ASYNC_R_INVALID_POOL_SIZE); 359e1051a39Sopenharmony_ci return 0; 360e1051a39Sopenharmony_ci } 361e1051a39Sopenharmony_ci 362e1051a39Sopenharmony_ci if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) 363e1051a39Sopenharmony_ci return 0; 364e1051a39Sopenharmony_ci 365e1051a39Sopenharmony_ci if (!ossl_init_thread_start(NULL, NULL, async_delete_thread_state)) 366e1051a39Sopenharmony_ci return 0; 367e1051a39Sopenharmony_ci 368e1051a39Sopenharmony_ci pool = OPENSSL_zalloc(sizeof(*pool)); 369e1051a39Sopenharmony_ci if (pool == NULL) { 370e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); 371e1051a39Sopenharmony_ci return 0; 372e1051a39Sopenharmony_ci } 373e1051a39Sopenharmony_ci 374e1051a39Sopenharmony_ci pool->jobs = sk_ASYNC_JOB_new_reserve(NULL, init_size); 375e1051a39Sopenharmony_ci if (pool->jobs == NULL) { 376e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ERR_R_MALLOC_FAILURE); 377e1051a39Sopenharmony_ci OPENSSL_free(pool); 378e1051a39Sopenharmony_ci return 0; 379e1051a39Sopenharmony_ci } 380e1051a39Sopenharmony_ci 381e1051a39Sopenharmony_ci pool->max_size = max_size; 382e1051a39Sopenharmony_ci 383e1051a39Sopenharmony_ci /* Pre-create jobs as required */ 384e1051a39Sopenharmony_ci while (init_size--) { 385e1051a39Sopenharmony_ci ASYNC_JOB *job; 386e1051a39Sopenharmony_ci job = async_job_new(); 387e1051a39Sopenharmony_ci if (job == NULL || !async_fibre_makecontext(&job->fibrectx)) { 388e1051a39Sopenharmony_ci /* 389e1051a39Sopenharmony_ci * Not actually fatal because we already created the pool, just 390e1051a39Sopenharmony_ci * skip creation of any more jobs 391e1051a39Sopenharmony_ci */ 392e1051a39Sopenharmony_ci async_job_free(job); 393e1051a39Sopenharmony_ci break; 394e1051a39Sopenharmony_ci } 395e1051a39Sopenharmony_ci job->funcargs = NULL; 396e1051a39Sopenharmony_ci sk_ASYNC_JOB_push(pool->jobs, job); /* Cannot fail due to reserve */ 397e1051a39Sopenharmony_ci curr_size++; 398e1051a39Sopenharmony_ci } 399e1051a39Sopenharmony_ci pool->curr_size = curr_size; 400e1051a39Sopenharmony_ci if (!CRYPTO_THREAD_set_local(&poolkey, pool)) { 401e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_ASYNC, ASYNC_R_FAILED_TO_SET_POOL); 402e1051a39Sopenharmony_ci goto err; 403e1051a39Sopenharmony_ci } 404e1051a39Sopenharmony_ci 405e1051a39Sopenharmony_ci return 1; 406e1051a39Sopenharmony_cierr: 407e1051a39Sopenharmony_ci async_empty_pool(pool); 408e1051a39Sopenharmony_ci sk_ASYNC_JOB_free(pool->jobs); 409e1051a39Sopenharmony_ci OPENSSL_free(pool); 410e1051a39Sopenharmony_ci return 0; 411e1051a39Sopenharmony_ci} 412e1051a39Sopenharmony_ci 413e1051a39Sopenharmony_cistatic void async_delete_thread_state(void *arg) 414e1051a39Sopenharmony_ci{ 415e1051a39Sopenharmony_ci async_pool *pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey); 416e1051a39Sopenharmony_ci 417e1051a39Sopenharmony_ci if (pool != NULL) { 418e1051a39Sopenharmony_ci async_empty_pool(pool); 419e1051a39Sopenharmony_ci sk_ASYNC_JOB_free(pool->jobs); 420e1051a39Sopenharmony_ci OPENSSL_free(pool); 421e1051a39Sopenharmony_ci CRYPTO_THREAD_set_local(&poolkey, NULL); 422e1051a39Sopenharmony_ci } 423e1051a39Sopenharmony_ci async_local_cleanup(); 424e1051a39Sopenharmony_ci async_ctx_free(); 425e1051a39Sopenharmony_ci} 426e1051a39Sopenharmony_ci 427e1051a39Sopenharmony_civoid ASYNC_cleanup_thread(void) 428e1051a39Sopenharmony_ci{ 429e1051a39Sopenharmony_ci if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) 430e1051a39Sopenharmony_ci return; 431e1051a39Sopenharmony_ci 432e1051a39Sopenharmony_ci async_delete_thread_state(NULL); 433e1051a39Sopenharmony_ci} 434e1051a39Sopenharmony_ci 435e1051a39Sopenharmony_ciASYNC_JOB *ASYNC_get_current_job(void) 436e1051a39Sopenharmony_ci{ 437e1051a39Sopenharmony_ci async_ctx *ctx; 438e1051a39Sopenharmony_ci 439e1051a39Sopenharmony_ci if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) 440e1051a39Sopenharmony_ci return NULL; 441e1051a39Sopenharmony_ci 442e1051a39Sopenharmony_ci ctx = async_get_ctx(); 443e1051a39Sopenharmony_ci if (ctx == NULL) 444e1051a39Sopenharmony_ci return NULL; 445e1051a39Sopenharmony_ci 446e1051a39Sopenharmony_ci return ctx->currjob; 447e1051a39Sopenharmony_ci} 448e1051a39Sopenharmony_ci 449e1051a39Sopenharmony_ciASYNC_WAIT_CTX *ASYNC_get_wait_ctx(ASYNC_JOB *job) 450e1051a39Sopenharmony_ci{ 451e1051a39Sopenharmony_ci return job->waitctx; 452e1051a39Sopenharmony_ci} 453e1051a39Sopenharmony_ci 454e1051a39Sopenharmony_civoid ASYNC_block_pause(void) 455e1051a39Sopenharmony_ci{ 456e1051a39Sopenharmony_ci async_ctx *ctx; 457e1051a39Sopenharmony_ci 458e1051a39Sopenharmony_ci if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) 459e1051a39Sopenharmony_ci return; 460e1051a39Sopenharmony_ci 461e1051a39Sopenharmony_ci ctx = async_get_ctx(); 462e1051a39Sopenharmony_ci if (ctx == NULL || ctx->currjob == NULL) { 463e1051a39Sopenharmony_ci /* 464e1051a39Sopenharmony_ci * We're not in a job anyway so ignore this 465e1051a39Sopenharmony_ci */ 466e1051a39Sopenharmony_ci return; 467e1051a39Sopenharmony_ci } 468e1051a39Sopenharmony_ci ctx->blocked++; 469e1051a39Sopenharmony_ci} 470e1051a39Sopenharmony_ci 471e1051a39Sopenharmony_civoid ASYNC_unblock_pause(void) 472e1051a39Sopenharmony_ci{ 473e1051a39Sopenharmony_ci async_ctx *ctx; 474e1051a39Sopenharmony_ci 475e1051a39Sopenharmony_ci if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) 476e1051a39Sopenharmony_ci return; 477e1051a39Sopenharmony_ci 478e1051a39Sopenharmony_ci ctx = async_get_ctx(); 479e1051a39Sopenharmony_ci if (ctx == NULL || ctx->currjob == NULL) { 480e1051a39Sopenharmony_ci /* 481e1051a39Sopenharmony_ci * We're not in a job anyway so ignore this 482e1051a39Sopenharmony_ci */ 483e1051a39Sopenharmony_ci return; 484e1051a39Sopenharmony_ci } 485e1051a39Sopenharmony_ci if (ctx->blocked > 0) 486e1051a39Sopenharmony_ci ctx->blocked--; 487e1051a39Sopenharmony_ci} 488