return 0;
}
+int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
+ ASYNC_stack_free_fn free_fn)
+{
+ return 0;
+}
+
+void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
+ ASYNC_stack_free_fn *free_fn)
+{
+ if (alloc_fn != NULL)
+ *alloc_fn = NULL;
+ if (free_fn != NULL)
+ *free_fn = NULL;
+}
+
void async_local_cleanup(void)
{
}
#define STACKSIZE 32768
+static void *async_stack_alloc(size_t *num);
+static void async_stack_free(void *addr);
+
+static int allow_customize = 1;
+static ASYNC_stack_alloc_fn stack_alloc_impl = async_stack_alloc;
+static ASYNC_stack_free_fn stack_free_impl = async_stack_free;
+
int ASYNC_is_capable(void)
{
ucontext_t ctx;
return getcontext(&ctx) == 0;
}
+int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
+ ASYNC_stack_free_fn free_fn)
+{
+ if (!allow_customize)
+ return 0;
+ if (alloc_fn != NULL)
+ stack_alloc_impl = alloc_fn;
+ if (free_fn != NULL)
+ stack_free_impl = free_fn;
+ return 1;
+}
+
+void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
+ ASYNC_stack_free_fn *free_fn)
+{
+ if (alloc_fn != NULL)
+ *alloc_fn = stack_alloc_impl;
+ if (free_fn != NULL)
+ *free_fn = stack_free_impl;
+}
+
+static void *async_stack_alloc(size_t *num)
+{
+ return OPENSSL_malloc(*num);
+}
+
+static void async_stack_free(void *addr)
+{
+ OPENSSL_free(addr);
+}
+
void async_local_cleanup(void)
{
}
fibre->env_init = 0;
#endif
if (getcontext(&fibre->fibre) == 0) {
- fibre->fibre.uc_stack.ss_sp = OPENSSL_malloc(STACKSIZE);
+ size_t num = STACKSIZE;
+
+ /*
+ * Disallow customisation after the first
+ * stack is allocated.
+ */
+ if (allow_customize)
+ allow_customize = 0;
+
+ fibre->fibre.uc_stack.ss_sp = stack_alloc_impl(&num);
if (fibre->fibre.uc_stack.ss_sp != NULL) {
- fibre->fibre.uc_stack.ss_size = STACKSIZE;
+ fibre->fibre.uc_stack.ss_size = num;
fibre->fibre.uc_link = NULL;
makecontext(&fibre->fibre, async_start_func, 0);
return 1;
void async_fibre_free(async_fibre *fibre)
{
- OPENSSL_free(fibre->fibre.uc_stack.ss_sp);
+ stack_free_impl(fibre->fibre.uc_stack.ss_sp);
fibre->fibre.uc_stack.ss_sp = NULL;
}
return 1;
}
+int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
+ ASYNC_stack_free_fn free_fn)
+{
+ return 0;
+}
+
+void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
+ ASYNC_stack_free_fn *free_fn)
+{
+ if (alloc_fn != NULL)
+ *alloc_fn = NULL;
+ if (free_fn != NULL)
+ *free_fn = NULL;
+}
+
void async_local_cleanup(void)
{
async_ctx *ctx = async_get_ctx();
ASYNC_get_wait_ctx,
ASYNC_init_thread, ASYNC_cleanup_thread, ASYNC_start_job, ASYNC_pause_job,
-ASYNC_get_current_job, ASYNC_block_pause, ASYNC_unblock_pause, ASYNC_is_capable
+ASYNC_get_current_job, ASYNC_block_pause, ASYNC_unblock_pause, ASYNC_is_capable,
+ASYNC_stack_alloc_fn, ASYNC_stack_free_fn, ASYNC_set_mem_functions, ASYNC_get_mem_functions
- asynchronous job management functions
=head1 SYNOPSIS
int ASYNC_is_capable(void);
+ typedef void *(*ASYNC_stack_alloc_fn)(size_t *num);
+ typedef void (*ASYNC_stack_free_fn)(void *addr);
+ int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
+ ASYNC_stack_free_fn free_fn);
+ void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
+ ASYNC_stack_free_fn *free_fn);
+
=head1 DESCRIPTION
OpenSSL implements asynchronous capabilities through an B<ASYNC_JOB>. This
Some platforms cannot support async operations. The ASYNC_is_capable() function
can be used to detect whether the current platform is async capable or not.
+Custom memory allocation functions are supported for the POSIX platform.
+Custom memory allocation functions allow alternative methods of allocating
+stack memory such as mmap, or using stack memory from the current thread.
+Using an ASYNC_stack_alloc_fn callback also allows manipulation of the stack
+size, which defaults to 32k.
+The stack size can be altered by allocating a stack of a size different to
+the requested size, and passing back the new stack size in the callback's I<*num>
+parameter.
+
=head1 RETURN VALUES
ASYNC_init_thread returns 1 on success or 0 otherwise.
ASYNC_is_capable() returns 1 if the current platform is async capable or 0
otherwise.
+ASYNC_set_mem_functions returns 1 if custom stack allocators are supported by
+the current platform and no allocations have already occurred or 0 otherwise.
+
=head1 NOTES
On Windows platforms the F<< <openssl/async.h> >> header is dependent on some
int ASYNC_is_capable(void);
+typedef void *(*ASYNC_stack_alloc_fn)(size_t *num);
+typedef void (*ASYNC_stack_free_fn)(void *addr);
+
+int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
+ ASYNC_stack_free_fn free_fn);
+void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
+ ASYNC_stack_free_fn *free_fn);
+
int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *ctx, int *ret,
int (*func)(void *), void *args, size_t size);
int ASYNC_pause_job(void);
static int ctr = 0;
static ASYNC_JOB *currjob = NULL;
+static int custom_alloc_used = 0;
+static int custom_free_used = 0;
static int only_pause(void *args)
{
return ret;
}
+static void *test_alloc_stack(size_t *num)
+{
+ custom_alloc_used = 1;
+ return OPENSSL_malloc(*num);
+}
+
+static void test_free_stack(void *addr)
+{
+ custom_free_used = 1;
+ OPENSSL_free(addr);
+}
+
+static int test_ASYNC_set_mem_functions(void)
+{
+ ASYNC_stack_alloc_fn alloc_fn;
+ ASYNC_stack_free_fn free_fn;
+
+ /* Not all platforms support this */
+ if (ASYNC_set_mem_functions(test_alloc_stack, test_free_stack) == 0) return 1;
+
+ ASYNC_get_mem_functions(&alloc_fn, &free_fn);
+
+ if ((alloc_fn != test_alloc_stack) || (free_fn != test_free_stack)) {
+ fprintf(stderr,
+ "test_ASYNC_set_mem_functions() - setting and retrieving custom allocators failed\n");
+ return 0;
+ }
+
+ if (!ASYNC_init_thread(1, 1)) {
+ fprintf(stderr,
+ "test_ASYNC_set_mem_functions() - failed initialising ctx pool\n");
+ return 0;
+ }
+ ASYNC_cleanup_thread();
+
+ if (!custom_alloc_used || !custom_free_used) {
+ fprintf(stderr,
+ "test_ASYNC_set_mem_functions() - custom allocation functions not used\n");
+
+ return 0;
+ }
+
+ return 1;
+}
+
int main(int argc, char **argv)
{
if (!ASYNC_is_capable()) {
|| !test_ASYNC_get_current_job()
|| !test_ASYNC_WAIT_CTX_get_all_fds()
|| !test_ASYNC_block_pause()
- || !test_ASYNC_start_job_ex()) {
+ || !test_ASYNC_start_job_ex()
+ || !test_ASYNC_set_mem_functions()) {
return 1;
}
}
BN_signed_bn2lebin ? 3_1_0 EXIST::FUNCTION:
BN_signed_native2bn ? 3_1_0 EXIST::FUNCTION:
BN_signed_bn2native ? 3_1_0 EXIST::FUNCTION:
+ASYNC_set_mem_functions ? 3_1_0 EXIST::FUNCTION:
+ASYNC_get_mem_functions ? 3_1_0 EXIST::FUNCTION:
custom_ext_parse_cb datatype
pem_password_cb datatype
ssl_ct_validation_cb datatype
+ASYNC_stack_alloc_fn datatype
+ASYNC_stack_free_fn datatype
#
ASN1_BIT_STRING_digest define
BIO_append_filename define