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