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