#include #include #include #include #include #include #include #include "nmglobal.h" #include "randnum.h" /************************ ** BITFIELD OPERATIONS ** *************************/ static clock_t DoBitfieldIteration(unsigned long *bitarraybase, unsigned long *bitoparraybase, long bitoparraysize, 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); /************* ** DoBitops ** ************** ** Perform the bit operations test portion of the CPU ** benchmark. Returns the iterations per second. */ void DoBitops(void) { const char* context = "CPU:Bitfields"; BitOpStruct* locbitopstruct = &global_bitopstruct; unsigned long* bitarraybase = NULL; unsigned long* bitoparraybase = NULL; clock_t total_time = 0; int iterations = 0; unsigned long nbitops; static int is_adjusted = FALSE; if (is_adjusted == FALSE) { is_adjusted = TRUE; bitarraybase = realloc(bitarraybase, locbitopstruct->bitfieldarraysize * sizeof(unsigned long)); if (!bitarraybase) { fprintf(stderr, "Error in %s, could not allocate memory. Exitting...\n", context); exit(1); } /* ** Initialize bitfield operations array to [2,30] elements */ locbitopstruct->bitoparraysize = 30L; while(1) { bitoparraybase = malloc(locbitopstruct->bitoparraysize * 2 * sizeof(unsigned long)); if (!bitoparraybase) { fprintf(stderr, "Error in %s, could not allocate memory. Exitting...\n", context); free(bitarraybase); 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(bitarraybase, bitoparraybase, locbitopstruct->bitoparraysize, &nbitops) > MINIMUM_TICKS) { break; } locbitopstruct->bitoparraysize += 100L; } } else { /* ** Don't need to do self adjustment, just allocate ** the array space. */ bitarraybase = malloc(locbitopstruct->bitfieldarraysize * sizeof(unsigned long)); if (!bitarraybase) { fprintf(stderr, "Error in %s, could not allocate memory. Exitting...\n", context); exit(1); } bitoparraybase = malloc(locbitopstruct->bitoparraysize * 2 * sizeof(unsigned long)); if (!bitoparraybase) { fprintf(stderr, "Error in %s, could not allocate memory. Exitting...\n", context); free(bitarraybase); 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(bitarraybase, bitoparraybase, locbitopstruct->bitoparraysize,&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(bitarraybase); free(bitoparraybase); locbitopstruct->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 *bitarraybase, unsigned long *bitoparraybase, long bitoparraysize, 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 < global_bitopstruct.bitfieldarraysize; i++) { #ifdef _LP64 *(bitarraybase+i) = 0x5555555555555555UL; #else *(bitarraybase+i) = 0x55555555UL; #endif } randnum(13); for (i = 0; i < bitoparraysize; i++) { /* First item is offset */ *(bitoparraybase + i + i) = bitoffset = abs_randwc((int32_t)262140); /* Next item is run length */ *nbitops += *(bitoparraybase + i + i + 1L) = abs_randwc((int32_t)262140 - bitoffset); } start = clock(); for(i = 0; i < bitoparraysize; i++) { switch(i % 3) { case 2: /* Complement run of bits */ FlipBitRun(bitarraybase, *(bitoparraybase+i+i), *(bitoparraybase+i+i+1)); break; default: ToggleBitRun(bitarraybase, *(bitoparraybase+i+i), *(bitoparraybase+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++; } } }