source: trunk/mmap.c @ 767

Last change on this file since 767 was 767, checked in by moo, 3 years ago

check return value to avoid gcc warning

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