6d31e4
From 772ddd6500a74220e641782cc2ee892433197192 Mon Sep 17 00:00:00 2001
6d31e4
From: IBM developers
6d31e4
Date: Mon, 25 May 2020 14:09:48 +0200
6d31e4
Subject: [PATCH] Fix for Z hardware-accelerated deflate for s390x
6d31e4
 architectures
6d31e4
6d31e4
---
6d31e4
 configure                     |  7 +++
6d31e4
 contrib/s390/dfltcc.c         | 94 ++++++++++++++++++++---------------
6d31e4
 contrib/s390/dfltcc_deflate.h | 10 ++--
6d31e4
 deflate.c                     | 12 +++--
6d31e4
 4 files changed, 76 insertions(+), 47 deletions(-)
6d31e4
6d31e4
diff --git a/configure b/configure
6d31e4
index 66caece..bfe4386 100755
6d31e4
--- a/configure
6d31e4
+++ b/configure
6d31e4
@@ -114,6 +114,7 @@ case "$1" in
6d31e4
       echo '  configure [--const] [--zprefix] [--prefix=PREFIX]  [--eprefix=EXPREFIX]' | tee -a configure.log
6d31e4
       echo '    [--static] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log
6d31e4
       echo '    [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log
6d31e4
+      echo '    [--dfltcc]' | tee -a configure.log
6d31e4
         exit 0 ;;
6d31e4
     -p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;;
6d31e4
     -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;;
6d31e4
@@ -137,6 +138,12 @@ case "$1" in
6d31e4
     -c* | --const) zconst=1; shift ;;
6d31e4
     -w* | --warn) warn=1; shift ;;
6d31e4
     -d* | --debug) debug=1; shift ;;
6d31e4
+    --dfltcc)
6d31e4
+	    CFLAGS="$CFLAGS -DDFLTCC"
6d31e4
+      OBJC="$OBJC dfltcc.o"
6d31e4
+	    PIC_OBJC="$PIC_OBJC dfltcc.lo"
6d31e4
+      shift
6d31e4
+      ;; 
6d31e4
     *)
6d31e4
       echo "unknown option: $1" | tee -a configure.log
6d31e4
       echo "$0 --help for help" | tee -a configure.log
6d31e4
diff --git a/contrib/s390/dfltcc.c b/contrib/s390/dfltcc.c
6d31e4
index d187796..face8f1 100644
6d31e4
--- a/contrib/s390/dfltcc.c
6d31e4
+++ b/contrib/s390/dfltcc.c
6d31e4
@@ -2,8 +2,8 @@
6d31e4
 
6d31e4
 /*
6d31e4
    Use the following commands to build zlib with DFLTCC support:
6d31e4
-        $ CFLAGS=-DDFLTCC ./configure
6d31e4
-        $ make OBJA=dfltcc.o PIC_OBJA=dfltcc.lo
6d31e4
+        $ ./configure --dfltcc
6d31e4
+        $ make 
6d31e4
 */
6d31e4
 
6d31e4
 #define _GNU_SOURCE
