upstream nginx-0.7.31
[nginx.git] / nginx / src / os / unix / ngx_freebsd_init.c
1
2 /*
3  * Copyright (C) Igor Sysoev
4  */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9
10
11 /* FreeBSD 3.0 at least */
12 char    ngx_freebsd_kern_ostype[16];
13 char    ngx_freebsd_kern_osrelease[128];
14 int     ngx_freebsd_kern_osreldate;
15 int     ngx_freebsd_hw_ncpu;
16 int     ngx_freebsd_kern_ipc_somaxconn;
17 u_long  ngx_freebsd_net_inet_tcp_sendspace;
18
19 /* FreeBSD 4.9 */
20 int     ngx_freebsd_machdep_hlt_logical_cpus;
21
22
23 ngx_uint_t  ngx_freebsd_sendfile_nbytes_bug;
24 ngx_uint_t  ngx_freebsd_use_tcp_nopush;
25 ngx_uint_t  ngx_freebsd_debug_malloc;
26
27
28 static ngx_os_io_t ngx_freebsd_io = {
29     ngx_unix_recv,
30     ngx_readv_chain,
31     ngx_udp_unix_recv,
32     ngx_unix_send,
33 #if (NGX_HAVE_SENDFILE)
34     ngx_freebsd_sendfile_chain,
35     NGX_IO_SENDFILE
36 #else
37     ngx_writev_chain,
38     0
39 #endif
40 };
41
42
43 typedef struct {
44     char        *name;
45     void        *value;
46     size_t       size;
47     ngx_uint_t   exists;
48 } sysctl_t;
49
50
51 sysctl_t sysctls[] = {
52     { "hw.ncpu",
53       &ngx_freebsd_hw_ncpu,
54       sizeof(ngx_freebsd_hw_ncpu), 0 },
55
56     { "machdep.hlt_logical_cpus",
57       &ngx_freebsd_machdep_hlt_logical_cpus,
58       sizeof(ngx_freebsd_machdep_hlt_logical_cpus), 0 },
59
60     { "net.inet.tcp.sendspace",
61       &ngx_freebsd_net_inet_tcp_sendspace,
62       sizeof(ngx_freebsd_net_inet_tcp_sendspace), 0 },
63
64     { "kern.ipc.somaxconn",
65       &ngx_freebsd_kern_ipc_somaxconn,
66       sizeof(ngx_freebsd_kern_ipc_somaxconn), 0 },
67
68     { NULL, NULL, 0, 0 }
69 };
70
71
72 void
73 ngx_debug_init()
74 {
75 #if (NGX_DEBUG_MALLOC)
76
77 #if __FreeBSD_version >= 500014
78     _malloc_options = "J";
79 #else
80     malloc_options = "J";
81 #endif
82
83     ngx_freebsd_debug_malloc = 1;
84
85 #else
86     char  *mo;
87
88     mo = getenv("MALLOC_OPTIONS");
89
90     if (mo && ngx_strchr(mo, 'J')) {
91         ngx_freebsd_debug_malloc = 1;
92     }
93 #endif
94 }
95
96
97 ngx_int_t
98 ngx_os_specific_init(ngx_log_t *log)
99 {
100     int         version, somaxconn;
101     size_t      size;
102     ngx_err_t   err;
103     ngx_uint_t  i;
104
105     size = sizeof(ngx_freebsd_kern_ostype);
106     if (sysctlbyname("kern.ostype",
107                      ngx_freebsd_kern_ostype, &size, NULL, 0) == -1) {
108         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
109                       "sysctlbyname(kern.ostype) failed");
110
111         if (ngx_errno != NGX_ENOMEM) {
112             return NGX_ERROR;
113         }
114
115         ngx_freebsd_kern_ostype[size - 1] = '\0';
116     }
117
118     size = sizeof(ngx_freebsd_kern_osrelease);
119     if (sysctlbyname("kern.osrelease",
120                      ngx_freebsd_kern_osrelease, &size, NULL, 0) == -1) {
121         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
122                       "sysctlbyname(kern.osrelease) failed");
123
124         if (ngx_errno != NGX_ENOMEM) {
125             return NGX_ERROR;
126         }
127
128         ngx_freebsd_kern_osrelease[size - 1] = '\0';
129     }
130
131
132     size = sizeof(int);
133     if (sysctlbyname("kern.osreldate",
134                      &ngx_freebsd_kern_osreldate, &size, NULL, 0) == -1) {
135         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
136                       "sysctlbyname(kern.osreldate) failed");
137         return NGX_ERROR;
138     }
139
140     version = ngx_freebsd_kern_osreldate;
141
142
143 #if (NGX_HAVE_SENDFILE)
144
145     /*
146      * The determination of the sendfile() "nbytes bug" is complex enough.
147      * There are two sendfile() syscalls: a new #393 has no bug while
148      * an old #336 has the bug in some versions and has not in others.
149      * Besides libc_r wrapper also emulates the bug in some versions.
150      * There is no way to say exactly if syscall #336 in FreeBSD circa 4.6
151      * has the bug.  We use the algorithm that is correct at least for
152      * RELEASEs and for syscalls only (not libc_r wrapper).
153      *
154      * 4.6.1-RELEASE and below have the bug
155      * 4.6.2-RELEASE and above have the new syscall
156      *
157      * We detect the new sendfile() syscall available at the compile time
158      * to allow an old binary to run correctly on an updated FreeBSD system.
159      */
160
161 #if (__FreeBSD__ == 4 && __FreeBSD_version >= 460102) \
162     || __FreeBSD_version == 460002 || __FreeBSD_version >= 500039
163
164     /* a new syscall without the bug */
165
166     ngx_freebsd_sendfile_nbytes_bug = 0;
167
168 #else
169
170     /* an old syscall that may have the bug */
171
172     ngx_freebsd_sendfile_nbytes_bug = 1;
173
174 #endif
175
176 #endif /* NGX_HAVE_SENDFILE */
177
178
179     if ((version < 500000 && version >= 440003) || version >= 500017) {
180         ngx_freebsd_use_tcp_nopush = 1;
181     }
182
183
184     for (i = 0; sysctls[i].name; i++) {
185         size = sysctls[i].size;
186
187         if (sysctlbyname(sysctls[i].name, sysctls[i].value, &size, NULL, 0)
188             == 0)
189         {
190             sysctls[i].exists = 1;
191             continue;
192         }
193
194         err = ngx_errno;
195
196         if (err == NGX_ENOENT) {
197             continue;
198         }
199
200         ngx_log_error(NGX_LOG_ALERT, log, err,
201                       "sysctlbyname(%s) failed", sysctls[i].name);
202         return NGX_ERROR;
203     }
204
205     if (ngx_freebsd_machdep_hlt_logical_cpus) {
206         ngx_ncpu = ngx_freebsd_hw_ncpu / 2;
207
208     } else {
209         ngx_ncpu = ngx_freebsd_hw_ncpu;
210     }
211
212     somaxconn = version < 600008 ? 32676 : 65535;
213
214     if (ngx_freebsd_kern_ipc_somaxconn > somaxconn) {
215         ngx_log_error(NGX_LOG_ALERT, log, 0,
216                       "sysctl kern.ipc.somaxconn must be no more than %d",
217                       somaxconn);
218         return NGX_ERROR;
219     }
220
221     ngx_tcp_nodelay_and_tcp_nopush = 1;
222
223     ngx_os_io = ngx_freebsd_io;
224
225     return NGX_OK;
226 }
227
228
229 void
230 ngx_os_specific_status(ngx_log_t *log)
231 {
232     u_long      value;
233     ngx_uint_t  i;
234
235     ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s",
236                   ngx_freebsd_kern_ostype, ngx_freebsd_kern_osrelease);
237
238 #ifdef __DragonFly_version
239     ngx_log_error(NGX_LOG_NOTICE, log, 0,
240                   "kern.osreldate: %d, built on %d",
241                   ngx_freebsd_kern_osreldate, __DragonFly_version);
242 #else
243     ngx_log_error(NGX_LOG_NOTICE, log, 0,
244                   "kern.osreldate: %d, built on %d",
245                   ngx_freebsd_kern_osreldate, __FreeBSD_version);
246 #endif
247
248     for (i = 0; sysctls[i].name; i++) {
249         if (sysctls[i].exists) {
250             if (sysctls[i].size == sizeof(long)) {
251                 value = *(long *) sysctls[i].value;
252
253             } else {
254                 value = *(int *) sysctls[i].value;
255             }
256
257             ngx_log_error(NGX_LOG_NOTICE, log, 0, "%s: %l",
258                           sysctls[i].name, value);
259         }
260     }
261 }