Coverage Report

Created: 2026-08-19 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/haproxy/include/import/slz-prv.h
Line
Count
Source
1
/*
2
 * Copyright (C) 2013-2015 Willy Tarreau <w@1wt.eu>
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining
5
 * a copy of this software and associated documentation files (the
6
 * "Software"), to deal in the Software without restriction, including
7
 * without limitation the rights to use, copy, modify, merge, publish,
8
 * distribute, sublicense, and/or sell copies of the Software, and to
9
 * permit persons to whom the Software is furnished to do so, subject to
10
 * the following conditions:
11
 *
12
 * The above copyright notice and this permission notice shall be
13
 * included in all copies or substantial portions of the Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
 * OTHER DEALINGS IN THE SOFTWARE.
23
 */
24
25
#ifndef _SLZ_PRV_H
26
#define _SLZ_PRV_H
27
28
/* We have two macros UNALIGNED_LE_OK and UNALIGNED_FASTER. The latter indicates
29
 * that using unaligned data is faster than a simple shift. On x86 32-bit at
30
 * least it is not the case as the per-byte access is 30% faster. A core2-duo on
31
 * x86_64 is 7% faster to read one byte + shifting by 8 than to read one word,
32
 * but a core i5 is 7% faster doing the unaligned read, so we privilege more
33
 * recent implementations here.
34
 */
35
#if defined(__x86_64__)
36
#define UNALIGNED_LE_OK
37
#define UNALIGNED_FASTER
38
#define USE_64BIT_QUEUE
39
#define HAVE_FAST_MULT
40
#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
41
#define UNALIGNED_LE_OK
42
//#define UNALIGNED_FASTER
43
#elif defined(__ARMEL__) && defined(__ARM_ARCH_7A__)
44
#define UNALIGNED_LE_OK
45
#define UNALIGNED_FASTER
46
#elif defined(__ARM_ARCH_8A) || defined(__ARM_FEATURE_UNALIGNED)
47
#define UNALIGNED_LE_OK
48
#define UNALIGNED_FASTER
49
#define HAVE_FAST_MULT
50
#endif
51
52
/* Log2 of the size of the hash table used for the references table. */
53
0
#define HASH_BITS 13
54
55
/* uses the most suitable crc32 function to update crc on <buf, len> */
56
static inline uint32_t update_crc(uint32_t crc, const void *buf, int len)
57
0
{
58
0
  return slz_crc32_by4(crc, buf, len);
59
0
}
Unexecuted instantiation: slz.c:update_crc
Unexecuted instantiation: slz_common.c:update_crc
60
61
/* This hash provides good average results on HTML contents, and is among the
62
 * few which provide almost optimal results on various different pages.
63
 */
64
static inline uint32_t slz_hash(uint32_t a)
65
0
{
66
#if defined(__ARM_FEATURE_CRC32)
67
#  if defined(__ARM_ARCH_ISA_A64)
68
  // 64 bit mode
69
  __asm__ volatile("crc32w %w0,%w0,%w1" : "+r"(a) : "r"(0));
70
#  else
71
  // 32 bit mode (e.g. armv7 compiler building for armv8
72
  __asm__ volatile("crc32w %0,%0,%1" : "+r"(a) : "r"(0));
73
#  endif
74
  return a >> (32 - HASH_BITS);
75
#elif defined(__SSE4_2__) && defined(USE_CRC32C_HASH)
76
  // SSE 4.2 offers CRC32C which is a bit slower than the multiply
77
  // but provides a slightly smoother hash
78
  __asm__ volatile("crc32l %1,%0" : "+r"(a) : "r"(0));
79
  return a >> (32 - HASH_BITS);
80
#elif defined(HAVE_FAST_MULT)
81
  // optimal factor for HASH_BITS=12 and HASH_BITS=13 among 48k tested: 0x1af42f
82
0
  return (a * 0x1af42f) >> (32 - HASH_BITS);
83
#else
84
  return ((a << 19) + (a << 6) - a) >> (32 - HASH_BITS);
85
#endif
86
0
}
Unexecuted instantiation: slz.c:slz_hash
Unexecuted instantiation: slz_common.c:slz_hash
87
88
/* This function compares buffers <a> and <b> and reads 32 or 64 bits at a time
89
 * during the approach. It makes us of unaligned little endian memory accesses
90
 * on capable architectures. <max> is the maximum number of bytes that can be
91
 * read, so both <a> and <b> must have at least <max> bytes ahead. <max> may
92
 * safely be null or negative if that simplifies computations in the caller.
93
 */
94
static inline long memmatch(const unsigned char *a, const unsigned char *b, long max)
95
0
{
96
0
  long len = 0;
97
98
0
#ifdef UNALIGNED_LE_OK
99
0
  unsigned long xor;
100
101
0
  while (1) {
102
0
    if ((long)(len + 2 * sizeof(long)) > max) {
103
0
      while (len < max) {
104
0
        if (a[len] != b[len])
105
0
          break;
106
0
        len++;
107
0
      }
108
0
      return len;
109
0
    }
110
111
0
    xor = *(long *)&a[len] ^ *(long *)&b[len];
112
0
    if (xor)
113
0
      break;
114
0
    len += sizeof(long);
115
116
0
    xor = *(long *)&a[len] ^ *(long *)&b[len];
117
0
    if (xor)
118
0
      break;
119
0
    len += sizeof(long);
120
0
  }
121
122
0
#if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
123
  /* x86 has bsf. We know that xor is non-null here */
124
0
  asm("bsf %1,%0\n" : "=r"(xor) : "0" (xor));
125
0
  return len + xor / 8;
126
#else
127
  if (sizeof(long) > 4 && !(xor & 0xffffffff)) {
128
    /* This code is optimized out on 32-bit archs, but we still
129
     * need to shift in two passes to avoid a warning. It is
130
     * properly optimized out as a single shift.
131
     */
132
    xor >>= 16; xor >>= 16;
133
    if (xor & 0xffff) {
134
      if (xor & 0xff)
135
        return len + 4;
136
      return len + 5;
137
    }
138
    if (xor & 0xffffff)
139
      return len + 6;
140
    return len + 7;
141
  }
142
143
  if (xor & 0xffff) {
144
    if (xor & 0xff)
145
      return len;
146
    return len + 1;
147
  }
148
  if (xor & 0xffffff)
149
    return len + 2;
150
  return len + 3;
151
#endif // x86
152
153
#else // UNALIGNED_LE_OK
154
  /* This is the generic version for big endian or unaligned-incompatible
155
   * architectures.
156
   */
157
  while (len < max) {
158
    if (a[len] != b[len])
159
      break;
160
    len++;
161
  }
162
  return len;
163
164
#endif
165
0
}
Unexecuted instantiation: slz.c:memmatch
Unexecuted instantiation: slz_common.c:memmatch
166
167
/* helper function to reverse bits in <input> which is expected to be
168
 * <len> bits long.
169
 */
170
static inline short rev_short(short input, int len)
171
0
{
172
0
  short ret = 0;
173
0
174
0
  while (len) {
175
0
    ret <<= 1;
176
0
    ret |= (input & 1);
177
0
    input >>= 1;
178
0
    len--;
179
0
  }
180
0
181
0
  return ret;
182
0
}
Unexecuted instantiation: slz.c:rev_short
Unexecuted instantiation: slz_common.c:rev_short
183
184
#endif