@@ -49,6 +49,9 @@ pthread_mutex_t atomics_mutex = PTHREAD_MUTEX_INITIALIZER;
4949/* Lock for global stats */
5050static pthread_mutex_t stats_lock ;
5151
52+ /* Lock to cause worker threads to hang up after being woken */
53+ static pthread_mutex_t worker_hang_lock ;
54+
5255/* Free list of CQ_ITEM structs */
5356static CQ_ITEM * cqi_freelist ;
5457static pthread_mutex_t cqi_freelist_lock ;
@@ -59,10 +62,6 @@ static uint32_t item_lock_count;
5962unsigned int item_lock_hashpower ;
6063#define hashsize (n ) ((unsigned long int)1<<(n))
6164#define hashmask (n ) (hashsize(n)-1)
62- /* this lock is temporarily engaged during a hash table expansion */
63- static pthread_mutex_t item_global_lock ;
64- /* thread-specific variable for deeply finding the item lock type */
65- static pthread_key_t item_lock_type_key ;
6665
6766static LIBEVENT_DISPATCHER_THREAD dispatcher_thread ;
6867
@@ -112,22 +111,8 @@ unsigned short refcount_decr(unsigned short *refcount) {
112111#endif
113112}
114113
115- /* Convenience functions for calling *only* when in ITEM_LOCK_GLOBAL mode */
116- void item_lock_global (void ) {
117- mutex_lock (& item_global_lock );
118- }
119-
120- void item_unlock_global (void ) {
121- mutex_unlock (& item_global_lock );
122- }
123-
124114void item_lock (uint32_t hv ) {
125- uint8_t * lock_type = pthread_getspecific (item_lock_type_key );
126- if (likely (* lock_type == ITEM_LOCK_GRANULAR )) {
127- mutex_lock (& item_locks [hv & hashmask (item_lock_hashpower )]);
128- } else {
129- mutex_lock (& item_global_lock );
130- }
115+ mutex_lock (& item_locks [hv & hashmask (item_lock_hashpower )]);
131116}
132117
133118/* Special case. When ITEM_LOCK_GLOBAL mode is enabled, this should become a
@@ -150,12 +135,7 @@ void item_trylock_unlock(void *lock) {
150135}
151136
152137void item_unlock (uint32_t hv ) {
153- uint8_t * lock_type = pthread_getspecific (item_lock_type_key );
154- if (likely (* lock_type == ITEM_LOCK_GRANULAR )) {
155- mutex_unlock (& item_locks [hv & hashmask (item_lock_hashpower )]);
156- } else {
157- mutex_unlock (& item_global_lock );
158- }
138+ mutex_unlock (& item_locks [hv & hashmask (item_lock_hashpower )]);
159139}
160140
161141static void wait_for_thread_registration (int nthreads ) {
@@ -169,25 +149,44 @@ static void register_thread_initialized(void) {
169149 init_count ++ ;
170150 pthread_cond_signal (& init_cond );
171151 pthread_mutex_unlock (& init_lock );
152+ /* Force worker threads to pile up if someone wants us to */
153+ pthread_mutex_lock (& worker_hang_lock );
154+ pthread_mutex_unlock (& worker_hang_lock );
172155}
173156
174- void switch_item_lock_type (enum item_lock_types type ) {
157+ /* Must not be called with any deeper locks held:
158+ * item locks, cache_lock, stats_lock, etc
159+ */
160+ void pause_threads (enum pause_thread_types type ) {
175161 char buf [1 ];
176162 int i ;
177163
164+ buf [0 ] = 0 ;
178165 switch (type ) {
179- case ITEM_LOCK_GRANULAR :
180- buf [0 ] = 'l' ;
166+ case PAUSE_ALL_THREADS :
167+ slabs_rebalancer_pause ();
168+ lru_crawler_pause ();
169+ case PAUSE_WORKER_THREADS :
170+ buf [0 ] = 'p' ;
171+ pthread_mutex_lock (& worker_hang_lock );
181172 break ;
182- case ITEM_LOCK_GLOBAL :
183- buf [0 ] = 'g' ;
173+ case RESUME_ALL_THREADS :
174+ slabs_rebalancer_resume ();
175+ lru_crawler_resume ();
176+ case RESUME_WORKER_THREADS :
177+ pthread_mutex_unlock (& worker_hang_lock );
184178 break ;
185179 default :
186180 fprintf (stderr , "Unknown lock type: %d\n" , type );
187181 assert (1 == 0 );
188182 break ;
189183 }
190184
185+ /* Only send a message if we have one. */
186+ if (buf [0 ] == 0 ) {
187+ return ;
188+ }
189+
191190 pthread_mutex_lock (& init_lock );
192191 init_count = 0 ;
193192 for (i = 0 ; i < settings .num_threads ; i ++ ) {
@@ -374,13 +373,6 @@ static void *worker_libevent(void *arg) {
374373 * all threads have finished initializing.
375374 */
376375
377- /* set an indexable thread-specific memory item for the lock type.
378- * this could be unnecessary if we pass the conn *c struct through
379- * all item_lock calls...
380- */
381- me -> item_lock_type = ITEM_LOCK_GRANULAR ;
382- pthread_setspecific (item_lock_type_key , & me -> item_lock_type );
383-
384376 register_thread_initialized ();
385377
386378 event_base_loop (me -> base , 0 );
@@ -425,13 +417,8 @@ static void thread_libevent_process(int fd, short which, void *arg) {
425417 cqi_free (item );
426418 }
427419 break ;
428- /* we were told to flip the lock type and report in */
429- case 'l' :
430- me -> item_lock_type = ITEM_LOCK_GRANULAR ;
431- register_thread_initialized ();
432- break ;
433- case 'g' :
434- me -> item_lock_type = ITEM_LOCK_GLOBAL ;
420+ /* we were told to pause and report in */
421+ case 'p' :
435422 register_thread_initialized ();
436423 break ;
437424 }
@@ -784,6 +771,7 @@ void memcached_thread_init(int nthreads, struct event_base *main_base) {
784771
785772 pthread_mutex_init (& cache_lock , NULL );
786773 pthread_mutex_init (& stats_lock , NULL );
774+ pthread_mutex_init (& worker_hang_lock , NULL );
787775
788776 pthread_mutex_init (& init_lock , NULL );
789777 pthread_cond_init (& init_cond , NULL );
@@ -803,6 +791,13 @@ void memcached_thread_init(int nthreads, struct event_base *main_base) {
803791 power = 13 ;
804792 }
805793
794+ if (power >= hashpower ) {
795+ fprintf (stderr , "Hash table power size (%d) cannot be equal to or less than item lock table (%d)\n" , hashpower , power );
796+ fprintf (stderr , "Item lock table grows with `-t N` (worker threadcount)\n" );
797+ fprintf (stderr , "Hash table grows with `-o hashpower=N` \n" );
798+ exit (1 );
799+ }
800+
806801 item_lock_count = hashsize (power );
807802 item_lock_hashpower = power ;
808803
@@ -814,8 +809,6 @@ void memcached_thread_init(int nthreads, struct event_base *main_base) {
814809 for (i = 0 ; i < item_lock_count ; i ++ ) {
815810 pthread_mutex_init (& item_locks [i ], NULL );
816811 }
817- pthread_key_create (& item_lock_type_key , NULL );
818- pthread_mutex_init (& item_global_lock , NULL );
819812
820813 threads = calloc (nthreads , sizeof (LIBEVENT_THREAD ));
821814 if (! threads ) {
0 commit comments