diff options
Diffstat (limited to 'libglusterfs/src/event-epoll.c')
-rw-r--r-- | libglusterfs/src/event-epoll.c | 94 |
1 files changed, 84 insertions, 10 deletions
diff --git a/libglusterfs/src/event-epoll.c b/libglusterfs/src/event-epoll.c index ff191129da0..92420f3734e 100644 --- a/libglusterfs/src/event-epoll.c +++ b/libglusterfs/src/event-epoll.c @@ -317,6 +317,7 @@ event_register_epoll (struct event_pool *event_pool, int fd, { int idx = -1; int ret = -1; + int destroy = 0; struct epoll_event epoll_event = {0, }; struct event_data *ev_data = (void *)&epoll_event.data; struct event_slot_epoll *slot = NULL; @@ -324,6 +325,24 @@ event_register_epoll (struct event_pool *event_pool, int fd, GF_VALIDATE_OR_GOTO ("event", event_pool, out); + /* TODO: Even with the below check, there is a possiblity of race, + * What if the destroy mode is set after the check is done. + * Not sure of the best way to prevent this race, ref counting + * is one possibility. + * There is no harm in registering and unregistering the fd + * even after destroy mode is set, just that such fds will remain + * open until unregister is called, also the events on that fd will be + * notified, until one of the poller thread is alive. + */ + pthread_mutex_lock (&event_pool->mutex); + { + destroy = event_pool->destroy; + } + pthread_mutex_unlock (&event_pool->mutex); + + if (destroy == 1) + goto out; + idx = event_slot_alloc (event_pool, fd); if (idx == -1) { gf_log ("epoll", GF_LOG_ERROR, @@ -609,6 +628,12 @@ event_dispatch_epoll_worker (void *data) gf_log ("epoll", GF_LOG_INFO, "Started thread with index %d", myindex); + pthread_mutex_lock (&event_pool->mutex); + { + event_pool->activethreadcount++; + } + pthread_mutex_unlock (&event_pool->mutex); + for (;;) { if (event_pool->eventthreadcount < myindex) { /* ...time to die, thread count was decreased below @@ -623,7 +648,9 @@ event_dispatch_epoll_worker (void *data) /* if found true in critical section, * die */ event_pool->pollers[myindex - 1] = 0; + event_pool->activethreadcount--; timetodie = 1; + pthread_cond_broadcast (&event_pool->cond); } } pthread_mutex_unlock (&event_pool->mutex); @@ -676,6 +703,8 @@ event_dispatch_epoll (struct event_pool *event_pool) if (pollercount <= 0) pollercount = 1; + event_pool->activethreadcount++; + for (i = 0; i < pollercount; i++) { ev_data = GF_CALLOC (1, sizeof (*ev_data), gf_common_mt_event_pool); @@ -729,6 +758,12 @@ event_dispatch_epoll (struct event_pool *event_pool) if (event_pool->pollers[0] != 0) pthread_join (event_pool->pollers[0], NULL); + pthread_mutex_lock (&event_pool->mutex); + { + event_pool->activethreadcount--; + } + pthread_mutex_unlock (&event_pool->mutex); + return ret; } @@ -736,21 +771,26 @@ int event_reconfigure_threads_epoll (struct event_pool *event_pool, int value) { int i; - int ret; + int ret = 0; pthread_t t_id; int oldthreadcount; struct event_thread_data *ev_data = NULL; - /* Set to MAX if greater */ - if (value > EVENT_MAX_THREADS) - value = EVENT_MAX_THREADS; - - /* Default pollers to 1 in case this is set incorrectly */ - if (value <= 0) - value = 1; - pthread_mutex_lock (&event_pool->mutex); { + /* Reconfigure to 0 threads is allowed only in destroy mode */ + if (event_pool->destroy == 1) { + value = 0; + } else { + /* Set to MAX if greater */ + if (value > EVENT_MAX_THREADS) + value = EVENT_MAX_THREADS; + + /* Default pollers to 1 in case this is set incorrectly */ + if (value <= 0) + value = 1; + } + oldthreadcount = event_pool->eventthreadcount; if (oldthreadcount < value) { @@ -797,6 +837,39 @@ event_reconfigure_threads_epoll (struct event_pool *event_pool, int value) return 0; } +/* This function is the destructor for the event_pool data structure + * Should be called only after poller_threads_destroy() is called, + * else will lead to crashes. + */ +static int +event_pool_destroy_epoll (struct event_pool *event_pool) +{ + int ret = 0, i = 0, j = 0; + struct event_slot_epoll *table = NULL; + + ret = close (event_pool->fd); + + for (i = 0; i < EVENT_EPOLL_TABLES; i++) { + if (event_pool->ereg[i]) { + table = event_pool->ereg[i]; + event_pool->ereg[i] = NULL; + for (j = 0; j < EVENT_EPOLL_SLOTS; j++) { + LOCK_DESTROY (&table[j].lock); + } + GF_FREE (table); + } + } + + pthread_mutex_destroy (&event_pool->mutex); + pthread_cond_destroy (&event_pool->cond); + + GF_FREE (event_pool->evcache); + GF_FREE (event_pool->reg); + GF_FREE (event_pool); + + return ret; +} + struct event_ops event_ops_epoll = { .new = event_pool_new_epoll, .event_register = event_register_epoll, @@ -804,7 +877,8 @@ struct event_ops event_ops_epoll = { .event_unregister = event_unregister_epoll, .event_unregister_close = event_unregister_close_epoll, .event_dispatch = event_dispatch_epoll, - .event_reconfigure_threads = event_reconfigure_threads_epoll + .event_reconfigure_threads = event_reconfigure_threads_epoll, + .event_pool_destroy = event_pool_destroy_epoll }; #endif |