~ubuntu-branches/ubuntu/saucy/memcached/saucy-201305271046

« back to all changes in this revision

Viewing changes to thread.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman
  • Date: 2011-12-20 11:10:01 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20111220111001-vtqvn3gyffijao4d
Tags: 1.4.10-0ubuntu1
* New upstream release
  - Multiple bug fixes
  - General work on performance improvement
  - Improvements in speed between 3 and 6 worker threads

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
static CQ_ITEM *cqi_freelist;
47
47
static pthread_mutex_t cqi_freelist_lock;
48
48
 
 
49
static pthread_mutex_t *item_locks;
 
50
/* size of the item lock hash table */
 
51
static uint32_t item_lock_count;
 
52
/* size - 1 for lookup masking */
 
53
static uint32_t item_lock_mask;
 
54
 
49
55
static LIBEVENT_DISPATCHER_THREAD dispatcher_thread;
50
56
 
51
57
/*
64
70
 
65
71
static void thread_libevent_process(int fd, short which, void *arg);
66
72
 
 
73
void item_lock(uint32_t hv) {
 
74
    mutex_lock(&item_locks[hv & item_lock_mask]);
 
75
}
 
76
 
 
77
void item_unlock(uint32_t hv) {
 
78
    pthread_mutex_unlock(&item_locks[hv & item_lock_mask]);
 
79
}
 
80
 
67
81
/*
68
82
 * Initializes a connection queue.
69
83
 */
328
342
 */
329
343
item *item_alloc(char *key, size_t nkey, int flags, rel_time_t exptime, int nbytes) {
330
344
    item *it;
331
 
    pthread_mutex_lock(&cache_lock);
 
345
    /* do_item_alloc handles its own locks */
332
346
    it = do_item_alloc(key, nkey, flags, exptime, nbytes);
333
 
    pthread_mutex_unlock(&cache_lock);
334
347
    return it;
335
348
}
336
349
 
340
353
 */
341
354
item *item_get(const char *key, const size_t nkey) {
342
355
    item *it;
343
 
    pthread_mutex_lock(&cache_lock);
344
 
    it = do_item_get(key, nkey);
345
 
    pthread_mutex_unlock(&cache_lock);
 
356
    uint32_t hv;
 
357
    hv = hash(key, nkey, 0);
 
358
    item_lock(hv);
 
359
    it = do_item_get(key, nkey, hv);
 
360
    item_unlock(hv);
346
361
    return it;
347
362
}
348
363
 
349
364
item *item_touch(const char *key, size_t nkey, uint32_t exptime) {
350
365
    item *it;
351
 
    pthread_mutex_lock(&cache_lock);
352
 
    it = do_item_touch(key, nkey, exptime);
353
 
    pthread_mutex_unlock(&cache_lock);
 
366
    uint32_t hv;
 
367
    hv = hash(key, nkey, 0);
 
368
    item_lock(hv);
 
369
    it = do_item_touch(key, nkey, exptime, hv);
 
370
    item_unlock(hv);
354
371
    return it;
355
372
}
356
373
 
359
376
 */
360
377
int item_link(item *item) {
361
378
    int ret;
 
379
    uint32_t hv;
362
380
 
363
 
    pthread_mutex_lock(&cache_lock);
364
 
    ret = do_item_link(item);
365
 
    pthread_mutex_unlock(&cache_lock);
 
381
    hv = hash(ITEM_key(item), item->nkey, 0);
 
382
    item_lock(hv);
 
383
    ret = do_item_link(item, hv);
 
384
    item_unlock(hv);
366
385
    return ret;
367
386
}
368
387
 
371
390
 * needed.
372
391
 */
373
392
void item_remove(item *item) {
374
 
    pthread_mutex_lock(&cache_lock);
 
393
    uint32_t hv;
 
394
    hv = hash(ITEM_key(item), item->nkey, 0);
 
395
 
 
396
    item_lock(hv);
375
397
    do_item_remove(item);
376
 
    pthread_mutex_unlock(&cache_lock);
 
398
    item_unlock(hv);
377
399
}
378
400
 
379
401
/*
381
403
 * Unprotected by a mutex lock since the core server does not require
382
404
 * it to be thread-safe.
383
405
 */
384
 
