| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/mman.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <err.h>
- #include <getopt.h>
- #include <nmmintrin.h>
- #include <time.h>
- #include <libutil.h>
- #define POLY 0x82f63b78
- static uint32_t crc32c_poly[256];
- /*
- * Create Poly table
- */
- static void crc32_table()
- {
- uint32_t crc;
- for (uint32_t i = 0; i < 256; i++) {
- crc = i;
- crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
- crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
- crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
- crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
- crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
- crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
- crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
- crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
- crc32c_poly[i] = crc;
- }
- }
- /*
- * CRC32C software computing
- *
- * @data: buffer
- * @length: size
- */
- uint32_t crc32c(const char *data, size_t length)
- {
- uint32_t crc = ~(0U);
-
- printf("Software computing:\n");
- printf("------------------\n");
- while (length--) {
- crc = crc32c_poly[(crc ^ (uint32_t)(*data++)) & 0xFFL] ^ (crc >> 8);
- }
- return crc ^ 0xffffffff;
- }
- /*
- * CRC32C hardware intrinsics
- *
- * @data: buffer
- * @length: size
- */
- uint32_t crc32c_hw(const char *data, size_t length)
- {
- uint32_t crc = ~(0U);
-
- printf("Hardware computing:\n");
- printf("------------------\n");
- while (length--) {
- crc = _mm_crc32_u8(crc, (unsigned char)(*data++));
- }
- return crc ^ 0xffffffff;
- }
- /*
- * smart helpers
- */
- void fd_close(int *fd)
- {
- close(*fd);
- *fd = -1;
- }
- #define _smartfd __attribute((cleanup(fd_close)))
- void file_close(FILE **fd)
- {
- fclose(*fd);
- *fd = NULL;
- }
- #define _smartfile __attribute((cleanup(file_close)))
- [[noreturn]] static int usage(void)
- {
- fputs("crc32c [--input file]\n", stderr);
- exit (EXIT_SUCCESS);
- }
- /*
- * Print human readable numbers
- *
- * @width: spaces
- * @bytes: value in bytes
- */
- static void printsize(size_t width, off_t bytes)
- {
- /*
- * Reserve one space before the size and allocate room for
- * the trailing '\0'.
- */
- char buf[5];
- humanize_number(buf, sizeof(buf), (int64_t)bytes, "",
- HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
- (void)printf("%*s", (u_int)width, buf);
- }
- int main(int argc, char *argv[])
- {
- static struct option longopts[] = {
- { "input", required_argument, NULL, 'i' },
- { NULL, 0, NULL, 0 }
- };
- int ch;
- _smartfd int fd = -1;
- char *inputfile = NULL;
- while ((ch = getopt_long(argc, argv, "hi:", longopts, NULL)) != -1) {
- switch (ch) {
- case 'i':
- inputfile = optarg;
- break;
- case 0:
- /* long option */
- break;
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
- if (*argv || (inputfile == NULL))
- usage();
- fd = open(inputfile, O_RDONLY);
- if (fd < 0) {
- err(EXIT_FAILURE, "failed to open %s:", inputfile);
- }
- /* File analysis */
- struct stat statbuf = { 0 };
- fstat(fd, & statbuf);
- printf("Parsing");
- printsize(8, statbuf.st_size);
- puts(".\n");
- char *addr = (char *)mmap(NULL, (size_t)statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- if (addr == NULL)
- err(EXIT_FAILURE, "Failed to map file %s:\n", inputfile);
- /* CRC32C */
- crc32_table();
- clock_t t1, t0;
- t0 = clock();
- uint32_t c = crc32c(addr, (size_t)statbuf.st_size);
- t1 = clock();
- printf("CRC32C => %08x: %6.3f ms\n", c, 1000.0 * (double)(t1 - t0) / CLOCKS_PER_SEC);
- printf("\n");
- c = crc32c_hw(addr, (size_t)statbuf.st_size);
- t0 = clock();
- printf("CRC32C => %08x: %6.3f ms\n", c, 1000.0 * (double)(t0 - t1) / CLOCKS_PER_SEC);
- munmap(addr, (size_t)statbuf.st_size);
- return EXIT_SUCCESS;
- }
|