From 7744285dc3d8f475be32d69242eeea71b6819271 Mon Sep 17 00:00:00 2001 From: "roberto@maverick64" Date: Sun, 13 Feb 2011 18:58:51 +0100 Subject: [PATCH] move caching locking to rwlock --- cache.c | 18 +++++++--- lock.c | 61 +++++++++++++++++++++++++++++++-- master.c | 4 +-- plugins/python/uwsgi_pymodule.c | 16 ++++----- uwsgi.c | 4 +-- uwsgi.h | 6 ++++ 6 files changed, 91 insertions(+), 18 deletions(-) diff --git a/cache.c b/cache.c index 62096cb3..ac8858ec 100644 --- a/cache.c +++ b/cache.c @@ -174,18 +174,28 @@ end: } -void cache_command(char *key, uint16_t keylen, char *val, uint64_t vallen, void *data) { +void cache_command(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) { struct wsgi_request *wsgi_req = (struct wsgi_request *) data; + uint64_t tmp_vallen = 0; if (vallen > 0) { if (!uwsgi_strncmp(key, keylen, "key", 3)) { - val = uwsgi_cache_get(val, vallen, &vallen); - if (val && vallen > 0) { + val = uwsgi_cache_get(val, vallen, &tmp_vallen); + if (val && tmp_vallen > 0) { wsgi_req->response_size = write(wsgi_req->poll.fd, val, vallen); } } + else if (!uwsgi_strncmp(key, keylen, "get", 3)) { + val = uwsgi_cache_get(val, vallen, &tmp_vallen); + if (val && vallen > 0) { + wsgi_req->response_size = write(wsgi_req->poll.fd, val, tmp_vallen); + } + else { + wsgi_req->response_size = write(wsgi_req->poll.fd, "HTTP/1.0 404 Not Found\r\n\r\n

Not Found

", 44); + } + } } } @@ -228,7 +238,7 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) { case 4: // dict if (wsgi_req->uh.pktsize > 0) { - //uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh.pktsize, cache_command, (void *) wsgi_req); + uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh.pktsize, cache_command, (void *) wsgi_req); } break; } diff --git a/lock.c b/lock.c index e75fcfce..e2e27274 100644 --- a/lock.c +++ b/lock.c @@ -4,6 +4,7 @@ #ifdef UWSGI_LOCK_USE_MUTEX #define UWSGI_LOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t) +#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlockattr_t) + sizeof(pthread_rwlock_t) // REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!! void uwsgi_lock_init(void *lock) { @@ -25,6 +26,18 @@ void uwsgi_lock_init(void *lock) { } +void uwsgi_rlock(void *lock) { + pthread_rwlock_rdlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t)); +} + +void uwsgi_wlock(void *lock) { + pthread_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t)); +} + +void uwsgi_rwunlock(void *lock) { + pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t)); +} + void uwsgi_lock(void *lock) { pthread_mutex_lock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t)); @@ -35,6 +48,26 @@ void uwsgi_unlock(void *lock) { pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t)); } +void uwsgi_rwlock_init(void *lock) { + + if (pthread_rwlockattr_init((pthread_rwlockattr_t *) lock)) { + uwsgi_log("unable to allocate rwlock structure\n"); + exit(1); + } + if (pthread_rwlockattr_setpshared((pthread_rwlockattr_t *) lock, PTHREAD_PROCESS_SHARED)) { + uwsgi_log("unable to share rwlock\n"); + exit(1); + } + + if (pthread_rwlock_init((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t), (pthread_rwlockattr_t *) lock)) { + uwsgi_log("unable to initialize rwlock\n"); + exit(1); + } + + +} + + #endif @@ -43,7 +76,13 @@ void uwsgi_unlock(void *lock) { #include #include -#define UWSGI_LOCK_SIZE sizeof(struct umtx) +#define UWSGI_LOCK_SIZE sizeof(struct umtx) +#define UWSGI_RWLOCK_SIZE sizeof(struct umtx) + +#define uwsgi_rwlock_init uwsgi_lock_init +#define uwsgi_rlock uwsgi_lock +#define uwsgi_wlock uwsgi_lock +#define uwsgi_rwunlock uwsgi_lock void uwsgi_lock_init(void *lock) { umtx_init((struct umtx*) lock); @@ -62,7 +101,13 @@ void uwsgi_unlock(void *lock) { #ifdef UWSGI_LOCK_USE_OSX_SPINLOCK -#define UWSGI_LOCK_SIZE sizeof(OSSpinLock) +#define UWSGI_LOCK_SIZE sizeof(OSSpinLock) +#define UWSGI_RWLOCK_SIZE sizeof(OSSpinLock) + +#define uwsgi_rwlock_init uwsgi_lock_init +#define uwsgi_rlock uwsgi_lock +#define uwsgi_wlock uwsgi_lock +#define uwsgi_rwunlock uwsgi_lock void uwsgi_lock_init(void *lock) { @@ -109,3 +154,15 @@ void *uwsgi_mmap_shared_lock() { return addr; } + +void *uwsgi_mmap_shared_rwlock() { + void *addr = NULL; + addr = mmap(NULL, UWSGI_RWLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); + + if (addr == NULL) { + uwsgi_error("mmap()"); + exit(1); + } + + return addr; +} diff --git a/master.c b/master.c index 57d169cc..cec2b9b0 100644 --- a/master.c +++ b/master.c @@ -584,13 +584,13 @@ void master_loop(char **argv, char **environ) { // remove expired cache items if (uwsgi.cache_max_items > 0) { for(i=0;i< (int)uwsgi.cache_max_items;i++) { - uwsgi_lock(uwsgi.cache_lock); + uwsgi_wlock(uwsgi.cache_lock); if (uwsgi.cache_items[i].expires) { if (uwsgi.cache_items[i].expires < current_time) { uwsgi_cache_del(uwsgi.cache_items[i].key, uwsgi.cache_items[i].keysize); } } - uwsgi_unlock(uwsgi.cache_lock); + uwsgi_rwunlock(uwsgi.cache_lock); } } diff --git a/plugins/python/uwsgi_pymodule.c b/plugins/python/uwsgi_pymodule.c index b23ff8d7..c9c7efb9 100644 --- a/plugins/python/uwsgi_pymodule.c +++ b/plugins/python/uwsgi_pymodule.c @@ -2368,13 +2368,13 @@ PyObject *py_uwsgi_cache_del(PyObject * self, PyObject * args) { uwsgi_simple_send_string(remote, 111, 2, key, keylen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); } else if (uwsgi.cache_max_items) { - uwsgi_lock(uwsgi.cache_lock); + uwsgi_wlock(uwsgi.cache_lock); if (uwsgi_cache_del(key, strlen(key))) { - uwsgi_unlock(uwsgi.cache_lock); + uwsgi_rwunlock(uwsgi.cache_lock); Py_INCREF(Py_None); return Py_None; } - uwsgi_unlock(uwsgi.cache_lock); + uwsgi_rwunlock(uwsgi.cache_lock); } Py_INCREF(Py_True); @@ -2405,13 +2405,13 @@ PyObject *py_uwsgi_cache_set(PyObject * self, PyObject * args) { uwsgi_simple_send_string2(remote, 111, 1, key, keylen, value, vallen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]); } else if (uwsgi.cache_max_items) { - uwsgi_lock(uwsgi.cache_lock); + uwsgi_wlock(uwsgi.cache_lock); if (uwsgi_cache_set(key, keylen, value, vallen, expires)) { - uwsgi_unlock(uwsgi.cache_lock); + uwsgi_rwunlock(uwsgi.cache_lock); Py_INCREF(Py_None); return Py_None; } - uwsgi_unlock(uwsgi.cache_lock); + uwsgi_rwunlock(uwsgi.cache_lock); } Py_INCREF(Py_True); @@ -2478,7 +2478,7 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) { #ifdef UWSGI_DEBUG gettimeofday(&tv, NULL); #endif - uwsgi_lock(uwsgi.cache_lock); + uwsgi_rlock(uwsgi.cache_lock); value = uwsgi_cache_get(key, keylen, &valsize); res = PyString_FromStringAndSize(value, valsize); #ifdef UWSGI_DEBUG @@ -2487,7 +2487,7 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) { uwsgi_log("[slow] cache get done in %d microseconds (%llu bytes value)\n", (tv2.tv_sec* (1000*1000) + tv2.tv_usec) - (tv.tv_sec* (1000*1000) + tv.tv_usec), (unsigned long long) valsize); } #endif - uwsgi_unlock(uwsgi.cache_lock); + uwsgi_rwunlock(uwsgi.cache_lock); return res; } diff --git a/uwsgi.c b/uwsgi.c index 55f599d8..dddc3210 100644 --- a/uwsgi.c +++ b/uwsgi.c @@ -1106,8 +1106,8 @@ int uwsgi_start(void *v_argv) { uwsgi.shared->cache_first_available_item = 1; uwsgi.shared->cache_unused_stack_ptr = 0; - uwsgi.cache_lock = uwsgi_mmap_shared_lock(); - uwsgi_lock_init(uwsgi.cache_lock); + uwsgi.cache_lock = uwsgi_mmap_shared_rwlock(); + uwsgi_rwlock_init(uwsgi.cache_lock); uwsgi.p[111] = &uwsgi_cache_plugin; diff --git a/uwsgi.h b/uwsgi.h index cdcb3a1a..82106578 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -1346,6 +1346,11 @@ void uwsgi_lock_init(void *); void uwsgi_lock(void *); void uwsgi_unlock(void *); +void uwsgi_rwlock_init(void *); +void uwsgi_rlock(void *); +void uwsgi_wlock(void *); +void uwsgi_rwunlock(void *); + inline void *uwsgi_malloc(size_t); @@ -1367,6 +1372,7 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int, int); void *uwsgi_mmap_shared_lock(void); +void *uwsgi_mmap_shared_rwlock(void); void uwsgi_register_signal(uint8_t, uint8_t, void *, uint8_t, char *, uint8_t); void uwsgi_register_file_monitor(uint8_t, char *, uint8_t, void *, uint8_t);