/src/openssl/crypto/async/arch/async_posix.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2015-2022 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 | | |
10 | | /* This must be the first #include file */ |
11 | | #include "../async_local.h" |
12 | | |
13 | | #ifdef ASYNC_POSIX |
14 | | |
15 | | # include <stddef.h> |
16 | | # include <unistd.h> |
17 | | # include <openssl/err.h> |
18 | | # include <openssl/crypto.h> |
19 | | |
20 | 0 | #define STACKSIZE 32768 |
21 | | |
22 | | static CRYPTO_RWLOCK *async_mem_lock; |
23 | | |
24 | | static void *async_stack_alloc(size_t *num); |
25 | | static void async_stack_free(void *addr); |
26 | | |
27 | | int async_local_init(void) |
28 | 2 | { |
29 | 2 | async_mem_lock = CRYPTO_THREAD_lock_new(); |
30 | 2 | return async_mem_lock != NULL; |
31 | 2 | } |
32 | | |
33 | | void async_local_deinit(void) |
34 | 2 | { |
35 | 2 | CRYPTO_THREAD_lock_free(async_mem_lock); |
36 | 2 | } |
37 | | |
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; |
41 | | |
42 | | int ASYNC_is_capable(void) |
43 | 0 | { |
44 | 0 | ucontext_t ctx; |
45 | | |
46 | | /* |
47 | | * Some platforms provide getcontext() but it does not work (notably |
48 | | * MacOSX PPC64). Check for a working getcontext(); |
49 | | */ |
50 | 0 | return getcontext(&ctx) == 0; |
51 | 0 | } |
52 | | |
53 | | int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn, |
54 | | ASYNC_stack_free_fn free_fn) |
55 | 0 | { |
56 | 0 | OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL); |
57 | |
|
58 | 0 | if (!CRYPTO_THREAD_write_lock(async_mem_lock)) |
59 | 0 | return 0; |
60 | 0 | if (!allow_customize) { |
61 | 0 | CRYPTO_THREAD_unlock(async_mem_lock); |
62 | 0 | return 0; |
63 | 0 | } |
64 | 0 | CRYPTO_THREAD_unlock(async_mem_lock); |
65 | |
|
66 | 0 | if (alloc_fn != NULL) |
67 | 0 | stack_alloc_impl = alloc_fn; |
68 | 0 | if (free_fn != NULL) |
69 | 0 | stack_free_impl = free_fn; |
70 | 0 | return 1; |
71 | 0 | } |
72 | | |
73 | | void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn, |
74 | | ASYNC_stack_free_fn *free_fn) |
75 | 0 | { |
76 | 0 | if (alloc_fn != NULL) |
77 | 0 | *alloc_fn = stack_alloc_impl; |
78 | 0 | if (free_fn != NULL) |
79 | 0 | *free_fn = stack_free_impl; |
80 | 0 | } |
81 | | |
82 | | static void *async_stack_alloc(size_t *num) |
83 | 0 | { |
84 | 0 | return OPENSSL_malloc(*num); |
85 | 0 | } |
86 | | |
87 | | static void async_stack_free(void *addr) |
88 | 0 | { |
89 | 0 | OPENSSL_free(addr); |
90 | 0 | } |
91 | | |
92 | | void async_local_cleanup(void) |
93 | 0 | { |
94 | 0 | } |
95 | | |
96 | | int async_fibre_makecontext(async_fibre *fibre) |
97 | 0 | { |
98 | 0 | #ifndef USE_SWAPCONTEXT |
99 | 0 | fibre->env_init = 0; |
100 | 0 | #endif |
101 | 0 | if (getcontext(&fibre->fibre) == 0) { |
102 | 0 | size_t num = STACKSIZE; |
103 | | |
104 | | /* |
105 | | * Disallow customisation after the first |
106 | | * stack is allocated. |
107 | | */ |
108 | 0 | if (allow_customize) { |
109 | 0 | if (!CRYPTO_THREAD_write_lock(async_mem_lock)) |
110 | 0 | return 0; |
111 | 0 | allow_customize = 0; |
112 | 0 | CRYPTO_THREAD_unlock(async_mem_lock); |
113 | 0 | } |
114 | | |
115 | 0 | fibre->fibre.uc_stack.ss_sp = stack_alloc_impl(&num); |
116 | 0 | if (fibre->fibre.uc_stack.ss_sp != NULL) { |
117 | 0 | fibre->fibre.uc_stack.ss_size = num; |
118 | 0 | fibre->fibre.uc_link = NULL; |
119 | 0 | makecontext(&fibre->fibre, async_start_func, 0); |
120 | 0 | return 1; |
121 | 0 | } |
122 | 0 | } else { |
123 | 0 | fibre->fibre.uc_stack.ss_sp = NULL; |
124 | 0 | } |
125 | 0 | return 0; |
126 | 0 | } |
127 | | |
128 | | void async_fibre_free(async_fibre *fibre) |
129 | 0 | { |
130 | 0 | stack_free_impl(fibre->fibre.uc_stack.ss_sp); |
131 | 0 | fibre->fibre.uc_stack.ss_sp = NULL; |
132 | 0 | } |
133 | | |
134 | | #endif |