source: trunk/mmap.c @ 21

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

friendly anonymous mmap name for win32

File size: 4.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
14#   define XcacheCreateFileMapping(size, perm, name) \
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;
45#ifdef ZEND_WIN32
46    HANDLE hmap;
47    HANDLE hmap_ro;
48#endif
[1]49};
50
[11]51#undef NDEBUG
[1]52#ifdef ALLOC_DEBUG
53#   define inline
54#else
55#   define NDEBUG
56#endif
57#include <assert.h>
58/* }}} */
59#define CHECK(x, e) do { if ((x) == NULL) { zend_error(E_ERROR, "XCache: " e); goto err; } } while (0)
[11]60#define PTR_ADD(ptr, v) (((char *) (ptr)) + (v))
61#define PTR_SUB(ptr, v) (((char *) (ptr)) - (v))
[1]62
63int xc_shm_can_readonly(xc_shm_t *shm) /* {{{ */
64{
65    return shm->ptr_ro != NULL;
66}
67/* }}} */
68int xc_shm_is_readwrite(xc_shm_t *shm, const void *p) /* {{{ */
69{
70    return p >= shm->ptr && (char *)p < (char *)shm->ptr + shm->size;
71}
72/* }}} */
73int xc_shm_is_readonly(xc_shm_t *shm, const void *p) /* {{{ */
74{
75    return xc_shm_can_readonly(shm) && p >= shm->ptr_ro && (char *)p < (char *)shm->ptr_ro + shm->size;
76}
77/* }}} */
78void *xc_shm_to_readwrite(xc_shm_t *shm, void *p) /* {{{ */
79{
80    if (shm->diff) {
81        assert(xc_shm_is_readonly(p));
[11]82        p = PTR_SUB(p, -shm->diff);
[1]83    }
84    assert(xc_shm_is_readwrite(p));
85    return p;
86}
87/* }}} */
88void *xc_shm_to_readonly(xc_shm_t *shm, void *p) /* {{{ */
89{
90    assert(xc_shm_is_readwrite(p));
91    if (shm->diff) {
[11]92        p = PTR_ADD(p, shm->diff);
[1]93        assert(xc_shm_is_readonly(p));
94    }
95    return p;
96}
97/* }}} */
98
99void xc_shm_destroy(xc_shm_t *shm) /* {{{ */
100{
101    if (shm->ptr_ro) {
102        munmap(shm->ptr_ro, shm->size);
103        /*
104        shm->ptr_ro = NULL;
105        */
106    }
107    if (shm->ptr) {
108        /* shm->size depends on shm->ptr */
109        munmap(shm->ptr, shm->size);
110        /*
111        shm->ptr = NULL;
112        */
113    }
[11]114#ifdef ZEND_WIN32
115    if (shm->hmap) {
116        CloseHandle(shm->hmap);
117    }
118    if (shm->hmap_ro) {
119        CloseHandle(shm->hmap_ro);
120    }
121#endif
122
123    if (shm->name) {
124#ifdef __CYGWIN__
125        unlink(shm->name);
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/* }}} */
138xc_shm_t *xc_shm_init(const char *path, xc_shmsize_t size, zend_bool readonly_protection) /* {{{ */
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];
[1]150
151    CHECK(shm = calloc(1, sizeof(xc_shm_t)), "shm OOM");
152    shm->size = size;
[11]153
[1]154    if (path == NULL || !path[0]) {
[11]155        static int inc = 0;
[21]156        snprintf(tmpname, sizeof(tmpname) - 1, "%s.%d.%d.%d", TMP_PATH, (int) getuid(), inc ++, rand());
[11]157        path = tmpname;
[1]158    }
[11]159
160    shm->name = strdup(path);
161
162#ifndef ZEND_WIN32
163#   define XCACHE_MMAP_PERMISSION (S_IRUSR | S_IWUSR)
164    fd = open(shm->name, O_RDWR, XCACHE_MMAP_PERMISSION);
[1]165    if (fd == -1) {
[11]166        fd = open(shm->name, O_CREAT | O_RDWR, XCACHE_MMAP_PERMISSION);
[1]167        if (fd == -1) {
168            goto err;
169        }
170    }
171    ftruncate(fd, size);
[11]172#endif
[1]173
[11]174#ifdef ZEND_WIN32
175    shm->hmap = XcacheCreateFileMapping(size, PAGE_READWRITE, shm->name);
176    shm->ptr = (LPSTR) MapViewOfFile(shm->hmap, FILE_MAP_WRITE, 0, 0, 0);
177#else
[1]178    shm->ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
[11]179#endif
180
181    if (shm->ptr == XCACHE_MAP_FAILED) {
[1]182        shm->ptr = NULL;
183        goto err;
184    }
185
186    ro_ok = 0;
187    if (readonly_protection) {
[11]188#ifdef ZEND_WIN32
189        shm->hmap_ro = XcacheCreateFileMapping(size, PAGE_READONLY, shm->name);
190        shm->ptr_ro = (LPSTR) MapViewOfFile(shm->hmap_ro, FILE_MAP_READ, 0, 0, 0);
191#else
[1]192        shm->ptr_ro = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
[11]193#endif
[1]194        romem = shm->ptr_ro;
195
196        /* {{{ check if ptr_ro works */
197        do {
[11]198            if (shm->ptr_ro == XCACHE_MAP_FAILED || shm->ptr_ro == shm->ptr) {
[1]199                break;
200            }
201            *(char *)shm->ptr = 1;
202            if (*(char *)romem != 1) {
203                break;
204            }
205            *(char *)shm->ptr = 2;
206            if (*(char *)romem != 2) {
207                break;
208            }
209            ro_ok = 1;
210        } while (0);
211    }
212
213    if (ro_ok) {
[11]214        shm->diff = PTR_SUB(shm->ptr_ro, (char *) shm->ptr);
[1]215        assert(abs(shm->diff) >= size);
216    }
217    else {
[11]218        if (shm->ptr_ro != XCACHE_MAP_FAILED) {
[1]219            munmap(shm->ptr_ro, size);
220        }
221        shm->ptr_ro = NULL;
222        shm->diff = 0;
223    }
224    /* }}} */
225
226    close(fd);
[11]227#ifndef __CYGWIN__
228    unlink(shm->name);
229#endif
[1]230
231    return shm;
232
233err:
[11]234    if (fd != -1) {
235        close(fd);
236    }
[1]237    if (shm) {
238        xc_shm_destroy(shm);
239    }
240    return NULL;
241}
242/* }}} */
243
244void *xc_shm_ptr(xc_shm_t *shm) /* {{{ */
245{
246    return shm->ptr;
247}
248/* }}} */
Note: See TracBrowser for help on using the repository browser.