1
0
Fork 0

reconstruct shm/allocator

git-svn-id: svn://svn.lighttpd.net/xcache/trunk@148 c26eb9a1-5813-0410-bd6c-c2e55f420ca7
1.1
Xuefer 2006-09-09 00:56:44 +00:00
parent a29d074126
commit 42efedb793
15 changed files with 578 additions and 101 deletions

View File

@ -31,8 +31,8 @@ processor.lo: $(XCACHE_PROC_C) $(XCACHE_PROC_H) $(srcdir)/processor.c
$(builddir)/disassembler.lo: $(XCACHE_PROC_H) $(srcdir)/processor.c
disassembler.lo: $(XCACHE_PROC_H) $(srcdir)/processor.c
$(builddir)/xcache.lo: $(XCACHE_PROC_H) $(srcdir)/myshm.h $(srcdir)/stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.c $(srcdir)/foreachcoresig.h
xcache.lo: $(XCACHE_PROC_H) $(srcdir)/myshm.h $(srcdir)/stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.c $(srcdir)/foreachcoresig.h
$(builddir)/xcache.lo: $(XCACHE_PROC_H) $(srcdir)/xc_shm.h $(srcdir)/stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.c $(srcdir)/foreachcoresig.h
xcache.lo: $(XCACHE_PROC_H) $(srcdir)/xc_shm.h $(srcdir)/stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.c $(srcdir)/foreachcoresig.h
xcachesvnclean: clean
cat $(srcdir)/.cvsignore | grep -v Makefile | xargs rm -f

View File

@ -27,6 +27,8 @@ if test "$PHP_XCACHE" != "no"; then
xcache.c \
mmap.c \
mem.c \
xc_malloc.c \
xc_shm.c \
const_string.c \
opcode_spec.c \
stack.c \

View File

