src/os/win32/ngx_shmem.c - nginx source code

Global variables defined

Functions defined

Macros 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. /*
  8. * Base addresses selected by system for shared memory mappings are likely
  9. * to be different on Windows Vista and later versions due to address space
  10. * layout randomization.  This is however incompatible with storing absolute
  11. * addresses within the shared memory.
  12. *
  13. * To make it possible to store absolute addresses we create mappings
  14. * at the same address in all processes by starting mappings at predefined
  15. * addresses.  The addresses were selected somewhat randomly in order to
  16. * minimize the probability that some other library doing something similar
  17. * conflicts with us.  The addresses are from the following typically free
  18. * blocks:
  19. *
  20. * - 0x10000000 .. 0x70000000 (about 1.5 GB in total) on 32-bit platforms
  21. * - 0x000000007fff0000 .. 0x000007f68e8b0000 (about 8 TB) on 64-bit platforms
  22. *
  23. * Additionally, we allow to change the mapping address once it was detected
  24. * to be different from one originally used.  This is needed to support
  25. * reconfiguration.
  26. */


  27. #ifdef _WIN64
  28. #define NGX_SHMEM_BASE  0x0000047047e00000
  29. #else
  30. #define NGX_SHMEM_BASE  0x2efe0000
  31. #endif


  32. ngx_uint_t  ngx_allocation_granularity;


  33. ngx_int_t
  34. ngx_shm_alloc(ngx_shm_t *shm)
  35. {
  36.     u_char         *name;
  37.     uint64_t        size;
  38.     static u_char  *base = (u_char *) NGX_SHMEM_BASE;

  39.     name = ngx_alloc(shm->name.len + 2 + NGX_INT32_LEN, shm->log);
  40.     if (name == NULL) {
  41.         return NGX_ERROR;
  42.     }

  43.     (void) ngx_sprintf(name, "%V_%s%Z", &shm->name, ngx_unique);

  44.     ngx_set_errno(0);

  45.     size = shm->size;

  46.     shm->handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
  47.                                     (u_long) (size >> 32),
  48.                                     (u_long) (size & 0xffffffff),
  49.                                     (char *) name);

  50.     if (shm->handle == NULL) {
  51.         ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
  52.                       "CreateFileMapping(%uz, %s) failed",
  53.                       shm->size, name);
  54.         ngx_free(name);

  55.         return NGX_ERROR;
  56.     }

  57.     ngx_free(name);

  58.     if (ngx_errno == ERROR_ALREADY_EXISTS) {
  59.         shm->exists = 1;
  60.     }

  61.     shm->addr = MapViewOfFileEx(shm->handle, FILE_MAP_WRITE, 0, 0, 0, base);

  62.     if (shm->addr != NULL) {
  63.         base += ngx_align(size, ngx_allocation_granularity);
  64.         return NGX_OK;
  65.     }

  66.     ngx_log_debug3(NGX_LOG_DEBUG_CORE, shm->log, ngx_errno,
  67.                    "MapViewOfFileEx(%uz, %p) of file mapping \"%V\" failed, "
  68.                    "retry without a base address",
  69.                    shm->size, base, &shm->name);

  70.     /*
  71.      * Order of shared memory zones may be different in the master process
  72.      * and worker processes after reconfiguration.  As a result, the above
  73.      * may fail due to a conflict with a previously created mapping remapped
  74.      * to a different address.  Additionally, there may be a conflict with
  75.      * some other uses of the memory.  In this case we retry without a base
  76.      * address to let the system assign the address itself.
  77.      */

  78.     shm->addr = MapViewOfFile(shm->handle, FILE_MAP_WRITE, 0, 0, 0);

  79.     if (shm->addr != NULL) {
  80.         return NGX_OK;
  81.     }

  82.     ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
  83.                   "MapViewOfFile(%uz) of file mapping \"%V\" failed",
  84.                   shm->size, &shm->name);

  85.     if (CloseHandle(shm->handle) == 0) {
  86.         ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
  87.                       "CloseHandle() of file mapping \"%V\" failed",
  88.                       &shm->name);
  89.     }

  90.     return NGX_ERROR;
  91. }


  92. ngx_int_t
  93. ngx_shm_remap(ngx_shm_t *shm, u_char *addr)
  94. {
  95.     if (UnmapViewOfFile(shm->addr) == 0) {
  96.         ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
  97.                       "UnmapViewOfFile(%p) of file mapping \"%V\" failed",
  98.                       shm->addr, &shm->name);
  99.         return NGX_ERROR;
  100.     }

  101.     shm->addr = MapViewOfFileEx(shm->handle, FILE_MAP_WRITE, 0, 0, 0, addr);

  102.     if (shm->addr != NULL) {
  103.         return NGX_OK;
  104.     }

  105.     ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
  106.                   "MapViewOfFileEx(%uz, %p) of file mapping \"%V\" failed",
  107.                   shm->size, addr, &shm->name);

  108.     return NGX_ERROR;
  109. }


  110. void
  111. ngx_shm_free(ngx_shm_t *shm)
  112. {
  113.     if (UnmapViewOfFile(shm->addr) == 0) {
  114.         ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
  115.                       "UnmapViewOfFile(%p) of file mapping \"%V\" failed",
  116.                       shm->addr, &shm->name);
  117.     }

  118.     if (CloseHandle(shm->handle) == 0) {
  119.         ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
  120.                       "CloseHandle() of file mapping \"%V\" failed",
  121.                       &shm->name);
  122.     }
  123. }