source: trunk/mmap.c @ 1

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

initial import to online

File size: 3.3 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>
9/* mmap */
10#include <unistd.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <sys/mman.h>
15
16#include "php.h"
17#include "myshm.h"
18
19#ifndef max
20#define max(a, b) ((a) < (b) ? (b) : (a))
21#endif
22
23// {{{ xc_shm_t
24struct _xc_shm_t {
25    void *ptr;
26    void *ptr_ro;
27    long  diff;
28    xc_shmsize_t size;
29};
30
31#ifdef ALLOC_DEBUG
32#   undef NDEBUG
33#   define inline
34#else
35#   define NDEBUG
36#endif
37#include <assert.h>
38/* }}} */
39#define CHECK(x, e) do { if ((x) == NULL) { zend_error(E_ERROR, "XCache: " e); goto err; } } while (0)
40
41int xc_shm_can_readonly(xc_shm_t *shm) /* {{{ */
42{
43    return shm->ptr_ro != NULL;
44}
45/* }}} */
46int xc_shm_is_readwrite(xc_shm_t *shm, const void *p) /* {{{ */
47{
48    return p >= shm->ptr && (char *)p < (char *)shm->ptr + shm->size;
49}
50/* }}} */
51int xc_shm_is_readonly(xc_shm_t *shm, const void *p) /* {{{ */
52{
53    return xc_shm_can_readonly(shm) && p >= shm->ptr_ro && (char *)p < (char *)shm->ptr_ro + shm->size;
54}
55/* }}} */
56void *xc_shm_to_readwrite(xc_shm_t *shm, void *p) /* {{{ */
57{
58    if (shm->diff) {
59        assert(xc_shm_is_readonly(p));
60        p = p - shm->diff;
61    }
62    assert(xc_shm_is_readwrite(p));
63    return p;
64}
65/* }}} */
66void *xc_shm_to_readonly(xc_shm_t *shm, void *p) /* {{{ */
67{
68    assert(xc_shm_is_readwrite(p));
69    if (shm->diff) {
70        p = p + shm->diff;
71        assert(xc_shm_is_readonly(p));
72    }
73    return p;
74}
75/* }}} */
76
77void xc_shm_destroy(xc_shm_t *shm) /* {{{ */
78{
79    if (shm->ptr_ro) {
80        munmap(shm->ptr_ro, shm->size);
81        /*
82        shm->ptr_ro = NULL;
83        */
84    }
85    if (shm->ptr) {
86        /* shm->size depends on shm->ptr */
87        munmap(shm->ptr, shm->size);
88        /*
89        shm->ptr = NULL;
90        */
91    }
92    /*
93    shm->size = NULL;
94    shm->diff = 0;
95    */
96
97    free(shm);
98    return;
99}
100/* }}} */
101xc_shm_t *xc_shm_init(const char *path, xc_shmsize_t size, zend_bool readonly_protection) /* {{{ */
102{
103    xc_shm_t *shm = NULL;
104    int fd;
105    int ro_ok;
106    volatile void *romem;
107    int created = 0;
108
109    CHECK(shm = calloc(1, sizeof(xc_shm_t)), "shm OOM");
110    shm->size = size;
111    if (path == NULL || !path[0]) {
112        path = "/tmp/xcache";
113    }
114    fd = open(path, O_RDWR, S_IRUSR | S_IWUSR);
115    if (fd == -1) {
116        created = 1;
117        fd = open(path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
118        if (fd == -1) {
119            if (created) {
120                unlink(path);
121            }
122            goto err;
123        }
124    }
125    ftruncate(fd, size);
126
127    shm->ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
128    if (shm->ptr == MAP_FAILED) {
129        shm->ptr = NULL;
130        close(fd);
131        if (created) {
132            unlink(path);
133        }
134        goto err;
135    }
136
137    ro_ok = 0;
138    if (readonly_protection) {
139        shm->ptr_ro = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
140        romem = shm->ptr_ro;
141
142        /* {{{ check if ptr_ro works */
143        do {
144            if (shm->ptr_ro == MAP_FAILED || shm->ptr_ro == shm->ptr) {
145                break;
146            }
147            *(char *)shm->ptr = 1;
148            if (*(char *)romem != 1) {
149                break;
150            }
151            *(char *)shm->ptr = 2;
152            if (*(char *)romem != 2) {
153                break;
154            }
155            ro_ok = 1;
156        } while (0);
157    }
158
159    if (ro_ok) {
160        shm->diff = shm->ptr_ro - shm->ptr;
161        assert(abs(shm->diff) >= size);
162    }
163    else {
164        if (shm->ptr_ro != MAP_FAILED) {
165            munmap(shm->ptr_ro, size);
166        }
167        shm->ptr_ro = NULL;
168        shm->diff = 0;
169    }
170    /* }}} */
171
172    close(fd);
173    if (created) {
174        unlink(path);
175    }
176
177    return shm;
178
179err:
180    if (shm) {
181        xc_shm_destroy(shm);
182    }
183    return NULL;
184}
185/* }}} */
186
187void *xc_shm_ptr(xc_shm_t *shm) /* {{{ */
188{
189    return shm->ptr;
190}
191/* }}} */
Note: See TracBrowser for help on using the repository browser.