Add a set of zlibwrapper interfaces for users to fit uadk interfaces quickly.
Changelog:
v1->v2: - Fix fork dead lock problem.
Yang Shen (2): uadk/comp - support reset session zlibwrapper: add zlibwrapper to adapt for zlib interface
Makefile.am | 2 +- include/wd_comp.h | 9 +- libwd_comp.map | 11 ++ wd_comp.c | 15 ++ wd_zlibwrapper.c | 343 ++++++++++++++++++++++++++++++++++++++++++++++ wd_zlibwrapper.h | 112 +++++++++++++++ 6 files changed, 490 insertions(+), 2 deletions(-) create mode 100644 wd_zlibwrapper.c create mode 100644 wd_zlibwrapper.h
-- 2.24.0
The 'stream_pos' in sess is automatically changed auto by uadk after a stream request is end. But sometimes users want to drop an old request and send a new request with the old sess.
So add the interface 'wd_comp_reset_sess' to allow the user set the 'stream_pos' to 'WD_COMP_STREAM_NEW' whenever they want.
Signed-off-by: Yang Shen shenyang39@huawei.com --- include/wd_comp.h | 9 ++++++++- wd_comp.c | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/include/wd_comp.h b/include/wd_comp.h index 782e5d2..45b0d0b 100644 --- a/include/wd_comp.h +++ b/include/wd_comp.h @@ -158,11 +158,18 @@ struct wd_comp_sess_setup { handle_t wd_comp_alloc_sess(struct wd_comp_sess_setup *setup);
/** - * wd_comp_free_sess() - Free a wd comp session. + * wd_comp_free_sess() - Free a wd comp session. * @h_sess: The sess to be freed. */ void wd_comp_free_sess(handle_t h_sess);
+/** + * wd_comp_reset_sess() - Reset a wd comp session. After reset h_sess, it can + * used for a new stream request. + * @h_sess: The sess to be reset. + */ +int wd_comp_reset_sess(handle_t h_sess); + /** * wd_do_comp_sync() - Send a sync compression request. * @h_sess: The session which request will be sent to. diff --git a/wd_comp.c b/wd_comp.c index 0e89304..32fda95 100644 --- a/wd_comp.c +++ b/wd_comp.c @@ -430,6 +430,21 @@ void wd_comp_free_sess(handle_t h_sess) free(sess); }
+int wd_comp_reset_sess(handle_t h_sess) +{ + struct wd_comp_sess *sess = (struct wd_comp_sess *)h_sess; + + if (!sess) { + WD_ERR("invalid: sess is NULL!\n"); + return -WD_EINVAL; + } + + sess->stream_pos = WD_COMP_STREAM_NEW; + memset(sess->ctx_buf, 0, HW_CTX_SIZE); + + return 0; +} + static void fill_comp_msg(struct wd_comp_sess *sess, struct wd_comp_msg *msg, struct wd_comp_req *req) {
The zlibwrapper is used for some users who want to use the uadk library without changing the app source code broad. They can change the app compression api only by calling the uadk zlibwrapper interface.
But there are some limits left for uadk zlibwrapper use scenes. First, only some useful interfaces are realized. The zlibwrapper only support test compression and decompression. Second, the zlib library has multiple flush types. But the uadk compression now only support the Z_SYNC_FLUSH and Z_FINISH, others are illegal.
Signed-off-by: Yang Shen shenyang39@huawei.com --- Makefile.am | 2 +- libwd_comp.map | 11 ++ wd_zlibwrapper.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++ wd_zlibwrapper.h | 112 ++++++++++++++++ 4 files changed, 467 insertions(+), 1 deletion(-) create mode 100644 wd_zlibwrapper.c create mode 100644 wd_zlibwrapper.h
diff --git a/Makefile.am b/Makefile.am index 4ef5c2c..ed41e4c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -62,7 +62,7 @@ libwd_la_SOURCES=wd.c wd_mempool.c wd.h \ v1/drv/hisi_rng_udrv.c v1/drv/hisi_rng_udrv.h
libwd_comp_la_SOURCES=wd_comp.c wd_comp.h wd_comp_drv.h wd_util.c wd_util.h \ - wd_sched.c wd_sched.h wd.c wd.h + wd_sched.c wd_sched.h wd.c wd.h wd_zlibwrapper.c wd_zlibwrapper.h
libhisi_zip_la_SOURCES=drv/hisi_comp.c hisi_comp.h drv/hisi_qm_udrv.c \ hisi_qm_udrv.h wd_comp_drv.h diff --git a/libwd_comp.map b/libwd_comp.map index eccec50..ce3e051 100644 --- a/libwd_comp.map +++ b/libwd_comp.map @@ -26,5 +26,16 @@ global: wd_sched_rr_alloc; wd_sched_rr_release;
+ wd_deflateInit_; + wd_deflateInit2_; + wd_deflate; + wd_deflateReset; + wd_deflateEnd; + wd_inflateInit_; + wd_inflateInit2_; + wd_inflate; + wd_inflateReset; + wd_inflateEnd; + local: *; }; diff --git a/wd_zlibwrapper.c b/wd_zlibwrapper.c new file mode 100644 index 0000000..441f4db --- /dev/null +++ b/wd_zlibwrapper.c @@ -0,0 +1,343 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2022 Huawei Technologies Co.,Ltd. All rights reserved. + */ + +/* === Dependencies === */ +#define _GNU_SOURCE + +#include <errno.h> +#include <math.h> +#include <numa.h> +#include <stdlib.h> +#include <stdio.h> + +#include "wd.h" +#include "wd_comp.h" +#include "wd_sched.h" +#include "wd_util.h" +#include "wd_zlibwrapper.h" +#include "drv/wd_comp_drv.h" + +#define max(a, b) ((a) > (b) ? (a) : (b)) + +enum uadk_init_status { + WD_ZLIB_UNINIT, + WD_ZLIB_INIT, +}; + +struct wd_zlibwrapper_config { + int count; + int status; +}; + +static pthread_mutex_t wd_zlib_mutex = PTHREAD_MUTEX_INITIALIZER; +static struct wd_zlibwrapper_config zlib_config = {0}; + +static void wd_zlib_unlock(void) +{ + pthread_mutex_unlock(&wd_zlib_mutex); + zlib_config.status = WD_ZLIB_UNINIT; +} + +static int wd_zlib_init(void) +{ + struct wd_ctx_nums *ctx_set_num; + struct wd_ctx_params cparams; + int ret, i; + + if (zlib_config.status == WD_ZLIB_INIT) + return 0; + + ctx_set_num = calloc(WD_DIR_MAX, sizeof(*ctx_set_num)); + if (!ctx_set_num) { + WD_ERR("failed to alloc ctx_set_size!\n"); + return -WD_ENOMEM; + } + + cparams.op_type_num = WD_DIR_MAX; + cparams.ctx_set_num = ctx_set_num; + cparams.bmp = numa_allocate_nodemask(); + if (!cparams.bmp) { + WD_ERR("failed to create nodemask!\n"); + ret = -WD_ENOMEM; + goto out_freectx; + } + + numa_bitmask_setall(cparams.bmp); + + for (i = 0; i < WD_DIR_MAX; i++) + ctx_set_num[i].sync_ctx_num = 2; + + ret = wd_comp_init2_("zlib", 0, 0, &cparams); + if (ret) + goto out_freebmp; + + zlib_config.status = WD_ZLIB_INIT; + +out_freebmp: + numa_free_nodemask(cparams.bmp); + +out_freectx: + free(ctx_set_num); + + return ret; +} + +static void wd_zlib_uninit(void) +{ + wd_comp_uninit2(); + zlib_config.status = WD_ZLIB_UNINIT; +} + +static int wd_zlib_analy_alg(int windowbits, int *alg, int *windowsize) +{ + static const int ZLIB_MAX_WBITS = 15; + static const int ZLIB_MIN_WBITS = 8; + static const int GZIP_MAX_WBITS = 31; + static const int GZIP_MIN_WBITS = 24; + static const int DEFLATE_MAX_WBITS = -8; + static const int DEFLATE_MIN_WBITS = -15; + static const int WBINS_ZLIB_4K = 12; + static const int WBINS_GZIP_4K = 27; + static const int WBINS_DEFLATE_4K = -12; + int ret = Z_STREAM_ERROR; + + if ((windowbits >= ZLIB_MIN_WBITS) && (windowbits <= ZLIB_MAX_WBITS)) { + *alg = WD_ZLIB; + *windowsize = max(windowbits - WBINS_ZLIB_4K, WD_COMP_WS_4K); + ret = Z_OK; + } else if ((windowbits >= GZIP_MIN_WBITS) && (windowbits <= GZIP_MAX_WBITS)) { + *alg = WD_GZIP; + *windowsize = max(windowbits - WBINS_GZIP_4K, WD_COMP_WS_4K); + ret = Z_OK; + } else if ((windowbits >= DEFLATE_MIN_WBITS) && (windowbits <= DEFLATE_MAX_WBITS)) { + *alg = WD_DEFLATE; + *windowsize = max(windowbits - WBINS_DEFLATE_4K, WD_COMP_WS_4K); + ret = Z_OK; + } + + return ret; +} + +static int wd_zlib_alloc_sess(z_streamp strm, int level, int windowbits, enum wd_comp_op_type type) +{ + struct wd_comp_sess_setup setup = {0}; + struct sched_params sparams = {0}; + int windowsize, alg, ret; + handle_t h_sess; + + ret = wd_zlib_analy_alg(windowbits, &alg, &windowsize); + if (ret < 0) { + WD_ERR("invalid: windowbits is %d!\n", windowbits); + return ret; + } + + setup.comp_lv = level; + setup.alg_type = alg; + setup.win_sz = windowsize; + setup.op_type = type; + sparams.type = type; + setup.sched_param = &sparams; + + h_sess = wd_comp_alloc_sess(&setup); + if (!h_sess) { + WD_ERR("failed to alloc comp sess!\n"); + return Z_STREAM_ERROR; + } + strm->reserved = (__u64)h_sess; + + return Z_OK; +} + +static void wd_zlib_free_sess(z_streamp strm) +{ + wd_comp_free_sess((handle_t)strm->reserved); +} + +static int wd_zlib_do_request(z_streamp strm, int flush, enum wd_comp_op_type type) +{ + handle_t h_sess = strm->reserved; + struct wd_comp_req req = {0}; + int src_len = strm->avail_in; + int dst_len = strm->avail_out; + int ret; + + if (unlikely(flush != Z_SYNC_FLUSH && flush != Z_FINISH)) { + WD_ERR("invalid: flush is %d!\n", flush); + return Z_STREAM_ERROR; + } + + req.src = (void *)strm->next_in; + req.src_len = strm->avail_in; + req.dst = (void *)strm->next_out; + req.dst_len = strm->avail_out; + req.op_type = type; + req.data_fmt = WD_FLAT_BUF; + req.last = (flush == Z_FINISH) ? 1 : 0; + + ret = wd_do_comp_strm(h_sess, &req); + if (unlikely(ret)) { + WD_ERR("failed to do compress(%d)!\n", ret); + return Z_STREAM_ERROR; + } + + strm->avail_in = src_len - req.src_len; + strm->avail_out = dst_len - req.dst_len; + strm->total_in += req.src_len; + strm->total_out += req.dst_len; + + if (flush == Z_FINISH && req.src_len == src_len) + ret = Z_STREAM_END; + + return ret; +} + +/* === Compression === */ +int wd_deflateInit_(z_streamp strm, int level, const char *version, int stream_size) + +{ + return wd_deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); +} + +int wd_deflateInit2_(z_streamp strm, int level, int method, int windowBits, + int memLevel, int strategy, const char *version, int stream_size) +{ + int ret; + + pthread_atfork(NULL, NULL, wd_zlib_unlock); + + pthread_mutex_lock(&wd_zlib_mutex); + ret = wd_zlib_init(); + if (unlikely(ret < 0)) + goto out_unlock; + + strm->total_in = 0; + strm->total_out = 0; + + ret = wd_zlib_alloc_sess(strm, level, windowBits, WD_DIR_COMPRESS); + if (unlikely(ret < 0)) + goto out_uninit; + + __atomic_add_fetch(&zlib_config.count, 1, __ATOMIC_RELAXED); + pthread_mutex_unlock(&wd_zlib_mutex); + + return 0; + +out_uninit: + wd_zlib_uninit(); + +out_unlock: + pthread_mutex_unlock(&wd_zlib_mutex); + + return ret; +} + +int wd_deflate(z_streamp strm, int flush) +{ + return wd_zlib_do_request(strm, flush, WD_DIR_COMPRESS); +} + +int wd_deflateReset(z_streamp strm) +{ + wd_comp_reset_sess((handle_t)strm->reserved); + + strm->total_in = 0; + strm->total_out = 0; + + return Z_OK; +} + +int wd_deflateEnd(z_streamp strm) +{ + int ret; + + wd_zlib_free_sess(strm); + + pthread_mutex_lock(&wd_zlib_mutex); + + ret = __atomic_sub_fetch(&zlib_config.count, 1, __ATOMIC_RELAXED); + if (ret != 0) + goto out_unlock; + + wd_zlib_uninit(); + +out_unlock: + pthread_mutex_unlock(&wd_zlib_mutex); + + return Z_OK; +} + +/* === Decompression === */ +int wd_inflateInit_(z_streamp strm, const char *version, int stream_size) +{ + return wd_inflateInit2_(strm, MAX_WBITS, version, stream_size); +} + +int wd_inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size) +{ + int ret; + + pthread_atfork(NULL, NULL, wd_zlib_unlock); + + pthread_mutex_lock(&wd_zlib_mutex); + ret = wd_zlib_init(); + if (unlikely(ret < 0)) + goto out_unlock; + + strm->total_in = 0; + strm->total_out = 0; + + ret = wd_zlib_alloc_sess(strm, 0, windowBits, WD_DIR_DECOMPRESS); + if (unlikely(ret < 0)) + goto out_uninit; + + __atomic_add_fetch(&zlib_config.count, 1, __ATOMIC_RELAXED); + pthread_mutex_unlock(&wd_zlib_mutex); + + return 0; + +out_uninit: + wd_zlib_uninit(); + +out_unlock: + pthread_mutex_unlock(&wd_zlib_mutex); + + return ret; +} + +int wd_inflate(z_streamp strm, int flush) +{ + return wd_zlib_do_request(strm, flush, WD_DIR_DECOMPRESS); +} + +int wd_inflateReset(z_streamp strm) +{ + wd_comp_reset_sess((handle_t)strm->reserved); + + strm->total_in = 0; + strm->total_out = 0; + + return Z_OK; +} + +int wd_inflateEnd(z_streamp strm) +{ + int ret; + + wd_zlib_free_sess(strm); + + pthread_mutex_lock(&wd_zlib_mutex); + + ret = __atomic_sub_fetch(&zlib_config.count, 1, __ATOMIC_RELAXED); + if (ret != 0) + goto out_unlock; + + wd_zlib_uninit(); + +out_unlock: + pthread_mutex_unlock(&wd_zlib_mutex); + + return Z_OK; +} diff --git a/wd_zlibwrapper.h b/wd_zlibwrapper.h new file mode 100644 index 0000000..6e840bc --- /dev/null +++ b/wd_zlibwrapper.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: Apache-2.0 */ +/* + * Copyright 2020-2022 Huawei Technologies Co.,Ltd. All rights reserved. + */ + +#ifndef UADK_ZLIBWRAPPER_H +#define UADK_ZLIBWRAPPER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.11" + +/* Allowed flush values; the same as zlib library */ +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 + +/* + * Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) + +#define Z_DEFLATED 0 +#define MAX_WBITS 15 +#define DEF_MEM_LEVEL 0 +#define Z_DEFAULT_STRATEGY 0 + +struct internal_state {}; + +typedef void (*alloc_func) (void *opaque, __u32 items, __u32 size); +typedef void (*free_func) (void *opaque, void *address); + +typedef struct z_stream_s { + /* next input byte */ + const __u8 *next_in; + /* number of bytes available at next_in */ + __u32 avail_in; + /* total number of input bytes read so far */ + __u64 total_in; + + /* next output byte will go here */ + __u8 *next_out; + /* remaining free space at next_out */ + __u32 avail_out; + /* total number of bytes output so far */ + __u64 total_out; + + /* last error message, NULL if no error */ + const char *msg; + /* not visible by applications */ + struct internal_state *state; + + /* used to allocate the internal state */ + alloc_func zalloc; + /* used to free the internal state */ + free_func zfree; + /* private data object passed to zalloc and zfree */ + void *opaque; + + /* + * Best guess about the data type: binary or text + * for deflate, or the decoding state for inflate. + */ + int data_type; + /* Adler-32 or CRC-32 value of the uncompressed data */ + __u64 adler; + /* reserved the wd_comp_sess */ + __u64 reserved; +} z_stream; + +typedef z_stream *z_streamp; + +int wd_deflateInit_(z_streamp strm, int level, const char *version, int stream_size); +int wd_deflateInit2_(z_streamp strm, int level, int method, int windowBits, + int memLevel, int strategy, const char *version, int stream_size); +int wd_deflate(z_streamp strm, int flush); +int wd_deflateReset(z_streamp strm); +int wd_deflateEnd(z_streamp strm); + +int wd_inflateInit_(z_streamp strm, const char *version, int stream_size); +int wd_inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size); +int wd_inflate(z_streamp strm, int flush); +int wd_inflateReset(z_streamp strm); +int wd_inflateEnd(z_streamp strm); + +#define wd_deflateInit(strm, level) \ + wd_deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) + +#define wd_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + wd_deflateInit2_((strm), (level), (method), (windowBits), (memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) + +#define wd_inflateInit(strm) \ + wd_inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) + +#define wd_inflateInit2(strm, windowBits) \ + wd_inflateInit2_((strm), (windowBits), ZLIB_VERSION, (int)sizeof(z_stream)) + +#endif /* UADK_ZLIBWRAPPER_H */