From ee6bcf12231c47cec8bdc8df9b9e5fd41e7aa37c Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Wed, 27 Apr 2005 22:26:45 +0000 Subject: [PATCH] Refactor the CRC-32 code to enhance its usability. Move the actual CRC logic to a new function: crc32_raw() that obtains the initial CRC value as well as leaves any post-processing to the caller. As such, it can be used when the initial CRC value is not ~0U or when the final CRC value does need to be inverted (bitwise). It also means that crc32_raw() can be called repeatedly when the data is not available as a single block, such as for scatter/gather lists and the likes. Avoid the additional call overhead incured by the refactoring by moving the implementation off crc32() to sys/systm.h and making it inlinable. Since crc32_raw() is itself trivial and since it may be used in loops that iterate over fragments, having it available for inlining can be beneficial. Hence, move its implementation to sys/systm.h as well. Keep the original implementation of crc32() in libkern/crc32.c for documentation purposes (as a comment of course). Triggered by: Jose M Rodriguez (josemi at freebsd dot jazztel dot es) Discussed on: current@ Tested on: amd64, ia64 (BVO having GPT partitions) Jargon file candidate: BVO = By Virtue Of :-) --- sys/libkern/crc32.c | 33 ++++++++++++++++++--------------- sys/sys/systm.h | 22 +++++++++++++++++++++- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/sys/libkern/crc32.c b/sys/libkern/crc32.c index a6a162b718bf..4c937d29a568 100644 --- a/sys/libkern/crc32.c +++ b/sys/libkern/crc32.c @@ -94,18 +94,21 @@ uint32_t crc32_tab[] = { 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; -uint32_t -crc32(const void *buf, size_t size) -{ - const uint8_t *p; - uint32_t crc; - - p = buf; - crc = ~0U; - - while (size--) - crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); - - return crc ^ ~0U; -} - +/* + * A function that calculates the CRC-32 based on the table above is + * given below for documentation purposes. An equivalent implementation + * of this function that's actually used in the kernel can be found + * in sys/systm.h, where it can be inlined. + * + * uint32_t + * crc32(const void *buf, size_t size) + * { + * const uint8_t *p = buf; + * uint32_t crc; + * + * crc = ~0U; + * while (size--) + * crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + * return crc ^ ~0U; + * } + */ diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 0c114b3f7362..64545f7ec766 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -143,8 +143,28 @@ void panic(const char *, ...) __dead2 __printflike(1, 2); void cpu_boot(int); void cpu_rootconf(void); + extern uint32_t crc32_tab[]; -uint32_t crc32(const void *buf, size_t size); + +static __inline uint32_t +crc32_raw(const void *buf, size_t size, uint32_t crc) +{ + const uint8_t *p = buf; + + while (size--) + crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); + return (crc); +} + +static __inline uint32_t +crc32(const void *buf, size_t size) +{ + uint32_t crc; + + crc = crc32_raw(buf, size, ~0U); + return (crc ^ ~0U); +} + void critical_enter(void); void critical_exit(void); void init_param1(void);