src/os/unix/ngx_freebsd_init.c - nginx source code

Global variables defined

Data types defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>


  7. /* FreeBSD 3.0 at least */
  8. char    ngx_freebsd_kern_ostype[16];
  9. char    ngx_freebsd_kern_osrelease[128];
  10. int     ngx_freebsd_kern_osreldate;
  11. int     ngx_freebsd_hw_ncpu;
  12. int     ngx_freebsd_kern_ipc_somaxconn;
  13. u_long  ngx_freebsd_net_inet_tcp_sendspace;

  14. /* FreeBSD 4.9 */
  15. int     ngx_freebsd_machdep_hlt_logical_cpus;


  16. ngx_uint_t  ngx_freebsd_sendfile_nbytes_bug;
  17. ngx_uint_t  ngx_freebsd_use_tcp_nopush;

  18. ngx_uint_t  ngx_debug_malloc;


  19. static ngx_os_io_t ngx_freebsd_io = {
  20.     ngx_unix_recv,
  21.     ngx_readv_chain,
  22.     ngx_udp_unix_recv,
  23.     ngx_unix_send,
  24.     ngx_udp_unix_send,
  25.     ngx_udp_unix_sendmsg_chain,
  26. #if (NGX_HAVE_SENDFILE)
  27.     ngx_freebsd_sendfile_chain,
  28.     NGX_IO_SENDFILE
  29. #else
  30.     ngx_writev_chain,
  31.     0
  32. #endif
  33. };


  34. typedef struct {
  35.     char        *name;
  36.     void        *value;
  37.     size_t       size;
  38.     ngx_uint_t   exists;
  39. } sysctl_t;


  40. sysctl_t sysctls[] = {
  41.     { "hw.ncpu",
  42.       &ngx_freebsd_hw_ncpu,
  43.       sizeof(ngx_freebsd_hw_ncpu), 0 },

  44.     { "machdep.hlt_logical_cpus",
  45.       &ngx_freebsd_machdep_hlt_logical_cpus,
  46.       sizeof(ngx_freebsd_machdep_hlt_logical_cpus), 0 },

  47.     { "net.inet.tcp.sendspace",
  48.       &ngx_freebsd_net_inet_tcp_sendspace,
  49.       sizeof(ngx_freebsd_net_inet_tcp_sendspace), 0 },

  50.     { "kern.ipc.somaxconn",
  51.       &ngx_freebsd_kern_ipc_somaxconn,
  52.       sizeof(ngx_freebsd_kern_ipc_somaxconn), 0 },

  53.     { NULL, NULL, 0, 0 }
  54. };


  55. void
  56. ngx_debug_init(void)
  57. {
  58. #if (NGX_DEBUG_MALLOC)

  59. #if __FreeBSD_version >= 500014 && __FreeBSD_version < 1000011
  60.     _malloc_options = "J";
  61. #elif __FreeBSD_version < 500014
  62.     malloc_options = "J";
  63. #endif

  64.     ngx_debug_malloc = 1;

  65. #else
  66.     char  *mo;

  67.     mo = getenv("MALLOC_OPTIONS");

  68.     if (mo && ngx_strchr(mo, 'J')) {
  69.         ngx_debug_malloc = 1;
  70.     }
  71. #endif
  72. }


  73. ngx_int_t
  74. ngx_os_specific_init(ngx_log_t *log)
  75. {
  76.     int         version;
  77.     size_t      size;
  78.     ngx_err_t   err;
  79.     ngx_uint_t  i;

  80.     size = sizeof(ngx_freebsd_kern_ostype);
  81.     if (sysctlbyname("kern.ostype",
  82.                      ngx_freebsd_kern_ostype, &size, NULL, 0) == -1) {
  83.         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
  84.                       "sysctlbyname(kern.ostype) failed");

  85.         if (ngx_errno != NGX_ENOMEM) {
  86.             return NGX_ERROR;
  87.         }

  88.         ngx_freebsd_kern_ostype[size - 1] = '\0';
  89.     }

  90.     size = sizeof(ngx_freebsd_kern_osrelease);
  91.     if (sysctlbyname("kern.osrelease",
  92.                      ngx_freebsd_kern_osrelease, &size, NULL, 0) == -1) {
  93.         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
  94.                       "sysctlbyname(kern.osrelease) failed");

  95.         if (ngx_errno != NGX_ENOMEM) {
  96.             return NGX_ERROR;
  97.         }

  98.         ngx_freebsd_kern_osrelease[size - 1] = '\0';
  99.     }


  100.     size = sizeof(int);
  101.     if (sysctlbyname("kern.osreldate",
  102.                      &ngx_freebsd_kern_osreldate, &size, NULL, 0) == -1) {
  103.         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
  104.                       "sysctlbyname(kern.osreldate) failed");
  105.         return NGX_ERROR;
  106.     }

  107.     version = ngx_freebsd_kern_osreldate;


  108. #if (NGX_HAVE_SENDFILE)

  109.     /*
  110.      * The determination of the sendfile() "nbytes bug" is complex enough.
  111.      * There are two sendfile() syscalls: a new #393 has no bug while
  112.      * an old #336 has the bug in some versions and has not in others.
  113.      * Besides libc_r wrapper also emulates the bug in some versions.
  114.      * There is no way to say exactly if syscall #336 in FreeBSD circa 4.6
  115.      * has the bug.  We use the algorithm that is correct at least for
  116.      * RELEASEs and for syscalls only (not libc_r wrapper).
  117.      *
  118.      * 4.6.1-RELEASE and below have the bug
  119.      * 4.6.2-RELEASE and above have the new syscall
  120.      *
  121.      * We detect the new sendfile() syscall available at the compile time
  122.      * to allow an old binary to run correctly on an updated FreeBSD system.
  123.      */

  124. #if (__FreeBSD__ == 4 && __FreeBSD_version >= 460102) \
  125.     || __FreeBSD_version == 460002 || __FreeBSD_version >= 500039

  126.     /* a new syscall without the bug */

  127.     ngx_freebsd_sendfile_nbytes_bug = 0;

  128. #else

  129.     /* an old syscall that may have the bug */

  130.     ngx_freebsd_sendfile_nbytes_bug = 1;

  131. #endif

  132. #endif /* NGX_HAVE_SENDFILE */


  133.     if ((version < 500000 && version >= 440003) || version >= 500017) {
  134.         ngx_freebsd_use_tcp_nopush = 1;
  135.     }


  136.     for (i = 0; sysctls[i].name; i++) {
  137.         size = sysctls[i].size;

  138.         if (sysctlbyname(sysctls[i].name, sysctls[i].value, &size, NULL, 0)
  139.             == 0)
  140.         {
  141.             sysctls[i].exists = 1;
  142.             continue;
  143.         }

  144.         err = ngx_errno;

  145.         if (err == NGX_ENOENT) {
  146.             continue;
  147.         }

  148.         ngx_log_error(NGX_LOG_ALERT, log, err,
  149.                       "sysctlbyname(%s) failed", sysctls[i].name);
  150.         return NGX_ERROR;
  151.     }

  152.     if (ngx_freebsd_machdep_hlt_logical_cpus) {
  153.         ngx_ncpu = ngx_freebsd_hw_ncpu / 2;

  154.     } else {
  155.         ngx_ncpu = ngx_freebsd_hw_ncpu;
  156.     }

  157.     if (version < 600008 && ngx_freebsd_kern_ipc_somaxconn > 32767) {
  158.         ngx_log_error(NGX_LOG_ALERT, log, 0,
  159.                       "sysctl kern.ipc.somaxconn must be less than 32768");
  160.         return NGX_ERROR;
  161.     }

  162.     ngx_tcp_nodelay_and_tcp_nopush = 1;

  163.     ngx_os_io = ngx_freebsd_io;

  164.     return NGX_OK;
  165. }


  166. void
  167. ngx_os_specific_status(ngx_log_t *log)
  168. {
  169.     u_long      value;
  170.     ngx_uint_t  i;

  171.     ngx_log_error(NGX_LOG_NOTICE, log, 0, "OS: %s %s",
  172.                   ngx_freebsd_kern_ostype, ngx_freebsd_kern_osrelease);

  173. #ifdef __DragonFly_version
  174.     ngx_log_error(NGX_LOG_NOTICE, log, 0,
  175.                   "kern.osreldate: %d, built on %d",
  176.                   ngx_freebsd_kern_osreldate, __DragonFly_version);
  177. #else
  178.     ngx_log_error(NGX_LOG_NOTICE, log, 0,
  179.                   "kern.osreldate: %d, built on %d",
  180.                   ngx_freebsd_kern_osreldate, __FreeBSD_version);
  181. #endif

  182.     for (i = 0; sysctls[i].name; i++) {
  183.         if (sysctls[i].exists) {
  184.             if (sysctls[i].size == sizeof(long)) {
  185.                 value = *(long *) sysctls[i].value;

  186.             } else {
  187.                 value = *(int *) sysctls[i].value;
  188.             }

  189.             ngx_log_error(NGX_LOG_NOTICE, log, 0, "%s: %l",
  190.                           sysctls[i].name, value);
  191.         }
  192.     }
  193. }