]>
Commit | Line | Data |
---|---|---|
50108304 | 1 | /* |
fecb3aae | 2 | * Copyright 2015-2022 The OpenSSL Project Authors. All Rights Reserved. |
50108304 | 3 | * |
f3a95349 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
62867571 RS |
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 | |
50108304 MC |
8 | */ |
9 | ||
6e8ac508 | 10 | /* This must be the first #include file */ |
706457b7 | 11 | #include "../async_local.h" |
50108304 | 12 | |
636ca4ff | 13 | #ifdef ASYNC_POSIX |
6e8ac508 | 14 | |
50108304 | 15 | # include <stddef.h> |
f4da39d2 | 16 | # include <unistd.h> |
83c48d96 | 17 | # include <openssl/err.h> |
43ed2429 | 18 | # include <openssl/crypto.h> |
50108304 | 19 | |
06754949 MC |
20 | #define STACKSIZE 32768 |
21 | ||
43ed2429 ACB |
22 | static CRYPTO_RWLOCK *async_mem_lock; |
23 | ||
f6f56f47 ACB |
24 | static void *async_stack_alloc(size_t *num); |
25 | static void async_stack_free(void *addr); | |
26 | ||
43ed2429 ACB |
27 | int async_local_init(void) |
28 | { | |
29 | async_mem_lock = CRYPTO_THREAD_lock_new(); | |
30 | return async_mem_lock != NULL; | |
31 | } | |
32 | ||
33 | void async_local_deinit(void) | |
34 | { | |
35 | CRYPTO_THREAD_lock_free(async_mem_lock); | |
36 | } | |
37 | ||
f6f56f47 ACB |
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 | ||
667867cc | 42 | int ASYNC_is_capable(void) |
22a34c2f | 43 | { |
c521edc3 MC |
44 | 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 | return getcontext(&ctx) == 0; | |
22a34c2f MC |
51 | } |
52 | ||
f6f56f47 ACB |
53 | int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn, |
54 | ASYNC_stack_free_fn free_fn) | |
55 | { | |
43ed2429 ACB |
56 | OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL); |
57 | ||
58 | if (!CRYPTO_THREAD_write_lock(async_mem_lock)) | |
59 | return 0; | |
60 | if (!allow_customize) { | |
61 | CRYPTO_THREAD_unlock(async_mem_lock); | |
f6f56f47 | 62 | return 0; |
43ed2429 ACB |
63 | } |
64 | CRYPTO_THREAD_unlock(async_mem_lock); | |
65 | ||
f6f56f47 ACB |
66 | if (alloc_fn != NULL) |
67 | stack_alloc_impl = alloc_fn; | |
68 | if (free_fn != NULL) | |
69 | stack_free_impl = free_fn; | |
70 | return 1; | |
71 | } | |
72 | ||
73 | void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn, | |
74 | ASYNC_stack_free_fn *free_fn) | |
75 | { | |
76 | if (alloc_fn != NULL) | |
77 | *alloc_fn = stack_alloc_impl; | |
78 | if (free_fn != NULL) | |
79 | *free_fn = stack_free_impl; | |
80 | } | |
81 | ||
82 | static void *async_stack_alloc(size_t *num) | |
83 | { | |
84 | return OPENSSL_malloc(*num); | |
85 | } | |
86 | ||
87 | static void async_stack_free(void *addr) | |
88 | { | |
89 | OPENSSL_free(addr); | |
90 | } | |
91 | ||
667867cc MC |
92 | void async_local_cleanup(void) |
93 | { | |
94 | } | |
22a34c2f | 95 | |
6e8ac508 | 96 | int async_fibre_makecontext(async_fibre *fibre) |
50108304 | 97 | { |
34675b2b | 98 | #ifndef USE_SWAPCONTEXT |
7070e5ca | 99 | fibre->env_init = 0; |
34675b2b | 100 | #endif |
6e8ac508 | 101 | if (getcontext(&fibre->fibre) == 0) { |
f6f56f47 ACB |
102 | size_t num = STACKSIZE; |
103 | ||
104 | /* | |
105 | * Disallow customisation after the first | |
106 | * stack is allocated. | |
107 | */ | |
43ed2429 ACB |
108 | if (allow_customize) { |
109 | if (!CRYPTO_THREAD_write_lock(async_mem_lock)) | |
110 | return 0; | |
f6f56f47 | 111 | allow_customize = 0; |
43ed2429 ACB |
112 | CRYPTO_THREAD_unlock(async_mem_lock); |
113 | } | |
f6f56f47 ACB |
114 | |
115 | fibre->fibre.uc_stack.ss_sp = stack_alloc_impl(&num); | |
6e8ac508 | 116 | if (fibre->fibre.uc_stack.ss_sp != NULL) { |
f6f56f47 | 117 | fibre->fibre.uc_stack.ss_size = num; |
6e8ac508 VD |
118 | fibre->fibre.uc_link = NULL; |
119 | makecontext(&fibre->fibre, async_start_func, 0); | |
120 | return 1; | |
121 | } | |
122 | } else { | |
123 | fibre->fibre.uc_stack.ss_sp = NULL; | |
124 | } | |
125 | return 0; | |
50108304 MC |
126 | } |
127 | ||
636ca4ff | 128 | void async_fibre_free(async_fibre *fibre) |
50108304 | 129 | { |
f6f56f47 | 130 | stack_free_impl(fibre->fibre.uc_stack.ss_sp); |
6e8ac508 | 131 | fibre->fibre.uc_stack.ss_sp = NULL; |
50108304 | 132 | } |
f4da39d2 | 133 | |
50108304 | 134 | #endif |