summaryrefslogtreecommitdiff
path: root/inflate.c
diff options
context:
space:
mode:
authorIlya Leoshkevich <iii@linux.ibm.com>2019-04-10 15:46:58 +0200
committerHans Kristian Rosbach <hk-github@circlestorm.org>2019-05-23 12:44:59 +0200
commit8e30d1173699412c11880db10de2bc10893a2448 (patch)
treec0f01036e13a061ab01c9710fa3d102edceb3a67 /inflate.c
parentedaf8cd770dcc1d5df99da6b1d81cf2c5818aa32 (diff)
Add support for IBM Z hardware-accelerated deflate
Future versions of IBM Z mainframes will provide DFLTCC instruction, which implements deflate algorithm in hardware with estimated compression and decompression performance orders of magnitude faster than the current zlib-ng and ratio comparable with that of level 1. This patch adds DFLTCC support to zlib-ng. In order to enable it, the following build commands should be used: $ ./configure --with-dfltcc-deflate --with-dfltcc-inflate $ make When built like this, zlib-ng would compress in hardware on level 1, and in software on all other levels. Decompression will always happen in hardware. In order to enable DFLTCC compression for levels 1-6 (i.e. to make it used by default) one could add -DDFLTCC_LEVEL_MASK=0x7e to CFLAGS when building zlib-ng. Two DFLTCC compression calls produce the same results only when they both are made on machines of the same generation, and when the respective buffers have the same offset relative to the start of the page. Therefore care should be taken when using hardware compression when reproducible results are desired. DFLTCC does not support every single zlib-ng feature, in particular: * inflate(Z_BLOCK) and inflate(Z_TREES) * inflateMark() * inflatePrime() * deflateParams() after the first deflate() call When used, these functions will either switch to software, or, in case this is not possible, gracefully fail. This patch tries to add DFLTCC support in a least intrusive way. All SystemZ-specific code was placed into a separate file, but unfortunately there is still a noticeable amount of changes in the main zlib-ng code. Below is the summary of those changes. DFLTCC takes as arguments a parameter block, an input buffer, an output buffer and a window. Since DFLTCC requires parameter block to be doubleword-aligned, and it's reasonable to allocate it alongside deflate and inflate states, ZALLOC_STATE, ZFREE_STATE and ZCOPY_STATE macros were introduced in order to encapsulate the allocation details. The same is true for window, for which ZALLOC_WINDOW and TRY_FREE_WINDOW macros were introduced. While for inflate software and hardware window formats match, this is not the case for deflate. Therefore, deflateSetDictionary and deflateGetDictionary need special handling, which is triggered using the new DEFLATE_SET_DICTIONARY_HOOK and DEFLATE_GET_DICTIONARY_HOOK macros. deflateResetKeep() and inflateResetKeep() now update the DFLTCC parameter block, which is allocated alongside zlib-ng state, using the new DEFLATE_RESET_KEEP_HOOK and INFLATE_RESET_KEEP_HOOK macros. In order to make unsupported deflateParams(), inflatePrime() and inflateMark() calls to fail gracefully, the new DEFLATE_PARAMS_HOOK, INFLATE_PRIME_HOOK and INFLATE_MARK_HOOK macros were introduced. The algorithm implemented in hardware has different compression ratio than the one implemented in software. In order for deflateBound() to return the correct results for the hardware implementation, the new DEFLATE_BOUND_ADJUST_COMPLEN and DEFLATE_NEED_CONSERVATIVE_BOUND macros were introduced. Actual compression and decompression are handled by the new DEFLATE_HOOK and INFLATE_TYPEDO_HOOK macros. Since inflation with DFLTCC manages the window on its own, calling updatewindow() is suppressed using the new INFLATE_NEED_UPDATEWINDOW() macro. In addition to compression, DFLTCC computes CRC-32 and Adler-32 checksums, therefore, whenever it's used, software checksumming needs to be suppressed using the new DEFLATE_NEED_CHECKSUM and INFLATE_NEED_CHECKSUM macros. DFLTCC will refuse to write an End-of-block Symbol if there is no input data, thus in some cases it is necessary to do this manually. In order to achieve this, bi_reverse and flush_pending were promoted from static to ZLIB_INTERNAL and exposed via deflate.h. Since the first call to dfltcc_inflate already needs the window, and it might be not allocated yet, inflate_ensure_window was factored out of updatewindow and made ZLIB_INTERNAL.
Diffstat (limited to 'inflate.c')
-rw-r--r--inflate.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/inflate.c b/inflate.c
index 4776b20..8a8d328 100644
--- a/inflate.c
+++ b/inflate.c
@@ -89,25 +89,29 @@
#include "functable.h"
/* Architecture-specific hooks. */
+#ifdef S390_DFLTCC_INFLATE
+# include "arch/s390/dfltcc_inflate.h"
+#else
/* Memory management for the inflate state. Useful for allocating arch-specific extension blocks. */
-#define ZALLOC_STATE(strm, items, size) ZALLOC(strm, items, size)
-#define ZFREE_STATE(strm, addr) ZFREE(strm, addr)
-#define ZCOPY_STATE(dst, src, size) memcpy(dst, src, size)
+# define ZALLOC_STATE(strm, items, size) ZALLOC(strm, items, size)
+# define ZFREE_STATE(strm, addr) ZFREE(strm, addr)
+# define ZCOPY_STATE(dst, src, size) memcpy(dst, src, size)
/* Memory management for the window. Useful for allocation the aligned window. */
-#define ZALLOC_WINDOW(strm, items, size) ZALLOC(strm, items, size)
-#define ZFREE_WINDOW(strm, addr) ZFREE(strm, addr)
+# define ZALLOC_WINDOW(strm, items, size) ZALLOC(strm, items, size)
+# define ZFREE_WINDOW(strm, addr) ZFREE(strm, addr)
/* Invoked at the end of inflateResetKeep(). Useful for initializing arch-specific extension blocks. */
-#define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0)
+# define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0)
/* Invoked at the beginning of inflatePrime(). Useful for updating arch-specific buffers. */
-#define INFLATE_PRIME_HOOK(strm, bits, value) do {} while (0)
+# define INFLATE_PRIME_HOOK(strm, bits, value) do {} while (0)
/* Invoked at the beginning of each block. Useful for plugging arch-specific inflation code. */
-#define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0)
+# define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0)
/* Returns whether zlib-ng should compute a checksum. Set to 0 if arch-specific inflation code already does that. */
-#define INFLATE_NEED_CHECKSUM(strm) 1
+# define INFLATE_NEED_CHECKSUM(strm) 1
/* Returns whether zlib-ng should update a window. Set to 0 if arch-specific inflation code already does that. */
-#define INFLATE_NEED_UPDATEWINDOW(strm) 1
+# define INFLATE_NEED_UPDATEWINDOW(strm) 1
/* Invoked at the beginning of inflateMark(). Useful for updating arch-specific pointers and offsets. */
-#define INFLATE_MARK_HOOK(strm) do {} while (0)
+# define INFLATE_MARK_HOOK(strm) do {} while (0)
+#endif
#ifdef MAKEFIXED
# ifndef BUILDFIXED