diff options
Diffstat (limited to 'app/nginx/src/os/unix/ngx_freebsd_init.c')
-rw-r--r-- | app/nginx/src/os/unix/ngx_freebsd_init.c | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/app/nginx/src/os/unix/ngx_freebsd_init.c b/app/nginx/src/os/unix/ngx_freebsd_init.c new file mode 100644 index 0000000..1823f02 --- /dev/null +++ b/app/nginx/src/os/unix/ngx_freebsd_init.c @@ -0,0 +1,262 @@ + +/* + * Copyright (C) Igor Sysoev + * Copyright (C) Nginx, Inc. + */ + + +#include <ngx_config.h> +#include <ngx_core.h> + + +/* FreeBSD 3.0 at least */ +char ngx_freebsd_kern_ostype[16]; +char ngx_freebsd_kern_osrelease[128]; +int ngx_freebsd_kern_osreldate; +int ngx_freebsd_hw_ncpu; +int ngx_freebsd_kern_ipc_somaxconn; +u_long ngx_freebsd_net_inet_tcp_sendspace; + +/* FreeBSD 4.9 */ +int ngx_freebsd_machdep_hlt_logical_cpus; + + +ngx_uint_t ngx_freebsd_sendfile_nbytes_bug; +ngx_uint_t ngx_freebsd_use_tcp_nopush; + +ngx_uint_t ngx_debug_malloc; + + +static ngx_os_io_t ngx_freebsd_io = { + ngx_unix_recv, + ngx_readv_chain, + ngx_udp_unix_recv, + ngx_unix_send, + ngx_udp_unix_send, + ngx_udp_unix_sendmsg_chain, +#if (NGX_HAVE_SENDFILE) + ngx_freebsd_sendfile_chain, + NGX_IO_SENDFILE +#else + ngx_writev_chain, + 0 +#endif +}; + + +typedef struct { + char *name; + void *value; + size_t size; + ngx_uint_t exists; +} sysctl_t; + + +sysctl_t sysctls[] = { + { "hw.ncpu", + &ngx_freebsd_hw_ncpu, + sizeof(ngx_freebsd_hw_ncpu), 0 }, + + { "machdep.hlt_logical_cpus", + &ngx_freebsd_machdep_hlt_logical_cpus, + sizeof(ngx_freebsd_machdep_hlt_logical_cpus), 0 }, + + { "net.inet.tcp.sendspace", + &ngx_freebsd_net_inet_tcp_sendspace, + sizeof(ngx_freebsd_net_inet_tcp_sendspace), 0 }, + + { "kern.ipc.somaxconn", + &ngx_freebsd_kern_ipc_somaxconn, + sizeof(ngx_freebsd_kern_ipc_somaxconn), 0 }, + + { NULL, NULL, 0, 0 } +}; + + +void +ngx_debug_init(void) +{ +#if (NGX_DEBUG_MALLOC) + +#if __FreeBSD_version >= 500014 && __FreeBSD_version < 1000011 + _malloc_options = "J"; +#elif __FreeBSD_version < 500014 + malloc_options = "J"; +#endif + + ngx_debug_malloc = 1; + +#else + char *mo; + + mo = getenv("MALLOC_OPTIONS"); + + if (mo && ngx_strchr(mo, 'J')) { + ngx_debug_malloc = 1; + } +#endif +} + + +ngx_int_t +ngx_os_specific_init(ngx_log_t *log) +{ + int version; + size_t size; + ngx_err_t err; + ngx_uint_t i; + + size = sizeof(ngx_freebsd_kern_ostype); + if (sysctlbyname("kern.ostype", + ngx_freebsd_kern_ostype, &size, NULL, 0) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "sysctlbyname(kern.ostype) failed"); + + if (ngx_errno != NGX_ENOMEM) { + return NGX_ERROR; + } + + ngx_freebsd_kern_ostype[size - 1] = '\0'; + } + + size = sizeof(ngx_freebsd_kern_osrelease); + if (sysctlbyname("kern.osrelease", + ngx_freebsd_kern_osrelease, &size, NULL, 0) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "sysctlbyname(kern.osrelease) failed"); + + if (ngx_errno != NGX_ENOMEM) { + return NGX_ERROR; + } + + ngx_freebsd_kern_osrelease[size - 1] = '\0'; + } + + + size = sizeof(int); + if (sysctlbyname("kern.osreldate", + &ngx_freebsd_kern_osreldate, &size, NULL, 0) == -1) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + "sysctlbyname(kern.osreldate) failed"); + return NGX_ERROR; + } + + version = ngx_freebsd_kern_osreldate; + + +#if (NGX_HAVE_SENDFILE) + + /* + * The determination of the sendfile() "nbytes bug" is complex enough. + * There are two sendfile() syscalls: a new #393 has no bug while + * an old #336 has the bug in some versions and has not in others. + * Besides libc_r wrapper also emulates the bug in some versions. + * There is no way to say exactly if syscall #336 in FreeBSD circa 4.6 + * has the bug. We use the algorithm that is correct at least for + * RELEASEs and for syscalls only (not libc_r wrapper). + * + * 4.6.1-RELEASE and below have the bug + * 4.6.2-RELEASE and above have the new syscall + * + * We detect the new sendfile() syscall available at the compile time + * to allow an old binary to run correctly on an updated FreeBSD system. + */ + +#if (__FreeBSD__ == 4 && __FreeBSD_version >= 460102) \ + || __FreeBSD_version == 460002 || __FreeBSD_version >= 500039 + + /* a new syscall without the bug */ + + ngx_freebsd_sendfile_nbytes_bug = 0; + +#else + + /* an old syscall that may have the bug */ + + ngx_freebsd_sendfile_nbytes_bug = 1; + +#endif + +#endif /* NGX_HAVE_SENDFILE */ + + + if ((version < 500000 && version >= 440003) || version >= 500017) { + ngx_freebsd_use_tcp_nopush = 1; + } + + + for (i = 0; sysctls[i].name; i++) { + size = sysctls[i].size; + + if (sysctlbyname(sysctls[i].name, sysctls[i].value, &size, NULL, 0) + == 0) + { + sysctls[i].exists = 1; + continue; + } + + err = ngx_errno; + + if (err == NGX_ENOENT) { + continue; + } + + ngx_log_error(NGX_LOG_ALERT, log, err, + "sysctlbyname(%s) failed", sysctls[i].name); + return NGX_ERROR; + } + + if (ngx_freebsd_machdep_hlt_logical_cpus) { + ngx_ncpu = ngx_freebsd_hw_ncpu / 2; + + } else { + ngx_ncpu = ngx_freebsd_hw_ncpu; + } + + if (version < 600008 && ngx_freebsd_kern_ipc_somaxconn > 32767) { + ngx_log_error(NGX_LOG_ALERT, log, 0, + "sysctl kern.ipc.somaxconn must be less than 32768"); + return NGX_ERROR; + } + + ngx_tcp_nodelay_and_tcp_nopush = 1; + + ngx_os_io = ngx_freebsd_io; + + return NGX_OK; +} + + +void +ngx_os_specific_status(ngx_log_t *log) +{ + u_long value; + ngx_uint_t i; + + ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s", + ngx_freebsd_kern_ostype, ngx_freebsd_kern_osrelease); + +#ifdef __DragonFly_version + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "kern.osreldate: %d, built on %d", + ngx_freebsd_kern_osreldate, __DragonFly_version); +#else + ngx_log_error(NGX_LOG_NOTICE, log, 0, + "kern.osreldate: %d, built on %d", + ngx_freebsd_kern_osreldate, __FreeBSD_version); +#endif + + for (i = 0; sysctls[i].name; i++) { + if (sysctls[i].exists) { + if (sysctls[i].size == sizeof(long)) { + value = *(long *) sysctls[i].value; + + } else { + value = *(int *) sysctls[i].value; + } + + ngx_log_error(NGX_LOG_NOTICE, log, 0, "%s: %l", + sysctls[i].name, value); + } + } +} |