-/* crypto/async/async.c */
/*
* Written by Matt Caswell (matt@openssl.org) for the OpenSSL project.
*/
*/
#undef _FORTIFY_SOURCE
+/* This must be the first #include file */
+#include "async_locl.h"
+
#include <openssl/err.h>
-#include <openssl/async.h>
+#include <internal/cryptlib_int.h>
#include <string.h>
-#include "async_locl.h"
#define ASYNC_JOB_RUNNING 0
#define ASYNC_JOB_PAUSING 1
return NULL;
}
+static async_ctx *async_get_ctx(void)
+{
+ OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL);
+ return async_arch_get_ctx();
+}
+
static int async_ctx_free(void)
{
async_ctx *ctx;
return NULL;
job = async_job_new();
- if (job) {
- async_fibre_makecontext(&job->fibrectx);
+ if (job != NULL) {
+ if (! async_fibre_makecontext(&job->fibrectx)) {
+ async_job_free(job);
+ return NULL;
+ }
pool->curr_size++;
}
}
void async_start_func(void)
{
ASYNC_JOB *job;
+ async_ctx *ctx = async_get_ctx();
while (1) {
/* Run the job */
- job = async_get_ctx()->currjob;
+ job = ctx->currjob;
job->ret = job->func(job->funcargs);
/* Stop the job */
job->status = ASYNC_JOB_STOPPING;
if (!async_fibre_swapcontext(&job->fibrectx,
- &async_get_ctx()->dispatcher, 1)) {
+ &ctx->dispatcher, 1)) {
/*
* Should not happen. Getting here will close the thread...can't do
* much about it
int ASYNC_start_job(ASYNC_JOB **job, int *ret, int (*func)(void *),
void *args, size_t size)
{
- if (async_get_ctx() == NULL && async_ctx_new() == NULL) {
+ async_ctx *ctx = async_get_ctx();
+ if (ctx == NULL)
+ ctx = async_ctx_new();
+ if (ctx == NULL) {
return ASYNC_ERR;
}
if (*job) {
- async_get_ctx()->currjob = *job;
+ ctx->currjob = *job;
}
for (;;) {
- if (async_get_ctx()->currjob != NULL) {
- if (async_get_ctx()->currjob->status == ASYNC_JOB_STOPPING) {
- *ret = async_get_ctx()->currjob->ret;
- async_release_job(async_get_ctx()->currjob);
- async_get_ctx()->currjob = NULL;
+ if (ctx->currjob != NULL) {
+ if (ctx->currjob->status == ASYNC_JOB_STOPPING) {
+ *ret = ctx->currjob->ret;
+ async_release_job(ctx->currjob);
+ ctx->currjob = NULL;
*job = NULL;
return ASYNC_FINISH;
}
- if (async_get_ctx()->currjob->status == ASYNC_JOB_PAUSING) {
- *job = async_get_ctx()->currjob;
- async_get_ctx()->currjob->status = ASYNC_JOB_PAUSED;
- async_get_ctx()->currjob = NULL;
+ if (ctx->currjob->status == ASYNC_JOB_PAUSING) {
+ *job = ctx->currjob;
+ ctx->currjob->status = ASYNC_JOB_PAUSED;
+ ctx->currjob = NULL;
return ASYNC_PAUSE;
}
- if (async_get_ctx()->currjob->status == ASYNC_JOB_PAUSED) {
- async_get_ctx()->currjob = *job;
+ if (ctx->currjob->status == ASYNC_JOB_PAUSED) {
+ ctx->currjob = *job;
/* Resume previous job */
- if (!async_fibre_swapcontext(&async_get_ctx()->dispatcher,
- &async_get_ctx()->currjob->fibrectx, 1)) {
+ if (!async_fibre_swapcontext(&ctx->dispatcher,
+ &ctx->currjob->fibrectx, 1)) {
ASYNCerr(ASYNC_F_ASYNC_START_JOB,
ASYNC_R_FAILED_TO_SWAP_CONTEXT);
goto err;
/* Should not happen */
ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_INTERNAL_ERROR);
- async_release_job(async_get_ctx()->currjob);
- async_get_ctx()->currjob = NULL;
+ async_release_job(ctx->currjob);
+ ctx->currjob = NULL;
*job = NULL;
return ASYNC_ERR;
}
/* Start a new job */
- if ((async_get_ctx()->currjob = async_get_pool_job()) == NULL) {
+ if ((ctx->currjob = async_get_pool_job()) == NULL) {
return ASYNC_NO_JOBS;
}
if (args != NULL) {
- async_get_ctx()->currjob->funcargs = OPENSSL_malloc(size);
- if (async_get_ctx()->currjob->funcargs == NULL) {
+ ctx->currjob->funcargs = OPENSSL_malloc(size);
+ if (ctx->currjob->funcargs == NULL) {
ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_MALLOC_FAILURE);
- async_release_job(async_get_ctx()->currjob);
- async_get_ctx()->currjob = NULL;
+ async_release_job(ctx->currjob);
+ ctx->currjob = NULL;
return ASYNC_ERR;
}
- memcpy(async_get_ctx()->currjob->funcargs, args, size);
+ memcpy(ctx->currjob->funcargs, args, size);
} else {
- async_get_ctx()->currjob->funcargs = NULL;
+ ctx->currjob->funcargs = NULL;
}
- async_get_ctx()->currjob->func = func;
- if (!async_fibre_swapcontext(&async_get_ctx()->dispatcher,
- &async_get_ctx()->currjob->fibrectx, 1)) {
+ ctx->currjob->func = func;
+ if (!async_fibre_swapcontext(&ctx->dispatcher,
+ &ctx->currjob->fibrectx, 1)) {
ASYNCerr(ASYNC_F_ASYNC_START_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
goto err;
}
}
err:
- async_release_job(async_get_ctx()->currjob);
- async_get_ctx()->currjob = NULL;
+ async_release_job(ctx->currjob);
+ ctx->currjob = NULL;
*job = NULL;
return ASYNC_ERR;
}
int ASYNC_pause_job(void)
{
ASYNC_JOB *job;
+ async_ctx *ctx = async_get_ctx();
- if (async_get_ctx() == NULL
- || async_get_ctx()->currjob == NULL
- || async_get_ctx()->blocked) {
+ if (ctx == NULL
+ || ctx->currjob == NULL
+ || ctx->blocked) {
/*
* Could be we've deliberately not been started within a job so this is
* counted as success.
return 1;
}
- job = async_get_ctx()->currjob;
+ job = ctx->currjob;
job->status = ASYNC_JOB_PAUSING;
if (!async_fibre_swapcontext(&job->fibrectx,
- &async_get_ctx()->dispatcher, 1)) {
+ &ctx->dispatcher, 1)) {
ASYNCerr(ASYNC_F_ASYNC_PAUSE_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
return 0;
}
} while (job);
}
-int ASYNC_init(int init_thread, size_t max_size, size_t init_size)
+int async_init(void)
{
- if (!async_thread_local_init())
+ if (!async_global_init())
return 0;
- if (init_thread)
- return ASYNC_init_thread(max_size, init_size);
-
return 1;
}
return 0;
}
+ OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL);
+ if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ASYNC)) {
+ ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
pool = OPENSSL_zalloc(sizeof *pool);
if (pool == NULL) {
ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE);
pool->max_size = max_size;
/* Pre-create jobs as required */
- while (init_size) {
+ while (init_size--) {
ASYNC_JOB *job;
job = async_job_new();
- if (job) {
- async_fibre_makecontext(&job->fibrectx);
- job->funcargs = NULL;
- sk_ASYNC_JOB_push(pool->jobs, job);
- curr_size++;
- init_size--;
- } else {
+ if (job == NULL || !async_fibre_makecontext(&job->fibrectx)) {
/*
- * Not actually fatal because we already created the pool, just skip
- * creation of any more jobs
+ * Not actually fatal because we already created the pool, just
+ * skip creation of any more jobs
*/
- init_size = 0;
+ async_job_free(job);
+ break;
}
+ job->funcargs = NULL;
+ sk_ASYNC_JOB_push(pool->jobs, job);
+ curr_size++;
}
pool->curr_size = curr_size;
-
if (!async_set_pool(pool)) {
ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_FAILED_TO_SET_POOL);
goto err;
sk_ASYNC_JOB_free(pool->jobs);
OPENSSL_free(pool);
(void)async_set_pool(NULL);
+ async_local_cleanup();
async_ctx_free();
}
async_free_pool_internal(async_get_pool());
}
-void ASYNC_cleanup(int cleanupthread)
-{
- /*
- * We don't actually have any global cleanup at the moment so just cleanup
- * the thread
- */
- if (cleanupthread)
- ASYNC_cleanup_thread();
-}
-
ASYNC_JOB *ASYNC_get_current_job(void)
{
async_ctx *ctx;
void ASYNC_block_pause(void)
{
- if (async_get_ctx() == NULL
- || async_get_ctx()->currjob == NULL) {
+ async_ctx *ctx = async_get_ctx();
+ if (ctx == NULL || ctx->currjob == NULL) {
/*
* We're not in a job anyway so ignore this
*/
return;
}
- async_get_ctx()->blocked++;
+ ctx->blocked++;
}
void ASYNC_unblock_pause(void)
{
- if (async_get_ctx() == NULL
- || async_get_ctx()->currjob == NULL) {
+ async_ctx *ctx = async_get_ctx();
+ if (ctx == NULL || ctx->currjob == NULL) {
/*
* We're not in a job anyway so ignore this
*/
return;
}
- if(async_get_ctx()->blocked > 0)
- async_get_ctx()->blocked--;
+ if(ctx->blocked > 0)
+ ctx->blocked--;
}