int main(int ac, char **av) { int nerr = 0; int ncpus; int i; if (ac > 1) loops = atol(av[1]); if (ac > 2) sec = atol(av[2]); if (ac > 3) threshold = atol(av[3]); smp_init(); ncpus = cpu_count(); if (ncpus > MAX_CPU) ncpus = MAX_CPU; for (i = 0; i < ncpus; ++i) on_cpu(i, kvm_clock_init, (void *)0); if (ac > 2) { printf("Wallclock test, threshold %ld\n", threshold); printf("Seconds get from host: %ld\n", sec); for (i = 0; i < ncpus; ++i) on_cpu(i, wallclock_test, &nerr); } printf("Check the stability of raw cycle ...\n"); pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT | PVCLOCK_RAW_CYCLE_BIT); if (cycle_test(ncpus, 1, &ti[0])) printf("Raw cycle is not stable\n"); else printf("Raw cycle is stable\n"); pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); printf("Monotonic cycle test:\n"); nerr += cycle_test(ncpus, 1, &ti[1]); printf("Measure the performance of raw cycle ...\n"); pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT | PVCLOCK_RAW_CYCLE_BIT); cycle_test(ncpus, 0, &ti[2]); printf("Measure the performance of adjusted cycle ...\n"); pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); cycle_test(ncpus, 0, &ti[3]); for (i = 0; i < ncpus; ++i) on_cpu(i, kvm_clock_clear, (void *)0); return nerr > 0 ? 1 : 0; }
int main(int ac, char **av) { int ncpus; int nerr = 0, i; long loops = DEFAULT_TEST_LOOPS; long sec = 0; long threshold = DEFAULT_THRESHOLD; if (ac > 1) loops = atol(av[1]); if (ac > 2) sec = atol(av[2]); if (ac > 3) threshold = atol(av[3]); smp_init(); ncpus = cpu_count(); if (ncpus > MAX_CPU) ncpus = MAX_CPU; for (i = 0; i < ncpus; ++i) on_cpu(i, kvm_clock_init, (void *)0); if (ac > 2) nerr += wallclock_test(sec, threshold); printf("Check the stability of raw cycle ...\n"); pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT | PVCLOCK_RAW_CYCLE_BIT); if (cycle_test(ncpus, loops, 1, &ti[0])) printf("Raw cycle is not stable\n"); else printf("Raw cycle is stable\n"); pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); printf("Monotonic cycle test:\n"); nerr += cycle_test(ncpus, loops, 1, &ti[1]); printf("Measure the performance of raw cycle ...\n"); pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT | PVCLOCK_RAW_CYCLE_BIT); cycle_test(ncpus, loops, 0, &ti[2]); printf("Measure the performance of adjusted cycle ...\n"); pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT); cycle_test(ncpus, loops, 0, &ti[3]); for (i = 0; i < ncpus; ++i) on_cpu(i, kvm_clock_clear, (void *)0); return nerr > 0 ? 1 : 0; }
/* This is the function that the threads run */ void *mem_twiddler(void *arg) { unsigned long thread_id, pages, pagesize, i, p; volatile long garbage; long *lp; int t,offset; char *my_region; unsigned long mapsize = *(unsigned long *)arg; /* Make sure each thread gets a unique ID */ pthread_mutex_lock(&ct_mutex); thread_id=created_threads++; pthread_mutex_unlock(&ct_mutex); if (parallel) { /* let main() go as soon as the thread is created */ mmap_done=1; pthread_cond_signal(&mmap_cond); } on_cpu(thread_id % num_cpus); pagesize=getpagesize(); pages=mapsize/pagesize; /* Map a chunk of memory */ if (verbose) printf("thread %ld: mapping %s RAM\n", thread_id,human_memsize(mapsize)); my_region=mmap(NULL,mapsize,PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE,-1,0); if (my_region == MAP_FAILED) { perror("mmap"); exit(1); } mmap_regions[thread_id] = my_region; /* Dirty each page of the mem region to fault them into existence */ for (i=0;i<pages;i++) { lp=(long *)&(my_region[i*pagesize]); lp[0]=0xDEADBEEF; /* magic number */ lp[1]=thread_id; lp[2]=i; } /* Okay, we have grabbed our memory - this thread is now live */ pthread_mutex_lock(<_mutex); live_threads++; pthread_mutex_unlock(<_mutex); if (verbose) printf("thread %ld: mapping complete\n",thread_id); /* let main() go now that the thread is finished initializing. */ if (!parallel) { mmap_done=1; pthread_cond_signal(&mmap_cond); } else if (live_threads == num_threads) { /* if this is the last thread to init, let main() know we're done */ pthread_cond_signal(&init_cond); } /* Wait for the signal to begin testing */ pthread_mutex_lock(&test_mutex); while (start.tv_sec == 0) { pthread_cond_wait(&test_start,&test_mutex); } running_threads++; pthread_mutex_unlock(&test_mutex); if (verbose) printf("thread %lu: test start\n",thread_id); loop_counters[thread_id]=0; while (!done) { /* Choose a random thread and a random page */ t = rand() % num_threads; p = rand() % pages; lp = (long *)&(mmap_regions[t][p*pagesize]); /* Check the info we wrote there earlier */ if (lp[0] != 0xDEADBEEF || lp[1] != t || lp[2] != p) { fprintf(stderr,"MEMORY CORRUPTION DETECTED\n"); fprintf(stderr,"thread %lu (CPU %lu) reading map %u, page %lu\n", thread_id,thread_id % num_cpus,t,p); fprintf(stderr,"read: %#lx %lu %lu should be: %#x %i %lu\n", lp[0],lp[1],lp[2],0xDEADBEEF,t,p); } /* choose a random word (other than the first 3 */ offset = (rand() % ((pagesize/sizeof(long))-3))+3; if (rand() % 2) { lp[offset] = rand(); } else { garbage = lp[offset]; } loop_counters[thread_id]++; } /* make sure everyone's finished before we unmap */ pthread_mutex_lock(&finish_mutex); if (verbose) printf("thread %lu finished.\n",thread_id); running_threads--; if (running_threads==0) pthread_cond_broadcast(&finish_cond); else while (running_threads) { pthread_cond_wait(&finish_cond,&finish_mutex); } pthread_mutex_unlock(&finish_mutex); /* Clean up and exit. */ if (verbose) printf("thread %lu unmapping and exiting\n",thread_id); if (munmap(my_region,mapsize) != 0) { perror("munmap"); exit(2); } return NULL; }