fixes #323: refix locking impl for threaded env
git-svn-id: svn://svn.lighttpd.net/xcache/trunk@1366 c26eb9a1-5813-0410-bd6c-c2e55f420ca73.1
parent
2c719b5b6a
commit
1267e8bb4f
@ -1,25 +1,25 @@
|
||||
$(XCACHE_INCLUDES_I) includes.lo $(builddir)/includes.lo: $(srcdir)/mod_cacher/xc_cache.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h
|
||||
$(XCACHE_INCLUDES_I) includes.lo $(builddir)/includes.lo: $(srcdir)/mod_cacher/xc_cache.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h
|
||||
mod_assembler/xc_assembler.lo $(builddir)/mod_assembler/xc_assembler.lo:
|
||||
mod_cacher/xc_cacher.lo $(builddir)/mod_cacher/xc_cacher.lo: $(srcdir)/mod_cacher/xc_cache.h $(srcdir)/mod_cacher/xc_cacher.h $(srcdir)/util/xc_align.h $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/util/xc_vector.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_sandbox.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(XCACHE_PROC_H)
|
||||
mod_coverager/xc_coverager.lo $(builddir)/mod_coverager/xc_coverager.lo: $(srcdir)/mod_coverager/xc_coverager.h $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h
|
||||
mod_cacher/xc_cacher.lo $(builddir)/mod_cacher/xc_cacher.lo: $(srcdir)/mod_cacher/xc_cache.h $(srcdir)/mod_cacher/xc_cacher.h $(srcdir)/util/xc_align.h $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/util/xc_vector.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_sandbox.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(XCACHE_PROC_H)
|
||||
mod_coverager/xc_coverager.lo $(builddir)/mod_coverager/xc_coverager.lo: $(srcdir)/mod_coverager/xc_coverager.h $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h
|
||||
mod_decoder/xc_decoder.lo $(builddir)/mod_decoder/xc_decoder.lo:
|
||||
mod_disassembler/xc_disassembler.lo $(builddir)/mod_disassembler/xc_disassembler.lo: $(srcdir)/mod_disassembler/xc_disassembler.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_sandbox.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(XCACHE_PROC_H)
|
||||
mod_disassembler/xc_disassembler.lo $(builddir)/mod_disassembler/xc_disassembler.lo: $(srcdir)/mod_disassembler/xc_disassembler.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_sandbox.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(XCACHE_PROC_H)
|
||||
mod_encoder/xc_encoder.lo $(builddir)/mod_encoder/xc_encoder.lo:
|
||||
mod_optimizer/xc_optimizer.lo $(builddir)/mod_optimizer/xc_optimizer.lo: $(srcdir)/mod_optimizer/xc_optimizer.h $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(XCACHE_PROC_H)
|
||||
mod_optimizer/xc_optimizer.lo $(builddir)/mod_optimizer/xc_optimizer.lo: $(srcdir)/mod_optimizer/xc_optimizer.h $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(XCACHE_PROC_H)
|
||||
util/xc_stack.lo $(builddir)/util/xc_stack.lo: $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h
|
||||
util/xc_trace.lo $(builddir)/util/xc_trace.lo: $(srcdir)/util/xc_trace.h
|
||||
xcache.lo $(builddir)/xcache.lo: $(srcdir)/util/xc_foreachcoresig.h $(srcdir)/util/xc_stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(XCACHE_PROC_H)
|
||||
xcache.lo $(builddir)/xcache.lo: $(srcdir)/util/xc_foreachcoresig.h $(srcdir)/util/xc_stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_ini.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h $(XCACHE_PROC_H)
|
||||
xcache/xc_allocator_bestfit.lo $(builddir)/xcache/xc_allocator_bestfit.lo: $(srcdir)/util/xc_align.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache/xc_allocator.h $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_allocator.lo $(builddir)/xcache/xc_allocator.lo: $(srcdir)/xcache/xc_allocator.h $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_compatibility.lo $(builddir)/xcache/xc_compatibility.lo: $(srcdir)/xcache/xc_compatibility.h
|
||||
xcache/xc_const_string.lo $(builddir)/xcache/xc_const_string.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_const_string_opcodes_php4.x.h $(srcdir)/xcache/xc_const_string_opcodes_php5.0.h $(srcdir)/xcache/xc_const_string_opcodes_php5.1.h $(srcdir)/xcache/xc_const_string_opcodes_php5.2.h $(srcdir)/xcache/xc_const_string_opcodes_php5.3.h $(srcdir)/xcache/xc_const_string_opcodes_php5.4.h $(srcdir)/xcache/xc_const_string_opcodes_php5.5.h $(srcdir)/xcache/xc_const_string_opcodes_php6.x.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_extension.lo $(builddir)/xcache/xc_extension.lo: $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_const_string.lo $(builddir)/xcache/xc_const_string.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_const_string_opcodes_php4.x.h $(srcdir)/xcache/xc_const_string_opcodes_php5.0.h $(srcdir)/xcache/xc_const_string_opcodes_php5.1.h $(srcdir)/xcache/xc_const_string_opcodes_php5.2.h $(srcdir)/xcache/xc_const_string_opcodes_php5.3.h $(srcdir)/xcache/xc_const_string_opcodes_php5.4.h $(srcdir)/xcache/xc_const_string_opcodes_php5.5.h $(srcdir)/xcache/xc_const_string_opcodes_php6.x.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_extension.lo $(builddir)/xcache/xc_extension.lo: $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_extension.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_ini.lo $(builddir)/xcache/xc_ini.lo: $(srcdir)/xcache/xc_ini.h
|
||||
xcache/xc_lock.lo $(builddir)/xcache/xc_lock.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_malloc.lo $(builddir)/xcache/xc_malloc.lo: $(srcdir)/util/xc_align.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_allocator.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_opcode_spec.lo $(builddir)/xcache/xc_opcode_spec.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_opcode_spec_def.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_malloc.lo $(builddir)/xcache/xc_malloc.lo: $(srcdir)/util/xc_align.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_allocator.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_mutex.lo $(builddir)/xcache/xc_mutex.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_opcode_spec.lo $(builddir)/xcache/xc_opcode_spec.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_const_string.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_opcode_spec_def.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_processor.lo $(builddir)/xcache/xc_processor.lo: $(XCACHE_PROC_C)
|
||||
xcache/xc_sandbox.lo $(builddir)/xcache/xc_sandbox.lo: $(srcdir)/util/xc_stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_sandbox.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h
|
||||
xcache/xc_sandbox.lo $(builddir)/xcache/xc_sandbox.lo: $(srcdir)/util/xc_stack.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_sandbox.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h
|
||||
xcache/xc_shm.lo $(builddir)/xcache/xc_shm.lo: $(srcdir)/xcache/xc_shm.h
|
||||
xcache/xc_shm_mmap.lo $(builddir)/xcache/xc_shm_mmap.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h
|
||||
xcache/xc_utils.lo $(builddir)/xcache/xc_utils.lo: $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_lock.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h
|
||||
xcache/xc_shm_mmap.lo $(builddir)/xcache/xc_shm_mmap.lo: $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h
|
||||
xcache/xc_utils.lo $(builddir)/xcache/xc_utils.lo: $(srcdir)/util/xc_stack.h $(srcdir)/util/xc_trace.h $(srcdir)/xcache_globals.h $(srcdir)/xcache.h $(srcdir)/xcache/xc_compatibility.h $(srcdir)/xcache/xc_mutex.h $(srcdir)/xcache/xc_opcode_spec.h $(srcdir)/xcache/xc_shm.h $(srcdir)/xcache/xc_utils.h
|
||||
|
@ -1,373 +0,0 @@
|
||||
#include "xc_lock.h"
|
||||
#include "xcache.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef ZEND_WIN32
|
||||
# include <process.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <fcntl.h>
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
/* {{{ detect what type of lock is needed */
|
||||
#ifdef ZTS
|
||||
# define XC_LOCK_NEED_TS
|
||||
#endif
|
||||
|
||||
#ifndef ZEND_WIN32
|
||||
# define XC_LOCK_NEED_INTERPROCESS
|
||||
#endif
|
||||
|
||||
#if defined(XC_LOCK_NEED_TS) && defined(XC_LOCK_NEED_INTERPROCESS)
|
||||
/* allow switching off interprocess support */
|
||||
# define XC_LOCK_HAVE_INTERPROCESS_SWITCH
|
||||
#endif
|
||||
/* }}} */
|
||||
|
||||
/* {{{ detect which lock is needed */
|
||||
#if defined(XC_LOCK_NEED_TS) && defined(XC_LOCK_NEED_INTERPROCESS)
|
||||
# ifdef PTHREADS
|
||||
# define XC_LOCK_USE_PTHREAD
|
||||
# ifndef _POSIX_THREAD_PROCESS_SHARED
|
||||
# define XC_LOCK_USE_FCNTL
|
||||
# endif
|
||||
# else
|
||||
# define XC_LOCK_USE_TSRM
|
||||
# define XC_LOCK_USE_FCNTL
|
||||
# endif
|
||||
#elif defined(XC_LOCK_NEED_TS)
|
||||
# define XC_LOCK_USE_TSRM
|
||||
#elif defined(XC_LOCK_NEED_INTERPROCESS)
|
||||
# define XC_LOCK_USE_FCNTL
|
||||
#else
|
||||
# define XC_LOCK_USE_NOOP
|
||||
#endif
|
||||
/* }}} */
|
||||
|
||||
/* {{{ fcntl lock impl */
|
||||
#ifdef XC_LOCK_USE_FCNTL
|
||||
#ifndef ZEND_WIN32
|
||||
typedef int HANDLE;
|
||||
# ifndef INVALID_HANDLE_VALUE
|
||||
# define INVALID_HANDLE_VALUE -1
|
||||
# endif
|
||||
#else
|
||||
# define close(h) CloseHandle(h)
|
||||
# define open(filename, mode, permission) CreateFile(filename, \
|
||||
GENERIC_READ | GENERIC_WRITE, \
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, \
|
||||
NULL, \
|
||||
OPEN_ALWAYS, \
|
||||
FILE_ATTRIBUTE_NORMAL, \
|
||||
NULL)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
HANDLE fd;
|
||||
#ifdef __CYGWIN__
|
||||
/* store the path for unlink() later */
|
||||
char *pathname;
|
||||
#endif
|
||||
} xc_fcntl_lock_t;
|
||||
|
||||
#ifndef ZEND_WIN32
|
||||
# define LCK_WR F_WRLCK
|
||||
# define LCK_RD F_RDLCK
|
||||
# define LCK_UN F_UNLCK
|
||||
# define LCK_NB 0
|
||||
static inline int dolock(xc_fcntl_lock_t *lck, int type)
|
||||
{
|
||||
int ret;
|
||||
struct flock lock;
|
||||
|
||||
lock.l_type = type;
|
||||
lock.l_start = 0;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_len = 1;
|
||||
lock.l_pid = 0;
|
||||
|
||||
do {
|
||||
ret = fcntl(lck->fd, F_SETLKW, &lock);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
|
||||
# include <win32/flock.h>
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# undef errno
|
||||
# define errno GetLastError()
|
||||
# define getuid() 0
|
||||
# define LCK_WR LOCKFILE_EXCLUSIVE_LOCK
|
||||
# define LCK_RD 0
|
||||
# define LCK_UN 0
|
||||
# define LCK_NB LOCKFILE_FAIL_IMMEDIATELY
|
||||
static inline int dolock(xc_fcntl_lock_t *lck, int type)
|
||||
{
|
||||
static OVERLAPPED offset = {0, 0, 0, 0, NULL};
|
||||
|
||||
if (type == LCK_UN) {
|
||||
return UnlockFileEx(lck->fd, 0, 1, 0, &offset);
|
||||
}
|
||||
else {
|
||||
return LockFileEx(lck->fd, type, 0, 1, 0, &offset);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* }}} */
|
||||
|
||||
static zend_bool xc_fcntl_init(xc_fcntl_lock_t *lck, const char *pathname) /* {{{ */
|
||||
{
|
||||
HANDLE fd;
|
||||
int size;
|
||||
char *myname;
|
||||
|
||||
if (pathname == NULL) {
|
||||
static int instanceId = 0;
|
||||
const char default_tmpdir[] = { DEFAULT_SLASH, 't', 'm', 'p', '\0' };
|
||||
const char *tmpdir;
|
||||
|
||||
tmpdir = getenv("TEMP");
|
||||
if (!tmpdir) {
|
||||
tmpdir = getenv("TMP");
|
||||
if (!tmpdir) {
|
||||
tmpdir = default_tmpdir;
|
||||
}
|
||||
}
|
||||
size = strlen(tmpdir) + sizeof("/.xcache.lock") - 1 + 3 * 10 + 100;
|
||||
myname = malloc(size);
|
||||
snprintf(myname, size - 1, "%s%c.xcache.%d.%d.%d.lock", tmpdir, DEFAULT_SLASH, (int) getuid(), (int) getpid(), ++instanceId);
|
||||
pathname = myname;
|
||||
}
|
||||
else {
|
||||
myname = NULL;
|
||||
}
|
||||
|
||||
fd = open(pathname, O_RDWR|O_CREAT, 0666);
|
||||
|
||||
if (fd != INVALID_HANDLE_VALUE) {
|
||||
lck->fd = fd;
|
||||
#ifdef __CYGWIN__
|
||||
size = strlen(pathname) + 1;
|
||||
lck->pathname = malloc(size);
|
||||
memcpy(lck->pathname, pathname, size);
|
||||
#else
|
||||
unlink(pathname);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
zend_error(E_ERROR, "xc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
|
||||
lck = NULL;
|
||||
}
|
||||
|
||||
if (myname) {
|
||||
free(myname);
|
||||
}
|
||||
|
||||
return lck ? 1 : 0;
|
||||
}
|
||||
/* }}} */
|
||||
static void xc_fcntl_destroy(xc_fcntl_lock_t *lck) /* {{{ */
|
||||
{
|
||||
close(lck->fd);
|
||||
#ifdef __CYGWIN__
|
||||
unlink(lck->pathname);
|
||||
free(lck->pathname);
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
static void xc_fcntl_lock(xc_fcntl_lock_t *lck) /* {{{ */
|
||||
{
|
||||
if (dolock(lck, LCK_WR) < 0) {
|
||||
zend_error(E_ERROR, "xc_fcntl_lock failed errno:%d", errno);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
static void xc_fcntl_rdlock(xc_fcntl_lock_t *lck) /* {{{ */
|
||||
{
|
||||
if (dolock(lck, LCK_RD) < 0) {
|
||||
zend_error(E_ERROR, "xc_fcntl_lock failed errno:%d", errno);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
static void xc_fcntl_unlock(xc_fcntl_lock_t *lck) /* {{{ */
|
||||
{
|
||||
if (dolock(lck, LCK_UN) < 0) {
|
||||
zend_error(E_ERROR, "xc_fcntl_unlock failed errno:%d", errno);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
#endif /* XC_LOCK_USE_FCNTL */
|
||||
|
||||
struct _xc_lock_t {
|
||||
#ifdef XC_LOCK_USE_NOOP
|
||||
int dummy;
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_TSRM
|
||||
MUTEX_T tsrm_mutex;
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_HAVE_INTERPROCESS_SWITCH
|
||||
zend_bool interprocess;
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_PTHREAD
|
||||
pthread_mutex_t pthread_mutex;
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_FCNTL
|
||||
xc_fcntl_lock_t fcntl_lock;
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
zend_bool locked;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef XC_LOCK_HAVE_INTERPROCESS_SWITCH
|
||||
# define XC_LOCK_INTERPROCESS (lck->interprocess)
|
||||
#else
|
||||
# define XC_LOCK_INTERPROCESS 1
|
||||
#endif
|
||||
|
||||
size_t xc_lock_size(void) /* {{{ */
|
||||
{
|
||||
return sizeof(xc_lock_t);
|
||||
}
|
||||
/* }}} */
|
||||
xc_lock_t *xc_lock_init(xc_lock_t *lck, const char *pathname, unsigned char interprocess) /* {{{ */
|
||||
{
|
||||
#ifdef XC_LOCK_HAVE_INTERPROCESS_SWITCH
|
||||
lck->interprocess = interprocess;
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_PTHREAD
|
||||
{
|
||||
pthread_mutexattr_t psharedm;
|
||||
pthread_mutexattr_init(&psharedm);
|
||||
pthread_mutexattr_setpshared(&psharedm, XC_LOCK_INTERPROCESS ? PTHREAD_PROCESS_PRIVATE : PTHREAD_PROCESS_SHARED);
|
||||
pthread_mutex_init(&lck->pthread_mutex, &psharedm);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_TSRM
|
||||
lck->tsrm_mutex = tsrm_mutex_alloc();
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_FCNTL
|
||||
if (XC_LOCK_INTERPROCESS) {
|
||||
xc_fcntl_init(&lck->fcntl_lock, pathname);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
lck->locked = 0;
|
||||
#endif
|
||||
|
||||
return lck;
|
||||
}
|
||||
/* }}} */
|
||||
void xc_lock_destroy(xc_lock_t *lck) /* {{{ */
|
||||
{
|
||||
#ifdef XC_LOCK_USE_PTHREAD
|
||||
pthread_mutex_destroy(&lck->pthread_mutex);
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_TSRM
|
||||
tsrm_mutex_free(lck->tsrm_mutex);
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_FCNTL
|
||||
if (XC_LOCK_INTERPROCESS) {
|
||||
xc_fcntl_destroy(&lck->fcntl_lock);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
void xc_lock(xc_lock_t *lck) /* {{{ */
|
||||
{
|
||||
#ifdef XC_LOCK_USE_PTHREAD
|
||||
if (pthread_mutex_lock(&lck->pthread_mutex) < 0) {
|
||||
zend_error(E_ERROR, "xc_lock failed errno:%d", errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_TSRM
|
||||
if (tsrm_mutex_lock(lck->tsrm_mutex) < 0) {
|
||||
zend_error(E_ERROR, "xc_lock failed errno:%d", errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_FCNTL
|
||||
if (XC_LOCK_INTERPROCESS) {
|
||||
xc_fcntl_lock(&lck->fcntl_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
assert(!lck->locked);
|
||||
lck->locked = 1;
|
||||
assert(lck->locked);
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
void xc_rdlock(xc_lock_t *lck) /* {{{ */
|
||||
{
|
||||
#ifdef XC_LOCK_USE_PTHREAD
|
||||
if (pthread_mutex_lock(&lck->pthread_mutex) < 0) {
|
||||
zend_error(E_ERROR, "xc_rdlock failed errno:%d", errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_TSRM
|
||||
if (tsrm_mutex_lock(lck->tsrm_mutex) < 0) {
|
||||
zend_error(E_ERROR, "xc_rdlock failed errno:%d", errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_FCNTL
|
||||
if (XC_LOCK_INTERPROCESS) {
|
||||
xc_fcntl_lock(&lck->fcntl_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
assert(!lck->locked);
|
||||
lck->locked = 1;
|
||||
assert(lck->locked);
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
void xc_unlock(xc_lock_t *lck) /* {{{ */
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
assert(lck->locked);
|
||||
lck->locked = 0;
|
||||
assert(!lck->locked);
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_FCNTL
|
||||
if (XC_LOCK_INTERPROCESS) {
|
||||
xc_fcntl_unlock(&lck->fcntl_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_TSRM
|
||||
if (tsrm_mutex_unlock(lck->tsrm_mutex) < 0) {
|
||||
zend_error(E_ERROR, "xc_unlock failed errno:%d", errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XC_LOCK_USE_PTHREAD
|
||||
if (pthread_mutex_unlock(&lck->pthread_mutex) < 0) {
|
||||
zend_error(E_ERROR, "xc_unlock failed errno:%d", errno);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
@ -1,18 +0,0 @@
|
||||
#ifndef XC_LOCK_H_1913F3DED68715D7CDA5A055E79FE0FF
|
||||
#define XC_LOCK_H_1913F3DED68715D7CDA5A055E79FE0FF
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif /* _MSC_VER > 1000 */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct _xc_lock_t xc_lock_t;
|
||||
|
||||
size_t xc_lock_size(void);
|
||||
xc_lock_t *xc_lock_init(xc_lock_t *lck, const char *pathname, unsigned char interprocess /* only with ZTS */);
|
||||
void xc_lock_destroy(xc_lock_t *lck);
|
||||
void xc_lock(xc_lock_t *lck);
|
||||
void xc_unlock(xc_lock_t *lck);
|
||||
|
||||
#endif /* XC_LOCK_H_1913F3DED68715D7CDA5A055E79FE0FF */
|
@ -0,0 +1,384 @@
|
||||
#include "xc_mutex.h"
|
||||
#include "xcache.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#ifdef ZEND_WIN32
|
||||
# include <process.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <fcntl.h>
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
/* {{{ detect what type of mutex is needed */
|
||||
#ifdef ZTS
|
||||
# define XC_MUTEX_NEED_TS
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FORK
|
||||
# define XC_MUTEX_NEED_INTERPROCESS
|
||||
#endif
|
||||
|
||||
#if defined(XC_MUTEX_NEED_TS) && defined(XC_MUTEX_NEED_INTERPROCESS)
|
||||
/* the check is not even needed for non-threaded env */
|
||||
# define XC_MUTEX_HAVE_INTERPROCESS_SWITCH
|
||||
#endif
|
||||
/* }}} */
|
||||
|
||||
/* {{{ detect which mutex is needed */
|
||||
#if defined(XC_MUTEX_NEED_TS) && defined(XC_MUTEX_NEED_INTERPROCESS)
|
||||
# ifdef PTHREADS
|
||||
# define XC_MUTEX_USE_PTHREAD
|
||||
# ifndef _POSIX_THREAD_PROCESS_SHARED
|
||||
# define XC_MUTEX_USE_FCNTL
|
||||
# endif
|
||||
# else
|
||||
# define XC_MUTEX_USE_TSRM
|
||||
# define XC_MUTEX_USE_FCNTL
|
||||
# endif
|
||||
#elif defined(XC_MUTEX_NEED_TS)
|
||||
# define XC_MUTEX_USE_TSRM
|
||||
#elif defined(XC_MUTEX_NEED_INTERPROCESS)
|
||||
# define XC_MUTEX_USE_FCNTL
|
||||
#else
|
||||
# define XC_MUTEX_USE_NOOP
|
||||
#endif
|
||||
/* }}} */
|
||||
|
||||
/* {{{ fcntl mutex impl */
|
||||
#ifdef XC_MUTEX_USE_FCNTL
|
||||
#ifndef ZEND_WIN32
|
||||
typedef int HANDLE;
|
||||
# ifndef INVALID_HANDLE_VALUE
|
||||
# define INVALID_HANDLE_VALUE -1
|
||||
# endif
|
||||
#else
|
||||
# define close(h) CloseHandle(h)
|
||||
# define open(filename, mode, permission) CreateFile(filename, \
|
||||
GENERIC_READ | GENERIC_WRITE, \
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, \
|
||||
NULL, \
|
||||
OPEN_ALWAYS, \
|
||||
FILE_ATTRIBUTE_NORMAL, \
|
||||
NULL)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
HANDLE fd;
|
||||
#ifdef __CYGWIN__
|
||||
/* store the path for unlink() later */
|
||||
char *pathname;
|
||||
#endif
|
||||
} xc_fcntl_mutex_t;
|
||||
|
||||
#ifndef ZEND_WIN32
|
||||
# define LCK_WR F_WRLCK
|
||||
# define LCK_RD F_RDLCK
|
||||
# define LCK_UN F_UNLCK
|
||||
# define LCK_NB 0
|
||||
static inline int dolock(xc_fcntl_mutex_t *fcntl_mutex, int type)
|
||||
{
|
||||
int ret;
|
||||
struct flock lock;
|
||||
|
||||
lock.l_type = type;
|
||||
lock.l_start = 0;
|
||||
lock.l_whence = SEEK_SET;
|
||||
lock.l_len = 1;
|
||||
lock.l_pid = 0;
|
||||
|
||||
do {
|
||||
ret = fcntl(fcntl_mutex->fd, F_SETLKW, &lock);
|
||||
} while (ret < 0 && errno == EINTR);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
|
||||
# include <win32/flock.h>
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
# include <sys/types.h>
|
||||
# include <sys/stat.h>
|
||||
# undef errno
|
||||
# define errno GetLastError()
|
||||
# define getuid() 0
|
||||
# define LCK_WR LOCKFILE_EXCLUSIVE_LOCK
|
||||
# define LCK_RD 0
|
||||
# define LCK_UN 0
|
||||
# define LCK_NB LOCKFILE_FAIL_IMMEDIATELY
|
||||
static inline int dolock(xc_fcntl_mutex_t *fcntl_mutex, int type)
|
||||
{
|
||||
static OVERLAPPED offset = {0, 0, 0, 0, NULL};
|
||||
|
||||
if (type == LCK_UN) {
|
||||
return UnlockFileEx(fcntl_mutex->fd, 0, 1, 0, &offset);
|
||||
}
|
||||
else {
|
||||
return LockFileEx(fcntl_mutex->fd, type, 0, 1, 0, &offset);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* }}} */
|
||||
|
||||
static zend_bool xc_fcntl_init(xc_fcntl_mutex_t *fcntl_mutex, const char *pathname) /* {{{ */
|
||||
{
|
||||
HANDLE fd;
|
||||
int size;
|
||||
char *myname;
|
||||
|
||||
if (pathname == NULL) {
|
||||
static int instanceId = 0;
|
||||
const char default_tmpdir[] = { DEFAULT_SLASH, 't', 'm', 'p', '\0' };
|
||||
const char *tmpdir;
|
||||
|
||||
tmpdir = getenv("TEMP");
|
||||
if (!tmpdir) {
|
||||
tmpdir = getenv("TMP");
|
||||
if (!tmpdir) {
|
||||
tmpdir = default_tmpdir;
|
||||
}
|
||||
}
|
||||
size = strlen(tmpdir) + sizeof("/.xcache.mutex") - 1 + 3 * 10 + 100;
|
||||
myname = malloc(size);
|
||||
snprintf(myname, size - 1, "%s%c.xcache.%d.%d.%d.mutex", tmpdir, DEFAULT_SLASH, (int) getuid(), (int) getpid(), ++instanceId);
|
||||
pathname = myname;
|
||||
}
|
||||
else {
|
||||
myname = NULL;
|
||||
}
|
||||
|
||||
fd = open(pathname, O_RDWR|O_CREAT, 0666);
|
||||
|
||||
if (fd != INVALID_HANDLE_VALUE) {
|
||||
fcntl_mutex->fd = fd;
|
||||
#ifdef __CYGWIN__
|
||||
size = strlen(pathname) + 1;
|
||||
fcntl_mutex->pathname = malloc(size);
|
||||
memcpy(fcntl_mutex->pathname, pathname, size);
|
||||
#else
|
||||
unlink(pathname);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
zend_error(E_ERROR, "xc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
|
||||
fcntl_mutex = NULL;
|
||||
}
|
||||
|
||||
if (myname) {
|
||||
free(myname);
|
||||
}
|
||||
|
||||
return fcntl_mutex ? 1 : 0;
|
||||
}
|
||||
/* }}} */
|
||||
static void xc_fcntl_destroy(xc_fcntl_mutex_t *fcntl_mutex) /* {{{ */
|
||||
{
|
||||
close(fcntl_mutex->fd);
|
||||
#ifdef __CYGWIN__
|
||||
unlink(fcntl_mutex->pathname);
|
||||
free(fcntl_mutex->pathname);
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
static void xc_fcntl_mutex(xc_fcntl_mutex_t *fcntl_mutex) /* {{{ */
|
||||
{
|
||||
if (dolock(fcntl_mutex, LCK_WR) < 0) {
|
||||
zend_error(E_ERROR, "xc_fcntl_mutex failed errno:%d", errno);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
static void xc_fcntl_rdlock(xc_fcntl_mutex_t *fcntl_mutex) /* {{{ */
|
||||
{
|
||||
if (dolock(fcntl_mutex, LCK_RD) < 0) {
|
||||
zend_error(E_ERROR, "xc_fcntl_mutex failed errno:%d", errno);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
static void xc_fcntl_unlock(xc_fcntl_mutex_t *fcntl_mutex) /* {{{ */
|
||||
{
|
||||
if (dolock(fcntl_mutex, LCK_UN) < 0) {
|
||||
zend_error(E_ERROR, "xc_fcntl_unlock failed errno:%d", errno);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
#endif /* XC_MUTEX_USE_FCNTL */
|
||||
|
||||
struct _xc_mutex_t {
|
||||
#ifdef XC_MUTEX_USE_NOOP
|
||||
int dummy;
|
||||
#endif
|
||||
|
||||
#ifdef XC_MUTEX_HAVE_INTERPROCESS_SWITCH
|
||||
zend_bool want_inter_process; /* whether the lock is created for inter process usage */
|
||||
#endif
|
||||
zend_bool shared; /* shared, or locally allocated */
|
||||
|
||||
#ifdef XC_MUTEX_USE_TSRM
|
||||
MUTEX_T tsrm_mutex;
|
||||
#endif
|
||||
|
||||
#ifdef XC_MUTEX_USE_PTHREAD
|
||||
pthread_mutex_t pthread_mutex;
|
||||
#endif
|
||||
|
||||
#ifdef XC_MUTEX_USE_FCNTL
|
||||
xc_fcntl_mutex_t fcntl_mutex;
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
zend_bool locked;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef XC_MUTEX_HAVE_INTERPROCESS_SWITCH
|
||||
# define xc_want_inter_process() (mutex->want_inter_process)
|
||||
#elif defined(HAVE_FORK)
|
||||
# define xc_want_inter_process() 1
|
||||
#else
|
||||
# define xc_want_inter_process() 0
|
||||
#endif
|
||||
|
||||
size_t xc_mutex_size(void) /* {{{ */
|
||||
{
|
||||
return sizeof(xc_mutex_t);
|
||||
}
|
||||
/* }}} */
|
||||
xc_mutex_t *xc_mutex_init(xc_mutex_t *const shared_mutex, const char *pathname, unsigned char want_inter_process) /* {{{ */
|
||||
{
|
||||
xc_mutex_t *mutex = NULL;
|
||||
|
||||
#ifndef HAVE_FORK
|
||||
want_inter_process = 0;
|
||||
#endif
|
||||
|
||||
/* if interprocessed is needed, shared_mutex is required to be a pre-allocated memory on shm
|
||||
* this function can always return non-shared memory if necessary despite shared memory is given
|
||||
*/
|
||||
|
||||
/* when inter-process is wanted, pthread lives in shm */
|
||||
#ifdef XC_MUTEX_USE_PTHREAD
|
||||
if (want_inter_process) {
|
||||
assert(shared_mutex);
|
||||
mutex = shared_mutex;
|
||||
mutex->shared = 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* all other mutex assumed live locally */
|
||||
mutex = calloc(1, sizeof(*mutex));
|
||||
mutex->shared = 0;
|
||||
#ifdef XC_MUTEX_HAVE_INTERPROCESS_SWITCH
|
||||
mutex->want_inter_process = want_inter_process;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef XC_MUTEX_USE_PTHREAD
|
||||
{
|
||||
/* If you see mutex leak using valgrind, see xc_mutex_destroy function */
|
||||
pthread_mutexattr_t psharedm;
|
||||
pthread_mutexattr_init(&psharedm);
|
||||
pthread_mutexattr_setpshared(&psharedm, xc_want_inter_process() ? PTHREAD_PROCESS_PRIVATE : PTHREAD_PROCESS_SHARED);
|
||||
pthread_mutex_init(&mutex->pthread_mutex, &psharedm);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XC_MUTEX_USE_TSRM
|
||||
mutex->tsrm_mutex = tsrm_mutex_alloc();
|
||||
#endif
|
||||
|
||||
#ifdef XC_MUTEX_USE_FCNTL
|
||||
if (xc_want_inter_process()) {
|
||||
xc_fcntl_init(&mutex->fcntl_mutex, pathname);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
mutex->locked = 0;
|
||||
#endif
|
||||
|
||||
return mutex;
|
||||
}
|
||||
/* }}} */
|
||||
void xc_mutex_destroy(xc_mutex_t *mutex) /* {{{ */
|
||||
{
|
||||
assert(mutex);
|
||||
|
||||
/* intended to not destroy mutex when mutex is shared between process */
|
||||
if (!mutex->shared) {
|
||||
#ifdef XC_MUTEX_USE_PTHREAD
|
||||
pthread_mutex_destroy(&mutex->pthread_mutex);
|
||||
#endif
|
||||
|
||||
#ifdef XC_MUTEX_USE_TSRM
|
||||
tsrm_mutex_free(mutex->tsrm_mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef XC_MUTEX_USE_FCNTL
|
||||
if (xc_want_inter_process()) {
|
||||
xc_fcntl_destroy(&mutex->fcntl_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!mutex->shared) {
|
||||
free(mutex);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
void xc_mutex_lock(xc_mutex_t *mutex) /* {{{ */
|
||||
{
|
||||
#ifdef XC_MUTEX_USE_PTHREAD
|
||||
if (pthread_mutex_lock(&mutex->pthread_mutex) < 0) {
|
||||
zend_error(E_ERROR, "xc_mutex failed errno:%d", errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XC_MUTEX_USE_TSRM
|
||||
if (tsrm_mutex_lock(mutex->tsrm_mutex) < 0) {
|
||||
zend_error(E_ERROR, "xc_mutex failed errno:%d", errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XC_MUTEX_USE_FCNTL
|
||||
if (xc_want_inter_process()) {
|
||||
xc_fcntl_mutex(&mutex->fcntl_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
assert(!mutex->locked);
|
||||
mutex->locked = 1;
|
||||
assert(mutex->locked);
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
||||
void xc_mutex_unlock(xc_mutex_t *mutex) /* {{{ */
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
assert(mutex->locked);
|
||||
mutex->locked = 0;
|
||||
assert(!mutex->locked);
|
||||
#endif
|
||||
|
||||
#ifdef XC_MUTEX_USE_FCNTL
|
||||
if (xc_want_inter_process()) {
|
||||
xc_fcntl_unlock(&mutex->fcntl_mutex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XC_MUTEX_USE_TSRM
|
||||
if (tsrm_mutex_unlock(mutex->tsrm_mutex) < 0) {
|
||||
zend_error(E_ERROR, "xc_mutex_unlock failed errno:%d", errno);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XC_MUTEX_USE_PTHREAD
|
||||
if (pthread_mutex_unlock(&mutex->pthread_mutex) < 0) {
|
||||
zend_error(E_ERROR, "xc_mutex_unlock failed errno:%d", errno);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* }}} */
|
@ -0,0 +1,18 @@
|
||||
#ifndef XC_MUTEX_H_1913F3DED68715D7CDA5A055E79FE0FF
|
||||
#define XC_MUTEX_H_1913F3DED68715D7CDA5A055E79FE0FF
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif /* _MSC_VER > 1000 */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct _xc_mutex_t xc_mutex_t;
|
||||
|
||||
size_t xc_mutex_size(void);
|
||||
xc_mutex_t *xc_mutex_init(xc_mutex_t *shared_mutex, const char *pathname, unsigned char want_inter_process);
|
||||
void xc_mutex_destroy(xc_mutex_t *mutex);
|
||||
void xc_mutex_lock(xc_mutex_t *mutex);
|
||||
void xc_mutex_unlock(xc_mutex_t *mutex);
|
||||
|
||||
#endif /* XC_MUTEX_H_1913F3DED68715D7CDA5A055E79FE0FF */
|
Loading…
Reference in new issue