source: trunk/xcache/xc_lock.c @ 1199

Last change on this file since 1199 was 1199, checked in by moo, 22 months ago

fix for ZTS

  • Property svn:eol-style set to native
File size: 5.9 KB
RevLine 
[1027]1#include "xc_lock.h"
2#include "xcache.h"
[1]3#include <stdio.h>
4#include <string.h>
[36]5#include <stdlib.h>
[1186]6#ifdef ZEND_WIN32
7#   include <process.h>
[1199]8#else
9#   include <unistd.h>
10#   include <fcntl.h>
11#   include <errno.h>
[1186]12#endif
[1]13
14#ifndef ZEND_WIN32
15typedef int HANDLE;
[62]16#   ifndef INVALID_HANDLE_VALUE
17#       define INVALID_HANDLE_VALUE -1
18#   endif
[928]19#else
20#   define close(h) CloseHandle(h)
21#   define open(filename, mode, permission) CreateFile(filename, \
22        GENERIC_READ | GENERIC_WRITE, \
23        FILE_SHARE_READ | FILE_SHARE_WRITE, \
24        NULL, \
25        OPEN_ALWAYS, \
26        FILE_ATTRIBUTE_NORMAL, \
27        NULL)
[1]28#endif
29
[1199]30typedef struct {
[1]31    HANDLE fd;
32    char *pathname;
[1199]33} xc_fcntl_lock_t;
[1]34
[1199]35/* {{{ fcntl lock impl */
[1]36#ifndef ZEND_WIN32
[11]37#   define LCK_WR F_WRLCK
38#   define LCK_RD F_RDLCK
39#   define LCK_UN F_UNLCK
40#   define LCK_NB 0
[1199]41static inline int dolock(xc_fcntl_lock_t *lck, int type)
[1198]42{
[1]43    int ret;
44    struct flock lock;
45
46    lock.l_type = type;
47    lock.l_start = 0;
48    lock.l_whence = SEEK_SET;
49    lock.l_len = 1;
50    lock.l_pid = 0;
51
52    do {
53        ret = fcntl(lck->fd, F_SETLKW, &lock);
54    } while (ret < 0 && errno == EINTR);
55    return ret;
56}
57#else
58
59#   include <win32/flock.h>
60#   include <io.h>
61#   include <fcntl.h>
62#   include <sys/types.h>
63#   include <sys/stat.h>
[928]64#   undef errno
65#   define errno GetLastError()
[11]66#   define getuid() 0
67#   define LCK_WR LOCKFILE_EXCLUSIVE_LOCK
68#   define LCK_RD 0
69#   define LCK_UN 0
70#   define LCK_NB LOCKFILE_FAIL_IMMEDIATELY
[1199]71static inline int dolock(xc_fcntl_lock_t *lck, int type)
[1198]72{
[1]73    static OVERLAPPED offset = {0, 0, 0, 0, NULL};
74
75    if (type == LCK_UN) {
[11]76        return UnlockFileEx((HANDLE)lck->fd, 0, 1, 0, &offset);
[1]77    }
78    else {
[11]79        return LockFileEx((HANDLE)lck->fd, type, 0, 1, 0, &offset);
[1]80    }
81}
[1199]82#endif
[1]83/* }}} */
84
[1199]85static zend_bool xc_fcntl_init(xc_fcntl_lock_t *lck, const char *pathname) /* {{{ */
[1]86{
87    HANDLE fd;
[62]88    int size;
89    char *myname;
[1]90
91    if (pathname == NULL) {
[1154]92        static int instanceId = 0;
[62]93        const char default_tmpdir[] = { DEFAULT_SLASH, 't', 'm', 'p', '\0' };
94        const char *tmpdir;
95
96        tmpdir = getenv("TEMP");
97        if (!tmpdir) {
98            tmpdir = getenv("TMP");
99            if (!tmpdir) {
100                tmpdir = default_tmpdir;
101            }
102        }
103        size = strlen(tmpdir) + sizeof("/.xcache.lock") - 1 + 3 * 10 + 100;
[282]104        myname = malloc(size);
[1154]105        snprintf(myname, size - 1, "%s%c.xcache.%d.%d.%d.lock", tmpdir, DEFAULT_SLASH, (int) getuid(), (int) getpid(), ++instanceId);
[1]106        pathname = myname;
107    }
[62]108    else {
109        myname = NULL;
110    }
[1]111
[928]112    fd = open(pathname, O_RDWR|O_CREAT, 0666);
[1]113
[62]114    if (fd != INVALID_HANDLE_VALUE) {
[1]115
116#ifndef __CYGWIN__
117        unlink(pathname);
118#endif
119        lck->fd = fd;
120        size = strlen(pathname) + 1;
121        lck->pathname = malloc(size);
122        memcpy(lck->pathname, pathname, size);
123    }
124    else {
[928]125        zend_error(E_ERROR, "xc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
[62]126        lck = NULL;
[1]127    }
[62]128
129    if (myname) {
[282]130        free(myname);
[62]131    }
132
[1199]133    return lck ? 1 : 0;
[1]134}
135/* }}} */
[1199]136static void xc_fcntl_destroy(xc_fcntl_lock_t *lck) /* {{{ */
[1198]137{
[928]138    close(lck->fd);
[1]139#ifdef __CYGWIN__
140    unlink(lck->pathname);
141#endif
142    free(lck->pathname);
143}
144/* }}} */
[1199]145static void xc_fcntl_lock(xc_fcntl_lock_t *lck) /* {{{ */
[1198]146{
[1]147    if (dolock(lck, LCK_WR) < 0) {
[928]148        zend_error(E_ERROR, "xc_fcntl_lock failed errno:%d", errno);
[1]149    }
150}
151/* }}} */
[1199]152static void xc_fcntl_rdlock(xc_fcntl_lock_t *lck) /* {{{ */
[1198]153{
[1]154    if (dolock(lck, LCK_RD) < 0) {
[928]155        zend_error(E_ERROR, "xc_fcntl_lock failed errno:%d", errno);
[1]156    }
157}
158/* }}} */
[1199]159static void xc_fcntl_unlock(xc_fcntl_lock_t *lck) /* {{{ */
[1198]160{
[1]161    if (dolock(lck, LCK_UN) < 0) {
[928]162        zend_error(E_ERROR, "xc_fcntl_unlock failed errno:%d", errno);
[1]163    }
164}
165/* }}} */
[1199]166
167#undef XC_INTERPROCESS_LOCK_IMPLEMENTED
168#undef XC_LOCK_UNSUED
169
170#ifdef ZEND_WIN32
171#   define XC_INTERPROCESS_LOCK_IMPLEMENTED
172#   ifndef ZTS
173#       define XC_LOCK_UNSUED
174#   endif
175#endif
176
177#if defined(PTHREADS)
178#   define XC_INTERPROCESS_LOCK_IMPLEMENTED
179#endif
180
181struct _xc_lock_t {
182#ifdef XC_LOCK_UNSUED
183    int dummy;
184#else
185#   ifdef ZTS
186    MUTEX_T tsrm_mutex;
187#   endif
188
189#   ifndef XC_INTERPROCESS_LOCK_IMPLEMENTED
190#       ifdef ZTS
191    zend_bool use_fcntl;
192#       endif
193    xc_fcntl_lock_t fcntl_lock;
194#   endif
195#endif
196};
197
198xc_lock_t *xc_lock_init(const char *pathname, int interprocess) /* {{{ */
199{
200#ifdef XC_LOCK_UNSUED
201    return (xc_lock_t *) 1;
202#else
203#   ifdef ZTS
204    xc_lock_t *lck = malloc(sizeof(xc_lock_t));
205#       if defined(PTHREADS)
206    pthread_mutexattr_t psharedm;
207    pthread_mutexattr_init(&psharedm);
208    pthread_mutexattr_setpshared(&psharedm, PTHREAD_PROCESS_SHARED);
209    lck->tsrm_mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
210    pthread_mutex_init(lck->tsrm_mutex, &psharedm);
211#       else
212    lck->tsrm_mutex = tsrm_mutex_alloc();
213#       endif
214#   endif
215#   ifndef XC_INTERPROCESS_LOCK_IMPLEMENTED
216#       ifdef ZTS
217    lck->use_fcntl = interprocess;
218    if (lck->use_fcntl)
219#       endif
220        xc_fcntl_init(&lck->fcntl_lock, pathname);
221#   endif
222    return lck;
223#endif
224}
225/* }}} */
226void xc_lock_destroy(xc_lock_t *lck) /* {{{ */
227{
228#ifdef XC_LOCK_UNSUED
229    /* do nothing */
230#else
231#   ifdef ZTS
232    tsrm_mutex_free(lck->tsrm_mutex);
233#   endif
234#   ifndef XC_INTERPROCESS_LOCK_IMPLEMENTED
235#       ifdef ZTS
236    if (lck->use_fcntl)
237#       endif
238        xc_fcntl_destroy(&lck->fcntl_lock);
239#   endif
240    free(lck);
241#endif
242}
243/* }}} */
244void xc_lock(xc_lock_t *lck) /* {{{ */
245{
246#ifdef XC_LOCK_UNSUED
247#else
248#   ifdef ZTS
249    if (tsrm_mutex_lock(lck->tsrm_mutex) < 0) {
250        zend_error(E_ERROR, "xc_lock failed errno:%d", errno);
251    }
252#   endif
253#   ifndef XC_INTERPROCESS_LOCK_IMPLEMENTED
254#       ifdef ZTS
255    if (lck->use_fcntl)
256#       endif
257        xc_fcntl_lock(&lck->fcntl_lock);
258#   endif
259#endif
260}
261/* }}} */
262void xc_rdlock(xc_lock_t *lck) /* {{{ */
263{
264#ifdef XC_LOCK_UNSUED
265#else
266#   ifdef ZTS
267    if (tsrm_mutex_lock(lck->tsrm_mutex) < 0) {
268        zend_error(E_ERROR, "xc_rdlock failed errno:%d", errno);
269    }
270#   endif
271#   ifndef XC_INTERPROCESS_LOCK_IMPLEMENTED
272#       ifdef ZTS
273    if (lck->use_fcntl)
274#       endif
275        xc_fcntl_lock(&lck->fcntl_lock);
276#   endif
277#endif
278}
279/* }}} */
280void xc_unlock(xc_lock_t *lck) /* {{{ */
281{
282#ifdef XC_LOCK_UNSUED
283#else
284#   ifndef XC_INTERPROCESS_LOCK_IMPLEMENTED
285#       ifdef ZTS
286    if (lck->use_fcntl)
287#       endif
288        xc_fcntl_unlock(&lck->fcntl_lock);
289#   endif
290#endif
291#   ifdef ZTS
292    if (tsrm_mutex_unlock(lck->tsrm_mutex) < 0) {
293        zend_error(E_ERROR, "xc_unlock failed errno:%d", errno);
294    }
295#   endif
296}
297/* }}} */
Note: See TracBrowser for help on using the repository browser.