source: trunk/mmap.c @ 57

Last change on this file since 57 was 57, checked in by moo, 9 years ago

never unlink the file not created by XCache

File size: 4.9 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
[57]14#   define XCacheCreateFileMapping(size, perm, name) \
[11]15        CreateFileMapping(INVALID_HANDLE_VALUE, NULL, perm, (sizeof(xc_shmsize_t) > 4) ? size >> 32 : 0, size & 0xffffffff, name)
16#   define XCACHE_MAP_FAILED NULL
17#   define munmap(p, s) UnmapViewOfFile(p)
18#else
19#   include <unistd.h>
20#   define XCACHE_MAP_FAILED MAP_FAILED
21#endif
22
[1]23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
[11]26
27#ifndef ZEND_WIN32
[1]28#include <sys/mman.h>
[11]29#endif
[1]30
31#include "php.h"
32#include "myshm.h"
33
34#ifndef max
35#define max(a, b) ((a) < (b) ? (b) : (a))
36#endif
37
38// {{{ xc_shm_t
39struct _xc_shm_t {
40    void *ptr;
41    void *ptr_ro;
42    long  diff;
43    xc_shmsize_t size;
[11]44    char *name;
[57]45    int newfile;
[11]46#ifdef ZEND_WIN32
47    HANDLE hmap;
48    HANDLE hmap_ro;
49#endif
[1]50};
51
[11]52#undef NDEBUG
[1]53#ifdef ALLOC_DEBUG
54#   define inline
55#else
56#   define NDEBUG
57#endif
58#include <assert.h>
59/* }}} */
60#define CHECK(x, e) do { if ((x) == NULL) { zend_error(E_ERROR, "XCache: " e); goto err; } } while (0)
[11]61#define PTR_ADD(ptr, v) (((char *) (ptr)) + (v))
62#define PTR_SUB(ptr, v) (((char *) (ptr)) - (v))
[1]63
64int xc_shm_can_readonly(xc_shm_t *shm) /* {{{ */
65{
66    return shm->ptr_ro != NULL;
67}
68/* }}} */
69int xc_shm_is_readwrite(xc_shm_t *shm, const void *p) /* {{{ */
70{
71    return p >= shm->ptr && (char *)p < (char *)shm->ptr + shm->size;
72}
73/* }}} */
74int xc_shm_is_readonly(xc_shm_t *shm, const void *p) /* {{{ */
75{
76    return xc_shm_can_readonly(shm) && p >= shm->ptr_ro && (char *)p < (char *)shm->ptr_ro + shm->size;
77}
78/* }}} */
79void *xc_shm_to_readwrite(xc_shm_t *shm, void *p) /* {{{ */
80{
81    if (shm->diff) {
82        assert(xc_shm_is_readonly(p));
[11]83        p = PTR_SUB(p, -shm->diff);
[1]84    }
85    assert(xc_shm_is_readwrite(p));
86    return p;
87}
88/* }}} */
89void *xc_shm_to_readonly(xc_shm_t *shm, void *p) /* {{{ */
90{
91    assert(xc_shm_is_readwrite(p));
92    if (shm->diff) {
[11]93        p = PTR_ADD(p, shm->diff);
[1]94        assert(xc_shm_is_readonly(p));
95    }
96    return p;
97}
98/* }}} */
99
100void xc_shm_destroy(xc_shm_t *shm) /* {{{ */
101{
102    if (shm->ptr_ro) {
103        munmap(shm->ptr_ro, shm->size);
104        /*
105        shm->ptr_ro = NULL;
106        */
107    }
108    if (shm->ptr) {
109        /* shm->size depends on shm->ptr */
110        munmap(shm->ptr, shm->size);
111        /*
112        shm->ptr = NULL;
113        */
114    }
[11]115#ifdef ZEND_WIN32
116    if (shm->hmap) {
117        CloseHandle(shm->hmap);
118    }
119    if (shm->hmap_ro) {
120        CloseHandle(shm->hmap_ro);
121    }
122#endif
123
124    if (shm->name) {
125#ifdef __CYGWIN__
[57]126        if (shm->newfile) {
127            unlink(shm->name);
128        }
[11]129#endif
130        free(shm->name);
131    }
[1]132    /*
133    shm->size = NULL;
134    shm->diff = 0;
135    */
136
137    free(shm);
138    return;
139}
140/* }}} */
141xc_shm_t *xc_shm_init(const char *path, xc_shmsize_t size, zend_bool readonly_protection) /* {{{ */
142{
[21]143#ifdef ZEND_WIN32
144#   define TMP_PATH "XCache"
145#else
146#   define TMP_PATH "/tmp/XCache"
147#endif
[1]148    xc_shm_t *shm = NULL;
[11]149    int fd = -1;
[1]150    int ro_ok;
151    volatile void *romem;
[21]152    char tmpname[sizeof(TMP_PATH) - 1 + 100];
[1]153
154    CHECK(shm = calloc(1, sizeof(xc_shm_t)), "shm OOM");
155    shm->size = size;
[11]156
[1]157    if (path == NULL || !path[0]) {
[11]158        static int inc = 0;
[21]159        snprintf(tmpname, sizeof(tmpname) - 1, "%s.%d.%d.%d", TMP_PATH, (int) getuid(), inc ++, rand());
[11]160        path = tmpname;
[1]161    }
[11]162
163    shm->name = strdup(path);
164
165#ifndef ZEND_WIN32
166#   define XCACHE_MMAP_PERMISSION (S_IRUSR | S_IWUSR)
167    fd = open(shm->name, O_RDWR, XCACHE_MMAP_PERMISSION);
[1]168    if (fd == -1) {
[11]169        fd = open(shm->name, O_CREAT | O_RDWR, XCACHE_MMAP_PERMISSION);
[57]170        shm->newfile = 1;
[1]171        if (fd == -1) {
172            goto err;
173        }
174    }
[57]175    if (strncmp(shm->name, "/tmp", 4) == 0) {
176        shm->newfile = 0;
177    }
[1]178    ftruncate(fd, size);
[11]179#endif
[1]180
[11]181#ifdef ZEND_WIN32
[57]182    shm->hmap = XCacheCreateFileMapping(size, PAGE_READWRITE, shm->name);
[11]183    shm->ptr = (LPSTR) MapViewOfFile(shm->hmap, FILE_MAP_WRITE, 0, 0, 0);
184#else
[1]185    shm->ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
[11]186#endif
187
188    if (shm->ptr == XCACHE_MAP_FAILED) {
[1]189        shm->ptr = NULL;
190        goto err;
191    }
192
193    ro_ok = 0;
194    if (readonly_protection) {
[11]195#ifdef ZEND_WIN32
[57]196        shm->hmap_ro = XCacheCreateFileMapping(size, PAGE_READONLY, shm->name);
[11]197        shm->ptr_ro = (LPSTR) MapViewOfFile(shm->hmap_ro, FILE_MAP_READ, 0, 0, 0);
198#else
[1]199        shm->ptr_ro = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
[11]200#endif
[1]201        romem = shm->ptr_ro;
202
203        /* {{{ check if ptr_ro works */
204        do {
[11]205            if (shm->ptr_ro == XCACHE_MAP_FAILED || shm->ptr_ro == shm->ptr) {
[1]206                break;
207            }
208            *(char *)shm->ptr = 1;
209            if (*(char *)romem != 1) {
210                break;
211            }
212            *(char *)shm->ptr = 2;
213            if (*(char *)romem != 2) {
214                break;
215            }
216            ro_ok = 1;
217        } while (0);
218    }
219
220    if (ro_ok) {
[11]221        shm->diff = PTR_SUB(shm->ptr_ro, (char *) shm->ptr);
[1]222        assert(abs(shm->diff) >= size);
223    }
224    else {
[11]225        if (shm->ptr_ro != XCACHE_MAP_FAILED) {
[1]226            munmap(shm->ptr_ro, size);
227        }
228        shm->ptr_ro = NULL;
229        shm->diff = 0;
230    }
231    /* }}} */
232
233    close(fd);
[11]234#ifndef __CYGWIN__
[57]235    if (shm->newfile) {
236        unlink(shm->name);
237    }
[11]238#endif
[1]239
240    return shm;
241
242err:
[11]243    if (fd != -1) {
244        close(fd);
245    }
[1]246    if (shm) {
247        xc_shm_destroy(shm);
248    }
249    return NULL;
250}
251/* }}} */
252
253void *xc_shm_ptr(xc_shm_t *shm) /* {{{ */
254{
255    return shm->ptr;
256}
257/* }}} */
Note: See TracBrowser for help on using the repository browser.