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