This source file includes following definitions.
- create_segments
- detach_segment
- segment_type_size
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
66
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
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;
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