#include #include #include #include #include #include #include #include "cleanbench.h" #include "randnum.h" /************************ ** BITFIELD OPERATIONS ** *************************/ #ifdef _LP64 #define ARRAY_SIZE 16384L #else #define ARRAY_SIZE 32768L #endif static clock_t DoBitfieldIteration(unsigned long *bitarray, unsigned long *bitoparray, long bitop_array_size, unsigned long *nbitops); static void ToggleBitRun(unsigned long *bitmap, unsigned long bit_addr, unsigned long nbits, unsigned int val); static void FlipBitRun(unsigned long *bitmap, unsigned long bit_addr, unsigned long nbits); static double results; /************* ** DoBitops ** ************** ** Perform the bit operations test portion of the CPU ** benchmark. Returns the iterations per second. */ void DoBitops(void) { const char* context = "CPU:Bitfields"; unsigned long* bitarray = NULL; unsigned long* bitoparray = NULL; clock_t total_time = 0; int iterations = 0; unsigned long nbitops; static int is_adjusted = FALSE; static int bitop_array_size = 30; if (is_adjusted == FALSE) { is_adjusted = TRUE; bitarray = realloc(bitarray, ARRAY_SIZE * sizeof(unsigned long)); if (!bitarray) { fprintf(stderr, "Error in %s, could not allocate memory. Exitting...\n", context); exit(1); } while(1) { bitoparray = malloc(bitop_array_size * 2 * sizeof(unsigned long)); if (!bitoparray) { fprintf(stderr, "Error in %s, could not allocate memory. Exitting...\n", context); free(bitarray); exit(1); } /* ** Do an iteration of the bitmap test. If the ** elapsed time is less than or equal to the permitted ** minimum, then de-allocate the array, reallocate a ** larger version, and try again. */ if(DoBitfieldIteration(bitarray, bitoparray, bitop_array_size, &nbitops) > MINIMUM_TICKS) { break; } bitop_array_size += 100; } } else { /* ** Don't need to do self adjustment, just allocate ** the array space. */ bitarray = malloc(ARRAY_SIZE * sizeof(unsigned long)); if (!bitarray) { fprintf(stderr, "Error in %s, could not allocate memory. Exitting...\n", context); exit(1); } bitoparray = malloc(bitop_array_size * 2 * sizeof(unsigned long)); if (!bitoparray) { fprintf(stderr, "Error in %s, could not allocate memory. Exitting...\n", context); free(bitarray); exit(1); } } /* ** All's well if we get here. Repeatedly perform bitops until the ** accumulated elapsed time is greater than # of seconds requested. */ do { total_time += DoBitfieldIteration(bitarray, bitoparray, bitop_array_size,&nbitops); iterations += nbitops; } while (total_time < MINIMUM_SECONDS * CLOCKS_PER_SEC); /* ** Clean up, calculate results, and go home. ** Also, set adjustment flag to show that we don't have ** to do self adjusting in the future. */ free(bitarray); free(bitoparray); results = (double)(iterations * CLOCKS_PER_SEC) / (double)total_time; } /************************ ** DoBitfieldIteration ** ************************* ** Perform a single iteration of the bitfield benchmark. ** Return the # of ticks accumulated by the operation. */ static clock_t DoBitfieldIteration(unsigned long *bitarray, unsigned long *bitoparray, long bitop_array_size, unsigned long *nbitops) { clock_t start, stop; long i; unsigned long bitoffset; /* ** Clear # bitops counter */ *nbitops = 0L; /* ** Construct a set of bitmap offsets and run lengths. ** The offset can be any random number from 0 to the ** size of the bitmap (in bits). The run length can ** be any random number from 1 to the number of bits ** between the offset and the end of the bitmap. ** Note that the bitmap has 8192 * 32 bits in it. ** (262,144 bits) */ /* ** Reset random number generator so things repeat. ** Also reset the bit array we work on. ** added by Uwe F. Mayer */ randnum(13); for (i = 0; i < ARRAY_SIZE; i++) { #ifdef _LP64 *(bitarray+i) = 0x5555555555555555UL; #else *(bitarray+i) = 0x55555555UL; #endif } randnum(13); for (i = 0; i < bitop_array_size; i++) { /* First item is offset */ *(bitoparray + i + i) = bitoffset = abs_randwc((int32_t)262140); /* Next item is run length */ *nbitops += *(bitoparray + i + i + 1L) = abs_randwc((int32_t)262140 - bitoffset); } start = clock(); for(i = 0; i < bitop_array_size; i++) { switch(i % 3) { case 2: /* Complement run of bits */ FlipBitRun(bitarray, *(bitoparray+i+i), *(bitoparray+i+i+1)); break; default: ToggleBitRun(bitarray, *(bitoparray+i+i), *(bitoparray+i+i+1), !i); break; } } stop = clock(); return stop - start; } /*************** ** FlipBitRun ** **************** ** Complements a run of bits. */ static void FlipBitRun(unsigned long *bitmap, unsigned long bit_addr, unsigned long nbits) { unsigned long bindex; /* Index into array */ unsigned long bitnumb; /* Bit number */ while (nbits--) { #ifdef _LP64 bindex=bit_addr>>6; /* Index is number /64 */ bitnumb=bit_addr % 64; /* Bit number in longword */ #else bindex=bit_addr>>5; /* Index is number /32 */ bitnumb=bit_addr % 32; /* Bit number in longword */ #endif bitmap[bindex]^=(1L<> 6; bitnumb = bit_addr % 64; bitmap[bindex] |= (1L << bitnumb); bit_addr++; } } else { for (; nbits != 0; nbits--) { bindex = bit_addr >> 6; bitnumb = bit_addr % 64; bitmap[bindex] &= ~(1L << bitnumb); bit_addr++; } } } double getBitfieldScore(void) { return results; }