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 int init_state; 23 int event_flags; 24 int read_buffer_size; 25 int 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