提交 22a34c2f 编写于 作者: M Matt Caswell

Implement windows async thread local variable support

Implements Thread Local Storage in the windows async port. This also has
some knock on effects to the posix and null implementations.
Reviewed-by: NRich Salz <rsalz@openssl.org>
上级 68487a9b
......@@ -76,10 +76,23 @@ int async_read1(OSSL_ASYNC_FD fd, void *buf)
return -1;
}
int async_thread_local_init(void)
int async_global_init(void)
{
return 0;
}
int async_local_init(void)
{
return 0;
}
void async_local_cleanup(void)
{
}
void async_global_cleanup(void)
{
}
#endif
......@@ -66,7 +66,7 @@ pthread_key_t posixpool;
#define STACKSIZE 32768
int async_thread_local_init(void)
int async_global_init(void)
{
if (pthread_key_create(&posixctx, NULL) != 0
|| pthread_key_create(&posixpool, NULL) != 0)
......@@ -75,6 +75,22 @@ int async_thread_local_init(void)
return 1;
}
int async_local_init(void)
{
if (!async_set_ctx(NULL) || ! async_set_pool(NULL))
return 0;
return 1;
}
void async_local_cleanup(void)
{
}
void async_global_cleanup(void)
{
}
int async_fibre_init(async_fibre *fibre)
{
void *stack = NULL;
......
......@@ -64,18 +64,80 @@ struct winpool {
size_t max_size;
};
static DWORD asyncwinpool = 0;
static DWORD asyncwinctx = 0;
static DWORD asyncwindispatch = 0;
void async_start_func(void);
int async_global_init(void)
{
asyncwinpool = TlsAlloc();
asyncwinctx = TlsAlloc();
asyncwindispatch = TlsAlloc();
if (asyncwinpool == TLS_OUT_OF_INDEXES || asyncwinctx == TLS_OUT_OF_INDEXES
|| asyncwindispatch == TLS_OUT_OF_INDEXES) {
if (asyncwinpool != TLS_OUT_OF_INDEXES) {
TlsFree(asyncwinpool);
}
if (asyncwinctx != TLS_OUT_OF_INDEXES) {
TlsFree(asyncwinctx);
}
if (asyncwindispatch != TLS_OUT_OF_INDEXES) {
TlsFree(asyncwindispatch);
}
return 0;
}
return 1;
}
int async_local_init(void)
{
return (TlsSetValue(asyncwinpool, NULL) != 0)
&& (TlsSetValue(asyncwinctx, NULL) != 0)
&& (TlsSetValue(asyncwindispatch, NULL) != 0);
}
void async_local_cleanup(void)
{
async_ctx *ctx = async_get_ctx();
if (ctx != NULL) {
async_fibre *fibre = &ctx->dispatcher;
if(fibre != NULL && fibre->fibre != NULL && fibre->converted) {
ConvertFiberToThread();
fibre->fibre = NULL;
}
}
}
void async_global_cleanup(void)
{
TlsFree(asyncwinpool);
TlsFree(asyncwinctx);
TlsFree(asyncwindispatch);
asyncwinpool = 0;
asyncwinctx = 0;
asyncwindispatch = 0;
}
int async_fibre_init_dispatcher(async_fibre *fibre)
{
LPVOID dispatcher;
dispatcher =
(LPVOID) CRYPTO_get_thread_local(CRYPTO_THREAD_LOCAL_ASYNC_DISPATCH);
dispatcher = (LPVOID)TlsGetValue(asyncwindispatch);
if (dispatcher == NULL) {
fibre->fibre = ConvertThreadToFiber(NULL);
CRYPTO_set_thread_local(CRYPTO_THREAD_LOCAL_ASYNC_DISPATCH,
(void *)fibre->fibre);
if (fibre->fibre == NULL) {
fibre->converted = 0;
fibre->fibre = GetCurrentFiber();
if (fibre->fibre == NULL)
return 0;
} else {
fibre->converted = 1;
}
if (TlsSetValue(asyncwindispatch, (LPVOID)fibre->fibre) == 0)
return 0;
} else {
fibre->fibre = dispatcher;
}
......@@ -125,15 +187,23 @@ int async_read1(OSSL_ASYNC_FD fd, void *buf)
async_pool *async_get_pool(void)
{
return (async_pool *)
CRYPTO_get_thread_local(CRYPTO_THREAD_LOCAL_ASYNC_POOL);
return (async_pool *)TlsGetValue(asyncwinpool);
}
int async_set_pool(async_pool *pool)
{
CRYPTO_set_thread_local(CRYPTO_THREAD_LOCAL_ASYNC_POOL, (void *)pool);
return 1;
return TlsSetValue(asyncwinpool, (LPVOID)pool) != 0;
}
async_ctx *async_get_ctx(void)
{
return (async_ctx *)TlsGetValue(asyncwinctx);
}
int async_set_ctx(async_ctx *ctx)
{
return TlsSetValue(asyncwinctx, (LPVOID)ctx) != 0;
}
#endif
......@@ -66,18 +66,18 @@
typedef struct async_fibre_st {
LPVOID fibre;
int converted;
} async_fibre;
# define async_set_ctx(nctx) \
(CRYPTO_set_thread_local(CRYPTO_THREAD_LOCAL_ASYNC_CTX, (void *)(nctx)))
# define async_get_ctx() \
((async_ctx *)CRYPTO_get_thread_local(CRYPTO_THREAD_LOCAL_ASYNC_CTX))
# define async_fibre_swapcontext(o,n,r) \
(SwitchToFiber((n)->fibre), 1)
# define async_fibre_makecontext(c) \
((c)->fibre = CreateFiber(0, async_start_func_win, 0))
# define async_fibre_free(f) (DeleteFiber((f)->fibre))
async_ctx *async_get_ctx(void);
int async_set_ctx(async_ctx *ctx);
int async_fibre_init_dispatcher(async_fibre *fibre);
VOID CALLBACK async_start_func_win(PVOID unused);
......
......@@ -330,7 +330,7 @@ static void async_empty_pool(async_pool *pool)
int ASYNC_init(int init_thread, size_t max_size, size_t init_size)
{
if (!async_thread_local_init())
if (!async_global_init())
return 0;
if (init_thread)
......@@ -349,6 +349,10 @@ 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);
return 0;
}
pool = OPENSSL_zalloc(sizeof *pool);
if (pool == NULL) {
ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE);
......@@ -383,7 +387,6 @@ int ASYNC_init_thread(size_t max_size, size_t init_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;
......@@ -404,6 +407,7 @@ static void async_free_pool_internal(async_pool *pool)
sk_ASYNC_JOB_free(pool->jobs);
OPENSSL_free(pool);
(void)async_set_pool(NULL);
async_local_cleanup();
async_ctx_free();
}
......
......@@ -83,6 +83,7 @@ static ERR_STRING_DATA ASYNC_str_reasons[] = {
{ERR_REASON(ASYNC_R_CANNOT_CREATE_WAIT_PIPE), "cannot create wait pipe"},
{ERR_REASON(ASYNC_R_FAILED_TO_SET_POOL), "failed to set pool"},
{ERR_REASON(ASYNC_R_FAILED_TO_SWAP_CONTEXT), "failed to swap context"},
{ERR_REASON(ASYNC_R_INIT_FAILED), "init failed"},
{ERR_REASON(ASYNC_R_INVALID_POOL_SIZE), "invalid pool size"},
{ERR_REASON(ASYNC_R_POOL_ALREADY_INITED), "pool already inited"},
{0, NULL}
......
......@@ -86,7 +86,10 @@ struct async_pool_st {
size_t max_size;
};
int async_thread_local_init(void);
int async_global_init(void);
int async_local_init(void);
void async_local_cleanup(void);
void async_global_cleanup(void);
void async_start_func(void);
int async_pipe(OSSL_ASYNC_FD *pipefds);
int async_close_fd(OSSL_ASYNC_FD fd);
......
......@@ -112,6 +112,7 @@ void ERR_load_ASYNC_strings(void);
# define ASYNC_R_CANNOT_CREATE_WAIT_PIPE 100
# define ASYNC_R_FAILED_TO_SET_POOL 101
# define ASYNC_R_FAILED_TO_SWAP_CONTEXT 102
# define ASYNC_R_INIT_FAILED 105
# define ASYNC_R_INVALID_POOL_SIZE 103
# define ASYNC_R_POOL_ALREADY_INITED 104
......
......@@ -4661,3 +4661,5 @@ ASYNC_get_wait_fd 5020 EXIST::FUNCTION:
ERR_load_ASYNC_strings 5021 EXIST::FUNCTION:
ASYNC_unblock_pause 5022 EXIST::FUNCTION:
ASYNC_block_pause 5023 EXIST::FUNCTION:
ASYNC_cleanup 5024 EXIST::FUNCTION:
ASYNC_init 5025 EXIST::FUNCTION:
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册