From 252d6d3aa62dccf0dc826644b7da0b6bafa3831b Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Wed, 22 Jul 2015 17:50:51 +0100 Subject: [PATCH] Add ASYNC_JOB pools It is expensive to create the ASYNC_JOB objects due to the "makecontext" call. This change adds support for pools of ASYNC_JOB objects so that we don't have to create a new ASYNC_JOB every time we want to use one. Reviewed-by: Rich Salz --- apps/Makefile | 46 ++++++------- apps/s_server.c | 8 ++- crypto/async/async.c | 126 ++++++++++++++++++++++++++++++------ include/openssl/async.h | 8 ++- include/openssl/safestack.h | 23 +++++++ util/libeay.num | 2 + 6 files changed, 168 insertions(+), 45 deletions(-) diff --git a/apps/Makefile b/apps/Makefile index 932f615146..a6d931c91c 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -802,29 +802,29 @@ s_client.o: ../include/openssl/tls1.h ../include/openssl/txt_db.h s_client.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h s_client.o: ../include/openssl/x509v3.h apps.h progs.h s_apps.h s_client.c s_client.o: timeouts.h -s_server.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h -s_server.o: ../include/openssl/bn.h ../include/openssl/buffer.h -s_server.o: ../include/openssl/comp.h ../include/openssl/conf.h -s_server.o: ../include/openssl/crypto.h ../include/openssl/dh.h -s_server.o: ../include/openssl/dtls1.h ../include/openssl/e_os2.h -s_server.o: ../include/openssl/ec.h ../include/openssl/ecdh.h -s_server.o: ../include/openssl/ecdsa.h ../include/openssl/engine.h -s_server.o: ../include/openssl/err.h ../include/openssl/evp.h -s_server.o: ../include/openssl/hmac.h ../include/openssl/lhash.h -s_server.o: ../include/openssl/obj_mac.h ../include/openssl/objects.h -s_server.o: ../include/openssl/ocsp.h ../include/openssl/opensslconf.h -s_server.o: ../include/openssl/opensslv.h ../include/openssl/ossl_typ.h -s_server.o: ../include/openssl/pem.h ../include/openssl/pem2.h -s_server.o: ../include/openssl/pkcs7.h ../include/openssl/rand.h -s_server.o: ../include/openssl/rsa.h ../include/openssl/safestack.h -s_server.o: ../include/openssl/sha.h ../include/openssl/srp.h -s_server.o: ../include/openssl/srtp.h ../include/openssl/ssl.h -s_server.o: ../include/openssl/ssl2.h ../include/openssl/ssl3.h -s_server.o: ../include/openssl/stack.h ../include/openssl/symhacks.h -s_server.o: ../include/openssl/tls1.h ../include/openssl/txt_db.h -s_server.o: ../include/openssl/x509.h ../include/openssl/x509_vfy.h -s_server.o: ../include/openssl/x509v3.h apps.h progs.h s_apps.h s_server.c -s_server.o: timeouts.h +s_server.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/async.h +s_server.o: ../include/openssl/bio.h ../include/openssl/bn.h +s_server.o: ../include/openssl/buffer.h ../include/openssl/comp.h +s_server.o: ../include/openssl/conf.h ../include/openssl/crypto.h +s_server.o: ../include/openssl/dh.h ../include/openssl/dtls1.h +s_server.o: ../include/openssl/e_os2.h ../include/openssl/ec.h +s_server.o: ../include/openssl/ecdh.h ../include/openssl/ecdsa.h +s_server.o: ../include/openssl/engine.h ../include/openssl/err.h +s_server.o: ../include/openssl/evp.h ../include/openssl/hmac.h +s_server.o: ../include/openssl/lhash.h ../include/openssl/obj_mac.h +s_server.o: ../include/openssl/objects.h ../include/openssl/ocsp.h +s_server.o: ../include/openssl/opensslconf.h ../include/openssl/opensslv.h +s_server.o: ../include/openssl/ossl_typ.h ../include/openssl/pem.h +s_server.o: ../include/openssl/pem2.h ../include/openssl/pkcs7.h +s_server.o: ../include/openssl/rand.h ../include/openssl/rsa.h +s_server.o: ../include/openssl/safestack.h ../include/openssl/sha.h +s_server.o: ../include/openssl/srp.h ../include/openssl/srtp.h +s_server.o: ../include/openssl/ssl.h ../include/openssl/ssl2.h +s_server.o: ../include/openssl/ssl3.h ../include/openssl/stack.h +s_server.o: ../include/openssl/symhacks.h ../include/openssl/tls1.h +s_server.o: ../include/openssl/txt_db.h ../include/openssl/x509.h +s_server.o: ../include/openssl/x509_vfy.h ../include/openssl/x509v3.h apps.h +s_server.o: progs.h s_apps.h s_server.c timeouts.h s_socket.o: ../e_os.h ../include/openssl/asn1.h ../include/openssl/bio.h s_socket.o: ../include/openssl/buffer.h ../include/openssl/comp.h s_socket.o: ../include/openssl/conf.h ../include/openssl/crypto.h diff --git a/apps/s_server.c b/apps/s_server.c index 548eacbbce..6fb8f675a3 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -143,6 +143,7 @@ #include #include #include +#include #include @@ -1657,8 +1658,10 @@ int s_server_main(int argc, char *argv[]) else SSL_CTX_sess_set_cache_size(ctx, 128); - if (async) + if (async) { SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC); + ASYNC_init_pool(0, 0, 0); + } #ifndef OPENSSL_NO_SRTP if (srtp_profiles != NULL) { @@ -1970,6 +1973,9 @@ int s_server_main(int argc, char *argv[]) bio_s_out = NULL; BIO_free(bio_s_msg); bio_s_msg = NULL; + if (async) { + ASYNC_free_pool(); + } return (ret); } diff --git a/crypto/async/async.c b/crypto/async/async.c index c0f362e2c8..6fed1979f9 100644 --- a/crypto/async/async.c +++ b/crypto/async/async.c @@ -61,6 +61,12 @@ #define ASYNC_JOB_PAUSED 2 #define ASYNC_JOB_STOPPING 3 +static size_t pool_max_size = 0; +static size_t curr_size = 0; + +DECLARE_STACK_OF(ASYNC_JOB) +static STACK_OF(ASYNC_JOB) *pool = NULL; + static ASYNC_CTX *ASYNC_CTX_new(void) { @@ -121,22 +127,60 @@ static void ASYNC_JOB_free(ASYNC_JOB *job) } } -void ASYNC_start_func(void) -{ +static ASYNC_JOB *async_get_pool_job(void) { ASYNC_JOB *job; - /* Run the job */ - job = ASYNC_get_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, 0)) { + if (pool == NULL) { /* - * Should not happen. Getting here will close the thread...can't do much - * about it + * Pool has not been initialised, so init with the defaults, i.e. + * global pool, with no max size and no pre-created jobs */ + if (ASYNC_init_pool(0, 0, 0) == 0) + return NULL; + } + + job = sk_ASYNC_JOB_pop(pool); + if (job == NULL) { + /* Pool is empty */ + if (pool_max_size && curr_size >= pool_max_size) { + /* Pool is at max size. We cannot continue */ + return NULL; + } + job = ASYNC_JOB_new(); + if (job) { + ASYNC_FIBRE_makecontext(&job->fibrectx); + curr_size++; + } + } + return job; +} + +static void async_release_job(ASYNC_JOB *job) { + if(job->funcargs) + OPENSSL_free(job->funcargs); + job->funcargs = NULL; + /* Ignore error return */ + sk_ASYNC_JOB_push(pool, job); +} + +void ASYNC_start_func(void) +{ + ASYNC_JOB *job; + + while (1) { + /* Run the job */ + job = ASYNC_get_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)) { + /* + * Should not happen. Getting here will close the thread...can't do much + * about it + */ + } } } @@ -155,7 +199,7 @@ int ASYNC_start_job(ASYNC_JOB **job, int *ret, int (*func)(void *), if(ASYNC_get_ctx()->currjob) { if(ASYNC_get_ctx()->currjob->status == ASYNC_JOB_STOPPING) { *ret = ASYNC_get_ctx()->currjob->ret; - ASYNC_JOB_free(ASYNC_get_ctx()->currjob); + async_release_job(ASYNC_get_ctx()->currjob); ASYNC_get_ctx()->currjob = NULL; *job = NULL; ASYNC_CTX_free(); @@ -179,7 +223,7 @@ int ASYNC_start_job(ASYNC_JOB **job, int *ret, int (*func)(void *), } /* Should not happen */ - ASYNC_JOB_free(ASYNC_get_ctx()->currjob); + async_release_job(ASYNC_get_ctx()->currjob); ASYNC_get_ctx()->currjob = NULL; *job = NULL; ASYNC_CTX_free(); @@ -187,15 +231,15 @@ int ASYNC_start_job(ASYNC_JOB **job, int *ret, int (*func)(void *), } /* Start a new job */ - if(!(ASYNC_get_ctx()->currjob = ASYNC_JOB_new())) { + if(!(ASYNC_get_ctx()->currjob = async_get_pool_job())) { ASYNC_CTX_free(); - return ASYNC_ERR; + return ASYNC_NO_JOBS; } if(args != NULL) { ASYNC_get_ctx()->currjob->funcargs = OPENSSL_malloc(size); if(!ASYNC_get_ctx()->currjob->funcargs) { - ASYNC_JOB_free(ASYNC_get_ctx()->currjob); + async_release_job(ASYNC_get_ctx()->currjob); ASYNC_get_ctx()->currjob = NULL; ASYNC_CTX_free(); return ASYNC_ERR; @@ -206,14 +250,13 @@ int ASYNC_start_job(ASYNC_JOB **job, int *ret, int (*func)(void *), } ASYNC_get_ctx()->currjob->func = func; - ASYNC_FIBRE_makecontext(&ASYNC_get_ctx()->currjob->fibrectx); if(!ASYNC_FIBRE_swapcontext(&ASYNC_get_ctx()->dispatcher, &ASYNC_get_ctx()->currjob->fibrectx, 1)) goto err; } err: - ASYNC_JOB_free(ASYNC_get_ctx()->currjob); + async_release_job(ASYNC_get_ctx()->currjob); ASYNC_get_ctx()->currjob = NULL; *job = NULL; ASYNC_CTX_free(); @@ -247,3 +290,48 @@ int ASYNC_in_job(void) return 0; } + +int ASYNC_init_pool(unsigned int local, size_t max_size, size_t init_size) +{ + if (local != 0) { + /* We only support a global pool so far */ + return 0; + } + + pool_max_size = max_size; + pool = sk_ASYNC_JOB_new_null(); + if (pool == NULL) { + return 0; + } + /* Pre-create jobs as required */ + 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, job); + curr_size++; + init_size--; + } else { + /* + * Not actually fatal because we already created the pool, just skip + * creation of any more jobs + */ + init_size = 0; + } + } + + return 1; +} + +void ASYNC_free_pool(void) +{ + ASYNC_JOB *job; + + do { + job = sk_ASYNC_JOB_pop(pool); + ASYNC_JOB_free(job); + } while (job); + sk_ASYNC_JOB_free(pool); +} diff --git a/include/openssl/async.h b/include/openssl/async.h index ff5985748d..1cd799202f 100644 --- a/include/openssl/async.h +++ b/include/openssl/async.h @@ -63,8 +63,12 @@ extern "C" { typedef struct async_job_st ASYNC_JOB; #define ASYNC_ERR 0 -#define ASYNC_PAUSE 1 -#define ASYNC_FINISH 2 +#define ASYNC_NO_JOBS 1 +#define ASYNC_PAUSE 2 +#define ASYNC_FINISH 3 + +int ASYNC_init_pool(unsigned int local, size_t max_size, size_t init_size); +void ASYNC_free_pool(void); int ASYNC_start_job(ASYNC_JOB **job, int *ret, int (*func)(void *), void *args, size_t size); diff --git a/include/openssl/safestack.h b/include/openssl/safestack.h index 785bec6ff2..f2fa57c460 100644 --- a/include/openssl/safestack.h +++ b/include/openssl/safestack.h @@ -412,6 +412,29 @@ DECLARE_SPECIAL_STACK_OF(OPENSSL_BLOCK, void) # define sk_ASN1_VALUE_sort(st) SKM_sk_sort(ASN1_VALUE, (st)) # define sk_ASN1_VALUE_is_sorted(st) SKM_sk_is_sorted(ASN1_VALUE, (st)) +# define sk_ASYNC_JOB_new(cmp) SKM_sk_new(ASYNC_JOB, (cmp)) +# define sk_ASYNC_JOB_new_null() SKM_sk_new_null(ASYNC_JOB) +# define sk_ASYNC_JOB_free(st) SKM_sk_free(ASYNC_JOB, (st)) +# define sk_ASYNC_JOB_num(st) SKM_sk_num(ASYNC_JOB, (st)) +# define sk_ASYNC_JOB_value(st, i) SKM_sk_value(ASYNC_JOB, (st), (i)) +# define sk_ASYNC_JOB_set(st, i, val) SKM_sk_set(ASYNC_JOB, (st), (i), (val)) +# define sk_ASYNC_JOB_zero(st) SKM_sk_zero(ASYNC_JOB, (st)) +# define sk_ASYNC_JOB_push(st, val) SKM_sk_push(ASYNC_JOB, (st), (val)) +# define sk_ASYNC_JOB_unshift(st, val) SKM_sk_unshift(ASYNC_JOB, (st), (val)) +# define sk_ASYNC_JOB_find(st, val) SKM_sk_find(ASYNC_JOB, (st), (val)) +# define sk_ASYNC_JOB_find_ex(st, val) SKM_sk_find_ex(ASYNC_JOB, (st), (val)) +# define sk_ASYNC_JOB_delete(st, i) SKM_sk_delete(ASYNC_JOB, (st), (i)) +# define sk_ASYNC_JOB_delete_ptr(st, ptr) SKM_sk_delete_ptr(ASYNC_JOB, (st), (ptr)) +# define sk_ASYNC_JOB_insert(st, val, i) SKM_sk_insert(ASYNC_JOB, (st), (val), (i)) +# define sk_ASYNC_JOB_set_cmp_func(st, cmp) SKM_sk_set_cmp_func(ASYNC_JOB, (st), (cmp)) +# define sk_ASYNC_JOB_dup(st) SKM_sk_dup(ASYNC_JOB, st) +# define sk_ASYNC_JOB_pop_free(st, free_func) SKM_sk_pop_free(ASYNC_JOB, (st), (free_func)) +# define sk_ASYNC_JOB_deep_copy(st, copy_func, free_func) SKM_sk_deep_copy(ASYNC_JOB, (st), (copy_func), (free_func)) +# define sk_ASYNC_JOB_shift(st) SKM_sk_shift(ASYNC_JOB, (st)) +# define sk_ASYNC_JOB_pop(st) SKM_sk_pop(ASYNC_JOB, (st)) +# define sk_ASYNC_JOB_sort(st) SKM_sk_sort(ASYNC_JOB, (st)) +# define sk_ASYNC_JOB_is_sorted(st) SKM_sk_is_sorted(ASYNC_JOB, (st)) + # define sk_BIO_new(cmp) SKM_sk_new(BIO, (cmp)) # define sk_BIO_new_null() SKM_sk_new_null(BIO) # define sk_BIO_free(st) SKM_sk_free(BIO, (st)) diff --git a/util/libeay.num b/util/libeay.num index 8a6c4c528e..4b6893d97f 100755 --- a/util/libeay.num +++ b/util/libeay.num @@ -4654,3 +4654,5 @@ ASYNC_pause_job 5013 EXIST::FUNCTION: ASYNC_job_is_waiting 5014 NOEXIST::FUNCTION: ASYNC_in_job 5015 EXIST::FUNCTION: ASYNC_start_job 5016 EXIST::FUNCTION: +ASYNC_init_pool 5017 EXIST::FUNCTION: +ASYNC_free_pool 5018 EXIST::FUNCTION: -- 2.34.1