6d31e4
@@ -230,31 +230,28 @@ struct dfltcc_state {
6d31e4
 /*
6d31e4
    Compress.
6d31e4
  */
6d31e4
-local inline int dfltcc_are_params_ok(int level,
6d31e4
-                                      uInt window_bits,
6d31e4
-                                      int strategy,
6d31e4
-                                      uLong level_mask);
6d31e4
-local inline int dfltcc_are_params_ok(level, window_bits, strategy, level_mask)
6d31e4
+local inline int dfltcc_can_deflate_with_params(z_streamp strm,
6d31e4
+                                                 int level,
6d31e4
+                                                 uInt window_bits,
6d31e4
+                                                 int strategy);
6d31e4
+local inline int dfltcc_can_deflate_with_params(strm,
6d31e4
+                                                 level,
6d31e4
+                                                 window_bits,
6d31e4
+                                                 strategy)
6d31e4
+    z_streamp strm; 
6d31e4
     int level;
6d31e4
     uInt window_bits;
6d31e4
     int strategy;
6d31e4
-    uLong level_mask;
6d31e4
-{
6d31e4
-    return (level_mask & (1 << level)) != 0 &&
6d31e4
-        (window_bits == HB_BITS) &&
6d31e4
-        (strategy == Z_FIXED || strategy == Z_DEFAULT_STRATEGY);
6d31e4
-}
6d31e4
-
6d31e4
-
6d31e4
-int ZLIB_INTERNAL dfltcc_can_deflate(strm)
6d31e4
-    z_streamp strm;
6d31e4
 {
6d31e4
     deflate_state FAR *state = (deflate_state FAR *)strm->state;
6d31e4
     struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
6d31e4
 
6d31e4
     /* Unsupported compression settings */
6d31e4
-    if (!dfltcc_are_params_ok(state->level, state->w_bits, state->strategy,
6d31e4
-                              dfltcc_state->level_mask))
6d31e4
+    if ((dfltcc_state->level_mask & (1 << level)) == 0)
6d31e4
+        return 0;
6d31e4
+    if (window_bits != HB_BITS)
6d31e4
+        return 0;
6d31e4
+    if (strategy != Z_FIXED && strategy != Z_DEFAULT_STRATEGY) 
6d31e4
         return 0;
6d31e4
 
6d31e4
     /* Unsupported hardware */
6d31e4
@@ -266,6 +263,17 @@ int ZLIB_INTERNAL dfltcc_can_deflate(strm)
6d31e4
     return 1;
6d31e4
 }
6d31e4
 
6d31e4
+int ZLIB_INTERNAL dfltcc_can_deflate(strm)
6d31e4
+    z_streamp strm;
6d31e4
+{
6d31e4
+    deflate_state FAR *state = (deflate_state FAR *)strm->state;
6d31e4
+
6d31e4
+    return dfltcc_can_deflate_with_params(strm,
6d31e4
+                                          state->level,
6d31e4
+                                          state->w_bits,
6d31e4
+                                          state->strategy);
6d31e4
+} 
6d31e4
+
6d31e4
 local void dfltcc_gdht OF((z_streamp strm));
6d31e4
 local void dfltcc_gdht(strm)
6d31e4
     z_streamp strm;
6d31e4
@@ -349,22 +357,24 @@ again:
6d31e4
     soft_bcc = 0;
6d31e4
     no_flush = flush == Z_NO_FLUSH;
6d31e4
 
6d31e4
-    /* Trailing empty block. Switch to software, except when Continuation Flag
6d31e4
-     * is set, which means that DFLTCC has buffered some output in the
6d31e4
-     * parameter block and needs to be called again in order to flush it.
6d31e4
+    /* No input data. Return, except when Continuation Flag is set, which means
6d31e4
+     * that DFLTCC has buffered some output in the parameter block and needs to
6d31e4
+     * be called again in order to flush it. 
6d31e4
      */
6d31e4
-    if (flush == Z_FINISH && strm->avail_in == 0 && !param->cf) {
6d31e4
-        if (param->bcf) {
6d31e4
-            /* A block is still open, and the hardware does not support closing
6d31e4
-             * blocks without adding data. Thus, close it manually.
6d31e4
-             */
6d31e4
+    if (strm->avail_in == 0 && !param->cf) {
6d31e4
+        /* A block is still open, and the hardware does not support closing
6d31e4
+         * blocks without adding data. Thus, close it manually.
6d31e4
+         */
6d31e4
+        if (!no_flush && param->bcf) { 
6d31e4
             send_eobs(strm, param);
6d31e4
             param->bcf = 0;
6d31e4
         }
6d31e4
-        return 0;
6d31e4
-    }
6d31e4
-
6d31e4
-    if (strm->avail_in == 0 && !param->cf) {
6d31e4
+        /* Let one of deflate_* functions write a trailing empty block. */
6d31e4
+        if (flush == Z_FINISH)
6d31e4
+            return 0;
6d31e4
+        /* Clear history. */
6d31e4
+        if (flush == Z_FULL_FLUSH)
6d31e4
+            param->hl = 0; 
6d31e4
         *result = need_more;
6d31e4
         return 1;
6d31e4
     }
6d31e4
@@ -418,7 +428,7 @@ again:
6d31e4
     param->cvt = state->wrap == 2 ? CVT_CRC32 : CVT_ADLER32;
6d31e4
     if (!no_flush)
6d31e4
         /* We need to close a block. Always do this in software - when there is
6d31e4
-         * no input data, the hardware will not nohor BCC. */
6d31e4
+         * no input data, the hardware will not honor BCC. */
6d31e4
         soft_bcc = 1;
6d31e4
     if (flush == Z_FINISH && !param->bcf)
6d31e4
         /* We are about to open a BFINAL block, set Block Header Final bit
6d31e4
@@ -433,8 +443,8 @@ again:
6d31e4
     param->sbb = (unsigned int)state->bi_valid;
6d31e4
     if (param->sbb > 0)
6d31e4
         *strm->next_out = (Bytef)state->bi_buf;
6d31e4
-    if (param->hl)
6d31e4
-        param->nt = 0; /* Honor history */
6d31e4
+    /* Honor history and check value */
6d31e4
+    param->nt = 0; 
6d31e4
     param->cv = state->wrap == 2 ? ZSWAP32(strm->adler) : strm->adler;
6d31e4
 
6d31e4
     /* When opening a block, choose a Huffman-Table Type */
6d31e4
@@ -792,17 +802,20 @@ void ZLIB_INTERNAL dfltcc_free_window(strm, w)
6d31e4
    fly with deflateParams, we need to convert between hardware and software
6d31e4
    window formats.
6d31e4
 */
6d31e4
-int ZLIB_INTERNAL dfltcc_deflate_params(strm, level, strategy)
6d31e4
+int ZLIB_INTERNAL dfltcc_deflate_params(strm, level, strategy, flush)
6d31e4
     z_streamp strm;
6d31e4
     int level;
6d31e4
     int strategy;
6d31e4
+    int *flush;
6d31e4
 {
6d31e4
     deflate_state FAR *state = (deflate_state FAR *)strm->state;
6d31e4
     struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
6d31e4
     struct dfltcc_param_v0 FAR *param = &dfltcc_state->param;
6d31e4
     int could_deflate = dfltcc_can_deflate(strm);
6d31e4
-    int can_deflate = dfltcc_are_params_ok(level, state->w_bits, strategy,
6d31e4
-                                           dfltcc_state->level_mask);
6d31e4
+    int can_deflate = dfltcc_can_deflate_with_params(strm,
6d31e4
+                                                     level,
6d31e4
+                                                     state->w_bits,
6d31e4
+                                                     strategy); 
6d31e4
 
6d31e4
     if (can_deflate == could_deflate)
6d31e4
         /* We continue to work in the same mode - no changes needed */
6d31e4
@@ -812,8 +825,11 @@ int ZLIB_INTERNAL dfltcc_deflate_params(strm, level, strategy)
6d31e4
         /* DFLTCC was not used yet - no changes needed */
6d31e4
         return Z_OK;
6d31e4
 
6d31e4
-    /* Switching between hardware and software is not implemented */
6d31e4
-    return Z_STREAM_ERROR;
6d31e4
+    /* For now, do not convert between window formats - simply get rid of the
6d31e4
+     * old data instead.
6d31e4
+     */
6d31e4
+    *flush = Z_FULL_FLUSH;
6d31e4
+    return Z_OK; 
6d31e4
 }
6d31e4
 
6d31e4
 /*
6d31e4
diff --git a/contrib/s390/dfltcc_deflate.h b/contrib/s390/dfltcc_deflate.h
6d31e4
index a129a91..947b1e4 100644
6d31e4
--- a/contrib/s390/dfltcc_deflate.h
6d31e4
+++ b/contrib/s390/dfltcc_deflate.h
6d31e4
@@ -9,7 +9,8 @@ int ZLIB_INTERNAL dfltcc_deflate OF((z_streamp strm,
6d31e4
                                      block_state *result));
6d31e4
 int ZLIB_INTERNAL dfltcc_deflate_params OF((z_streamp strm,
6d31e4
                                             int level,
6d31e4
-                                            int strategy));
6d31e4
+                                            int strategy,
6d31e4
+                                            int *flush)); 
6d31e4
 int ZLIB_INTERNAL dfltcc_deflate_set_dictionary OF((z_streamp strm,
6d31e4
                                                     const Bytef *dictionary,
6d31e4
                                                     uInt dict_length));
6d31e4
@@ -29,11 +30,14 @@ int ZLIB_INTERNAL dfltcc_deflate_get_dictionary OF((z_streamp strm,
6d31e4
     } while (0)
6d31e4
 #define DEFLATE_RESET_KEEP_HOOK(strm) \
6d31e4
     dfltcc_reset((strm), sizeof(deflate_state))
6d31e4
-#define DEFLATE_PARAMS_HOOK(strm, level, strategy) \
6d31e4
+#define DEFLATE_PARAMS_HOOK(strm, level, strategy, hook_flush) \
6d31e4
     do { \
6d31e4
         int err; \
6d31e4
 \
6d31e4
-        err = dfltcc_deflate_params((strm), (level), (strategy)); \
6d31e4
+        err = dfltcc_deflate_params((strm), \
6d31e4
+                                    (level), \
6d31e4
+                                    (strategy), \
6d31e4
+                                    (hook_flush)); \ 
6d31e4
         if (err == Z_STREAM_ERROR) \
6d31e4
             return err; \
6d31e4
     } while (0)
6d31e4
diff --git a/deflate.c b/deflate.c
6d31e4
index 9b09718..9284483 100644
6d31e4
--- a/deflate.c
6d31e4
+++ b/deflate.c
6d31e4
@@ -74,7 +74,7 @@ const char deflate_copyright[] =
6d31e4
 #define DEFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0)
6d31e4
 #define DEFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0)
6d31e4
 #define DEFLATE_RESET_KEEP_HOOK(strm) do {} while (0)
6d31e4
-#define DEFLATE_PARAMS_HOOK(strm, level, strategy) do {} while (0)
6d31e4
+#define DEFLATE_PARAMS_HOOK(strm, level, strategy, hook_flush) do {} while (0)
6d31e4
 #define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, sourceLen) do {} while (0)
6d31e4
 #define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) 0
6d31e4
 #define DEFLATE_HOOK(strm, flush, bstate) 0
6d31e4
@@ -589,6 +589,7 @@ int ZEXPORT deflateParams(strm, level, strategy)
6d31e4
 {
6d31e4
     deflate_state *s;
6d31e4
     compress_func func;
6d31e4
+    int hook_flush = Z_NO_FLUSH;
6d31e4
 
6d31e4
     if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
6d31e4
     s = strm->state;
6d31e4
@@ -601,13 +602,14 @@ int ZEXPORT deflateParams(strm, level, strategy)
6d31e4
     if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
6d31e4
         return Z_STREAM_ERROR;
6d31e4
     }
6d31e4
-    DEFLATE_PARAMS_HOOK(strm, level, strategy);
6d31e4
+    DEFLATE_PARAMS_HOOK(strm, level, strategy, &hook_flush);
6d31e4
     func = configuration_table[s->level].func;
6d31e4
 
6d31e4
-    if ((strategy != s->strategy || func != configuration_table[level].func) &&
6d31e4
-        s->high_water) {
6d31e4
+    if ((strategy != s->strategy || func != configuration_table[level].func ||
6d31e4
+        hook_flush != Z_NO_FLUSH) && s->high_water) {
6d31e4
         /* Flush the last buffer: */
6d31e4
-        int err = deflate(strm, Z_BLOCK);
6d31e4
+        int err = deflate(strm, RANK(hook_flush) > RANK(Z_BLOCK) ?
6d31e4
+                          hook_flush : Z_BLOCK); 
6d31e4
         if (err == Z_STREAM_ERROR)
6d31e4
             return err;
6d31e4
         if (strm->avail_out == 0)
6d31e4
-- 
6d31e4
2.24.1
6d31e4