xref: /memcached-1.4.29/thread.c (revision 93c25c58)
1 /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  * Thread management for memcached.
4  *
5  *  $Id$
6  */
7 #include "memcached.h"
8 #include <stdio.h>
9 #include <errno.h>
10 #include <stdlib.h>
11 #include <errno.h>
12 
13 #ifdef HAVE_MALLOC_H
14 #include <malloc.h>
15 #endif
16 
17 #ifdef HAVE_STRING_H
18 #include <string.h>
19 #endif
20 
21 #ifdef USE_THREADS
22 
23 #include <pthread.h>
24 
25 #define ITEMS_PER_ALLOC 64
26 
27 /* An item in the connection queue. */
28 typedef struct conn_queue_item CQ_ITEM;
29 struct conn_queue_item {
30     int     sfd;
31     int     init_state;
32     int     event_flags;
33     int     read_buffer_size;
34     int     is_udp;
35     CQ_ITEM *next;
36 };
37 
38 /* A connection queue. */
39 typedef struct conn_queue CQ;
40 struct conn_queue {
41     CQ_ITEM *head;
42     CQ_ITEM *tail;
43     pthread_mutex_t lock;
44     pthread_cond_t  cond;
45 };
46 
47 /* Lock for connection freelist */
48 static pthread_mutex_t conn_lock;
49 
50 /* Lock for cache operations (item_*, assoc_*) */
51 static pthread_mutex_t cache_lock;
52 
53 /* Lock for slab allocator operations */
54 static pthread_mutex_t slabs_lock;
55 
56 /* Lock for global stats */
57 static pthread_mutex_t stats_lock;
58 
59 /* Free list of CQ_ITEM structs */
60 static CQ_ITEM *cqi_freelist;
61 static pthread_mutex_t cqi_freelist_lock;
62 
63 /*
64  * Each libevent instance has a wakeup pipe, which other threads
65  * can use to signal that they've put a new connection on its queue.
66  */
67 typedef struct {
68     pthread_t thread_id;        /* unique ID of this thread */
69     struct event_base *base;    /* libevent handle this thread uses */
70     struct event notify_event;  /* listen event for notify pipe */
71     int notify_receive_fd;      /* receiving end of notify pipe */
72     int notify_send_fd;         /* sending end of notify pipe */
73     CQ  new_conn_queue;         /* queue of new connections to handle */
74 } LIBEVENT_THREAD;
75 
76 static LIBEVENT_THREAD *threads;
77 
78 /*
79  * Number of threads that have finished setting themselves up.
80  */
81 static int init_count = 0;
82 static pthread_mutex_t init_lock;
83 static pthread_cond_t init_cond;
84 
85 
86 static void thread_libevent_process(int fd, short which, void *arg);
87 
88 /*
89  * Initializes a connection queue.
90  */
91 static void cq_init(CQ *cq) {
92     pthread_mutex_init(&cq->lock, NULL);
93     pthread_cond_init(&cq->cond, NULL);
94     cq->head = NULL;
95     cq->tail = NULL;
96 }
97 
98 /*
99  * Waits for work on a connection queue.
100  */
101 static CQ_ITEM *cq_pop(CQ *cq) {
102     CQ_ITEM *item;
103 
104     pthread_mutex_lock(&cq->lock);
105     while (NULL == cq->head)
106         pthread_cond_wait(&cq->cond, &cq->lock);
107     item = cq->head;
108     cq->head = item->next;
109     if (NULL == cq->head)
110         cq->tail = NULL;
111     pthread_mutex_unlock(&cq->lock);
112 
113     return item;
114 }
115 
116 /*
117  * Looks for an item on a connection queue, but doesn't block if there isn't
118  * one.
119  * Returns the item, or NULL if no item is available
120  */
121 static CQ_ITEM *cq_peek(CQ *cq) {
122     CQ_ITEM *item;
123 
124     pthread_mutex_lock(&cq->lock);
125     item = cq->head;
126     if (NULL != item) {
127         cq->head = item->next;
128         if (NULL == cq->head)
129             cq->tail = NULL;
130     }
131     pthread_mutex_unlock(&cq->lock);
132 
133     return item;
134 }
135 
136 /*
137  * Adds an item to a connection queue.
138  */
139 static void cq_push(CQ *cq, CQ_ITEM *item) {
140     item->next = NULL;
141 
142     pthread_mutex_lock(&cq->lock);
143     if (NULL == cq->tail)
144         cq->head = item;
145     else
146         cq->tail->next = item;
147     cq->tail = item;
148     pthread_cond_signal(&cq->cond);
149     pthread_mutex_unlock(&cq->lock);
150 }
151 
152 /*
153  * Returns a fresh connection queue item.
154  */
155 static CQ_ITEM *cqi_new() {
156     CQ_ITEM *item = NULL;
157     pthread_mutex_lock(&cqi_freelist_lock);
158     if (cqi_freelist) {
159         item = cqi_freelist;
160         cqi_freelist = item->next;
161     }
162     pthread_mutex_unlock(&cqi_freelist_lock);
163 
164     if (NULL == item) {
165         int i;
166 
167         /* Allocate a bunch of items at once to reduce fragmentation */
168         item = malloc(sizeof(CQ_ITEM) * ITEMS_PER_ALLOC);
169         if (NULL == item)
170             return NULL;
171 
172         /*
173          * Link together all the new items except the first one
174          * (which we'll return to the caller) for placement on
175          * the freelist.
176          */
177         for (i = 2; i < ITEMS_PER_ALLOC; i++)
178             item[i - 1].next = &item[i];
179 
180         pthread_mutex_lock(&cqi_freelist_lock);
181         item[ITEMS_PER_ALLOC - 1].next = cqi_freelist;
182         cqi_freelist = &item[1];
183         pthread_mutex_unlock(&cqi_freelist_lock);
184     }
185 
186     return item;
187 }
188 
189 
190 /*
191  * Frees a connection queue item (adds it to the freelist.)
192  */
193 static void cqi_free(CQ_ITEM *item) {
194     pthread_mutex_lock(&cqi_freelist_lock);
195     item->next = cqi_freelist;
196     cqi_freelist = item;
197     pthread_mutex_unlock(&cqi_freelist_lock);
198 }
199 
200 
201 /*
202  * Creates a worker thread.
203  */
204 static void create_worker(void *(*func)(void *), void *arg) {
205     pthread_t       thread;
206     pthread_attr_t  attr;
207     int             ret;
208 
209     pthread_attr_init(&attr);
210 
211     if ((ret = pthread_create(&thread, &attr, func, arg)) != 0) {
212         fprintf(stderr, "Can't create thread: %s\n",
213                 strerror(ret));
214         exit(1);
215     }
216 }
217 
218 
219 /*
220  * Pulls a conn structure from the freelist, if one is available.
221  */
222 conn *mt_conn_from_freelist() {
223     conn *c;
224 
225     pthread_mutex_lock(&conn_lock);
226     c = do_conn_from_freelist();
227     pthread_mutex_unlock(&conn_lock);
228 
229     return c;
230 }
231 
232 
233 /*
234  * Adds a conn structure to the freelist.
235  *
236  * Returns 0 on success, 1 if the structure couldn't be added.
237  */
238 bool mt_conn_add_to_freelist(conn *c) {
239     bool result;
240 
241     pthread_mutex_lock(&conn_lock);
242     result = do_conn_add_to_freelist(c);
243     pthread_mutex_unlock(&conn_lock);
244 
245     return result;
246 }
247 
248 /****************************** LIBEVENT THREADS *****************************/
249 
250 /*
251  * Set up a thread's information.
252  */
253 static void setup_thread(LIBEVENT_THREAD *me) {
254     if (! me->base) {
255         me->base = event_init();
256         if (! me->base) {
257             fprintf(stderr, "Can't allocate event base\n");
258             exit(1);
259         }
260     }
261 
262     /* Listen for notifications from other threads */
263     event_set(&me->notify_event, me->notify_receive_fd,
264               EV_READ | EV_PERSIST, thread_libevent_process, me);
265     event_base_set(me->base, &me->notify_event);
266 
267     if (event_add(&me->notify_event, 0) == -1) {
268         fprintf(stderr, "Can't monitor libevent notify pipe\n");
269         exit(1);
270     }
271 
272     cq_init(&me->new_conn_queue);
273 }
274 
275 
276 /*
277  * Worker thread: main event loop
278  */
279 static void *worker_libevent(void *arg) {
280     LIBEVENT_THREAD *me = arg;
281 
282     /* Any per-thread setup can happen here; thread_init() will block until
283      * all threads have finished initializing.
284      */
285 
286     pthread_mutex_lock(&init_lock);
287     init_count++;
288     pthread_cond_signal(&init_cond);
289     pthread_mutex_unlock(&init_lock);
290 
291     return (void*) event_base_loop(me->base, 0);
292 }
293 
294 
295 /*
296  * Processes an incoming "handle a new connection" item. This is called when
297  * input arrives on the libevent wakeup pipe.
298  */
299 static void thread_libevent_process(int fd, short which, void *arg) {
300     LIBEVENT_THREAD *me = arg;
301     CQ_ITEM *item;
302     char buf[1];
303 
304     if (read(fd, buf, 1) != 1)
305         if (settings.verbose > 0)
306             fprintf(stderr, "Can't read from libevent pipe\n");
307 
308     item = cq_peek(&me->new_conn_queue);
309 
310     if (NULL != item) {
311         conn *c = conn_new(item->sfd, item->init_state, item->event_flags,
312                            item->read_buffer_size, item->is_udp, me->base);
313         if (c == NULL) {
314             if (item->is_udp) {
315                 fprintf(stderr, "Can't listen for events on UDP socket\n");
316                 exit(1);
317             } else {
318                 if (settings.verbose > 0) {
319                     fprintf(stderr, "Can't listen for events on fd %d\n",
320                         item->sfd);
321                 }
322                 close(item->sfd);
323             }
324         }
325         cqi_free(item);
326     }
327 }
328 
329 /* Which thread we assigned a connection to most recently. */
330 static int last_thread = -1;
331 
332 /*
333  * Dispatches a new connection to another thread. This is only ever called
334  * from the main thread, either during initialization (for UDP) or because
335  * of an incoming connection.
336  */
337 void dispatch_conn_new(int sfd, int init_state, int event_flags,
338                        int read_buffer_size, int is_udp) {
339     CQ_ITEM *item = cqi_new();
340     int thread = (last_thread + 1) % settings.num_threads;
341 
342     last_thread = thread;
343 
344     item->sfd = sfd;
345     item->init_state = init_state;
346     item->event_flags = event_flags;
347     item->read_buffer_size = read_buffer_size;
348     item->is_udp = is_udp;
349 
350     cq_push(&threads[thread].new_conn_queue, item);
351     if (write(threads[thread].notify_send_fd, "", 1) != 1) {
352         perror("Writing to thread notify pipe");
353     }
354 }
355 
356 /*
357  * Returns true if this is the thread that listens for new TCP connections.
358  */
359 int mt_is_listen_thread() {
360     return pthread_self() == threads[0].thread_id;
361 }
362 
363 /********************************* ITEM ACCESS *******************************/
364 
365 /*
366  * Walks through the list of deletes that have been deferred because the items
367  * were locked down at the tmie.
368  */
369 void mt_run_deferred_deletes() {
370     pthread_mutex_lock(&cache_lock);
371     do_run_deferred_deletes();
372     pthread_mutex_unlock(&cache_lock);
373 }
374 
375 /*
376  * Allocates a new item.
377  */
378 item *mt_item_alloc(char *key, size_t nkey, int flags, rel_time_t exptime, int nbytes) {
379     item *it;
380     pthread_mutex_lock(&cache_lock);
381     it = do_item_alloc(key, nkey, flags, exptime, nbytes);
382     pthread_mutex_unlock(&cache_lock);
383     return it;
384 }
385 
386 /*
387  * Returns an item if it hasn't been marked as expired or deleted,
388  * lazy-expiring as needed.
389  */
390 item *mt_item_get_notedeleted(const char *key, const size_t nkey, bool *delete_locked) {
391     item *it;
392     pthread_mutex_lock(&cache_lock);
393     it = do_item_get_notedeleted(key, nkey, delete_locked);
394     pthread_mutex_unlock(&cache_lock);
395     return it;
396 }
397 
398 /*
399  * Links an item into the LRU and hashtable.
400  */
401 int mt_item_link(item *item) {
402     int ret;
403 
404     pthread_mutex_lock(&cache_lock);
405     ret = do_item_link(item);
406     pthread_mutex_unlock(&cache_lock);
407     return ret;
408 }
409 
410 /*
411  * Decrements the reference count on an item and adds it to the freelist if
412  * needed.
413  */
414 void mt_item_remove(item *item) {
415     pthread_mutex_lock(&cache_lock);
416     do_item_remove(item);
417     pthread_mutex_unlock(&cache_lock);
418 }
419 
420 /*
421  * Replaces one item with another in the hashtable.
422  */
423 int mt_item_replace(item *old, item *new) {
424     int ret;
425 
426     pthread_mutex_lock(&cache_lock);
427     ret = do_item_replace(old, new);
428     pthread_mutex_unlock(&cache_lock);
429     return ret;
430 }
431 
432 /*
433  * Unlinks an item from the LRU and hashtable.
434  */
435 void mt_item_unlink(item *item) {
436     pthread_mutex_lock(&cache_lock);
437     do_item_unlink(item);
438     pthread_mutex_unlock(&cache_lock);
439 }
440 
441 /*
442  * Moves an item to the back of the LRU queue.
443  */
444 void mt_item_update(item *item) {
445     pthread_mutex_lock(&cache_lock);
446     do_item_update(item);
447     pthread_mutex_unlock(&cache_lock);
448 }
449 
450 /*
451  * Adds an item to the deferred-delete list so it can be reaped later.
452  */
453 char *mt_defer_delete(item *item, time_t exptime) {
454     char *ret;
455 
456     pthread_mutex_lock(&cache_lock);
457     ret = do_defer_delete(item, exptime);
458     pthread_mutex_unlock(&cache_lock);
459     return ret;
460 }
461 
462 /*
463  * Does arithmetic on a numeric item value.
464  */
465 char *mt_add_delta(item *item, int incr, const unsigned int delta, char *buf) {
466     char *ret;
467 
468     pthread_mutex_lock(&cache_lock);
469     ret = do_add_delta(item, incr, delta, buf);
470     pthread_mutex_unlock(&cache_lock);
471     return ret;
472 }
473 
474 /*
475  * Stores an item in the cache (high level, obeys set/add/replace semantics)
476  */
477 int mt_store_item(item *item, int comm) {
478     int ret;
479 
480     pthread_mutex_lock(&cache_lock);
481     ret = do_store_item(item, comm);
482     pthread_mutex_unlock(&cache_lock);
483     return ret;
484 }
485 
486 /*
487  * Flushes expired items after a flush_all call
488  */
489 void mt_item_flush_expired() {
490     pthread_mutex_lock(&cache_lock);
491     do_item_flush_expired();
492     pthread_mutex_unlock(&cache_lock);
493 }
494 
495 /*
496  * Dumps part of the cache
497  */
498 char *mt_item_cachedump(unsigned int slabs_clsid, unsigned int limit, unsigned int *bytes) {
499     char *ret;
500 
501     pthread_mutex_lock(&cache_lock);
502     ret = do_item_cachedump(slabs_clsid, limit, bytes);
503     pthread_mutex_unlock(&cache_lock);
504     return ret;
505 }
506 
507 /*
508  * Dumps statistics about slab classes
509  */
510 char *mt_item_stats(int *bytes) {
511     char *ret;
512 
513     pthread_mutex_lock(&cache_lock);
514     ret = do_item_stats(bytes);
515     pthread_mutex_unlock(&cache_lock);
516     return ret;
517 }
518 
519 /*
520  * Dumps a list of objects of each size in 32-byte increments
521  */
522 char *mt_item_stats_sizes(int *bytes) {
523     char *ret;
524 
525     pthread_mutex_lock(&cache_lock);
526     ret = do_item_stats_sizes(bytes);
527     pthread_mutex_unlock(&cache_lock);
528     return ret;
529 }
530 
531 /****************************** HASHTABLE MODULE *****************************/
532 
533 void mt_assoc_move_next_bucket() {
534     pthread_mutex_lock(&cache_lock);
535     do_assoc_move_next_bucket();
536     pthread_mutex_unlock(&cache_lock);
537 }
538 
539 /******************************* SLAB ALLOCATOR ******************************/
540 
541 void *mt_slabs_alloc(size_t size) {
542     void *ret;
543 
544     pthread_mutex_lock(&slabs_lock);
545     ret = do_slabs_alloc(size);
546     pthread_mutex_unlock(&slabs_lock);
547     return ret;
548 }
549 
550 void mt_slabs_free(void *ptr, size_t size) {
551     pthread_mutex_lock(&slabs_lock);
552     do_slabs_free(ptr, size);
553     pthread_mutex_unlock(&slabs_lock);
554 }
555 
556 char *mt_slabs_stats(int *buflen) {
557     char *ret;
558 
559     pthread_mutex_lock(&slabs_lock);
560     ret = do_slabs_stats(buflen);
561     pthread_mutex_unlock(&slabs_lock);
562     return ret;
563 }
564 
565 #ifdef ALLOW_SLABS_REASSIGN
566 int mt_slabs_reassign(unsigned char srcid, unsigned char dstid) {
567     int ret;
568 
569     pthread_mutex_lock(&slabs_lock);
570     ret = do_slabs_reassign(srcid, dstid);
571     pthread_mutex_unlock(&slabs_lock);
572     return ret;
573 }
574 #endif
575 
576 /******************************* GLOBAL STATS ******************************/
577 
578 void mt_stats_lock() {
579     pthread_mutex_lock(&stats_lock);
580 }
581 
582 void mt_stats_unlock() {
583     pthread_mutex_unlock(&stats_lock);
584 }
585 
586 /*
587  * Initializes the thread subsystem, creating various worker threads.
588  *
589  * nthreads  Number of event handler threads to spawn
590  * main_base Event base for main thread
591  */
592 void thread_init(int nthreads, struct event_base *main_base) {
593     int         i;
594 
595     pthread_mutex_init(&cache_lock, NULL);
596     pthread_mutex_init(&conn_lock, NULL);
597     pthread_mutex_init(&slabs_lock, NULL);
598     pthread_mutex_init(&stats_lock, NULL);
599 
600     pthread_mutex_init(&init_lock, NULL);
601     pthread_cond_init(&init_cond, NULL);
602 
603     pthread_mutex_init(&cqi_freelist_lock, NULL);
604     cqi_freelist = NULL;
605 
606     threads = malloc(sizeof(LIBEVENT_THREAD) * nthreads);
607     if (! threads) {
608         perror("Can't allocate thread descriptors");
609         exit(1);
610     }
611 
612     threads[0].base = main_base;
613     threads[0].thread_id = pthread_self();
614 
615     for (i = 0; i < nthreads; i++) {
616         int fds[2];
617         if (pipe(fds)) {
618             perror("Can't create notify pipe");
619             exit(1);
620         }
621 
622         threads[i].notify_receive_fd = fds[0];
623         threads[i].notify_send_fd = fds[1];
624 
625     setup_thread(&threads[i]);
626     }
627 
628     /* Create threads after we've done all the libevent setup. */
629     for (i = 1; i < nthreads; i++) {
630         create_worker(worker_libevent, &threads[i]);
631     }
632 
633     /* Wait for all the threads to set themselves up before returning. */
634     pthread_mutex_lock(&init_lock);
635     init_count++; /* main thread */
636     while (init_count < nthreads) {
637         pthread_cond_wait(&init_cond, &init_lock);
638     }
639     pthread_mutex_unlock(&init_lock);
640 }
641 
642 #endif
643