2 * Copyright 2015-2022 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 /* This must be the first #include file */
11 #include "../async_local.h"
17 # include <openssl/err.h>
18 # include <openssl/crypto.h>
20 #define STACKSIZE 32768
22 static CRYPTO_RWLOCK
*async_mem_lock
;
24 static void *async_stack_alloc(size_t *num
);
25 static void async_stack_free(void *addr
);
27 int async_local_init(void)
29 async_mem_lock
= CRYPTO_THREAD_lock_new();
30 return async_mem_lock
!= NULL
;
33 void async_local_deinit(void)
35 CRYPTO_THREAD_lock_free(async_mem_lock
);
38 static int allow_customize
= 1;
39 static ASYNC_stack_alloc_fn stack_alloc_impl
= async_stack_alloc
;
40 static ASYNC_stack_free_fn stack_free_impl
= async_stack_free
;
42 int ASYNC_is_capable(void)
47 * Some platforms provide getcontext() but it does not work (notably
48 * MacOSX PPC64). Check for a working getcontext();
50 return getcontext(&ctx
) == 0;
53 int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn
,
54 ASYNC_stack_free_fn free_fn
)
56 OPENSSL_init_crypto(OPENSSL_INIT_ASYNC
, NULL
);
58 if (!CRYPTO_THREAD_write_lock(async_mem_lock
))
60 if (!allow_customize
) {
61 CRYPTO_THREAD_unlock(async_mem_lock
);
64 CRYPTO_THREAD_unlock(async_mem_lock
);
67 stack_alloc_impl
= alloc_fn
;
69 stack_free_impl
= free_fn
;
73 void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn
*alloc_fn
,
74 ASYNC_stack_free_fn
*free_fn
)
77 *alloc_fn
= stack_alloc_impl
;
79 *free_fn
= stack_free_impl
;
82 static void *async_stack_alloc(size_t *num
)
84 return OPENSSL_malloc(*num
);
87 static void async_stack_free(void *addr
)
92 void async_local_cleanup(void)
96 int async_fibre_makecontext(async_fibre
*fibre
)
98 #ifndef USE_SWAPCONTEXT
101 if (getcontext(&fibre
->fibre
) == 0) {
102 size_t num
= STACKSIZE
;
105 * Disallow customisation after the first
106 * stack is allocated.
108 if (allow_customize
) {
109 if (!CRYPTO_THREAD_write_lock(async_mem_lock
))
112 CRYPTO_THREAD_unlock(async_mem_lock
);
115 fibre
->fibre
.uc_stack
.ss_sp
= stack_alloc_impl(&num
);
116 if (fibre
->fibre
.uc_stack
.ss_sp
!= NULL
) {
117 fibre
->fibre
.uc_stack
.ss_size
= num
;
118 fibre
->fibre
.uc_link
= NULL
;
119 makecontext(&fibre
->fibre
, async_start_func
, 0);
122 ERR_raise(ERR_LIB_ASYNC
, ERR_R_MALLOC_FAILURE
);
124 fibre
->fibre
.uc_stack
.ss_sp
= NULL
;
129 void async_fibre_free(async_fibre
*fibre
)
131 stack_free_impl(fibre
->fibre
.uc_stack
.ss_sp
);
132 fibre
->fibre
.uc_stack
.ss_sp
= NULL
;