Auto init/deinit libcrypto

This builds on the previous commit to auto initialise/deinitialise
libcrypto.

Reviewed-by: Richard Levitte <levitte@openssl.org>
This commit is contained in:
Matt Caswell
2016-02-08 16:43:03 +00:00
parent b184e3ef73
commit 7b9f8f7f03
45 changed files with 422 additions and 347 deletions

View File

@@ -62,6 +62,7 @@
#include "async_locl.h"
#include <openssl/err.h>
#include <internal/cryptlib_int.h>
#include <string.h>
#define ASYNC_JOB_RUNNING 0
@@ -94,6 +95,12 @@ err:
return NULL;
}
static async_ctx *async_get_ctx(void)
{
OPENSSL_INIT_crypto_library_start(OPENSSL_INIT_ASYNC, NULL);
return async_arch_get_ctx();
}
static int async_ctx_free(void)
{
async_ctx *ctx;
@@ -191,16 +198,17 @@ static void async_release_job(ASYNC_JOB *job) {
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
@@ -213,36 +221,39 @@ void async_start_func(void)
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;
@@ -252,41 +263,41 @@ int ASYNC_start_job(ASYNC_JOB **job, int *ret, int (*func)(void *),
/* 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;
}
@@ -295,10 +306,11 @@ 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.
@@ -306,11 +318,11 @@ int ASYNC_pause_job(void)
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;
}
@@ -331,14 +343,11 @@ static void async_empty_pool(async_pool *pool)
} while (job);
}
int ASYNC_init(int init_thread, size_t max_size, size_t init_size)
int async_init(void)
{
if (!async_global_init())
return 0;
if (init_thread)
return ASYNC_init_thread(max_size, init_size);
return 1;
}
@@ -352,10 +361,12 @@ int ASYNC_init_thread(size_t max_size, size_t init_size)
return 0;
}
if (!async_local_init()) {
ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_INIT_FAILED);
OPENSSL_INIT_crypto_library_start(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);
@@ -417,16 +428,6 @@ void ASYNC_cleanup_thread(void)
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;
@@ -464,25 +465,25 @@ void ASYNC_clear_wake(ASYNC_JOB *job)
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--;
}