XRootD
XrdOucCRC32C.cc File Reference
#include <pthread.h>
#include "XrdOuc/XrdOucCRC32C.hh"
+ Include dependency graph for XrdOucCRC32C.cc:

Go to the source code of this file.

Macros

#define POLY   0x82f63b78
 

Functions

uint32_t crc32c (uint32_t crc, void const *buf, size_t len)
 
uint32_t crc32c_combine (uint32_t crcA, uint32_t crcB, size_t lengthB)
 merge two CRC32 such that result = crc32(dataB, lengthB, crc32(dataA, lengthA)) More...
 
static void crc32c_init_sw_big (void)
 
static void crc32c_init_sw_little (void)
 
uint32_t crc32c_sw (uint32_t crc, void const *buf, size_t len)
 
uint32_t crc32c_sw_big (uint32_t crc, void const *buf, size_t len)
 
uint32_t crc32c_sw_little (uint32_t crc, void const *buf, size_t len)
 
static uint64_t swap (uint64_t x)
 

Variables

static pthread_once_t crc32c_once_big = PTHREAD_ONCE_INIT
 
static pthread_once_t crc32c_once_little = PTHREAD_ONCE_INIT
 
static uint64_t crc32c_table_big [8][256]
 
static uint32_t crc32c_table_big_byte [256]
 
static uint32_t crc32c_table_little [8][256]
 

Macro Definition Documentation

◆ POLY

#define POLY   0x82f63b78

Definition at line 54 of file XrdOucCRC32C.cc.

Function Documentation

◆ crc32c()

uint32_t crc32c ( uint32_t  crc,
void const *  buf,
size_t  len 
)

Definition at line 277 of file XrdOucCRC32C.cc.

277  {
278  return crc32c_sw(crc, buf, len);
279 }
uint32_t crc32c_sw(uint32_t crc, void const *buf, size_t len)

References crc32c_sw().

Referenced by XrdEc::ObjCfg::ObjCfg(), XrdOucCRC::Calc32C(), XrdPfc::Info::CalcCksumStore(), XrdPfc::Info::CalcCksumSyncedAndAStats(), XrdOssCsiPages::FetchRangeUnaligned_postblock(), XrdOssCsiPages::FetchRangeUnaligned_preblock(), XrdOssCsiPages::StoreRangeUnaligned_postblock(), XrdOssCsiPages::StoreRangeUnaligned_preblock(), XrdOssCsiPages::truncate(), XrdOssCsiPages::UpdateRangeHoleUntilPage(), and XrdOucCRC::Ver32C().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crc32c_combine()

uint32_t crc32c_combine ( uint32_t  crcA,
uint32_t  crcB,
size_t  lengthB 
)

merge two CRC32 such that result = crc32(dataB, lengthB, crc32(dataA, lengthA))

CRC32 => 32 bits

Definition at line 437 of file XrdOucCRC32C.cc.

438 {
439  // Original source from Stephan Brumme
440  // https://github.com/stbrumme/crc32
441  // https://create.stephan-brumme.com/crc32/
442  // based on Mark Adler's crc_combine from
443  // https://github.com/madler/pigz/blob/master/pigz.c
444 
445  // main idea:
446  // - if you have two equally-sized blocks A and B,
447  // then you can create a block C = A ^ B
448  // which has the property crc(C) = crc(A) ^ crc(B)
449  // - if you append length(B) zeros to A and call it A' (think of it as AAAA000)
450  // and prepend length(A) zeros to B and call it B' (think of it as 0000BBB)
451  // then exists a C' = A' ^ B'
452  // - remember: if you XOR someting with zero, it remains unchanged: X ^ 0 = X
453  // - that means C' = A concat B so that crc(A concat B) = crc(C') = crc(A') ^ crc(B')
454  // - the trick is to compute crc(A') based on crc(A)
455  // and crc(B') based on crc(B)
456  // - since B' starts with many zeros, the crc of those initial zeros is still zero
457  // - that means crc(B') = crc(B)
458  // - unfortunately the trailing zeros of A' change the crc, so usually crc(A') != crc(A)
459  // - the following code is a fast algorithm to compute crc(A')
460  // - starting with crc(A) and appending length(B) zeros, needing just log2(length(B)) iterations
461  // - the details are explained by the original author at
462  // https://stackoverflow.com/questions/23122312/crc-calculation-of-a-mostly-static-data-stream/23126768
463  //
464  // notes:
465  // - I squeezed everything into one function to keep global namespace clean (original code two helper functions)
466  // - most original comments are still in place, I added comments where these helper functions where made inline code
467  // - performance-wise there isn't any differenze to the original zlib/pigz code
468 
469  // degenerated case
470  if (lengthB == 0)
471  return crcA;
472 
474  const uint32_t CrcBits = 32;
475 
476  uint32_t odd [CrcBits]; // odd-power-of-two zeros operator
477  uint32_t even[CrcBits]; // even-power-of-two zeros operator
478 
479  // put operator for one zero bit in odd
480  odd[0] = POLY; // CRC-32 polynomial
481  for (int i = 1; i < (int)CrcBits; i++)
482  odd[i] = 1 << (i - 1);
483 
484  // put operator for two zero bits in even
485  // same as gf2_matrix_square(even, odd);
486  for (int i = 0; i < (int)CrcBits; i++)
487  {
488  uint32_t vec = odd[i];
489  even[i] = 0;
490  for (int j = 0; vec != 0; j++, vec >>= 1)
491  if (vec & 1)
492  even[i] ^= odd[j];
493  }
494  // put operator for four zero bits in odd
495  // same as gf2_matrix_square(odd, even);
496  for (int i = 0; i < (int)CrcBits; i++)
497  {
498  uint32_t vec = even[i];
499  odd[i] = 0;
500  for (int j = 0; vec != 0; j++, vec >>= 1)
501  if (vec & 1)
502  odd[i] ^= even[j];
503  }
504 
505  // the following loop becomes much shorter if I keep swapping even and odd
506  uint32_t* a = even;
507  uint32_t* b = odd;
508  // apply secondLength zeros to firstCrc32
509  for (; lengthB > 0; lengthB >>= 1)
510  {
511  // same as gf2_matrix_square(a, b);
512  for (int i = 0; i < (int)CrcBits; i++)
513  {
514  uint32_t vec = b[i];
515  a[i] = 0;
516  for (int j = 0; vec != 0; j++, vec >>= 1)
517  if (vec & 1)
518  a[i] ^= b[j];
519  }
520 
521  // apply zeros operator for this bit
522  if (lengthB & 1)
523  {
524  // same as firstCrc32 = gf2_matrix_times(a, firstCrc32);
525  uint32_t sum = 0;
526  for (int i = 0; crcA != 0; i++, crcA >>= 1)
527  if (crcA & 1)
528  sum ^= a[i];
529  crcA = sum;
530  }
531 
532  // switch even and odd
533  uint32_t* t = a; a = b; b = t;
534  }
535 
536  // return combined crc
537  return crcA ^ crcB;
538 }
#define POLY
Definition: XrdOucCRC32C.cc:54