int item_replace(item *old_it, item *new_it) {
385
 
    return do_item_replace(old_it, new_it);
 
406
int item_replace(item *old_it, item *new_it, const uint32_t hv) {
 
407
    return do_item_replace(old_it, new_it, hv);
386
408
}
387
409
 
388
410
/*
389
411
 * Unlinks an item from the LRU and hashtable.
390
412
 */
391
413
void item_unlink(item *item) {
392
 
    pthread_mutex_lock(&cache_lock);
393
 
    do_item_unlink(item);
394
 
    pthread_mutex_unlock(&cache_lock);
 
414
    uint32_t hv;
 
415
    hv = hash(ITEM_key(item), item->nkey, 0);
 
416
    item_lock(hv);
 
417
    do_item_unlink(item, hv);
 
418
    item_unlock(hv);
395
419
}
396
420
 
397
421
/*
398
422
 * Moves an item to the back of the LRU queue.
399
423
 */
400
424
void item_update(item *item) {
401
 
    pthread_mutex_lock(&cache_lock);
 
425
    uint32_t hv;
 
426
    hv = hash(ITEM_key(item), item->nkey, 0);
 
427
 
 
428
    item_lock(hv);
402
429
    do_item_update(item);
403
 
    pthread_mutex_unlock(&cache_lock);
 
430
    item_unlock(hv);
404
431
}
405
432
 
406
433
/*
411
438
                                 const int64_t delta, char *buf,
412
439
                                 uint64_t *cas) {
413
440
    enum delta_result_type ret;
 
441
    uint32_t hv;
414
442
 
415
 
    pthread_mutex_lock(&cache_lock);
416
 
    ret = do_add_delta(c, key, nkey, incr, delta, buf, cas);
417
 
    pthread_mutex_unlock(&cache_lock);
 
443
    hv = hash(key, nkey, 0);
 
444
    item_lock(hv);
 
445
    ret = do_add_delta(c, key, nkey, incr, delta, buf, cas, hv);
 
446
    item_unlock(hv);
418
447
    return ret;
419
448
}
420
449
 
423
452
 */
424
453
enum store_item_type store_item(item *item, int comm, conn* c) {
425
454
    enum store_item_type ret;
 
455
    uint32_t hv;
426
456
 
427
 
    pthread_mutex_lock(&cache_lock);
428
 
    ret = do_store_item(item, comm, c);
429
 
    pthread_mutex_unlock(&cache_lock);
 
457
    hv = hash(ITEM_key(item), item->nkey, 0);
 
458
    item_lock(hv);
 
459
    ret = do_store_item(item, comm, c, hv);
 
460
    item_unlock(hv);
430
461
    return ret;
431
462
}
432
463
 
434
465
 * Flushes expired items after a flush_all call
435
466
 */
436
467
void item_flush_expired() {
437
 
    pthread_mutex_lock(&cache_lock);
 
468
    mutex_lock(&cache_lock);
438
469
    do_item_flush_expired();
439
470
    pthread_mutex_unlock(&cache_lock);
440
471
}
445
476
char *item_cachedump(unsigned int slabs_clsid, unsigned int limit, unsigned int *bytes) {
446
477
    char *ret;
447
478
 
448
 
    pthread_mutex_lock(&cache_lock);
 
479
    mutex_lock(&cache_lock);
449
480
    ret = do_item_cachedump(slabs_clsid, limit, bytes);
450
481
    pthread_mutex_unlock(&cache_lock);
451
482
    return ret;
455
486
 * Dumps statistics about slab classes
456
487
 */
457
488
void  item_stats(ADD_STAT add_stats, void *c) {
458
 
    pthread_mutex_lock(&cache_lock);
 
489
    mutex_lock(&cache_lock);
459
490
    do_item_stats(add_stats, c);
460
491
    pthread_mutex_unlock(&cache_lock);
461
492
}
464
495
 * Dumps a list of objects of each size in 32-byte increments
465
496
 */
466
497
void  item_stats_sizes(ADD_STAT add_stats, void *c) {
467
 
    pthread_mutex_lock(&cache_lock);
 
498
    mutex_lock(&cache_lock);
468
499
    do_item_stats_sizes(add_stats, c);
469
500
    pthread_mutex_unlock(&cache_lock);
470
501
}
594
625
 */
595
626
void thread_init(int nthreads, struct event_base *main_base) {
596
627
    int         i;
 
628
    int         power;
597
629
 
598
630
    pthread_mutex_init(&cache_lock, NULL);
599
631
    pthread_mutex_init(&stats_lock, NULL);
604
636
    pthread_mutex_init(&cqi_freelist_lock, NULL);
605
637
    cqi_freelist = NULL;
606
638
 
 
639
    /* Want a wide lock table, but don't waste memory */
 
640
    if (nthreads < 3) {
 
641
        power = 10;
 
642
    } else if (nthreads < 4) {
 
643
        power = 11;
 
644
    } else if (nthreads < 5) {
 
645
        power = 12;
 
646
    } else {
 
647
        /* 8192 buckets, and central locks don't scale much past 5 threads */
 
648
        power = 13;
 
649
    }
 
650
 
 
651
    item_lock_count = ((unsigned long int)1 << (power));
 
652
    item_lock_mask  = item_lock_count - 1;
 
653
 
 
654
    item_locks = calloc(item_lock_count, sizeof(pthread_mutex_t));
 
655
    if (! item_locks) {
 
656
        perror("Can't allocate item locks");
 
657
        exit(1);
 
658
    }
 
659
    for (i = 0; i < item_lock_count; i++) {
 
660
        pthread_mutex_init(&item_locks[i], NULL);
 
661
    }
 
662
 
607
663
    threads = calloc(nthreads, sizeof(LIBEVENT_THREAD));
608
664
    if (! threads) {
609
665
        perror("Can't allocate thread descriptors");