source: trunk/mmap.c @ 924

Last change on this file since 924 was 924, checked in by moo, 22 months ago

fix invalidate CRT parameters

  • Property svn:eol-style set to native
File size: 6.8 KB
Line 
1
2#include <stdio.h>
3#include <assert.h>
4#include <limits.h>
5#include <string.h>
6#include <stdlib.h>
7
8/* mmap */
9#ifdef ZEND_WIN32
10#   define ftruncate chsize
11#   define getuid() 0
12#   include <process.h>
13#   define XCacheCreateFileMapping(size, perm, name) \
14        CreateFileMapping(INVALID_HANDLE_VALUE, NULL, perm, (sizeof(xc_shmsize_t) > 4) ? size >> 32 : 0, size & 0xffffffff, name)
15#   define XCACHE_MAP_FAILED NULL
16#   define munmap(p, s) UnmapViewOfFile(p)
17#else
18#   include <unistd.h>
19/* make sure to mark(change) it to NULL to keep consistent */
20#   define XCACHE_MAP_FAILED MAP_FAILED
21#endif
22
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26
27#ifndef ZEND_WIN32
28#include <sys/mman.h>
29#endif
30
31#include "php.h"
32#define XC_SHM_IMPL _xc_mmap_shm_t
33#include "xc_shm.h"
34#include "utils.h"
35
36#ifndef max
37#define max(a, b) ((a) < (b) ? (b) : (a))
38#endif
39
40/* {{{ xc_shm_t */
41struct _xc_mmap_shm_t {
42    xc_shm_handlers_t *handlers;
43    void *ptr;
44    void *ptr_ro;
45    long  diff;
46    xc_shmsize_t size;
47    xc_shmsize_t memoffset;
48    char *name;
49#ifdef ZEND_WIN32
50    HANDLE hmap;
51    HANDLE hmap_ro;
52#else
53    int newfile;
54#endif
55};
56
57/* }}} */
58#define CHECK(x, e) do { if ((x) == NULL) { zend_error(E_ERROR, "XCache: " e); goto err; } } while (0)
59#define PTR_ADD(ptr, v) (((char *) (ptr)) + (v))
60#define PTR_SUB(ptr, v) (((char *) (ptr)) - (v))
61
62static XC_SHM_CAN_READONLY(xc_mmap_can_readonly) /* {{{ */
63{
64    return shm->ptr_ro != NULL;
65}
66/* }}} */
67static XC_SHM_IS_READWRITE(xc_mmap_is_readwrite) /* {{{ */
68{
69    return p >= shm->ptr && (char *)p < (char *)shm->ptr + shm->size;
70}
71/* }}} */
72static XC_SHM_IS_READONLY(xc_mmap_is_readonly) /* {{{ */
73{
74    return xc_mmap_can_readonly(shm) && p >= shm->ptr_ro && (char *)p < (char *)shm->ptr_ro + shm->size;
75}
76/* }}} */
77static XC_SHM_TO_READWRITE(xc_mmap_to_readwrite) /* {{{ */
78{
79    if (shm->diff) {
80        assert(xc_mmap_is_readonly(shm, p));
81        p = PTR_SUB(p, shm->diff);
82    }
83    assert(xc_mmap_is_readwrite(shm, p));
84    return p;
85}
86/* }}} */
87static XC_SHM_TO_READONLY(xc_mmap_to_readonly) /* {{{ */
88{
89    assert(xc_mmap_is_readwrite(shm, p));
90    if (shm->diff) {
91        p = PTR_ADD(p, shm->diff);
92        assert(xc_mmap_is_readonly(shm, p));
93    }
94    return p;
95}
96/* }}} */
97
98static XC_SHM_DESTROY(xc_mmap_destroy) /* {{{ */
99{
100    if (shm->ptr_ro) {
101        munmap(shm->ptr_ro, shm->size);
102        /*
103        shm->ptr_ro = NULL;
104        */
105    }
106    if (shm->ptr) {
107        /* shm->size depends on shm->ptr */
108        munmap(shm->ptr, shm->size);
109        /*
110        shm->ptr = NULL;
111        */
112    }
113#ifdef ZEND_WIN32
114    if (shm->hmap) {
115        CloseHandle(shm->hmap);
116    }
117    if (shm->hmap_ro) {
118        CloseHandle(shm->hmap_ro);
119    }
120#endif
121
122    if (shm->name) {
123#ifndef ZEND_WIN32
124#   ifdef __CYGWIN__
125        if (shm->newfile) {
126            unlink(shm->name);
127        }
128#   endif
129#endif
130        free(shm->name);
131    }
132    /*
133    shm->size = NULL;
134    shm->diff = 0;
135    */
136
137    free(shm);
138    return;
139}
140/* }}} */
141static XC_SHM_INIT(xc_mmap_init) /* {{{ */
142{
143#ifdef ZEND_WIN32
144#   define TMP_PATH "XCache"
145#else
146#   define TMP_PATH "/tmp/XCache"
147    int fd = -1;
148#endif
149    xc_shm_t *shm = NULL;
150    int ro_ok;
151    volatile void *romem;
152    char tmpname[sizeof(TMP_PATH) - 1 + 100];
153    const char *errstr = NULL;
154    const char *path = (const char *) arg1;
155
156    CHECK(shm = calloc(1, sizeof(xc_shm_t)), "shm OOM");
157    shm->size = size;
158
159    if (path == NULL || !path[0]) {
160        static int inc = 0;
161        snprintf(tmpname, sizeof(tmpname) - 1, "%s.%d.%d.%d.%d", TMP_PATH, (int) getuid(), (int) getpid(), inc ++, rand());
162        path = tmpname;
163    }
164#ifdef ZEND_WIN32
165    else {
166        static int inc2 = 0;
167        snprintf(tmpname, sizeof(tmpname) - 1, "%s.%d.%d.%d.%d", path, (int) getuid(), (int) getpid(), inc2 ++, rand());
168        path = tmpname;
169    }
170#endif
171
172    shm->name = strdup(path);
173
174#ifndef ZEND_WIN32
175#   define XCACHE_MMAP_PERMISSION (S_IRUSR | S_IWUSR)
176    fd = open(shm->name, O_RDWR, XCACHE_MMAP_PERMISSION);
177    if (fd == -1) {
178        /* do not create file in /dev */
179        if (strncmp(shm->name, "/dev", 4) == 0) {
180            perror(shm->name);
181            errstr = "Cannot open file set by xcache.mmap_path, check the xcache.size/var_size against system limitation";
182            goto err;
183        }
184        fd = open(shm->name, O_CREAT | O_RDWR, XCACHE_MMAP_PERMISSION);
185        shm->newfile = 1;
186        if (fd == -1) {
187            perror(shm->name);
188            errstr = "Cannot open or create file set by xcache.mmap_path, check the path permission or check xcache.size/var_size against system limitation";
189            goto err;
190        }
191    }
192
193    if (ftruncate(fd, size) != 0 && errno != EINVAL) {
194        perror(shm->name);
195        errstr = "Failed to ftruncate the file";
196        goto err;
197    }
198#endif
199
200#ifdef ZEND_WIN32
201    shm->hmap = XCacheCreateFileMapping(size, PAGE_READWRITE, shm->name);
202    shm->ptr = (LPSTR) MapViewOfFile(shm->hmap, FILE_MAP_WRITE, 0, 0, 0);
203#else
204    shm->ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
205#endif
206
207    if (shm->ptr == XCACHE_MAP_FAILED) {
208        perror(shm->name);
209        errstr = "Failed creating file mapping";
210        shm->ptr = NULL;
211        goto err;
212    }
213
214    /* {{{ readonly protection, mmap it readonly and check if ptr_ro works */
215    if (readonly_protection) {
216        ro_ok = 0;
217
218#ifdef ZEND_WIN32
219        shm->hmap_ro = XCacheCreateFileMapping(size, PAGE_READONLY, shm->name);
220        shm->ptr_ro = (LPSTR) MapViewOfFile(shm->hmap_ro, FILE_MAP_READ, 0, 0, 0);
221#else
222        shm->ptr_ro = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
223#endif
224        if (shm->ptr_ro == XCACHE_MAP_FAILED) {
225            shm->ptr_ro = NULL;
226        }
227        romem = shm->ptr_ro;
228
229        do {
230            if (romem == NULL || romem == shm->ptr) {
231                break;
232            }
233            *(char *)shm->ptr = 1;
234            if (*(char *)romem != 1) {
235                break;
236            }
237            *(char *)shm->ptr = 2;
238            if (*(char *)romem != 2) {
239                break;
240            }
241            ro_ok = 1;
242        } while (0);
243
244        if (ro_ok) {
245            shm->diff = PTR_SUB(shm->ptr_ro, (char *) shm->ptr);
246            /* no overlap */
247            assert(abs(shm->diff) >= size);
248        }
249        else {
250            if (shm->ptr_ro) {
251                munmap(shm->ptr_ro, size);
252            }
253#ifdef ZEND_WIN32
254            if (shm->hmap_ro) {
255                CloseHandle(shm->hmap_ro);
256            }
257#endif
258            shm->ptr_ro = NULL;
259            shm->diff = 0;
260        }
261    }
262
263    /* }}} */
264
265#ifndef ZEND_WIN32
266    close(fd);
267
268#   ifndef __CYGWIN__
269    if (shm->newfile) {
270        unlink(shm->name);
271    }
272#   endif
273#endif
274
275    return shm;
276
277err:
278#ifndef ZEND_WIN32
279    if (fd != -1) {
280        close(fd);
281    }
282#endif
283    if (shm) {
284        xc_mmap_destroy(shm);
285    }
286    if (errstr) {
287        fprintf(stderr, "%s\n", errstr);
288        zend_error(E_ERROR, "%s", errstr);
289    }
290    return NULL;
291}
292/* }}} */
293
294static XC_SHM_MEMINIT(xc_mmap_meminit) /* {{{ */
295{
296    xc_mem_t *mem;
297    if (shm->memoffset + size > shm->size) {
298        zend_error(E_ERROR, "XCache: internal error at %s#%d", __FILE__, __LINE__);
299        return NULL;
300    }
301    mem = (xc_mem_t *) PTR_ADD(shm->ptr, shm->memoffset);
302    shm->memoffset += size;
303    mem->handlers = shm->handlers->memhandlers;
304    mem->handlers->init(shm, mem, size);
305    return mem;
306}
307/* }}} */
308static XC_SHM_MEMDESTROY(xc_mmap_memdestroy) /* {{{ */
309{
310}
311/* }}} */
312
313static xc_shm_handlers_t xc_shm_mmap_handlers = XC_SHM_HANDLERS(mmap);
314void xc_shm_mmap_register() /* {{{ */
315{
316    CHECK(xc_shm_mmap_handlers.memhandlers = xc_mem_scheme_find("mem"), "cannot find mem handlers");
317    if (xc_shm_scheme_register("mmap", &xc_shm_mmap_handlers) == 0) {
318        zend_error(E_ERROR, "XCache: failed to register mmap shm_scheme");
319    }
320err:
321    return;
322}
323/* }}} */
Note: See TracBrowser for help on using the repository browser.