upstream nginx-0.7.31
[nginx.git] / nginx / src / core / ngx_cpuinfo.c
1
2 /*
3  * Copyright (C) Igor Sysoev
4  */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9
10
11 #if (( __i386__ || __amd64__ ) && ( __GNUC__ || __INTEL_COMPILER ))
12
13
14 static ngx_inline void ngx_cpuid(uint32_t i, uint32_t *buf);
15
16
17 #if ( __i386__ )
18
19 static ngx_inline void
20 ngx_cpuid(uint32_t i, uint32_t *buf)
21 {
22
23     /*
24      * we could not use %ebx as output parameter if gcc builds PIC,
25      * and we could not save %ebx on stack, because %esp is used,
26      * when the -fomit-frame-pointer optimization is specified.
27      */
28
29     __asm__ (
30
31     "    mov    %%ebx, %%esi;  "
32
33     "    cpuid;                "
34     "    mov    %%eax, (%1);   "
35     "    mov    %%ebx, 4(%1);  "
36     "    mov    %%edx, 8(%1);  "
37     "    mov    %%ecx, 12(%1); "
38
39     "    mov    %%esi, %%ebx;  "
40
41     : : "a" (i), "D" (buf) : "ecx", "edx", "esi", "memory" );
42 }
43
44
45 #else /* __amd64__ */
46
47
48 static ngx_inline void
49 ngx_cpuid(uint32_t i, uint32_t *buf)
50 {
51     uint32_t  eax, ebx, ecx, edx;
52
53     __asm__ (
54
55         "cpuid"
56
57     : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (i) );
58
59     buf[0] = eax;
60     buf[1] = ebx;
61     buf[2] = edx;
62     buf[3] = ecx;
63 }
64
65
66 #endif
67
68
69 /* auto detect the L2 cache line size of modern and widespread CPUs */
70
71 void
72 ngx_cpuinfo(void)
73 {
74     u_char    *vendor;
75     uint32_t   vbuf[5], cpu[4];
76
77     vbuf[0] = 0;
78     vbuf[1] = 0;
79     vbuf[2] = 0;
80     vbuf[3] = 0;
81     vbuf[4] = 0;
82
83     ngx_cpuid(0, vbuf);
84
85     vendor = (u_char *) &vbuf[1];
86
87     if (vbuf[0] == 0) {
88         return;
89     }
90
91     ngx_cpuid(1, cpu);
92
93     if (ngx_strcmp(vendor, "GenuineIntel") == 0) {
94
95         switch ((cpu[0] & 0xf00) >> 8) {
96
97         /* Pentium */
98         case 5:
99             ngx_cacheline_size = 32;
100             break;
101
102         /* Pentium Pro, II, III */
103         case 6:
104             ngx_cacheline_size = 32;
105
106             if ((cpu[0] & 0xf0) >= 0xd0) {
107                 /* Intel Core */
108                 ngx_cacheline_size = 64;
109             }
110
111             break;
112
113         /*
114          * Pentium 4, although its cache line size is 64 bytes,
115          * it prefetches up to two cache lines during memory read
116          */
117         case 15:
118             ngx_cacheline_size = 128;
119             break;
120         }
121
122     } else if (ngx_strcmp(vendor, "AuthenticAMD") == 0) {
123         ngx_cacheline_size = 64;
124     }
125 }
126
127 #else
128
129
130 void
131 ngx_cpuinfo(void)
132 {
133 }
134
135
136 #endif