root/ext/opcache/shared_alloc_shm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. create_segments
  2. detach_segment
  3. segment_type_size

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend OPcache                                                         |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Andi Gutmans <andi@zend.com>                                |
  16    |          Zeev Suraski <zeev@zend.com>                                |
  17    |          Stanislav Malyshev <stas@zend.com>                          |
  18    |          Dmitry Stogov <dmitry@zend.com>                             |
  19    +----------------------------------------------------------------------+
  20 */
  21 
  22 #include "zend_shared_alloc.h"
  23 
  24 #ifdef USE_SHM
  25 
  26 #if defined(__FreeBSD__)
  27 # include <machine/param.h>
  28 #endif
  29 #include <sys/types.h>
  30 #include <sys/shm.h>
  31 #include <sys/ipc.h>
  32 #include <dirent.h>
  33 #include <signal.h>
  34 #include <stdio.h>
  35 #include <stdlib.h>
  36 #include <unistd.h>
  37 #include <errno.h>
  38 
  39 #include <sys/stat.h>
  40 #include <fcntl.h>
  41 
  42 #ifndef MIN
  43 # define MIN(x, y) ((x) > (y)? (y) : (x))
  44 #endif
  45 
  46 #define SEG_ALLOC_SIZE_MAX 32*1024*1024
  47 #define SEG_ALLOC_SIZE_MIN 2*1024*1024
  48 
  49 typedef struct  {
  50     zend_shared_segment common;
  51     int shm_id;
  52 } zend_shared_segment_shm;
  53 
  54 static int create_segments(size_t requested_size, zend_shared_segment_shm ***shared_segments_p, int *shared_segments_count, char **error_in)
  55 {
  56         int i;
  57         size_t allocate_size = 0, remaining_bytes = requested_size, seg_allocate_size;
  58         int first_segment_id = -1;
  59         key_t first_segment_key = -1;
  60         struct shmid_ds sds;
  61         int shmget_flags;
  62         zend_shared_segment_shm *shared_segments;
  63 
  64     seg_allocate_size = SEG_ALLOC_SIZE_MAX;
  65     /* determine segment size we _really_ need:
  66      * no more than to include requested_size
  67      */
  68     while (requested_size * 2 <= seg_allocate_size && seg_allocate_size > SEG_ALLOC_SIZE_MIN) {
  69         seg_allocate_size >>= 1;
  70     }
  71 
  72         shmget_flags = IPC_CREAT|SHM_R|SHM_W|IPC_EXCL;
  73 
  74         /* try allocating this much, if not - try shrinking */
  75         while (seg_allocate_size >= SEG_ALLOC_SIZE_MIN) {
  76                 allocate_size = MIN(requested_size, seg_allocate_size);
  77                 first_segment_id = shmget(first_segment_key, allocate_size, shmget_flags);
  78                 if (first_segment_id != -1) {
  79                         break;
  80                 }
  81                 seg_allocate_size >>= 1; /* shrink the allocated block */
  82         }
  83 
  84         if (first_segment_id == -1) {
  85                 *error_in = "shmget";
  86                 return ALLOC_FAILURE;
  87         }
  88 
  89         *shared_segments_count = ((requested_size - 1) / seg_allocate_size) + 1;
  90         *shared_segments_p = (zend_shared_segment_shm **) calloc(1, (*shared_segments_count) * sizeof(zend_shared_segment_shm) + sizeof(void *) * (*shared_segments_count));
  91         if (!*shared_segments_p) {
  92                 *error_in = "calloc";
  93                 return ALLOC_FAILURE;
  94         }
  95         shared_segments = (zend_shared_segment_shm *)((char *)(*shared_segments_p) + sizeof(void *) * (*shared_segments_count));
  96         for (i = 0; i < *shared_segments_count; i++) {
  97                 (*shared_segments_p)[i] = shared_segments + i;
  98         }
  99 
 100         remaining_bytes = requested_size;
 101         for (i = 0; i < *shared_segments_count; i++) {
 102                 allocate_size = MIN(remaining_bytes, seg_allocate_size);
 103                 if (i != 0) {
 104                         shared_segments[i].shm_id = shmget(IPC_PRIVATE, allocate_size, shmget_flags);
 105                 } else {
 106                         shared_segments[i].shm_id = first_segment_id;
 107                 }
 108 
 109                 if (shared_segments[i].shm_id == -1) {
 110                         return ALLOC_FAILURE;
 111                 }
 112 
 113                 shared_segments[i].common.p = shmat(shared_segments[i].shm_id, NULL, 0);
 114                 if (shared_segments[i].common.p == (void *)-1) {
 115                         *error_in = "shmat";
 116                         shmctl(shared_segments[i].shm_id, IPC_RMID, &sds);
 117                         return ALLOC_FAILURE;
 118                 }
 119                 shmctl(shared_segments[i].shm_id, IPC_RMID, &sds);
 120 
 121                 shared_segments[i].common.pos = 0;
 122                 shared_segments[i].common.size = allocate_size;
 123                 remaining_bytes -= allocate_size;
 124         }
 125         return ALLOC_SUCCESS;
 126 }
 127 
 128 static int detach_segment(zend_shared_segment_shm *shared_segment)
 129 {
 130         shmdt(shared_segment->common.p);
 131         return 0;
 132 }
 133 
 134 static size_t segment_type_size(void)
 135 {
 136         return sizeof(zend_shared_segment_shm);
 137 }
 138 
 139 zend_shared_memory_handlers zend_alloc_shm_handlers = {
 140         (create_segments_t)create_segments,
 141         (detach_segment_t)detach_segment,
 142         segment_type_size
 143 };
 144 
 145 #endif /* USE_SHM */

/* [<][>][^][v][top][bottom][index][help] */