References POLY.

Referenced by XrdOucCRC::Combine32C().

+ Here is the caller graph for this function:

◆ crc32c_init_sw_big()

static void crc32c_init_sw_big ( void  )
static

Definition at line 359 of file XrdOucCRC32C.cc.

359  {
360  for (unsigned n = 0; n < 256; n++) {
361  uint32_t crc = n;
362  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
363  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
364  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
365  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
366  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
367  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
368  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
369  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
370  crc32c_table_big_byte[n] = crc;
371  }
372  for (unsigned n = 0; n < 256; n++) {
373  uint32_t crc = crc32c_table_big_byte[n];
374  crc32c_table_big[0][n] = swap(crc);
375  for (unsigned k = 1; k < 8; k++) {
376  crc = crc32c_table_big_byte[crc & 0xff] ^ (crc >> 8);
377  crc32c_table_big[k][n] = swap(crc);
378  }
379  }
380 }
static uint64_t swap(uint64_t x)
static uint64_t crc32c_table_big[8][256]
static uint32_t crc32c_table_big_byte[256]

References crc32c_table_big, crc32c_table_big_byte, POLY, and swap().

Referenced by crc32c_sw_big().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crc32c_init_sw_little()

static void crc32c_init_sw_little ( void  )
static

Definition at line 286 of file XrdOucCRC32C.cc.

286  {
287  for (unsigned n = 0; n < 256; n++) {
288  uint32_t crc = n;
289  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
290  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
291  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
292  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
293  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
294  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
295  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
296  crc = crc & 1 ? (crc >> 1) ^ POLY : crc >> 1;
297  crc32c_table_little[0][n] = crc;
298  }
299  for (unsigned n = 0; n < 256; n++) {
300  uint32_t crc = crc32c_table_little[0][n];
301  for (unsigned k = 1; k < 8; k++) {
302  crc = crc32c_table_little[0][crc & 0xff] ^ (crc >> 8);
303  crc32c_table_little[k][n] = crc;
304  }
305  }
306 }
static uint32_t crc32c_table_little[8][256]

References crc32c_table_little, and POLY.

Referenced by crc32c_sw_little().

+ Here is the caller graph for this function:

◆ crc32c_sw()

uint32_t crc32c_sw ( uint32_t  crc,
void const *  buf,
size_t  len 
)

Definition at line 424 of file XrdOucCRC32C.cc.

424  {
425  static int const little = 1;
426  if (*(char const *)&little)
427  return crc32c_sw_little(crc, buf, len);
428  else
429  return crc32c_sw_big(crc, buf, len);
430 }
uint32_t crc32c_sw_big(uint32_t crc, void const *buf, size_t len)
uint32_t crc32c_sw_little(uint32_t crc, void const *buf, size_t len)

References crc32c_sw_big(), and crc32c_sw_little().

Referenced by crc32c().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crc32c_sw_big()

uint32_t crc32c_sw_big ( uint32_t  crc,
void const *  buf,
size_t  len 
)

Definition at line 384 of file XrdOucCRC32C.cc.

