David Marec 9 miesięcy temu
rodzic
commit
90562bd5bf
3 zmienionych plików z 206 dodań i 0 usunięć
  1. 24 0
      crc32/Makefile
  2. 23 0
      crc32/README.md
  3. 159 0
      crc32/crc32c.c

+ 24 - 0
crc32/Makefile

@@ -0,0 +1,24 @@
+CFLAGS+=-O3 -Wall -fPIE -fno-strict-aliasing
+CFLAGS+=-Wformat -Wformat=2 -Wconversion -Wimplicit-fallthrough
+CFLAGS+=-Werror=format-security -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3
+CFLAGS+=-fstack-clash-protection -fstack-protector-strong
+CFLAGS+=-fstrict-flex-arrays=3 -msse4.2
+
+LDFLAGS+=-msse4.2 -Wl,-O3,--sort-common,--as-needed,-z,relro,-z,now,--strip-all -pie
+LDFLAGS+=-Wl,-z,nodlopen -Wl,-z,noexecstack,--no-copy-dt-needed-entries
+
+PROG=crc32c
+PROG_OBJS=crc32c.o
+
+.PHONY: clean
+.MAIN: $(PROG)
+
+$(PROG): $(PROG_OBJS)
+	$(CC) -o ${.TARGET} ${.ALLSRC} $(LDFLAGS)
+
+%o: 
+	$(CC) -o ${.TARGET} -c ${.IMPSRC}
+
+clean:
+	rm -f *.o $(PROG)
+

+ 23 - 0
crc32/README.md

@@ -0,0 +1,23 @@
+# CRC32 computing
+
+Different CRC32C (Castagnoli) implementation
+
+# software
+
+Portable implementation.
+
+# Hardware
+
+Compiler Intrinsics implementation.
+
+Intel SSE4.2 required.
+
+ARM also provides intrinsics in ACME, `march=+crc+`.
+
+
+# TODO
+
+Design alignment steps for better performances.
+
+
+

+ 159 - 0
crc32/crc32c.c

@@ -0,0 +1,159 @@
+#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>
+
+#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:");
+	printf("------------------");
+
+    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:");
+	printf("------------------");
+    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);
+}
+
+
+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 %zu bytes.\n", statbuf.st_size);
+
+	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: %d\n", c, (t1 - t0) * CLOCKS_PER_SEC);
+	c = crc32c_hw(addr, (size_t)statbuf.st_size);
+	t0 = clock();
+	printf("CRC32C => %08x: %d\n", c, (t0 - t1) * CLOCKS_PER_SEC);
+
+	munmap(addr, (size_t)statbuf.st_size);
+
+	return EXIT_SUCESS;
+}
+