1
1
openmpi/opal/util/crc.c
Nathan Hjelm 4d92c9989e more c99 updates
This commit does two things. It removes checks for C99 required
headers (stdlib.h, string.h, signal.h, etc). Additionally it removes
definitions for required C99 types (intptr_t, int64_t, int32_t, etc).

Signed-off-by: Nathan Hjelm <hjelmn@me.com>
2015-06-25 10:14:13 -06:00

1200 строки
38 KiB
C

/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2006 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2014 Intel, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#include "opal_config.h"
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif /* HAVE_STDIO_H */
#include <stdlib.h>
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif /* HAVE_STRINGS_H */
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif /* HAVE_UNISTD_H */
#include "opal/util/crc.h"
#if (OPAL_ALIGNMENT_LONG == 8)
#define OPAL_CRC_WORD_MASK_ 0x7
#elif (OPAL_ALIGNMENT_LONG == 4)
#define OPAL_CRC_WORD_MASK_ 0x3
#else
#define OPAL_CRC_WORD_MASK_ 0xFFFF
#endif
#define WORDALIGNED(v) \
(((intptr_t)v & OPAL_CRC_WORD_MASK_) ? false : true)
#define INTALIGNED(v) \
(((intptr_t)v & 3) ? false : true)
/*
* this version of bcopy_csum() looks a little too long, but it
* handles cumulative checksumming for arbitrary lengths and address
* alignments as best as it can; the contents of lastPartialLong and
* lastPartialLength are updated to reflected the last partial word's
* value and length (in bytes) -- this should allow proper handling of
* checksumming contiguous or noncontiguous buffers via multiple calls
* of bcopy_csum() - Mitch
*/
unsigned long
opal_bcopy_csum_partial (
const void * source,
void * destination,
size_t copylen,
size_t csumlen,
unsigned long * lastPartialLong,
size_t* lastPartialLength
)
{
unsigned long * src = (unsigned long *) source;
unsigned long * dest = (unsigned long *) destination;
unsigned long csum = 0;
size_t csumlenresidue;
unsigned long i, temp;
csumlenresidue = (csumlen > copylen) ? (csumlen - copylen) : 0;
temp = *lastPartialLong;
if (WORDALIGNED(source) && WORDALIGNED(dest)) {
if (*lastPartialLength) {
/* do we have enough data to fill out the partial word? */
if (copylen >= (sizeof(unsigned long) - *lastPartialLength)) { /* YES, we do... */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned long) - *lastPartialLength));
memcpy(dest, ((char *)&temp + *lastPartialLength),
(sizeof(unsigned long) - *lastPartialLength));
src = (unsigned long *)((char *)src + sizeof(unsigned long) - *lastPartialLength);
dest = (unsigned long *)((char *)dest + sizeof(unsigned long) - *lastPartialLength);
csum += (temp - *lastPartialLong);
copylen -= sizeof(unsigned long) - *lastPartialLength;
/* now we have an unaligned source and an unaligned destination */
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
*lastPartialLength = 0;
*lastPartialLong = 0;
}
else { /* NO, we don't... */
memcpy(((char *)&temp + *lastPartialLength), src, copylen);
memcpy(dest, ((char *)&temp + *lastPartialLength), copylen);
src = (unsigned long *)((char *)src + copylen);
dest = (unsigned long *)((char *)dest + copylen);
csum += (temp - *lastPartialLong);
*lastPartialLong = temp;
*lastPartialLength += copylen;
copylen = 0;
}
}
else { /* fast path... */
size_t numLongs = copylen/sizeof(unsigned long);
for(i = 0; i < numLongs; i++) {
csum += *src;
*dest++ = *src++;
}
*lastPartialLong = 0;
*lastPartialLength = 0;
if (WORDALIGNED(copylen) && (csumlenresidue == 0)) {
return(csum);
}
else {
copylen -= i * sizeof(unsigned long);
}
}
} else if (WORDALIGNED(source)) {
if (*lastPartialLength) {
/* do we have enough data to fill out the partial word? */
if (copylen >= (sizeof(unsigned long) - *lastPartialLength)) { /* YES, we do... */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned long) - *lastPartialLength));
memcpy(dest, ((char *)&temp + *lastPartialLength),
(sizeof(unsigned long) - *lastPartialLength));
src = (unsigned long *)((char *)src + sizeof(unsigned long) - *lastPartialLength);
dest = (unsigned long *)((char *)dest + sizeof(unsigned long) - *lastPartialLength);
csum += (temp - *lastPartialLong);
copylen -= sizeof(unsigned long) - *lastPartialLength;
/* now we have an unaligned source and an unknown alignment for our destination */
if (WORDALIGNED(dest)) {
size_t numLongs = copylen/sizeof(unsigned long);
for(i = 0; i < numLongs; i++) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
*dest++ = temp;
}
copylen -= i * sizeof(unsigned long);
}
else {
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
}
*lastPartialLong = 0;
*lastPartialLength = 0;
}
else { /* NO, we don't... */
memcpy(((char *)&temp + *lastPartialLength), src, copylen);
memcpy(dest, ((char *)&temp + *lastPartialLength), copylen);
src = (unsigned long *)((char *)src + copylen);
dest = (unsigned long *)((char *)dest + copylen);
csum += (temp - *lastPartialLong);
*lastPartialLong = temp;
*lastPartialLength += copylen;
copylen = 0;
}
}
else {
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
temp = *src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
*lastPartialLong = 0;
*lastPartialLength = 0;
}
} else if (WORDALIGNED(dest)) {
if (*lastPartialLength) {
/* do we have enough data to fill out the partial word? */
if (copylen >= (sizeof(unsigned long) - *lastPartialLength)) { /* YES, we do... */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned long) - *lastPartialLength));
memcpy(dest, ((char *)&temp + *lastPartialLength),
(sizeof(unsigned long) - *lastPartialLength));
src = (unsigned long *)((char *)src + sizeof(unsigned long) - *lastPartialLength);
dest = (unsigned long *)((char *)dest + sizeof(unsigned long) - *lastPartialLength);
csum += (temp - *lastPartialLong);
copylen -= sizeof(unsigned long) - *lastPartialLength;
/* now we have a source of unknown alignment and a unaligned destination */
if (WORDALIGNED(src)) {
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
temp = *src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
*lastPartialLong = 0;
*lastPartialLength = 0;
}
else {
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
*lastPartialLength = 0;
*lastPartialLong = 0;
}
}
else { /* NO, we don't... */
memcpy(((char *)&temp + *lastPartialLength), src, copylen);
memcpy(dest, ((char *)&temp + *lastPartialLength), copylen);
src = (unsigned long *)((char *)src + copylen);
dest = (unsigned long *)((char *)dest + copylen);
csum += (temp - *lastPartialLong);
*lastPartialLong = temp;
*lastPartialLength += copylen;
copylen = 0;
}
}
else {
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
*dest++ = temp;
}
*lastPartialLength = 0;
*lastPartialLong = 0;
}
} else {
if (*lastPartialLength) {
/* do we have enough data to fill out the partial word? */
if (copylen >= (sizeof(unsigned long) - *lastPartialLength)) { /* YES, we do... */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned long) - *lastPartialLength));
memcpy(dest, ((char *)&temp + *lastPartialLength),
(sizeof(unsigned long) - *lastPartialLength));
src = (unsigned long *)((char *)src + sizeof(unsigned long) - *lastPartialLength);
dest = (unsigned long *)((char *)dest + sizeof(unsigned long) - *lastPartialLength);
csum += (temp - *lastPartialLong);
copylen -= sizeof(unsigned long) - *lastPartialLength;
/* now we have an unknown alignment for our source and destination */
if (WORDALIGNED(src) && WORDALIGNED(dest)) {
size_t numLongs = copylen/sizeof(unsigned long);
for(i = 0; i < numLongs; i++) {
csum += *src;
*dest++ = *src++;
}
copylen -= i * sizeof(unsigned long);
}
else { /* safe but slower for all other alignments */
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
}
*lastPartialLong = 0;
*lastPartialLength = 0;
}
else { /* NO, we don't... */
memcpy(((char *)&temp + *lastPartialLength), src, copylen);
memcpy(dest, ((char *)&temp + *lastPartialLength), copylen);
src = (unsigned long *)((char *)src + copylen);
dest = (unsigned long *)((char *)dest + copylen);
csum += (temp - *lastPartialLong);
*lastPartialLong = temp;
*lastPartialLength += copylen;
copylen = 0;
}
}
else {
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
*lastPartialLength = 0;
*lastPartialLong = 0;
}
}
/* if copylen is non-zero there was a bit left, less than an unsigned long's worth */
if ((copylen != 0) && (csumlenresidue == 0)) {
temp = *lastPartialLong;
if (*lastPartialLength) {
if (copylen >= (sizeof(unsigned long) - *lastPartialLength)) {
/* copy all remaining bytes from src to dest */
unsigned long copytemp = 0;
memcpy(&copytemp, src, copylen);
memcpy(dest, &copytemp, copylen);
/* fill out rest of partial word and add to checksum */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned long) - *lastPartialLength));
/* avoid unsigned arithmetic overflow by subtracting the old partial
* word from the new one before adding to the checksum...
*/
csum += (temp - *lastPartialLong);
copylen -= sizeof(unsigned long) - *lastPartialLength;
src = (unsigned long *)((char *)src + sizeof(unsigned long) - *lastPartialLength);
*lastPartialLength = copylen;
/* reset temp, and calculate next partial word */
temp = 0;
if (copylen) {
memcpy(&temp, src, copylen);
}
/* add it to the the checksum */
csum += temp;
*lastPartialLong = temp;
}
else {
/* copy all remaining bytes from src to dest */
unsigned long copytemp = 0;
memcpy(&copytemp, src, copylen);
memcpy(dest, &copytemp, copylen);
/* fill out rest of partial word and add to checksum */
memcpy(((char *)&temp + *lastPartialLength), src,
copylen);
/* avoid unsigned arithmetic overflow by subtracting the old partial
* word from the new one before adding to the checksum...
*/
csum += temp - *lastPartialLong;
*lastPartialLong = temp;
*lastPartialLength += copylen;
}
}
else { /* fast path... */
/* temp and *lastPartialLong are 0 if *lastPartialLength is 0... */
memcpy(&temp, src, copylen);
csum += temp;
memcpy(dest, &temp, copylen);
*lastPartialLong = temp;
*lastPartialLength = copylen;
/* done...return the checksum */
}
}
else if (csumlenresidue != 0) {
if (copylen != 0) {
temp = 0;
memcpy(&temp, src, copylen);
memcpy(dest, &temp, copylen);
}
if (csumlenresidue < (sizeof(unsigned long) - copylen - *lastPartialLength)) {
temp = *lastPartialLong;
memcpy(((char *)&temp + *lastPartialLength), src, (copylen + csumlenresidue));
/* avoid unsigned arithmetic overflow by subtracting the old partial */
/* word from the new one before adding to the checksum... */
csum += temp - *lastPartialLong;
src++;
*lastPartialLong = temp;
*lastPartialLength += copylen + csumlenresidue;
csumlenresidue = 0;
}
else {
/* we have enough chksum data to fill out our last partial */
/* word */
temp = *lastPartialLong;
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned long) - *lastPartialLength));
/* avoid unsigned arithmetic overflow by subtracting the old partial */
/* word from the new one before adding to the checksum... */
csum += temp - *lastPartialLong;
src = (unsigned long *)((char *)src + sizeof(unsigned long) - *lastPartialLength);
csumlenresidue -= sizeof(unsigned long) - *lastPartialLength - copylen;
*lastPartialLength = 0;
*lastPartialLong = 0;
}
if (WORDALIGNED(src)) {
for (i = 0; i < csumlenresidue/sizeof(unsigned long); i++) {
csum += *src++;
}
}
else {
for (i = 0; i < csumlenresidue/sizeof(unsigned long); i++) {
memcpy(&temp, src, sizeof(temp));
csum += temp;
src++;
}
}
csumlenresidue -= i * sizeof(unsigned long);
if (csumlenresidue) {
temp = 0;
memcpy(&temp, src, csumlenresidue);
csum += temp;
*lastPartialLong = temp;
*lastPartialLength = csumlenresidue;
}
} /* end else if (csumlenresidue != 0) */
return csum;
}
unsigned int
opal_bcopy_uicsum_partial (
const void * source,
void * destination,
size_t copylen,
size_t csumlen,
unsigned int* lastPartialInt,
size_t* lastPartialLength
)
{
unsigned int * src = (unsigned int *) source;
unsigned int * dest = (unsigned int *) destination;
unsigned int csum = 0;
size_t csumlenresidue;
unsigned long i;
unsigned int temp;
csumlenresidue = (csumlen > copylen) ? (csumlen - copylen) : 0;
temp = *lastPartialInt;
if (INTALIGNED(source) && INTALIGNED(dest)) {
if (*lastPartialLength) {
/* do we have enough data to fill out the partial word? */
if (copylen >= (sizeof(unsigned int) - *lastPartialLength)) { /* YES, we do... */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned int) - *lastPartialLength));
memcpy(dest, ((char *)&temp + *lastPartialLength),
(sizeof(unsigned int) - *lastPartialLength));
src = (unsigned int *)((char *)src + sizeof(unsigned int) - *lastPartialLength);
dest = (unsigned int *)((char *)dest + sizeof(unsigned int) - *lastPartialLength);
csum += (temp - *lastPartialInt);
copylen -= sizeof(unsigned int) - *lastPartialLength;
/* now we have an unaligned source and an unaligned destination */
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
*lastPartialLength = 0;
*lastPartialInt = 0;
}
else { /* NO, we don't... */
memcpy(((char *)&temp + *lastPartialLength), src, copylen);
memcpy(dest, ((char *)&temp + *lastPartialLength), copylen);
src = (unsigned int *)((char *)src + copylen);
dest = (unsigned int *)((char *)dest + copylen);
csum += (temp - *lastPartialInt);
*lastPartialInt = temp;
*lastPartialLength += copylen;
copylen = 0;
}
}
else { /* fast path... */
size_t numLongs = copylen/sizeof(unsigned int);
for(i = 0; i < numLongs; i++) {
csum += *src;
*dest++ = *src++;
}
*lastPartialInt = 0;
*lastPartialLength = 0;
if (INTALIGNED(copylen) && (csumlenresidue == 0)) {
return(csum);
}
else {
copylen -= i * sizeof(unsigned int);
}
}
} else if (INTALIGNED(source)) {
if (*lastPartialLength) {
/* do we have enough data to fill out the partial word? */
if (copylen >= (sizeof(unsigned int) - *lastPartialLength)) { /* YES, we do... */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned int) - *lastPartialLength));
memcpy(dest, ((char *)&temp + *lastPartialLength),
(sizeof(unsigned int) - *lastPartialLength));
src = (unsigned int *)((char *)src + sizeof(unsigned int) - *lastPartialLength);
dest = (unsigned int *)((char *)dest + sizeof(unsigned int) - *lastPartialLength);
csum += (temp - *lastPartialInt);
copylen -= sizeof(unsigned int) - *lastPartialLength;
/* now we have an unaligned source and an unknown alignment for our destination */
if (INTALIGNED(dest)) {
size_t numLongs = copylen/sizeof(unsigned int);
for(i = 0; i < numLongs; i++) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
*dest++ = temp;
}
copylen -= i * sizeof(unsigned int);
}
else {
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
}
*lastPartialInt = 0;
*lastPartialLength = 0;
}
else { /* NO, we don't... */
memcpy(((char *)&temp + *lastPartialLength), src, copylen);
memcpy(dest, ((char *)&temp + *lastPartialLength), copylen);
src = (unsigned int *)((char *)src + copylen);
dest = (unsigned int *)((char *)dest + copylen);
csum += (temp - *lastPartialInt);
*lastPartialInt = temp;
*lastPartialLength += copylen;
copylen = 0;
}
}
else {
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
temp = *src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
*lastPartialInt = 0;
*lastPartialLength = 0;
}
} else if (INTALIGNED(dest)) {
if (*lastPartialLength) {
/* do we have enough data to fill out the partial word? */
if (copylen >= (sizeof(unsigned int) - *lastPartialLength)) { /* YES, we do... */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned int) - *lastPartialLength));
memcpy(dest, ((char *)&temp + *lastPartialLength),
(sizeof(unsigned int) - *lastPartialLength));
src = (unsigned int *)((char *)src + sizeof(unsigned int) - *lastPartialLength);
dest = (unsigned int *)((char *)dest + sizeof(unsigned int) - *lastPartialLength);
csum += (temp - *lastPartialInt);
copylen -= sizeof(unsigned int) - *lastPartialLength;
/* now we have a source of unknown alignment and a unaligned destination */
if (INTALIGNED(src)) {
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
temp = *src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
*lastPartialInt = 0;
*lastPartialLength = 0;
}
else {
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
*lastPartialLength = 0;
*lastPartialInt = 0;
}
}
else { /* NO, we don't... */
memcpy(((char *)&temp + *lastPartialLength), src, copylen);
memcpy(dest, ((char *)&temp + *lastPartialLength), copylen);
src = (unsigned int *)((char *)src + copylen);
dest = (unsigned int *)((char *)dest + copylen);
csum += (temp - *lastPartialInt);
*lastPartialInt = temp;
*lastPartialLength += copylen;
copylen = 0;
}
}
else {
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
*dest++ = temp;
}
*lastPartialLength = 0;
*lastPartialInt = 0;
}
} else {
if (*lastPartialLength) {
/* do we have enough data to fill out the partial word? */
if (copylen >= (sizeof(unsigned int) - *lastPartialLength)) { /* YES, we do... */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned int) - *lastPartialLength));
memcpy(dest, ((char *)&temp + *lastPartialLength),
(sizeof(unsigned int) - *lastPartialLength));
src = (unsigned int *)((char *)src + sizeof(unsigned int) - *lastPartialLength);
dest = (unsigned int *)((char *)dest + sizeof(unsigned int) - *lastPartialLength);
csum += (temp - *lastPartialInt);
copylen -= sizeof(unsigned int) - *lastPartialLength;
/* now we have an unknown alignment for our source and destination */
if (INTALIGNED(src) && INTALIGNED(dest)) {
size_t numLongs = copylen/sizeof(unsigned int);
for(i = 0; i < numLongs; i++) {
csum += *src;
*dest++ = *src++;
}
copylen -= i * sizeof(unsigned int);
}
else { /* safe but slower for all other alignments */
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
}
*lastPartialInt = 0;
*lastPartialLength = 0;
}
else { /* NO, we don't... */
memcpy(((char *)&temp + *lastPartialLength), src, copylen);
memcpy(dest, ((char *)&temp + *lastPartialLength), copylen);
src = (unsigned int *)((char *)src + copylen);
dest = (unsigned int *)((char *)dest + copylen);
csum += (temp - *lastPartialInt);
*lastPartialInt = temp;
*lastPartialLength += copylen;
copylen = 0;
}
}
else {
for( ;copylen >= sizeof(*src); copylen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
memcpy(dest, &temp, sizeof(temp));
dest++;
}
*lastPartialLength = 0;
*lastPartialInt = 0;
}
}
/* if copylen is non-zero there was a bit left, less than an unsigned int's worth */
if ((copylen != 0) && (csumlenresidue == 0)) {
temp = *lastPartialInt;
if (*lastPartialLength) {
if (copylen >= (sizeof(unsigned int) - *lastPartialLength)) {
/* copy all remaining bytes from src to dest */
unsigned int copytemp = 0;
memcpy(&copytemp, src, copylen);
memcpy(dest, &copytemp, copylen);
/* fill out rest of partial word and add to checksum */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned int) - *lastPartialLength));
/* avoid unsigned arithmetic overflow by subtracting the old partial
* word from the new one before adding to the checksum...
*/
csum += (temp - *lastPartialInt);
copylen -= sizeof(unsigned int) - *lastPartialLength;
src = (unsigned int *)((char *)src + sizeof(unsigned int) - *lastPartialLength);
*lastPartialLength = copylen;
/* reset temp, and calculate next partial word */
temp = 0;
if (copylen) {
memcpy(&temp, src, copylen);
}
/* add it to the the checksum */
csum += temp;
*lastPartialInt = temp;
}
else {
/* copy all remaining bytes from src to dest */
unsigned int copytemp = 0;
memcpy(&copytemp, src, copylen);
memcpy(dest, &copytemp, copylen);
/* fill out rest of partial word and add to checksum */
memcpy(((char *)&temp + *lastPartialLength), src,
copylen);
/* avoid unsigned arithmetic overflow by subtracting the old partial
* word from the new one before adding to the checksum...
*/
csum += temp - *lastPartialInt;
*lastPartialInt = temp;
*lastPartialLength += copylen;
}
}
else { /* fast path... */
/* temp and *lastPartialInt are 0 if *lastPartialLength is 0... */
memcpy(&temp, src, copylen);
csum += temp;
memcpy(dest, &temp, copylen);
*lastPartialInt = temp;
*lastPartialLength = copylen;
/* done...return the checksum */
}
}
else if (csumlenresidue != 0) {
if (copylen != 0) {
temp = 0;
memcpy(&temp, src, copylen);
memcpy(dest, &temp, copylen);
}
if (csumlenresidue < (sizeof(unsigned int) - copylen - *lastPartialLength)) {
temp = *lastPartialInt;
memcpy(((char *)&temp + *lastPartialLength), src, (copylen + csumlenresidue));
/* avoid unsigned arithmetic overflow by subtracting the old partial
* word from the new one before adding to the checksum...
*/
csum += temp - *lastPartialInt;
src++;
*lastPartialInt = temp;
*lastPartialLength += copylen + csumlenresidue;
csumlenresidue = 0;
}
else {
/* we have enough chksum data to fill out our last partial
* word
*/
temp = *lastPartialInt;
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned int) - *lastPartialLength));
/* avoid unsigned arithmetic overflow by subtracting the old partial
* word from the new one before adding to the checksum...
*/
csum += temp - *lastPartialInt;
src = (unsigned int *)((char *)src + sizeof(unsigned int) - *lastPartialLength);
csumlenresidue -= sizeof(unsigned int) - *lastPartialLength - copylen;
*lastPartialLength = 0;
*lastPartialInt = 0;
}
if (INTALIGNED(src)) {
for (i = 0; i < csumlenresidue/sizeof(unsigned int); i++) {
csum += *src++;
}
}
else {
for (i = 0; i < csumlenresidue/sizeof(unsigned int); i++) {
memcpy(&temp, src, sizeof(temp));
csum += temp;
src++;
}
}
csumlenresidue -= i * sizeof(unsigned int);
if (csumlenresidue) {
temp = 0;
memcpy(&temp, src, csumlenresidue);
csum += temp;
*lastPartialInt = temp;
*lastPartialLength = csumlenresidue;
}
} /* end else if (csumlenresidue != 0) */
return csum;
}
/*
* csum() generates a bcopy_csum() - compatible checksum that can be
* called multiple times
*/
unsigned long
opal_csum_partial (
const void * source,
size_t csumlen,
unsigned long* lastPartialLong,
size_t* lastPartialLength
)
{
unsigned long * src = (unsigned long *) source;
unsigned long csum = 0;
unsigned long i, temp;
temp = *lastPartialLong;
if (WORDALIGNED(source)) {
if (*lastPartialLength) {
/* do we have enough data to fill out the partial word? */
if (csumlen >= (sizeof(unsigned long) - *lastPartialLength)) { /* YES, we do... */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned long) - *lastPartialLength));
src = (unsigned long *)((char *)src + sizeof(unsigned long) - *lastPartialLength);
csum += (temp - *lastPartialLong);
csumlen -= sizeof(unsigned long) - *lastPartialLength;
/* now we have an unaligned source */
for(i = 0; i < csumlen/sizeof(unsigned long); i++) {
memcpy(&temp, src, sizeof(temp));
csum += temp;
src++;
}
csumlen -= i * sizeof(unsigned long);
*lastPartialLong = 0;
*lastPartialLength = 0;
}
else { /* NO, we don't... */
memcpy(((char *)&temp + *lastPartialLength), src, csumlen);
src = (unsigned long *)((char *)src + csumlen);
csum += (temp - *lastPartialLong);
*lastPartialLong = temp;
*lastPartialLength += csumlen;
csumlen = 0;
}
}
else { /* fast path... */
size_t numLongs = csumlen/sizeof(unsigned long);
for(i = 0; i < numLongs; i++) {
csum += *src++;
}
*lastPartialLong = 0;
*lastPartialLength = 0;
if (WORDALIGNED(csumlen)) {
return(csum);
}
else {
csumlen -= i * sizeof(unsigned long);
}
}
} else {
if (*lastPartialLength) {
/* do we have enough data to fill out the partial word? */
if (csumlen >= (sizeof(unsigned long) - *lastPartialLength)) { /* YES, we do... */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned long) - *lastPartialLength));
src = (unsigned long *)((char *)src + sizeof(unsigned long) - *lastPartialLength);
csum += (temp - *lastPartialLong);
csumlen -= sizeof(unsigned long) - *lastPartialLength;
/* now we have a source of unknown alignment */
if (WORDALIGNED(src)) {
for(i = 0; i < csumlen/sizeof(unsigned long); i++) {
csum += *src++;
}
csumlen -= i * sizeof(unsigned long);
*lastPartialLong = 0;
*lastPartialLength = 0;
}
else {
for(i = 0; i < csumlen/sizeof(unsigned long); i++) {
memcpy(&temp, src, sizeof(temp));
csum += temp;
src++;
}
csumlen -= i * sizeof(unsigned long);
*lastPartialLong = 0;
*lastPartialLength = 0;
}
}
else { /* NO, we don't... */
memcpy(((char *)&temp + *lastPartialLength), src, csumlen);
src = (unsigned long *)((char *)src + csumlen);
csum += (temp - *lastPartialLong);
*lastPartialLong = temp;
*lastPartialLength += csumlen;
csumlen = 0;
}
}
else {
for( ;csumlen >= sizeof(*src); csumlen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
}
*lastPartialLength = 0;
*lastPartialLong = 0;
}
}
/* if csumlen is non-zero there was a bit left, less than an unsigned long's worth */
if (csumlen != 0) {
temp = *lastPartialLong;
if (*lastPartialLength) {
if (csumlen >= (sizeof(unsigned long) - *lastPartialLength)) {
/* fill out rest of partial word and add to checksum */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned long) - *lastPartialLength));
csum += (temp - *lastPartialLong);
csumlen -= sizeof(unsigned long) - *lastPartialLength;
src = (unsigned long *)((char *)src + sizeof(unsigned long) - *lastPartialLength);
*lastPartialLength = csumlen;
/* reset temp, and calculate next partial word */
temp = 0;
if (csumlen) {
memcpy(&temp, src, csumlen);
}
/* add it to the the checksum */
csum += temp;
*lastPartialLong = temp;
}
else {
/* fill out rest of partial word and add to checksum */
memcpy(((char *)&temp + *lastPartialLength), src,
csumlen);
csum += (temp - *lastPartialLong);
*lastPartialLong = temp;
*lastPartialLength += csumlen;
}
}
else { /* fast path... */
/* temp and *lastPartialLong are 0 if *lastPartialLength is 0... */
memcpy(&temp, src, csumlen);
csum += temp;
*lastPartialLong = temp;
*lastPartialLength = csumlen;
/* done...return the checksum */
}
}
return csum;
}
unsigned int
opal_uicsum_partial (
const void * source,
size_t csumlen,
unsigned int* lastPartialInt,
size_t* lastPartialLength
)
{
unsigned int * src = (unsigned int *) source;
unsigned int csum = 0;
unsigned int temp;
unsigned long i;
temp = *lastPartialInt;
if (INTALIGNED(source)) {
if (*lastPartialLength) {
/* do we have enough data to fill out the partial word? */
if (csumlen >= (sizeof(unsigned int) - *lastPartialLength)) { /* YES, we do... */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned int) - *lastPartialLength));
src = (unsigned int *)((char *)src + sizeof(unsigned int) - *lastPartialLength);
csum += (temp - *lastPartialInt);
csumlen -= sizeof(unsigned int) - *lastPartialLength;
/* now we have an unaligned source */
for(i = 0; i < csumlen/sizeof(unsigned int); i++) {
memcpy(&temp, src, sizeof(temp));
csum += temp;
src++;
}
csumlen -= i * sizeof(unsigned int);
*lastPartialInt = 0;
*lastPartialLength = 0;
}
else { /* NO, we don't... */
memcpy(((char *)&temp + *lastPartialLength), src, csumlen);
src = (unsigned int *)((char *)src + csumlen);
csum += (temp - *lastPartialInt);
*lastPartialInt = temp;
*lastPartialLength += csumlen;
csumlen = 0;
}
}
else { /* fast path... */
size_t numLongs = csumlen/sizeof(unsigned int);
for(i = 0; i < numLongs; i++) {
csum += *src++;
}
*lastPartialInt = 0;
*lastPartialLength = 0;
if (INTALIGNED(csumlen)) {
return(csum);
}
else {
csumlen -= i * sizeof(unsigned int);
}
}
} else {
if (*lastPartialLength) {
/* do we have enough data to fill out the partial word? */
if (csumlen >= (sizeof(unsigned int) - *lastPartialLength)) { /* YES, we do... */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned int) - *lastPartialLength));
src = (unsigned int *)((char *)src + sizeof(unsigned int) - *lastPartialLength);
csum += (temp - *lastPartialInt);
csumlen -= sizeof(unsigned int) - *lastPartialLength;
/* now we have a source of unknown alignment */
if (INTALIGNED(src)) {
for(i = 0; i < csumlen/sizeof(unsigned int); i++) {
csum += *src++;
}
csumlen -= i * sizeof(unsigned int);
*lastPartialInt = 0;
*lastPartialLength = 0;
}
else {
for(i = 0; i < csumlen/sizeof(unsigned int); i++) {
memcpy(&temp, src, sizeof(temp));
csum += temp;
src++;
}
csumlen -= i * sizeof(unsigned int);
*lastPartialInt = 0;
*lastPartialLength = 0;
}
}
else { /* NO, we don't... */
memcpy(((char *)&temp + *lastPartialLength), src, csumlen);
src = (unsigned int *)((char *)src + csumlen);
csum += (temp - *lastPartialInt);
*lastPartialInt = temp;
*lastPartialLength += csumlen;
csumlen = 0;
}
}
else {
for( ;csumlen >= sizeof(*src); csumlen -= sizeof(*src)) {
memcpy(&temp, src, sizeof(temp));
src++;
csum += temp;
}
*lastPartialLength = 0;
*lastPartialInt = 0;
}
}
/* if csumlen is non-zero there was a bit left, less than an unsigned int's worth */
if (csumlen != 0) {
temp = *lastPartialInt;
if (*lastPartialLength) {
if (csumlen >= (sizeof(unsigned int) - *lastPartialLength)) {
/* fill out rest of partial word and add to checksum */
memcpy(((char *)&temp + *lastPartialLength), src,
(sizeof(unsigned int) - *lastPartialLength));
csum += (temp - *lastPartialInt);
csumlen -= sizeof(unsigned int) - *lastPartialLength;
src = (unsigned int *)((char *)src + sizeof(unsigned int) - *lastPartialLength);
*lastPartialLength = csumlen;
/* reset temp, and calculate next partial word */
temp = 0;
if (csumlen) {
memcpy(&temp, src, csumlen);
}
/* add it to the the checksum */
csum += temp;
*lastPartialInt = temp;
}
else {
/* fill out rest of partial word and add to checksum */
memcpy(((char *)&temp + *lastPartialLength), src,
csumlen);
csum += (temp - *lastPartialInt);
*lastPartialInt = temp;
*lastPartialLength += csumlen;
}
}
else { /* fast path... */
/* temp and *lastPartialInt are 0 if *lastPartialLength is 0... */
memcpy(&temp, src, csumlen);
csum += temp;
*lastPartialInt = temp;
*lastPartialLength = csumlen;
/* done...return the checksum */
}
}
return csum;
}
/* globals for CRC32 bcopy and calculation routines */
static bool _opal_crc_table_initialized = false;
static unsigned int _opal_crc_table[256];
/* CRC32 table generation routine - thanks to Charles Michael Heard for his
* optimized CRC32 code...
*/
void opal_initialize_crc_table(void)
{
register int i,j;
register unsigned int crc_accum;
for (i = 0; i < 256; i++) {
crc_accum = (i << 24);
for (j = 0; j < 8; j++) {
if (crc_accum & 0x80000000)
crc_accum = (crc_accum << 1) ^ CRC_POLYNOMIAL;
else
crc_accum = (crc_accum << 1);
}
_opal_crc_table[i] = crc_accum;
}
/* set global bool to true to do this work once! */
_opal_crc_table_initialized = true;
return;
}
unsigned int opal_bcopy_uicrc_partial(
const void * source,
void * destination,
size_t copylen,
size_t crclen,
unsigned int partial_crc)
{
size_t crclenresidue = (crclen > copylen) ? (crclen - copylen) : 0;
register int i, j;
register unsigned char t;
unsigned int tmp;
if (!_opal_crc_table_initialized) {
opal_initialize_crc_table();
}
if (INTALIGNED(source) && INTALIGNED(destination)) {
register unsigned int * src = (unsigned int *)source;
register unsigned int * dst = (unsigned int *)destination;
register unsigned char *ts, *td;
/* copy whole integers */
while (copylen >= sizeof(unsigned int)) {
tmp = *src++;
*dst++ = tmp;
ts = (unsigned char *)&tmp;
for (j = 0; j < (int)sizeof(unsigned int); j++) {
i = ((partial_crc >> 24) ^ *ts++) & 0xff;
partial_crc = (partial_crc << 8) ^ _opal_crc_table[i];
}
copylen -= sizeof(unsigned int);
}
ts = (unsigned char *)src;
td = (unsigned char *)dst;
/* copy partial integer */
while (copylen--) {
t = *ts++;
*td++ = t;
i = ((partial_crc >> 24) ^ t) & 0xff;
partial_crc = (partial_crc << 8) ^ _opal_crc_table[i];
}
/* calculate CRC over remaining bytes... */
while (crclenresidue--) {
i = ((partial_crc >> 24) ^ *ts++) & 0xff;
partial_crc = (partial_crc << 8) ^ _opal_crc_table[i];
}
}
else {
register unsigned char * src = (unsigned char *)source;
register unsigned char * dst = (unsigned char *)destination;
while (copylen--) {
t = *src++;
*dst++ = t;
i = ((partial_crc >> 24) ^ t) & 0xff;
partial_crc = (partial_crc << 8) ^ _opal_crc_table[i];
}
while (crclenresidue--) {
i = ((partial_crc >> 24) ^ *src++) & 0xff;
partial_crc = (partial_crc << 8) ^ _opal_crc_table[i];
}
}
return partial_crc;
}
unsigned int opal_uicrc_partial(
const void * source, size_t crclen, unsigned int partial_crc)
{
register int i, j;
register unsigned char * t;
unsigned int tmp;
if (!_opal_crc_table_initialized) {
opal_initialize_crc_table();
}
if (INTALIGNED(source)) {
register unsigned int * src = (unsigned int *)source;
while (crclen >= sizeof(unsigned int)) {
tmp = *src++;
t = (unsigned char *)&tmp;
for (j = 0; j < (int)sizeof(unsigned int); j++) {
i = ((partial_crc >> 24) ^ *t++) & 0xff;
partial_crc = (partial_crc << 8) ^ _opal_crc_table[i];
}
crclen -= sizeof(unsigned int);
}
t = (unsigned char *)src;
while (crclen--) {
i = ((partial_crc >> 24) ^ *t++) & 0xff;
partial_crc = (partial_crc << 8) ^ _opal_crc_table[i];
}
}
else {
register unsigned char * src = (unsigned char *)source;
while (crclen--) {
i = ((partial_crc >> 24) ^ *src++) & 0xff;
partial_crc = (partial_crc << 8) ^ _opal_crc_table[i];
}
}
return partial_crc;
}