384  {
385  unsigned char const *next = (unsigned char const *)buf;
386 
387  pthread_once(&crc32c_once_big, crc32c_init_sw_big);
388  crc = ~crc;
389  while (len && ((uintptr_t)next & 7) != 0) {
390  crc = crc32c_table_big_byte[(crc ^ *next++) & 0xff] ^ (crc >> 8);
391  len--;
392  }
393  if (len >= 8) {
394  uint64_t crcw = swap(crc);
395  do {
396  crcw ^= *(uint64_t const *)next;
397  crcw = crc32c_table_big[0][crcw & 0xff] ^
398  crc32c_table_big[1][(crcw >> 8) & 0xff] ^
399  crc32c_table_big[2][(crcw >> 16) & 0xff] ^
400  crc32c_table_big[3][(crcw >> 24) & 0xff] ^
401  crc32c_table_big[4][(crcw >> 32) & 0xff] ^
402  crc32c_table_big[5][(crcw >> 40) & 0xff] ^
403  crc32c_table_big[6][(crcw >> 48) & 0xff] ^
404  crc32c_table_big[7][(crcw >> 56)];
405  next += 8;
406  len -= 8;
407  } while (len >= 8);
408  crc = swap(crcw);
409  }
410  while (len) {
411  crc = crc32c_table_big_byte[(crc ^ *next++) & 0xff] ^ (crc >> 8);
412  len--;
413  }
414  return ~crc;
415 }
static void crc32c_init_sw_big(void)
static pthread_once_t crc32c_once_big

References crc32c_init_sw_big(), crc32c_once_big, crc32c_table_big, crc32c_table_big_byte, and swap().

Referenced by crc32c_sw().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ crc32c_sw_little()

uint32_t crc32c_sw_little ( uint32_t  crc,
void const *  buf,
size_t  len 
)

Definition at line 310 of file XrdOucCRC32C.cc.

310  {
311  unsigned char const *next = (unsigned char const *)buf;
312 
314  crc = ~crc;
315  while (len && ((uintptr_t)next & 7) != 0) {
316  crc = crc32c_table_little[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
317  len--;
318  }
319  if (len >= 8) {
320  uint64_t crcw = crc;
321  do {
322  crcw ^= *(uint64_t const *)next;
323  crcw = crc32c_table_little[7][crcw & 0xff] ^
324  crc32c_table_little[6][(crcw >> 8) & 0xff] ^
325  crc32c_table_little[5][(crcw >> 16) & 0xff] ^
326  crc32c_table_little[4][(crcw >> 24) & 0xff] ^
327  crc32c_table_little[3][(crcw >> 32) & 0xff] ^
328  crc32c_table_little[2][(crcw >> 40) & 0xff] ^
329  crc32c_table_little[1][(crcw >> 48) & 0xff] ^
330  crc32c_table_little[0][crcw >> 56];
331  next += 8;
332  len -= 8;
333  } while (len >= 8);
334  crc = crcw;
335  }
336  while (len) {
337  crc = crc32c_table_little[0][(crc ^ *next++) & 0xff] ^ (crc >> 8);
338  len--;
339  }
340  return ~crc;
341 }
static pthread_once_t crc32c_once_little
static void crc32c_init_sw_little(void)

References crc32c_init_sw_little(), crc32c_once_little, and crc32c_table_little.

Referenced by crc32c_sw().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ swap()

static uint64_t swap ( uint64_t  x)
inlinestatic

Definition at line 348 of file XrdOucCRC32C.cc.

348  {
349  x = ((x << 8) & 0xff00ff00ff00ff00) | ((x >> 8) & 0xff00ff00ff00ff);
350  x = ((x << 16) & 0xffff0000ffff0000) | ((x >> 16) & 0xffff0000ffff);
351  return (x << 32) | (x >> 32);
352 }

Referenced by crc32c_init_sw_big(), crc32c_sw_big(), and XrdCl::StreamMutex::UnLock().

+ Here is the caller graph for this function:

Variable Documentation

◆ crc32c_once_big

pthread_once_t crc32c_once_big = PTHREAD_ONCE_INIT
static

Definition at line 356 of file XrdOucCRC32C.cc.

Referenced by crc32c_sw_big().

◆ crc32c_once_little

pthread_once_t crc32c_once_little = PTHREAD_ONCE_INIT
static

Definition at line 284 of file XrdOucCRC32C.cc.

Referenced by crc32c_sw_little().

◆ crc32c_table_big

uint64_t crc32c_table_big[8][256]
static

Definition at line 358 of file XrdOucCRC32C.cc.

Referenced by crc32c_init_sw_big(), and crc32c_sw_big().

◆ crc32c_table_big_byte

uint32_t crc32c_table_big_byte[256]
static

Definition at line 357 of file XrdOucCRC32C.cc.

Referenced by crc32c_init_sw_big(), and crc32c_sw_big().

◆ crc32c_table_little

uint32_t crc32c_table_little[8][256]
static

Definition at line 285 of file XrdOucCRC32C.cc.

Referenced by crc32c_init_sw_little(), and crc32c_sw_little().