@ -15,6 +15,8 @@ if (PHP_XCACHE != "no") {
xcache.c \
mmap.c \
mem.c \
xc_malloc.c \
xc_shm.c \
const_string.c \
opcode_spec.c \
stack.c \

80
mem.c
View File

@ -8,7 +8,9 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "mem.h"
#define XC_SHM_IMPL
#define XC_MEM_IMPL
#include "xc_shm.h"
#include "align.h"
#ifdef TEST
@ -36,6 +38,8 @@ struct _xc_block_t {
};
struct _xc_mem_t {
const xc_mem_handlers_t *handlers;
xc_shm_t *shm;
xc_memsize_t size;
xc_memsize_t avail; /* total free */
xc_block_t headblock[1]; /* just as a pointer to first block*/
@ -74,7 +78,7 @@ static void xc_block_check(xc_block_t *b) /* {{{ */
#endif
void *xc_mem_malloc(xc_mem_t *mem, xc_memsize_t size) /* {{{ */
static XC_MEM_MALLOC(xc_mem_malloc) /* {{{ */
{
xc_block_t *prev, *cur;
xc_block_t *newb, *b;
@ -182,7 +186,7 @@ void *xc_mem_malloc(xc_mem_t *mem, xc_memsize_t size) /* {{{ */
return p;
}
/* }}} */
int xc_mem_free(xc_mem_t *mem, const void *p) /* {{{ return block size freed */
static XC_MEM_FREE(xc_mem_free) /* {{{ return block size freed */
{
xc_block_t *cur, *b;
int size;
@ -236,7 +240,7 @@ int xc_mem_free(xc_mem_t *mem, const void *p) /* {{{ return block size freed */
return size;
}
/* }}} */
void *xc_mem_calloc(xc_mem_t *mem, xc_memsize_t memb, xc_memsize_t size) /* {{{ */
static XC_MEM_CALLOC(xc_mem_calloc) /* {{{ */
{
xc_memsize_t realsize = memb * size;
void *p = xc_mem_malloc(mem, realsize);
@ -247,7 +251,7 @@ void *xc_mem_calloc(xc_mem_t *mem, xc_memsize_t memb, xc_memsize_t size) /* {{{
return p;
}
/* }}} */
void *xc_mem_realloc(xc_mem_t *mem, const void *p, xc_memsize_t size) /* {{{ */
static XC_MEM_REALLOC(xc_mem_realloc) /* {{{ */
{
void *newp = xc_mem_malloc(mem, size);
if (p) {
@ -257,7 +261,7 @@ void *xc_mem_realloc(xc_mem_t *mem, const void *p, xc_memsize_t size) /* {{{ */
return newp;
}
/* }}} */
char *xc_mem_strndup(xc_mem_t *mem, const char *str, xc_memsize_t len) /* {{{ */
static XC_MEM_STRNDUP(xc_mem_strndup) /* {{{ */
{
void *p = xc_mem_malloc(mem, len + 1);
if (p) {
@ -266,56 +270,54 @@ char *xc_mem_strndup(xc_mem_t *mem, const char *str, xc_memsize_t len) /* {{{ */
return p;
}
/* }}} */
char *xc_mem_strdup(xc_mem_t *mem, const char *str) /* {{{ */
static XC_MEM_STRDUP(xc_mem_strdup) /* {{{ */
{
return xc_mem_strndup(mem, str, strlen(str));
}
/* }}} */
xc_memsize_t xc_mem_avail(xc_mem_t *mem) /* {{{ */
static XC_MEM_AVAIL(xc_mem_avail) /* {{{ */
{
return mem->avail;
}
/* }}} */
xc_memsize_t xc_mem_size(xc_mem_t *mem) /* {{{ */
static XC_MEM_SIZE(xc_mem_size) /* {{{ */
{
return mem->size;
}
/* }}} */
const xc_block_t *xc_mem_freeblock_first(xc_mem_t *mem) /* {{{ */
static XC_MEM_FREEBLOCK_FIRST(xc_mem_freeblock_first) /* {{{ */
{
return mem->headblock->next;
}
/* }}} */
const xc_block_t *xc_mem_freeblock_next(const xc_block_t *block) /* {{{ */
XC_MEM_FREEBLOCK_NEXT(xc_mem_freeblock_next) /* {{{ */
{
return block->next;
}
/* }}} */
xc_memsize_t xc_mem_block_size(const xc_block_t *block) /* {{{ */
XC_MEM_BLOCK_SIZE(xc_mem_block_size) /* {{{ */
{
return block->size;
}
/* }}} */
xc_memsize_t xc_mem_block_offset(const xc_mem_t *mem, const xc_block_t *block) /* {{{ */
XC_MEM_BLOCK_OFFSET(xc_mem_block_offset) /* {{{ */
{
return ((char *) block) - ((char *) mem);
}
/* }}} */
xc_mem_t *xc_mem_init(void *ptr, xc_memsize_t size) /* {{{ */
static XC_MEM_INIT(xc_mem_init) /* {{{ */
{
xc_mem_t *mem;
xc_block_t *b;
#define MINSIZE (ALIGN(sizeof(xc_mem_t)) + sizeof(xc_block_t))
/* requires at least the header and 1 tail block */
if (size < MINSIZE) {
fprintf(stderr, "xc_mem_init requires %d bytes at least\n", MINSIZE);
return NULL;
}
mem = (xc_mem_t *) ptr;
mem->shm = shm;
mem->size = size;
mem->avail = size - MINSIZE;
@ -331,7 +333,7 @@ xc_mem_t *xc_mem_init(void *ptr, xc_memsize_t size) /* {{{ */
return mem;
}
/* }}} */
void xc_mem_destroy(xc_mem_t *mem) /* {{{ */
static XC_MEM_DESTROY(xc_mem_destroy) /* {{{ */
{
}
/* }}} */
@ -380,3 +382,45 @@ int main()
}
/* }}} */
#endif
typedef struct {
const char *name;
const xc_mem_handlers_t *handlers;
} xc_mem_scheme_t;
static xc_mem_scheme_t xc_mem_schemes[10];
int xc_mem_scheme_register(const char *name, const xc_mem_handlers_t *handlers) /* {{{ */
{
int i;
for (i = 0; i < 10; i ++) {
if (!xc_mem_schemes[i].name) {
xc_mem_schemes[i].name = name;
xc_mem_schemes[i].handlers = handlers;
return 1;
}
}
return 0;
}
/* }}} */
const xc_mem_handlers_t *xc_mem_scheme_find(const char *name) /* {{{ */
{
int i;
for (i = 0; i < 10 && xc_mem_schemes[i].name; i ++) {
if (strcmp(xc_mem_schemes[i].name, name) == 0) {
return xc_mem_schemes[i].handlers;
}
}
return NULL;
}
/* }}} */
static xc_mem_handlers_t xc_mem_mem_handlers = XC_MEM_HANDLERS(mem);
void xc_shm_mem_init() /* {{{ */
{
memset(xc_mem_schemes, 0, sizeof(xc_mem_schemes));
if (xc_mem_scheme_register("mem", &xc_mem_mem_handlers) == 0) {
zend_error(E_ERROR, "XCache: failed to register mem mem_scheme");
}
}
/* }}} */

74
mem.h
View File

@ -2,19 +2,65 @@ typedef struct _xc_mem_t xc_mem_t;
typedef struct _xc_block_t xc_block_t;
typedef unsigned int xc_memsize_t;
void *xc_mem_malloc(xc_mem_t *mem, xc_memsize_t size);
int xc_mem_free(xc_mem_t *mem, const void *p);
void *xc_mem_calloc(xc_mem_t *mem, xc_memsize_t memb, xc_memsize_t size);
void *xc_mem_realloc(xc_mem_t *mem, const void *p, xc_memsize_t size);
char *xc_mem_strndup(xc_mem_t *mem, const char *str, xc_memsize_t len);
char *xc_mem_strdup(xc_mem_t *mem, const char *str);
const xc_block_t *xc_mem_freeblock_first(xc_mem_t *mem);
const xc_block_t *xc_mem_freeblock_next(const xc_block_t *block);
xc_memsize_t xc_mem_block_size(const xc_block_t *block);
xc_memsize_t xc_mem_block_offset(const xc_mem_t *mem, const xc_block_t *block);
/* shm::mem */
#define XC_MEM_MALLOC(func) void *func(xc_mem_t *mem, xc_memsize_t size)
#define XC_MEM_FREE(func) xc_memsize_t func(xc_mem_t *mem, const void *p)
#define XC_MEM_CALLOC(func) void *func(xc_mem_t *mem, xc_memsize_t memb, xc_memsize_t size)
#define XC_MEM_REALLOC(func) void *func(xc_mem_t *mem, const void *p, xc_memsize_t size)
#define XC_MEM_STRNDUP(func) char *func(xc_mem_t *mem, const char *str, xc_memsize_t len)
#define XC_MEM_STRDUP(func) char *func(xc_mem_t *mem, const char *str)
#define XC_MEM_AVAIL(func) xc_memsize_t func(xc_mem_t *mem)
#define XC_MEM_SIZE(func) xc_memsize_t func(xc_mem_t *mem)
#define XC_MEM_FREEBLOCK_FIRST(func) const xc_block_t *func(xc_mem_t *mem)
#define XC_MEM_FREEBLOCK_NEXT(func) const xc_block_t *func(const xc_block_t *block)
#define XC_MEM_BLOCK_SIZE(func) xc_memsize_t func(const xc_block_t *block)
#define XC_MEM_BLOCK_OFFSET(func) xc_memsize_t func(const xc_mem_t *mem, const xc_block_t *block)
xc_memsize_t xc_mem_avail(xc_mem_t *mem);
xc_memsize_t xc_mem_size(xc_mem_t *mem);
#define XC_MEM_INIT(func) xc_mem_t *func(xc_shm_t *shm, xc_mem_t *mem, xc_memsize_t size)
#define XC_MEM_DESTROY(func) void func(xc_mem_t *mem)
xc_mem_t *xc_mem_init(void *ptr, xc_memsize_t size);
void xc_mem_destroy(xc_mem_t *mem);
#define XC_MEM_HANDLERS(name) { \
xc_##name##_malloc \
, xc_##name##_free \
, xc_##name##_calloc \
, xc_##name##_realloc \
, xc_##name##_strndup \
, xc_##name##_strdup \
, xc_##name##_avail \
, xc_##name##_size \
, xc_##name##_freeblock_first \
, xc_##name##_freeblock_next \
, xc_##name##_block_size \
, xc_##name##_block_offset \
\
, xc_##name##_init \
, xc_##name##_destroy \
}
typedef struct {
XC_MEM_MALLOC((*malloc));
XC_MEM_FREE((*free));
XC_MEM_CALLOC((*calloc));
XC_MEM_REALLOC((*realloc));
XC_MEM_STRNDUP((*strndup));
XC_MEM_STRDUP((*strdup));
XC_MEM_AVAIL((*avail));
XC_MEM_SIZE((*size));
XC_MEM_FREEBLOCK_FIRST((*freeblock_first));
XC_MEM_FREEBLOCK_NEXT((*freeblock_next));
XC_MEM_BLOCK_SIZE((*block_size));
XC_MEM_BLOCK_OFFSET((*block_offset));
XC_MEM_INIT((*init));
XC_MEM_DESTROY((*destroy));
} xc_mem_handlers_t;
#ifndef XC_MEM_IMPL
struct _xc_mem_t {
const xc_mem_handlers_t *handlers;
xc_shm_t *shm;
};
#endif
int xc_mem_scheme_register(const char *name, const xc_mem_handlers_t *handlers);
const xc_mem_handlers_t *xc_mem_scheme_find(const char *name);

59
mmap.c
View File

@ -31,7 +31,8 @@
#endif
#include "php.h"
#include "myshm.h"
#define XC_SHM_IMPL
#include "xc_shm.h"
#ifndef max
#define max(a, b) ((a) < (b) ? (b) : (a))
@ -39,12 +40,14 @@
// {{{ xc_shm_t
struct _xc_shm_t {
xc_shm_handlers_t *handlers;
void *ptr;
void *ptr_ro;
long diff;
xc_shmsize_t size;
char *name;
int newfile;
xc_shmsize_t memoffset;
#ifdef ZEND_WIN32
HANDLE hmap;
HANDLE hmap_ro;
@ -63,43 +66,43 @@ struct _xc_shm_t {
#define PTR_ADD(ptr, v) (((char *) (ptr)) + (v))
#define PTR_SUB(ptr, v) (((char *) (ptr)) - (v))
int xc_shm_can_readonly(xc_shm_t *shm) /* {{{ */
static XC_SHM_CAN_READONLY(xc_mmap_can_readonly) /* {{{ */
{
return shm->ptr_ro != NULL;
}
/* }}} */
int xc_shm_is_readwrite(xc_shm_t *shm, const void *p) /* {{{ */
static XC_SHM_IS_READWRITE(xc_mmap_is_readwrite) /* {{{ */
{
return p >= shm->ptr && (char *)p < (char *)shm->ptr + shm->size;
}
/* }}} */
int xc_shm_is_readonly(xc_shm_t *shm, const void *p) /* {{{ */
static XC_SHM_IS_READONLY(xc_mmap_is_readonly) /* {{{ */
{
return xc_shm_can_readonly(shm) && p >= shm->ptr_ro && (char *)p < (char *)shm->ptr_ro + shm->size;
return xc_mmap_can_readonly(shm) && p >= shm->ptr_ro && (char *)p < (char *)shm->ptr_ro + shm->size;
}
/* }}} */
void *xc_shm_to_readwrite(xc_shm_t *shm, void *p) /* {{{ */
static XC_SHM_TO_READWRITE(xc_mmap_to_readwrite) /* {{{ */
{
if (shm->diff) {
assert(xc_shm_is_readonly(p));
assert(xc_mmap_is_readonly(p));
p = PTR_SUB(p, shm->diff);
}
assert(xc_shm_is_readwrite(p));
assert(xc_mmap_is_readwrite(p));
return p;
}
/* }}} */
void *xc_shm_to_readonly(xc_shm_t *shm, void *p) /* {{{ */
static XC_SHM_TO_READONLY(xc_mmap_to_readonly) /* {{{ */
{
assert(xc_shm_is_readwrite(p));
if (shm->diff) {
p = PTR_ADD(p, shm->diff);
assert(xc_shm_is_readonly(p));
assert(xc_mmap_is_readonly(p));
}
return p;
}
/* }}} */
void xc_shm_destroy(xc_shm_t *shm) /* {{{ */
static XC_SHM_DESTROY(xc_mmap_destroy) /* {{{ */
{
if (shm->ptr_ro) {
munmap(shm->ptr_ro, shm->size);
@ -140,7 +143,7 @@ void xc_shm_destroy(xc_shm_t *shm) /* {{{ */
return;
}
/* }}} */
xc_shm_t *xc_shm_init(const char *path, xc_shmsize_t size, zend_bool readonly_protection) /* {{{ */
static XC_SHM_INIT(xc_mmap_init) /* {{{ */
{
#ifdef ZEND_WIN32
# define TMP_PATH "XCache"
@ -153,6 +156,7 @@ xc_shm_t *xc_shm_init(const char *path, xc_shmsize_t size, zend_bool readonly_pr
volatile void *romem;
char tmpname[sizeof(TMP_PATH) - 1 + 100];
const char *errstr = NULL;
const char *path = (const char *) arg1;
CHECK(shm = calloc(1, sizeof(xc_shm_t)), "shm OOM");
shm->size = size;
@ -272,7 +276,7 @@ err:
close(fd);
}
if (shm) {
xc_shm_destroy(shm);
xc_mmap_destroy(shm);
}
if (errstr) {
fprintf(stderr, "%s\n", errstr);
@ -282,8 +286,33 @@ err:
}
/* }}} */
void *xc_shm_ptr(xc_shm_t *shm) /* {{{ */
static XC_SHM_MEMINIT(xc_mmap_meminit) /* {{{ */
{
return shm->ptr;
xc_mem_t *mem;
if (shm->memoffset + size > shm->size) {
zend_error(E_ERROR, "XCache: internal error at %s#%d", __FILE__, __LINE__);
return NULL;
}
mem = (xc_mem_t *) PTR_ADD(shm->ptr, shm->memoffset);
shm->memoffset += size;
mem->handlers = shm->handlers->memhandlers;
mem->handlers->init(shm, mem, size);
return mem;
}
/* }}} */
static XC_SHM_MEMDESTROY(xc_mmap_memdestroy) /* {{{ */
{
}
/* }}} */
static xc_shm_handlers_t xc_shm_mmap_handlers = XC_SHM_HANDLERS(mmap);
void xc_shm_mmap_register() /* {{{ */
{
CHECK(xc_shm_mmap_handlers.memhandlers = xc_mem_scheme_find("mem"), "cannot find mem handlers");
if (xc_shm_scheme_register("mmap", &xc_shm_mmap_handlers) == 0) {
zend_error(E_ERROR, "XCache: failed to register mmap shm_scheme");
}
err:
return;
}
/* }}} */

13
myshm.h
View File

@ -1,13 +0,0 @@
typedef struct _xc_shm_t xc_shm_t;
typedef size_t xc_shmsize_t;
int xc_shm_can_readonly(xc_shm_t *shm);
int xc_shm_is_readwrite(xc_shm_t *shm, const void *p);
int xc_shm_is_readonly(xc_shm_t *shm, const void *p);
void *xc_shm_to_readwrite(xc_shm_t *shm, void *p);
void *xc_shm_to_readonly(xc_shm_t *shm, void *p);
void *xc_shm_ptr(xc_shm_t *shm);
xc_shm_t *xc_shm_init(const char *path, xc_shmsize_t size, zend_bool readonly_protection);
void xc_shm_destroy(xc_shm_t *shm);

View File

@ -287,7 +287,7 @@ xc_entry_t *xc_processor_store_xc_entry_t(xc_entry_t *src TSRMLS_DC) {
}
/* mem :) */
processor.p = (char *)xc_mem_malloc(src->cache->mem, processor.size);
processor.p = (char *) src->cache->mem->handlers->malloc(src->cache->mem, processor.size);
if (processor.p == NULL) {
dst = NULL;
goto err_alloc;

View File

@ -117,11 +117,11 @@ dnl }}}
dnl {{{ FIXPOINTER
define(`FIXPOINTER', `FIXPOINTER_EX(`$1', `dst->$2')')
define(`FIXPOINTER_EX', `IFSTORE(`
$2 = ($1 *) xc_shm_to_readonly(processor->xce_src->cache->shm, (char *)$2);
$2 = ($1 *) processor->xce_src->cache->shm->handlers->to_readonly(processor->xce_src->cache->shm, (char *)$2);
')')
define(`UNFIXPOINTER', `UNFIXPOINTER_EX(`$1', `dst->$2')')
define(`UNFIXPOINTER_EX', `IFSTORE(`
$2 = ($1 *) xc_shm_to_readwrite(processor->xce_src->cache->shm, (char *)$2);
$2 = ($1 *) processor->xce_src->cache->shm->handlers->to_readwrite(processor->xce_src->cache->shm, (char *)$2);
')')
dnl }}}
dnl {{{ COPY

View File

@ -403,8 +403,6 @@ static void xc_sandbox_install(xc_sandbox_t *sandbox TSRMLS_DC) /* {{{ */
{
int i;
Bucket *b;
zend_llist_position lpos;
zend_file_handle *handle;
#ifdef HAVE_XCACHE_CONSTANT
b = TG(zend_constants).pListHead;

212
xc_malloc.c Normal file
View File

@ -0,0 +1,212 @@
#define XC_SHM_IMPL
#define XC_MEM_IMPL
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "xc_shm.h"
#include "php.h"
#include "align.h"
struct _xc_mem_t {
const xc_mem_handlers_t *handlers;
xc_shm_t *shm;
xc_memsize_t size;
xc_memsize_t avail; /* total free */
};
#define CHECK(x, e) do { if ((x) == NULL) { zend_error(E_ERROR, "XCache: " e); goto err; } } while (0)
static XC_MEM_MALLOC(xc_malloc_malloc) /* {{{ */
{
return malloc(size);
}
/* }}} */
static XC_MEM_FREE(xc_malloc_free) /* {{{ return block size freed */
{
free((void *) p);
return 0;
}
/* }}} */
static XC_MEM_CALLOC(xc_malloc_calloc) /* {{{ */
{
return calloc(memb, size);
}
/* }}} */
static XC_MEM_REALLOC(xc_malloc_realloc) /* {{{ */
{
return realloc((void *) p, size);
}
/* }}} */
static XC_MEM_STRNDUP(xc_malloc_strndup) /* {{{ */
{
char *p = malloc(len);
if (!p) {
return NULL;
}
return memcpy(p, str, len);
}
/* }}} */
static XC_MEM_STRDUP(xc_malloc_strdup) /* {{{ */
{
return xc_malloc_strndup(mem, str, strlen(str) + 1);
}
/* }}} */
static XC_MEM_AVAIL(xc_malloc_avail) /* {{{ */
{
return mem->avail;
}
/* }}} */
static XC_MEM_SIZE(xc_malloc_size) /* {{{ */
{
return mem->size;
}
/* }}} */
static XC_MEM_FREEBLOCK_FIRST(xc_malloc_freeblock_first) /* {{{ */
{
return (void *) -1;
}
/* }}} */
XC_MEM_FREEBLOCK_NEXT(xc_malloc_freeblock_next) /* {{{ */
{
return NULL;
}
/* }}} */
XC_MEM_BLOCK_SIZE(xc_malloc_block_size) /* {{{ */
{
return 0;
}
/* }}} */
XC_MEM_BLOCK_OFFSET(xc_malloc_block_offset) /* {{{ */
{
return 0;
}
/* }}} */
static XC_MEM_INIT(xc_mem_malloc_init) /* {{{ */
{
xc_block_t *b;
#define MINSIZE (ALIGN(sizeof(xc_mem_t)))
/* requires at least the header and 1 tail block */
if (size < MINSIZE) {
fprintf(stderr, "xc_mem_malloc_init requires %d bytes at least\n", MINSIZE);
return NULL;
}
mem->shm = shm;
mem->size = size;
mem->avail = size - MINSIZE;
#undef MINSIZE
return mem;
}
/* }}} */
static XC_MEM_DESTROY(xc_mem_malloc_destroy) /* {{{ */
{
}
/* }}} */
// {{{ xc_shm_t
struct _xc_shm_t {
xc_shm_handlers_t *handlers;
xc_shmsize_t size;
xc_shmsize_t memoffset;
};
#undef NDEBUG
#ifdef ALLOC_DEBUG
# define inline
#else
# define NDEBUG
#endif
#include <assert.h>
/* }}} */
static XC_SHM_CAN_READONLY(xc_malloc_can_readonly) /* {{{ */
{
return 0;
}
/* }}} */
static XC_SHM_IS_READWRITE(xc_malloc_is_readwrite) /* {{{ */
{
return 0;
}
/* }}} */
static XC_SHM_IS_READONLY(xc_malloc_is_readonly) /* {{{ */
{
return 0;
}
/* }}} */
static XC_SHM_TO_READWRITE(xc_malloc_to_readwrite) /* {{{ */
{
return p;
}
/* }}} */
static XC_SHM_TO_READONLY(xc_malloc_to_readonly) /* {{{ */
{
return p;
}
/* }}} */
static XC_SHM_DESTROY(xc_malloc_destroy) /* {{{ */
{
free(shm);
return;
}
/* }}} */
static XC_SHM_INIT(xc_malloc_init) /* {{{ */
{
xc_shm_t *shm;
CHECK(shm = calloc(1, sizeof(xc_shm_t)), "shm OOM");
shm->size = size;
return shm;
err:
return NULL;
}
/* }}} */
static XC_SHM_MEMINIT(xc_malloc_meminit) /* {{{ */
{
xc_mem_t *mem;
if (shm->memoffset + size > shm->size) {
zend_error(E_ERROR, "XCache: internal error at %s#%d", __FILE__, __LINE__);
return NULL;
}
shm->memoffset += size;
CHECK(mem = calloc(1, sizeof(xc_mem_t)), "mem OOM");
mem->handlers = shm->handlers->memhandlers;
mem->handlers->init(shm, mem, size);
return mem;
err:
return NULL;
}
/* }}} */
static XC_SHM_MEMDESTROY(xc_malloc_memdestroy) /* {{{ */
{
mem->handlers->destroy(mem);
free(mem);
}
/* }}} */
#define xc_malloc_destroy xc_mem_malloc_destroy
#define xc_malloc_init xc_mem_malloc_init
static xc_mem_handlers_t xc_mem_malloc_handlers = XC_MEM_HANDLERS(malloc);
#undef xc_malloc_init
#undef xc_malloc_destroy
static xc_shm_handlers_t xc_shm_malloc_handlers = XC_SHM_HANDLERS(malloc);
void xc_shm_malloc_register() /* {{{ */
{
if (xc_mem_scheme_register("malloc", &xc_mem_malloc_handlers) == 0) {
zend_error(E_ERROR, "XCache: failed to register malloc mem_scheme");
}
CHECK(xc_shm_malloc_handlers.memhandlers = xc_mem_scheme_find("malloc"), "cannot find malloc handlers");
if (xc_shm_scheme_register("malloc", &xc_shm_malloc_handlers) == 0) {
zend_error(E_ERROR, "XCache: failed to register malloc shm_scheme");
}
err:
return;
}
/* }}} */

76
xc_shm.c Normal file
View File

@ -0,0 +1,76 @@
#ifdef TEST
#include <limits.h>
#include <stdio.h>
#else
#include <php.h>
#endif
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "xc_shm.h"
typedef struct {
const char *name;
const xc_shm_handlers_t *handlers;
} xc_shm_scheme_t;
static xc_shm_scheme_t xc_shm_schemes[10];
void xc_shm_init_modules() /* {{{ */
{
memset(xc_shm_schemes, 0, sizeof(xc_shm_schemes));
extern void xc_shm_mem_init();
xc_shm_mem_init();
extern void xc_shm_malloc_register();
xc_shm_malloc_register();
extern void xc_shm_mmap_register();
xc_shm_mmap_register();
}
/* }}} */
int xc_shm_scheme_register(const char *name, const xc_shm_handlers_t *handlers) /* {{{ */
{
int i;
for (i = 0; i < 10; i ++) {
if (!xc_shm_schemes[i].name) {
xc_shm_schemes[i].name = name;
xc_shm_schemes[i].handlers = handlers;
return 1;
}
}
return 0;
}
/* }}} */
const xc_shm_handlers_t *xc_shm_scheme_find(const char *name) /* {{{ */
{
int i;
for (i = 0; i < 10 && xc_shm_schemes[i].name; i ++) {
if (strcmp(xc_shm_schemes[i].name, name) == 0) {
return xc_shm_schemes[i].handlers;
}
}
return NULL;
}
/* }}} */
xc_shm_t *xc_shm_init(const char *type, xc_shmsize_t size, int readonly_protection, const void *arg1, const void *arg2) /* {{{ */
{
const xc_shm_handlers_t *handlers = xc_shm_scheme_find(type);
if (handlers) {
xc_shm_t *shm = handlers->init(size, readonly_protection, arg1, arg2);
if (shm) {
shm->handlers = handlers;
}
return shm;
}
return NULL;
}
/* }}} */
void xc_shm_destroy(xc_shm_t *shm) /* {{{ */
{
shm->handlers->destroy(shm);
}
/* }}} */

60
xc_shm.h Normal file
View File

@ -0,0 +1,60 @@
typedef struct _xc_shm_t xc_shm_t;
typedef size_t xc_shmsize_t;
#include "mem.h"
/* shm */
#define XC_SHM_CAN_READONLY(func) int func(xc_shm_t *shm)
#define XC_SHM_IS_READWRITE(func) int func(xc_shm_t *shm, const void *p)
#define XC_SHM_IS_READONLY(func) int func(xc_shm_t *shm, const void *p)
#define XC_SHM_TO_READWRITE(func) void *func(xc_shm_t *shm, void *p)
#define XC_SHM_TO_READONLY(func) void *func(xc_shm_t *shm, void *p)
#define XC_SHM_INIT(func) xc_shm_t *func(xc_shmsize_t size, int readonly_protection, const void *arg1, const void *arg2)
#define XC_SHM_DESTROY(func) void func(xc_shm_t *shm)
#define XC_SHM_MEMINIT(func) xc_mem_t *func(xc_shm_t *shm, xc_memsize_t size)
#define XC_SHM_MEMDESTROY(func) void func(xc_mem_t *mem)
#define XC_SHM_HANDLERS(name) { \
NULL \
, xc_##name##_can_readonly \
, xc_##name##_is_readwrite \
, xc_##name##_is_readonly \
, xc_##name##_to_readwrite \
, xc_##name##_to_readonly \
\
, xc_##name##_init \
, xc_##name##_destroy \
\
, xc_##name##_meminit \
, xc_##name##_memdestroy \
}
typedef struct {
const xc_mem_handlers_t *memhandlers;
XC_SHM_CAN_READONLY((*can_readonly));
XC_SHM_IS_READWRITE((*is_readwrite));
XC_SHM_IS_READONLY((*is_readonly));
XC_SHM_TO_READWRITE((*to_readwrite));
XC_SHM_TO_READONLY((*to_readonly));
XC_SHM_INIT((*init));
XC_SHM_DESTROY((*destroy));
XC_SHM_MEMINIT((*meminit));
XC_SHM_MEMDESTROY((*memdestroy));
} xc_shm_handlers_t;
#ifndef XC_SHM_IMPL
struct _xc_shm_t {
const xc_shm_handlers_t *handlers;
};
#endif
void xc_shm_init_modules();
int xc_shm_scheme_register(const char *name, const xc_shm_handlers_t *handlers);
const xc_shm_handlers_t *xc_shm_scheme_find(const char *name);
xc_shm_t *xc_shm_init(const char *type, xc_shmsize_t size, int readonly_protection, const void *arg1, const void *arg2);
void xc_shm_destroy(xc_shm_t *shm);

View File

@ -67,6 +67,7 @@
/* }}} */
/* {{{ globals */
static char *xc_shm_scheme = NULL;
static char *xc_mmap_path = NULL;
static char *xc_coredump_dir = NULL;
@ -150,7 +151,7 @@ static inline int xc_entry_equal_dmz(xc_entry_t *a, xc_entry_t *b) /* {{{ */
/* }}} */
static void xc_entry_free_real_dmz(volatile xc_entry_t *xce) /* {{{ */
{
xc_mem_free(xce->cache->mem, (xc_entry_t *)xce);
xce->cache->mem->handlers->free(xce->cache->mem, (xc_entry_t *)xce);
}
/* }}} */
static void xc_entry_add_dmz(xc_entry_t *xce) /* {{{ */
@ -252,7 +253,6 @@ typedef XC_ENTRY_APPLY_FUNC((*cache_apply_dmz_func_t));
static void xc_entry_apply_dmz(xc_cache_t *cache, cache_apply_dmz_func_t apply_func TSRMLS_DC) /* {{{ */
{
xc_entry_t *p, **pp;
xc_entry_t *next;
int i, c;
for (i = 0, c = cache->hentry->size; i < c; i ++) {
@ -394,6 +394,7 @@ static void xc_fillinfo_dmz(int cachetype, xc_cache_t *cache, zval *return_value
xc_memsize_t avail = 0;
#endif
xc_mem_t *mem = cache->mem;
const xc_mem_handlers_t *handlers = mem->handlers;
zend_ulong interval = (cachetype == XC_TYPE_PHP) ? xc_php_gc_interval : xc_var_gc_interval;
add_assoc_long_ex(return_value, ZEND_STRS("slots"), cache->hentry->size);
@ -415,25 +416,25 @@ static void xc_fillinfo_dmz(int cachetype, xc_cache_t *cache, zval *return_value
MAKE_STD_ZVAL(blocks);
array_init(blocks);
add_assoc_long_ex(return_value, ZEND_STRS("size"), xc_mem_size(mem));
add_assoc_long_ex(return_value, ZEND_STRS("avail"), xc_mem_avail(mem));
add_assoc_long_ex(return_value, ZEND_STRS("size"), handlers->size(mem));
add_assoc_long_ex(return_value, ZEND_STRS("avail"), handlers->avail(mem));
add_assoc_bool_ex(return_value, ZEND_STRS("can_readonly"), xc_readonly_protection);
for (b = xc_mem_freeblock_first(mem); b; b = xc_mem_freeblock_next(b)) {
for (b = handlers->freeblock_first(mem); b; b = handlers->freeblock_next(b)) {
zval *bi;
MAKE_STD_ZVAL(bi);
array_init(bi);
add_assoc_long_ex(bi, ZEND_STRS("size"), xc_mem_block_size(b));
add_assoc_long_ex(bi, ZEND_STRS("offset"), xc_mem_block_offset(mem, b));
add_assoc_long_ex(bi, ZEND_STRS("size"), handlers->block_size(b));
add_assoc_long_ex(bi, ZEND_STRS("offset"), handlers->block_offset(mem, b));
add_next_index_zval(blocks, bi);
#ifndef NDEBUG
avail += xc_mem_block_size(b);
avail += handlers->block_size(b);
#endif
}
add_assoc_zval_ex(return_value, ZEND_STRS("free_blocks"), blocks);
assert(avail == xc_mem_avail(mem));
assert(avail == handlers->avail(mem));
}
/* }}} */
static void xc_fillentry_dmz(xc_entry_t *entry, int del, zval *list TSRMLS_DC) /* {{{ */
@ -1024,17 +1025,20 @@ restore:
/* gdb helper functions, but N/A for coredump */
int xc_is_rw(const void *p) /* {{{ */
{
xc_shm_t *shm;
int i;
if (!xc_initized) {
return 0;
}
for (i = 0; i < xc_php_hcache.size; i ++) {
if (xc_shm_is_readwrite(xc_php_caches[i]->shm, p)) {
shm = xc_php_caches[i]->shm;
if (shm->handlers->is_readwrite(shm, p)) {
return 1;
}
}
for (i = 0; i < xc_var_hcache.size; i ++) {
if (xc_shm_is_readwrite(xc_var_caches[i]->shm, p)) {
shm = xc_var_caches[i]->shm;
if (shm->handlers->is_readwrite(shm, p)) {
return 1;
}
}
@ -1043,17 +1047,20 @@ int xc_is_rw(const void *p) /* {{{ */
/* }}} */
int xc_is_ro(const void *p) /* {{{ */
{
xc_shm_t *shm;
int i;
if (!xc_initized) {
return 0;
}
for (i = 0; i < xc_php_hcache.size; i ++) {
if (xc_shm_is_readonly(xc_php_caches[i]->shm, p)) {
shm = xc_php_caches[i]->shm;
if (shm->handlers->is_readonly(shm, p)) {
return 1;
}
}
for (i = 0; i < xc_var_hcache.size; i ++) {
if (xc_shm_is_readonly(xc_var_caches[i]->shm, p)) {
shm = xc_var_caches[i]->shm;
if (shm->handlers->is_readonly(shm, p)) {
return 1;
}
}
@ -1127,11 +1134,11 @@ static xc_shm_t *xc_cache_destroy(xc_cache_t **caches, xc_hash_t *hcache) /* {{{
}
/* do NOT free
if (cache->entries) {
xc_mem_free(cache->mem, cache->entries);
cache->mem->handlers->free(cache->mem, cache->entries);
}
xc_mem_free(cache->mem, cache);
cache->mem->handlers->free(cache->mem, cache);
*/
xc_mem_destroy(cache->mem);
shm->handlers->memdestroy(cache->mem);
shm = cache->shm;
}
}
@ -1139,7 +1146,7 @@ static xc_shm_t *xc_cache_destroy(xc_cache_t **caches, xc_hash_t *hcache) /* {{{
return shm;
}
/* }}} */
static xc_cache_t **xc_cache_init(xc_shm_t *shm, char *ptr, xc_hash_t *hcache, xc_hash_t *hentry, xc_shmsize_t shmsize) /* {{{ */
static xc_cache_t **xc_cache_init(xc_shm_t *shm, xc_hash_t *hcache, xc_hash_t *hentry, xc_shmsize_t shmsize) /* {{{ */
{
xc_cache_t **caches = NULL, *cache;
xc_mem_t *mem;
@ -1163,10 +1170,9 @@ static xc_cache_t **xc_cache_init(xc_shm_t *shm, char *ptr, xc_hash_t *hcache, x
CHECK(caches = calloc(hcache->size, sizeof(xc_cache_t *)), "caches OOM");
for (i = 0; i < hcache->size; i ++) {
CHECK(mem = xc_mem_init(ptr, memsize), "Failed init memory allocator");
ptr += memsize;
CHECK(cache = xc_mem_calloc(mem, 1, sizeof(xc_cache_t)), "cache OOM");
CHECK(cache->entries = xc_mem_calloc(mem, hentry->size, sizeof(xc_entry_t*)), "entries OOM");
CHECK(mem = shm->handlers->meminit(shm, memsize), "Failed init memory allocator");
CHECK(cache = mem->handlers->calloc(mem, 1, sizeof(xc_cache_t)), "cache OOM");
CHECK(cache->entries = mem->handlers->calloc(mem, hentry->size, sizeof(xc_entry_t*)), "entries OOM");
CHECK(cache->lck = xc_lock_init(NULL), "can't create lock");
cache->hcache = hcache;
@ -1178,7 +1184,6 @@ static xc_cache_t **xc_cache_init(xc_shm_t *shm, char *ptr, xc_hash_t *hcache, x
cache->last_gc_expires = now;
caches[i] = cache;
}
assert(ptr <= (char*)xc_shm_ptr(shm) + shmsize);
return caches;
err:
@ -1213,27 +1218,24 @@ static void xc_destroy() /* {{{ */
static int xc_init(int module_number TSRMLS_DC) /* {{{ */
{
xc_shm_t *shm;
char *ptr;
xc_php_caches = xc_var_caches = NULL;
if (xc_php_size || xc_var_size) {
CHECK(shm = xc_shm_init(xc_mmap_path, ALIGN(xc_php_size) + ALIGN(xc_var_size), xc_readonly_protection), "Cannot create shm");
if (!xc_shm_can_readonly(shm)) {
CHECK(shm = xc_shm_init(xc_shm_scheme, ALIGN(xc_php_size) + ALIGN(xc_var_size), xc_readonly_protection, xc_mmap_path, NULL), "Cannot create shm");
if (!shm->handlers->can_readonly(shm)) {
xc_readonly_protection = 0;
}
ptr = (char *)xc_shm_ptr(shm);
if (xc_php_size) {
origin_compile_file = zend_compile_file;
zend_compile_file = xc_compile_file;
CHECK(xc_php_caches = xc_cache_init(shm, ptr, &xc_php_hcache, &xc_php_hentry, xc_php_size), "failed init opcode cache");
ptr += ALIGN(xc_php_size);
CHECK(xc_php_caches = xc_cache_init(shm, &xc_php_hcache, &xc_php_hentry, xc_php_size), "failed init opcode cache");
}
if (xc_var_size) {
CHECK(xc_var_caches = xc_cache_init(shm, ptr, &xc_var_hcache, &xc_var_hentry, xc_var_size), "failed init variable cache");
CHECK(xc_var_caches = xc_cache_init(shm, &xc_var_hcache, &xc_var_hentry, xc_var_size), "failed init variable cache");
}
}
return 1;
@ -2114,7 +2116,7 @@ PHP_INI_BEGIN()
#endif
PHP_INI_END()
/* }}} */
static int xc_config_long_disp(char *name, char *default_value) /* {{{ */
static int xc_config_string_disp(char *name, char *default_value) /* {{{ */
{
char *value;
char buf[100];
@ -2130,7 +2132,8 @@ static int xc_config_long_disp(char *name, char *default_value) /* {{{ */
return SUCCESS;
}
/* }}} */
#define xc_config_hash_disp xc_config_long_disp
#define xc_config_hash_disp xc_config_string_disp
#define xc_config_long_disp xc_config_string_disp
/* {{{ PHP_MINFO_FUNCTION(xcache) */
static PHP_MINFO_FUNCTION(xcache)
{
@ -2138,7 +2141,7 @@ static PHP_MINFO_FUNCTION(xcache)
char *ptr;
php_info_print_table_start();
php_info_print_table_header(2, "XCache Support", XCACHE_MODULES);
php_info_print_table_header(2, "XCache Support", "enabled");
php_info_print_table_row(2, "Version", XCACHE_VERSION);
php_info_print_table_row(2, "Modules Built", XCACHE_MODULES);
php_info_print_table_row(2, "Readonly Protection", xc_readonly_protection ? "enabled" : "N/A");
@ -2168,6 +2171,7 @@ static PHP_MINFO_FUNCTION(xcache)
php_info_print_table_start();
php_info_print_table_header(2, "Directive ", "Value");
xc_config_string_disp("xcache.shm_scheme", "mmap");
xc_config_long_disp("xcache.size", "0");
xc_config_hash_disp("xcache.count", "1");
xc_config_hash_disp("xcache.slots", "8K");
@ -2249,6 +2253,18 @@ static int xc_config_long(zend_ulong *p, char *name, char *default_value) /* {{{
return SUCCESS;
}
/* }}} */
static int xc_config_string(char **p, char *name, char *default_value) /* {{{ */
{
char *value;
if (cfg_get_string(name, &value) != SUCCESS) {
value = default_value;
}
*p = strdup(value);
return SUCCESS;
}
/* }}} */
/* {{{ PHP_MINIT_FUNCTION(xcache) */
static PHP_MINIT_FUNCTION(xcache)
{
@ -2277,6 +2293,7 @@ static PHP_MINIT_FUNCTION(xcache)
}
}
xc_config_string(&xc_shm_scheme, "xcache.shm_scheme", "mmap");
xc_config_long(&xc_php_size, "xcache.size", "0");
xc_config_hash(&xc_php_hcache, "xcache.count", "1");
xc_config_hash(&xc_php_hentry, "xcache.slots", "8K");
@ -2301,6 +2318,7 @@ static PHP_MINIT_FUNCTION(xcache)
}
xc_init_constant(module_number TSRMLS_CC);
xc_shm_init_modules();
if ((xc_php_size || xc_var_size) && xc_mmap_path && xc_mmap_path[0]) {
if (!xc_init(module_number TSRMLS_CC)) {
@ -2331,6 +2349,10 @@ static PHP_MSHUTDOWN_FUNCTION(xcache)
pefree(xc_mmap_path, 1);
xc_mmap_path = NULL;
}
if (xc_shm_scheme) {
pefree(xc_shm_scheme, 1);
xc_shm_scheme = NULL;
}
#ifdef HAVE_XCACHE_COVERAGER
xc_coverager_destroy();

View File

@ -15,8 +15,7 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "myshm.h"
#include "mem.h"
#include "xc_shm.h"
#include "lock.h"
#ifndef ZEND_WIN32