From 34692e439a25d8f78686ba449fadfaced8053ee7 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 27 Jan 2011 16:46:15 -0800 Subject: [PATCH] Added cache line size info in SDL_cpuinfo.h I also added an implementation to dynamically query it, but didn't expose it since most x86 CPUs have an L1 cache line size of 64 bytes. --- include/SDL_cpuinfo.h | 5 ++ src/cpuinfo/SDL_cpuinfo.c | 160 +++++++++++++++++++++++++------------- src/timer/SDL_timer.c | 6 +- test/testatomic.c | 17 ++-- 4 files changed, 121 insertions(+), 67 deletions(-) diff --git a/include/SDL_cpuinfo.h b/include/SDL_cpuinfo.h index 0cc4998e6..ea29df9da 100644 --- a/include/SDL_cpuinfo.h +++ b/include/SDL_cpuinfo.h @@ -39,6 +39,11 @@ extern "C" { /* *INDENT-ON* */ #endif +/* This is a guess for the cacheline size used for padding, and is correct + * for most x86 processors at this point. + */ +#define SDL_CACHELINE_SIZE 64 + /** * This function returns the number of CPU cores available. */ diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c index 3444f2fad..443d5c188 100644 --- a/src/cpuinfo/SDL_cpuinfo.c +++ b/src/cpuinfo/SDL_cpuinfo.c @@ -337,73 +337,125 @@ SDL_GetCPUCount() static const char * SDL_GetCPUType() { - static char SDL_CPUType[48]; + static char SDL_CPUType[13]; if (!SDL_CPUType[0]) { int i = 0; int a, b, c, d; + if (CPU_haveCPUID()) { + cpuid(0x00000000, a, b, c, d); + SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; + } + if (!SDL_CPUType[0]) { + SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType)); + } + } + return SDL_CPUType; +} + +static const char * +SDL_GetCPUName() +{ + static char SDL_CPUName[48]; + + if (!SDL_CPUName[0]) { + int i = 0; + int a, b, c, d; + if (CPU_haveCPUID()) { cpuid(0x80000000, a, b, c, d); if (a >= 0x80000004) { cpuid(0x80000002, a, b, c, d); - SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8; - SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8; - SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8; - SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8; - SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; - SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; - SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; - SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; - SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; - SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; - SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; - SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; - SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; - SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; - SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; - SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; + SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; + SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; + SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; + SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; cpuid(0x80000003, a, b, c, d); - SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8; - SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8; - SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8; - SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8; - SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; - SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; - SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; - SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; - SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; - SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; - SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; - SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; - SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; - SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; - SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; - SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; + SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; + SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; + SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; + SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; cpuid(0x80000004, a, b, c, d); - SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8; - SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8; - SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8; - SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8; - SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; - SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; - SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; - SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8; - SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; - SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; - SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; - SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8; - SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; - SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; - SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; - SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; + SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; + SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; + SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8; + SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8; + SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8; + SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; + SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8; } } - if (!SDL_CPUType[0]) { - SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType)); + if (!SDL_CPUName[0]) { + SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName)); } } - return SDL_CPUType; + return SDL_CPUName; +} + +static int +SDL_GetCPUCacheLineSize() +{ + const char *cpuType = SDL_GetCPUType(); + + if (SDL_strcmp(cpuType, "GenuineIntel") == 0) { + int a, b, c, d; + + cpuid(0x00000001, a, b, c, d); + return (((b >> 8) & 0xff) * 8); + } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) { + int a, b, c, d; + + cpuid(0x80000005, a, b, c, d); + return (c & 0xff); + } else { + /* Just make a guess here... */ + return SDL_CACHELINE_SIZE; + } } static Uint32 SDL_CPUFeatures = 0xFFFFFFFF; @@ -521,7 +573,9 @@ int main() { printf("CPU count: %d\n", SDL_GetCPUCount()); - printf("CPU name: %s\n", SDL_GetCPUType()); + printf("CPU type: %s\n", SDL_GetCPUType()); + printf("CPU name: %s\n", SDL_GetCPUName()); + printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize()); printf("RDTSC: %d\n", SDL_HasRDTSC()); printf("MMX: %d\n", SDL_HasMMX()); printf("MMXExt: %d\n", SDL_HasMMXExt()); diff --git a/src/timer/SDL_timer.c b/src/timer/SDL_timer.c index 2ad2e4e23..2efea24c3 100644 --- a/src/timer/SDL_timer.c +++ b/src/timer/SDL_timer.c @@ -24,6 +24,7 @@ #include "SDL_timer.h" #include "SDL_timer_c.h" #include "SDL_atomic.h" +#include "SDL_cpuinfo.h" #include "SDL_thread.h" /* #define DEBUG_TIMERS */ @@ -46,9 +47,6 @@ typedef struct _SDL_TimerMap struct _SDL_TimerMap *next; } SDL_TimerMap; -/* A reasonable guess */ -#define CACHELINE_SIZE 128 - /* The timers are kept in a sorted list */ typedef struct { /* Data used by the main thread */ @@ -58,7 +56,7 @@ typedef struct { SDL_mutex *timermap_lock; /* Padding to separate cache lines between threads */ - char pad[CACHELINE_SIZE]; + char cache_pad[SDL_CACHELINE_SIZE]; /* Data used to communicate with the timer thread */ SDL_SpinLock lock; diff --git a/test/testatomic.c b/test/testatomic.c index ecf134a2a..0c9b13a27 100644 --- a/test/testatomic.c +++ b/test/testatomic.c @@ -243,9 +243,6 @@ void RunEpicTest() #define NUM_WRITERS 4 #define EVENTS_PER_WRITER 1000000 -/* A decent guess for the size of a cache line on this architecture */ -#define CACHELINE 64 - /* The number of entries must be a power of 2 */ #define MAX_ENTRIES 256 #define WRAP_MASK (MAX_ENTRIES-1) @@ -260,22 +257,22 @@ typedef struct { SDL_EventQueueEntry entries[MAX_ENTRIES]; - char cache_pad1[CACHELINE-((sizeof(SDL_EventQueueEntry)*MAX_ENTRIES)%CACHELINE)]; + char cache_pad1[SDL_CACHELINE_SIZE-((sizeof(SDL_EventQueueEntry)*MAX_ENTRIES)%SDL_CACHELINE_SIZE)]; SDL_atomic_t enqueue_pos; - char cache_pad2[CACHELINE-sizeof(SDL_atomic_t)]; + char cache_pad2[SDL_CACHELINE_SIZE-sizeof(SDL_atomic_t)]; SDL_atomic_t dequeue_pos; - char cache_pad3[CACHELINE-sizeof(SDL_atomic_t)]; + char cache_pad3[SDL_CACHELINE_SIZE-sizeof(SDL_atomic_t)]; #ifdef TEST_SPINLOCK_FIFO SDL_SpinLock lock; SDL_atomic_t rwcount; SDL_atomic_t watcher; - char cache_pad4[CACHELINE-sizeof(SDL_SpinLock)-2*sizeof(SDL_atomic_t)]; + char cache_pad4[SDL_CACHELINE_SIZE-sizeof(SDL_SpinLock)-2*sizeof(SDL_atomic_t)]; #endif volatile SDL_bool active; @@ -470,10 +467,10 @@ typedef struct { SDL_EventQueue *queue; int index; - char padding1[CACHELINE-(sizeof(SDL_EventQueue*)+sizeof(int))%CACHELINE]; + char padding1[SDL_CACHELINE_SIZE-(sizeof(SDL_EventQueue*)+sizeof(int))%SDL_CACHELINE_SIZE]; int waits; SDL_bool lock_free; - char padding2[CACHELINE-sizeof(int)-sizeof(SDL_bool)]; + char padding2[SDL_CACHELINE_SIZE-sizeof(int)-sizeof(SDL_bool)]; } WriterData; typedef struct @@ -482,7 +479,7 @@ typedef struct int counters[NUM_WRITERS]; int waits; SDL_bool lock_free; - char padding[CACHELINE-(sizeof(SDL_EventQueue*)+sizeof(int)*NUM_WRITERS+sizeof(int)+sizeof(SDL_bool))%CACHELINE]; + char padding[SDL_CACHELINE_SIZE-(sizeof(SDL_EventQueue*)+sizeof(int)*NUM_WRITERS+sizeof(int)+sizeof(SDL_bool))%SDL_CACHELINE_SIZE]; } ReaderData; static int FIFO_Writer(void* _data)