Back to index

numactl  2.0.8~rc4
clearcache.c
Go to the documentation of this file.
00001 /* Clear the CPU cache for benchmark purposes. Pretty simple minded.
00002  * Might not work in some complex cache topologies.
00003  * When you switch CPUs it's a good idea to clear the cache after testing
00004  * too.
00005  */
00006 #include <unistd.h>
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include "clearcache.h"
00010 
00011 unsigned cache_size(void)
00012 {
00013        unsigned cs = 0;
00014 #ifdef _SC_LEVEL1_DCACHE_SIZE
00015        cs += sysconf(_SC_LEVEL1_DCACHE_SIZE);
00016 #endif
00017 #ifdef _SC_LEVEL2_DCACHE_SIZE
00018        cs += sysconf(_SC_LEVEL2_DCACHE_SIZE);
00019 #endif
00020 #ifdef _SC_LEVEL3_DCACHE_SIZE
00021        cs += sysconf(_SC_LEVEL3_DCACHE_SIZE);
00022 #endif
00023 #ifdef _SC_LEVEL4_DCACHE_SIZE
00024        cs += sysconf(_SC_LEVEL4_DCACHE_SIZE);
00025 #endif
00026        if (cs == 0) {
00027               static int warned;
00028               if (!warned) {
00029                      printf("Cannot determine CPU cache size\n");
00030                      warned = 1;
00031               }
00032               cs = 64*1024*1024;
00033        }
00034        cs *= 2; /* safety factor */
00035 
00036        return cs;
00037 }
00038 
00039 void fallback_clearcache(void)
00040 {
00041        static unsigned char *clearmem;
00042        unsigned cs = cache_size();
00043        unsigned i;
00044 
00045        if (!clearmem)
00046               clearmem = malloc(cs);
00047        if (!clearmem) {
00048               printf("Warning: cannot allocate %u bytes of clear cache buffer\n", cs);
00049               return;
00050        }
00051        for (i = 0; i < cs; i += 32)
00052               clearmem[i] = 1;
00053 }
00054 
00055 void clearcache(unsigned char *mem, unsigned size)
00056 {
00057 #if defined(__i386__) || defined(__x86_64__)
00058        unsigned i, cl, eax, feat;
00059        /* get clflush unit and feature */
00060        asm("cpuid" : "=a" (eax), "=b" (cl), "=d" (feat) : "0" (1) : "cx");
00061        if (!(feat & (1 << 19)))
00062               fallback_clearcache();
00063        cl = ((cl >> 8) & 0xff) * 8;
00064        for (i = 0; i < size; i += cl)
00065               asm("clflush %0" :: "m" (mem[i]));
00066 #elif defined(__ia64__)
00067         unsigned long cl, endcl;
00068         // flush probable 128 byte cache lines (but possibly 64 bytes)
00069         cl = (unsigned long)mem;
00070         endcl = (unsigned long)(mem + (size-1));
00071         for (; cl <= endcl; cl += 64)
00072                 asm ("fc %0" :: "r"(cl) : "memory" );
00073 #else
00074 #warning "Consider adding a clearcache implementation for your architecture"
00075        fallback_clearcache();
00076 #endif
00077 }