source: branches/1.0/mmap.c @ 83

Last change on this file since 83 was 83, checked in by moo, 8 years ago

fix win32 emulated anonymous mmap

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