diff options
| author | Markus F.X.J. Oberhumer <markus@oberhumer.com> | 2012-08-13 11:25:44 -0400 |
|---|---|---|
| committer | Markus F.X.J. Oberhumer <markus@oberhumer.com> | 2013-02-20 13:36:01 -0500 |
| commit | 8b975bd3f9089f8ee5d7bbfd798537b992bbc7e7 (patch) | |
| tree | 09078bdf5e805a5f921d8b7b592262ef3e877937 | |
| parent | b6bec26cea948148a9420e7a0ac337f925de49e7 (diff) | |
lib/lzo: Update LZO compression to current upstream version
This commit updates the kernel LZO code to the current upsteam version
which features a significant speed improvement - benchmarking the Calgary
and Silesia test corpora typically shows a doubled performance in
both compression and decompression on modern i386/x86_64/powerpc machines.
Signed-off-by: Markus F.X.J. Oberhumer <markus@oberhumer.com>
| -rw-r--r-- | include/linux/lzo.h | 15 | ||||
| -rw-r--r-- | lib/lzo/lzo1x_compress.c | 335 | ||||
| -rw-r--r-- | lib/lzo/lzo1x_decompress_safe.c | 350 | ||||
| -rw-r--r-- | lib/lzo/lzodefs.h | 38 |
4 files changed, 395 insertions, 343 deletions
diff --git a/include/linux/lzo.h b/include/linux/lzo.h index d793497ec1ca..a0848d9377e5 100644 --- a/include/linux/lzo.h +++ b/include/linux/lzo.h | |||
| @@ -4,28 +4,28 @@ | |||
| 4 | * LZO Public Kernel Interface | 4 | * LZO Public Kernel Interface |
| 5 | * A mini subset of the LZO real-time data compression library | 5 | * A mini subset of the LZO real-time data compression library |
| 6 | * | 6 | * |
| 7 | * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com> | 7 | * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com> |
| 8 | * | 8 | * |
| 9 | * The full LZO package can be found at: | 9 | * The full LZO package can be found at: |
| 10 | * http://www.oberhumer.com/opensource/lzo/ | 10 | * http://www.oberhumer.com/opensource/lzo/ |
| 11 | * | 11 | * |
| 12 | * Changed for kernel use by: | 12 | * Changed for Linux kernel use by: |
| 13 | * Nitin Gupta <nitingupta910@gmail.com> | 13 | * Nitin Gupta <nitingupta910@gmail.com> |
| 14 | * Richard Purdie <rpurdie@openedhand.com> | 14 | * Richard Purdie <rpurdie@openedhand.com> |
| 15 | */ | 15 | */ |
| 16 | 16 | ||
| 17 | #define LZO1X_MEM_COMPRESS (16384 * sizeof(unsigned char *)) | 17 | #define LZO1X_1_MEM_COMPRESS (8192 * sizeof(unsigned short)) |
| 18 | #define LZO1X_1_MEM_COMPRESS LZO1X_MEM_COMPRESS | 18 | #define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS |
| 19 | 19 | ||
| 20 | #define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3) | 20 | #define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3) |
| 21 | 21 | ||
| 22 | /* This requires 'workmem' of size LZO1X_1_MEM_COMPRESS */ | 22 | /* This requires 'wrkmem' of size LZO1X_1_MEM_COMPRESS */ |
| 23 | int lzo1x_1_compress(const unsigned char *src, size_t src_len, | 23 | int lzo1x_1_compress(const unsigned char *src, size_t src_len, |
| 24 | unsigned char *dst, size_t *dst_len, void *wrkmem); | 24 | unsigned char *dst, size_t *dst_len, void *wrkmem); |
| 25 | 25 | ||
| 26 | /* safe decompression with overrun testing */ | 26 | /* safe decompression with overrun testing */ |
| 27 | int lzo1x_decompress_safe(const unsigned char *src, size_t src_len, | 27 | int lzo1x_decompress_safe(const unsigned char *src, size_t src_len, |
| 28 | unsigned char *dst, size_t *dst_len); | 28 | unsigned char *dst, size_t *dst_len); |
| 29 | 29 | ||
| 30 | /* | 30 | /* |
| 31 | * Return values (< 0 = Error) | 31 | * Return values (< 0 = Error) |
| @@ -40,5 +40,6 @@ int lzo1x_decompress_safe(const unsigned char *src, size_t src_len, | |||
| 40 | #define LZO_E_EOF_NOT_FOUND (-7) | 40 | #define LZO_E_EOF_NOT_FOUND (-7) |
| 41 | #define LZO_E_INPUT_NOT_CONSUMED (-8) | 41 | #define LZO_E_INPUT_NOT_CONSUMED (-8) |
| 42 | #define LZO_E_NOT_YET_IMPLEMENTED (-9) | 42 | #define LZO_E_NOT_YET_IMPLEMENTED (-9) |
| 43 | #define LZO_E_INVALID_ARGUMENT (-10) | ||
| 43 | 44 | ||
| 44 | #endif | 45 | #endif |
diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c index a6040990a62e..236eb21167b5 100644 --- a/lib/lzo/lzo1x_compress.c +++ b/lib/lzo/lzo1x_compress.c | |||
| @@ -1,194 +1,243 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * LZO1X Compressor from MiniLZO | 2 | * LZO1X Compressor from LZO |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com> | 4 | * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com> |
| 5 | * | 5 | * |
| 6 | * The full LZO package can be found at: | 6 | * The full LZO package can be found at: |
| 7 | * http://www.oberhumer.com/opensource/lzo/ | 7 | * http://www.oberhumer.com/opensource/lzo/ |
| 8 | * | 8 | * |
| 9 | * Changed for kernel use by: | 9 | * Changed for Linux kernel use by: |
| 10 | * Nitin Gupta <nitingupta910@gmail.com> | 10 | * Nitin Gupta <nitingupta910@gmail.com> |
| 11 | * Richard Purdie <rpurdie@openedhand.com> | 11 | * Richard Purdie <rpurdie@openedhand.com> |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 16 | #include <linux/lzo.h> | ||
| 17 | #include <asm/unaligned.h> | 16 | #include <asm/unaligned.h> |
| 17 | #include <linux/lzo.h> | ||
| 18 | #include "lzodefs.h" | 18 | #include "lzodefs.h" |
| 19 | 19 | ||
| 20 | static noinline size_t | 20 | static noinline size_t |
| 21 | _lzo1x_1_do_compress(const unsigned char *in, size_t in_len, | 21 | lzo1x_1_do_compress(const unsigned char *in, size_t in_len, |
| 22 | unsigned char *out, size_t *out_len, void *wrkmem) | 22 | unsigned char *out, size_t *out_len, |
| 23 | size_t ti, void *wrkmem) | ||
| 23 | { | 24 | { |
| 25 | const unsigned char *ip; | ||
| 26 | unsigned char *op; | ||
| 24 | const unsigned char * const in_end = in + in_len; | 27 | const unsigned char * const in_end = in + in_len; |
| 25 | const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5; | 28 | const unsigned char * const ip_end = in + in_len - 20; |
| 26 | const unsigned char ** const dict = wrkmem; | 29 | const unsigned char *ii; |
| 27 | const unsigned char *ip = in, *ii = ip; | 30 | lzo_dict_t * const dict = (lzo_dict_t *) wrkmem; |
| 28 | const unsigned char *end, *m, *m_pos; | ||
| 29 | size_t m_off, m_len, dindex; | ||
| 30 | unsigned char *op = out; | ||
| 31 | 31 | ||
| 32 | ip += 4; | 32 | op = out; |
| 33 | ip = in; | ||
| 34 | ii = ip; | ||
| 35 | ip += ti < 4 ? 4 - ti : 0; | ||
| 33 | 36 | ||
| 34 | for (;;) { | 37 | for (;;) { |
| 35 | dindex = ((size_t)(0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK; | 38 | const unsigned char *m_pos; |
| 36 | m_pos = dict[dindex]; | 39 | size_t t, m_len, m_off; |
| 37 | 40 | u32 dv; | |
| 38 | if (m_pos < in) | ||
| 39 | goto literal; | ||
| 40 | |||
| 41 | if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET)) | ||
| 42 | goto literal; | ||
| 43 | |||
| 44 | m_off = ip - m_pos; | ||
| 45 | if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) | ||
| 46 | goto try_match; | ||
| 47 | |||
| 48 | dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f); | ||
| 49 | m_pos = dict[dindex]; | ||
| 50 | |||
| 51 | if (m_pos < in) | ||
| 52 | goto literal; | ||
| 53 | |||
| 54 | if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET)) | ||
| 55 | goto literal; | ||
| 56 | |||
| 57 | m_off = ip - m_pos; | ||
| 58 | if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) | ||
| 59 | goto try_match; | ||
| 60 | |||
| 61 | goto literal; | ||
| 62 | |||
| 63 | try_match: | ||
| 64 | if (get_unaligned((const unsigned short *)m_pos) | ||
| 65 | == get_unaligned((const unsigned short *)ip)) { | ||
| 66 | if (likely(m_pos[2] == ip[2])) | ||
| 67 | goto match; | ||
| 68 | } | ||
| 69 | |||
| 70 | literal: | 41 | literal: |
| 71 | dict[dindex] = ip; | 42 | ip += 1 + ((ip - ii) >> 5); |
| 72 | ++ip; | 43 | next: |
| 73 | if (unlikely(ip >= ip_end)) | 44 | if (unlikely(ip >= ip_end)) |
| 74 | break; | 45 | break; |
| 75 | continue; | 46 | dv = get_unaligned_le32(ip); |
| 76 | 47 | t = ((dv * 0x1824429d) >> (32 - D_BITS)) & D_MASK; | |
| 77 | match: | 48 | m_pos = in + dict[t]; |
| 78 | dict[dindex] = ip; | 49 | dict[t] = (lzo_dict_t) (ip - in); |
| 79 | if (ip != ii) { | 50 | if (unlikely(dv != get_unaligned_le32(m_pos))) |
| 80 | size_t t = ip - ii; | 51 | goto literal; |
| 81 | 52 | ||
| 53 | ii -= ti; | ||
| 54 | ti = 0; | ||
| 55 | t = ip - ii; | ||
| 56 | if (t != 0) { | ||
| 82 | if (t <= 3) { | 57 | if (t <= 3) { |
| 83 | op[-2] |= t; | 58 | op[-2] |= t; |
| 84 | } else if (t <= 18) { | 59 | COPY4(op, ii); |
| 60 | op += t; | ||
| 61 | } else if (t <= 16) { | ||
| 85 | *op++ = (t - 3); | 62 | *op++ = (t - 3); |
| 63 | COPY8(op, ii); | ||
| 64 | COPY8(op + 8, ii + 8); | ||
| 65 | op += t; | ||
| 86 | } else { | 66 | } else { |
| 87 | size_t tt = t - 18; | 67 | if (t <= 18) { |
