Added cache line size info in SDL_cpuinfo.h
authorSam Lantinga <slouken@libsdl.org>
Thu, 27 Jan 2011 16:46:15 -0800
changeset 5115427998ff3bcf
parent 5114 e337f792c6a7
child 5116 02b860cbc7ce
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
src/cpuinfo/SDL_cpuinfo.c
src/timer/SDL_timer.c
test/testatomic.c
     1.1 --- a/include/SDL_cpuinfo.h	Thu Jan 27 15:31:00 2011 -0800
     1.2 +++ b/include/SDL_cpuinfo.h	Thu Jan 27 16:46:15 2011 -0800
     1.3 @@ -39,6 +39,11 @@
     1.4  /* *INDENT-ON* */
     1.5  #endif
     1.6  
     1.7 +/* This is a guess for the cacheline size used for padding, and is correct
     1.8 + * for most x86 processors at this point.
     1.9 + */
    1.10 +#define SDL_CACHELINE_SIZE  64
    1.11 +
    1.12  /**
    1.13   *  This function returns the number of CPU cores available.
    1.14   */
     2.1 --- a/src/cpuinfo/SDL_cpuinfo.c	Thu Jan 27 15:31:00 2011 -0800
     2.2 +++ b/src/cpuinfo/SDL_cpuinfo.c	Thu Jan 27 16:46:15 2011 -0800
     2.3 @@ -337,73 +337,125 @@
     2.4  static const char *
     2.5  SDL_GetCPUType()
     2.6  {
     2.7 -    static char SDL_CPUType[48];
     2.8 +    static char SDL_CPUType[13];
     2.9  
    2.10      if (!SDL_CPUType[0]) {
    2.11          int i = 0;
    2.12          int a, b, c, d;
    2.13  
    2.14          if (CPU_haveCPUID()) {
    2.15 +            cpuid(0x00000000, a, b, c, d);
    2.16 +            SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
    2.17 +            SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
    2.18 +            SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
    2.19 +            SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
    2.20 +            SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
    2.21 +            SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
    2.22 +            SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
    2.23 +            SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
    2.24 +            SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
    2.25 +            SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
    2.26 +            SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
    2.27 +            SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
    2.28 +        }
    2.29 +        if (!SDL_CPUType[0]) {
    2.30 +            SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
    2.31 +        }
    2.32 +    }
    2.33 +    return SDL_CPUType;
    2.34 +}
    2.35 +
    2.36 +static const char *
    2.37 +SDL_GetCPUName()
    2.38 +{
    2.39 +    static char SDL_CPUName[48];
    2.40 +
    2.41 +    if (!SDL_CPUName[0]) {
    2.42 +        int i = 0;
    2.43 +        int a, b, c, d;
    2.44 +
    2.45 +        if (CPU_haveCPUID()) {
    2.46              cpuid(0x80000000, a, b, c, d);
    2.47              if (a >= 0x80000004) {
    2.48                  cpuid(0x80000002, a, b, c, d);
    2.49 -                SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8;
    2.50 -                SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8;
    2.51 -                SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8;
    2.52 -                SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8;
    2.53 -                SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
    2.54 -                SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
    2.55 -                SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
    2.56 -                SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
    2.57 -                SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
    2.58 -                SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
    2.59 -                SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
    2.60 -                SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
    2.61 -                SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
    2.62 -                SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
    2.63 -                SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
    2.64 -                SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
    2.65 +                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
    2.66 +                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
    2.67 +                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
    2.68 +                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
    2.69 +                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
    2.70 +                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
    2.71 +                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
    2.72 +                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
    2.73 +                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
    2.74 +                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
    2.75 +                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
    2.76 +                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
    2.77 +                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
    2.78 +                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
    2.79 +                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
    2.80 +                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
    2.81                  cpuid(0x80000003, a, b, c, d);
    2.82 -                SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8;
    2.83 -                SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8;
    2.84 -                SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8;
    2.85 -                SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8;
    2.86 -                SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
    2.87 -                SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
    2.88 -                SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
    2.89 -                SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
    2.90 -                SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
    2.91 -                SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
    2.92 -                SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
    2.93 -                SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
    2.94 -                SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
    2.95 -                SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
    2.96 -                SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
    2.97 -                SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
    2.98 +                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
    2.99 +                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   2.100 +                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   2.101 +                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   2.102 +                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   2.103 +                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   2.104 +                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   2.105 +                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   2.106 +                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   2.107 +                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   2.108 +                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   2.109 +                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   2.110 +                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   2.111 +                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   2.112 +                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   2.113 +                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   2.114                  cpuid(0x80000004, a, b, c, d);
   2.115 -                SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8;
   2.116 -                SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8;
   2.117 -                SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8;
   2.118 -                SDL_CPUType[i++] = (char)(a & 0xff); a >>= 8;
   2.119 -                SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   2.120 -                SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   2.121 -                SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   2.122 -                SDL_CPUType[i++] = (char)(b & 0xff); b >>= 8;
   2.123 -                SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   2.124 -                SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   2.125 -                SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   2.126 -                SDL_CPUType[i++] = (char)(c & 0xff); c >>= 8;
   2.127 -                SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   2.128 -                SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   2.129 -                SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   2.130 -                SDL_CPUType[i++] = (char)(d & 0xff); d >>= 8;
   2.131 +                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   2.132 +                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   2.133 +                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   2.134 +                SDL_CPUName[i++] = (char)(a & 0xff); a >>= 8;
   2.135 +                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   2.136 +                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   2.137 +                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   2.138 +                SDL_CPUName[i++] = (char)(b & 0xff); b >>= 8;
   2.139 +                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   2.140 +                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   2.141 +                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   2.142 +                SDL_CPUName[i++] = (char)(c & 0xff); c >>= 8;
   2.143 +                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   2.144 +                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   2.145 +                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   2.146 +                SDL_CPUName[i++] = (char)(d & 0xff); d >>= 8;
   2.147              }
   2.148          }
   2.149 -        if (!SDL_CPUType[0]) {
   2.150 -            SDL_strlcpy(SDL_CPUType, "Unknown", sizeof(SDL_CPUType));
   2.151 +        if (!SDL_CPUName[0]) {
   2.152 +            SDL_strlcpy(SDL_CPUName, "Unknown", sizeof(SDL_CPUName));
   2.153          }
   2.154      }
   2.155 -    return SDL_CPUType;
   2.156 +    return SDL_CPUName;
   2.157 +}
   2.158 +
   2.159 +static int
   2.160 +SDL_GetCPUCacheLineSize()
   2.161 +{
   2.162 +    const char *cpuType = SDL_GetCPUType();
   2.163 +
   2.164 +    if (SDL_strcmp(cpuType, "GenuineIntel") == 0) {
   2.165 +        int a, b, c, d;
   2.166 +
   2.167 +        cpuid(0x00000001, a, b, c, d);
   2.168 +        return (((b >> 8) & 0xff) * 8);
   2.169 +    } else if (SDL_strcmp(cpuType, "AuthenticAMD") == 0) {
   2.170 +        int a, b, c, d;
   2.171 +
   2.172 +        cpuid(0x80000005, a, b, c, d);
   2.173 +        return (c & 0xff);
   2.174 +    } else {
   2.175 +        /* Just make a guess here... */
   2.176 +        return SDL_CACHELINE_SIZE;
   2.177 +    }
   2.178  }
   2.179  
   2.180  static Uint32 SDL_CPUFeatures = 0xFFFFFFFF;
   2.181 @@ -521,7 +573,9 @@
   2.182  main()
   2.183  {
   2.184      printf("CPU count: %d\n", SDL_GetCPUCount());
   2.185 -    printf("CPU name: %s\n", SDL_GetCPUType());
   2.186 +    printf("CPU type: %s\n", SDL_GetCPUType());
   2.187 +    printf("CPU name: %s\n", SDL_GetCPUName());
   2.188 +    printf("CacheLine size: %d\n", SDL_GetCPUCacheLineSize());
   2.189      printf("RDTSC: %d\n", SDL_HasRDTSC());
   2.190      printf("MMX: %d\n", SDL_HasMMX());
   2.191      printf("MMXExt: %d\n", SDL_HasMMXExt());
     3.1 --- a/src/timer/SDL_timer.c	Thu Jan 27 15:31:00 2011 -0800
     3.2 +++ b/src/timer/SDL_timer.c	Thu Jan 27 16:46:15 2011 -0800
     3.3 @@ -24,6 +24,7 @@
     3.4  #include "SDL_timer.h"
     3.5  #include "SDL_timer_c.h"
     3.6  #include "SDL_atomic.h"
     3.7 +#include "SDL_cpuinfo.h"
     3.8  #include "SDL_thread.h"
     3.9  
    3.10  /* #define DEBUG_TIMERS */
    3.11 @@ -46,9 +47,6 @@
    3.12      struct _SDL_TimerMap *next;
    3.13  } SDL_TimerMap;
    3.14  
    3.15 -/* A reasonable guess */
    3.16 -#define CACHELINE_SIZE  128
    3.17 -
    3.18  /* The timers are kept in a sorted list */
    3.19  typedef struct {
    3.20      /* Data used by the main thread */
    3.21 @@ -58,7 +56,7 @@
    3.22      SDL_mutex *timermap_lock;
    3.23  
    3.24      /* Padding to separate cache lines between threads */
    3.25 -    char pad[CACHELINE_SIZE];
    3.26 +    char cache_pad[SDL_CACHELINE_SIZE];
    3.27  
    3.28      /* Data used to communicate with the timer thread */
    3.29      SDL_SpinLock lock;
     4.1 --- a/test/testatomic.c	Thu Jan 27 15:31:00 2011 -0800
     4.2 +++ b/test/testatomic.c	Thu Jan 27 16:46:15 2011 -0800
     4.3 @@ -243,9 +243,6 @@
     4.4  #define NUM_WRITERS 4
     4.5  #define EVENTS_PER_WRITER   1000000
     4.6  
     4.7 -/* A decent guess for the size of a cache line on this architecture */
     4.8 -#define CACHELINE   64
     4.9 -
    4.10  /* The number of entries must be a power of 2 */
    4.11  #define MAX_ENTRIES 256
    4.12  #define WRAP_MASK   (MAX_ENTRIES-1)
    4.13 @@ -260,22 +257,22 @@
    4.14  {
    4.15      SDL_EventQueueEntry entries[MAX_ENTRIES];
    4.16  
    4.17 -    char cache_pad1[CACHELINE-((sizeof(SDL_EventQueueEntry)*MAX_ENTRIES)%CACHELINE)];
    4.18 +    char cache_pad1[SDL_CACHELINE_SIZE-((sizeof(SDL_EventQueueEntry)*MAX_ENTRIES)%SDL_CACHELINE_SIZE)];
    4.19  
    4.20      SDL_atomic_t enqueue_pos;
    4.21  
    4.22 -    char cache_pad2[CACHELINE-sizeof(SDL_atomic_t)];
    4.23 +    char cache_pad2[SDL_CACHELINE_SIZE-sizeof(SDL_atomic_t)];
    4.24  
    4.25      SDL_atomic_t dequeue_pos;
    4.26  
    4.27 -    char cache_pad3[CACHELINE-sizeof(SDL_atomic_t)];
    4.28 +    char cache_pad3[SDL_CACHELINE_SIZE-sizeof(SDL_atomic_t)];
    4.29  
    4.30  #ifdef TEST_SPINLOCK_FIFO
    4.31      SDL_SpinLock lock;
    4.32      SDL_atomic_t rwcount;
    4.33      SDL_atomic_t watcher;
    4.34  
    4.35 -    char cache_pad4[CACHELINE-sizeof(SDL_SpinLock)-2*sizeof(SDL_atomic_t)];
    4.36 +    char cache_pad4[SDL_CACHELINE_SIZE-sizeof(SDL_SpinLock)-2*sizeof(SDL_atomic_t)];
    4.37  #endif
    4.38  
    4.39      volatile SDL_bool active;
    4.40 @@ -470,10 +467,10 @@
    4.41  {
    4.42      SDL_EventQueue *queue;
    4.43      int index;
    4.44 -    char padding1[CACHELINE-(sizeof(SDL_EventQueue*)+sizeof(int))%CACHELINE];
    4.45 +    char padding1[SDL_CACHELINE_SIZE-(sizeof(SDL_EventQueue*)+sizeof(int))%SDL_CACHELINE_SIZE];
    4.46      int waits;
    4.47      SDL_bool lock_free;
    4.48 -    char padding2[CACHELINE-sizeof(int)-sizeof(SDL_bool)];
    4.49 +    char padding2[SDL_CACHELINE_SIZE-sizeof(int)-sizeof(SDL_bool)];
    4.50  } WriterData;
    4.51  
    4.52  typedef struct
    4.53 @@ -482,7 +479,7 @@
    4.54      int counters[NUM_WRITERS];
    4.55      int waits;
    4.56      SDL_bool lock_free;
    4.57 -    char padding[CACHELINE-(sizeof(SDL_EventQueue*)+sizeof(int)*NUM_WRITERS+sizeof(int)+sizeof(SDL_bool))%CACHELINE];
    4.58 +    char padding[SDL_CACHELINE_SIZE-(sizeof(SDL_EventQueue*)+sizeof(int)*NUM_WRITERS+sizeof(int)+sizeof(SDL_bool))%SDL_CACHELINE_SIZE];
    4.59  } ReaderData;
    4.60  
    4.61  static int FIFO_Writer(void* _data)