#include #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 SetBitRun(unsigned long* bitmap, unsigned long bit_address, unsigned long num_bits); static void ClearBitRun(unsigned long* bitmap, unsigned long bit_address, unsigned long num_bits); static void FlipBitRun(unsigned long* bitmap, unsigned long bit_address, unsigned long num_bits); /************* ** DoBitops ** ************** ** Perform the bit operations test portion of the CPU ** benchmark. Returns the iterations per second. */ double DoBitops(void) { unsigned long* bitarray = NULL; unsigned long* bitoparray = NULL; clock_t total_time = 0; int iterations = 0; unsigned long nbitops; static bool is_adjusted = false; static int bitop_array_size = -70; /* -70 because we want to malloc 30 and we add 100 to it in the loop */ if (is_adjusted == false) { is_adjusted = true; bitarray = realloc(bitarray, ARRAY_SIZE * sizeof(unsigned long)); do { bitop_array_size += 100; bitoparray = malloc(bitop_array_size * 2 * sizeof(unsigned long)); /* ** 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. */ } while (DoBitfieldIteration(bitarray, bitoparray, bitop_array_size, &nbitops) <= MINIMUM_TICKS); } else { /* ** Don't need to do self adjustment, just allocate ** the array space. */ bitarray = malloc(ARRAY_SIZE * sizeof(unsigned long)); bitoparray = malloc(bitop_array_size * 2 * sizeof(unsigned long)); } /* ** 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); free(bitarray); free(bitoparray); return (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; void (*DoBitOp[])(unsigned long* bitmap, unsigned long bit_address, unsigned long num_bits) = { SetBitRun, ClearBitRun, FlipBitRun }; /* * ** 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) * */ memset(bitarray, 0x55, ARRAY_SIZE); 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++) { (*DoBitOp[i % 3])(bitarray, *(bitoparray + i + i), *(bitoparray + i + i + 1)); } stop = clock(); return stop - start; } /*************** ** FlipBitRun ** **************** ** Complements a run of bits. */ static void FlipBitRun(unsigned long* bitmap, unsigned long bit_address, unsigned long num_bits) { unsigned long bit_index; unsigned long bit_number; while (num_bits--) { #ifdef _LP64 bit_index = bit_address >> 6; bit_number = bit_address % 64; #else bit_index = bit_address >> 5; bit_number = bit_address % 32; #endif bitmap[bit_index] ^= (1L << bit_number); bit_address++; } } /***************************** * ** SetBitRun * *************************** * ** Set a run of num_bits starting * ** at bit_address in bitmap * */ static void SetBitRun(unsigned long* bitmap, unsigned long bit_address, unsigned long num_bits) { unsigned long bit_index; unsigned long bit_number; while (num_bits--) { #ifdef _LP64 bit_index = bit_address >> 6; bit_number = bit_address % 64; #else bit_index = bit_address >> 5; bit_number = bit_address % 32; #endif bitmap[bit_index] |= (1L << bit_number); bit_address++; } } /***************************** * ** ClearBitRun * *************************** * ** Clear a run of num_bits starting * ** at bit_address in bitmap * */ static void ClearBitRun(unsigned long* bitmap, unsigned long bit_address, unsigned long num_bits) { unsigned long bit_index; unsigned long bit_number; while (num_bits--) { #ifdef _LP64 bit_index = bit_address >> 6; bit_number = bit_address % 64; #else bit_index = bit_address >> 5; bit_number = bit_address % 32; #endif bitmap[bit_index] &= ~(1L << bit_number); bit_address++; } }