source: branches/1.2/mmap.c @ 380

Last change on this file since 380 was 380, checked in by moo, 7 years ago

make life easier for debugging

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