/*- * Copyright (c) 2008, Jung-uk Kim * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice unmodified, this list of conditions, and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #if !defined(__amd64__) && !defined(__i386__) #error "Unsupported architecture" #endif #if (__FreeBSD_version < 700110) #error "Unsupported OS version" #endif #ifdef USE_BUSY_LOOP #include #define LOOP_FACTOR 8 #define NLOOP(i) (UINT_MAX / LOOP_FACTOR * MIN((i), LOOP_FACTOR)) unsigned int sleep(unsigned int s) { unsigned int i; for (i = 0; i < NLOOP(s); i++) { /* * XXX GCC 4.2 may optimize it away without this. */ (void)sleep(0); } return (s > LOOP_FACTOR ? (s - LOOP_FACTOR) : 0); } #endif static void proc_bind(int cpu) { cpuset_t mask; CPU_ZERO(&mask); CPU_SET(cpu, &mask); if (cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(mask), &mask) < 0) err(1, "cpuset_setaffinity()"); } int main(void) { cpuset_t mask; struct timeval tv0, tv1; uint64_t tsc0, tsc1; int i; if (cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, sizeof(mask), &mask) < 0) err(1, "cpuset_getaffinity()"); for (i = 0; i < CPU_SETSIZE; i++) { if (!CPU_ISSET(i, &mask)) continue; proc_bind(i); gettimeofday(&tv0, NULL); tsc0 = rdtsc(); (void)sleep(1); tsc1 = rdtsc(); gettimeofday(&tv1, NULL); timersub(&tv1, &tv0, &tv1); tsc1 = (tsc1 - tsc0) / (tv1.tv_sec * 1000000ULL + tv1.tv_usec); printf("CPU #%d:\tTSC is running at %ju MHz.\n", i, (uintmax_t)tsc1); } return (0); }