/* Slab mover thread. * Sits waiting for a condition to jump off and shovel some memory about */ static void *slab_rebalance_thread(void *arg) { int was_busy = 0; /* So we first pass into cond_wait with the mutex held */ mutex_lock(&slabs_rebalance_lock); while (do_run_slab_rebalance_thread) { if (slab_rebalance_signal == 1) { if (slab_rebalance_start() < 0) { /* Handle errors with more specifity as required. */ slab_rebalance_signal = 0; } was_busy = 0; } else if (slab_rebalance_signal && slab_rebal.slab_start != NULL) { was_busy = slab_rebalance_move(); } if (slab_rebal.done) { slab_rebalance_finish(); } else if (was_busy) { /* Stuck waiting for some items to unlock, so slow down a bit * to give them a chance to free up */ usleep(50); } if (slab_rebalance_signal == 0) { /* always hold this lock while we're running */ pthread_cond_wait(&slab_rebalance_cond, &slabs_rebalance_lock); } } return NULL; }
/* Slab rebalancer thread. * Does not use spinlocks since it is not timing sensitive. Burn less CPU and * go to sleep if locks are contended */ static void *slab_maintenance_thread(void *arg) { int was_busy = 0; int src, dest; while (do_run_slab_thread) { if (slab_rebalance_signal == 1) { if (slab_rebalance_start() < 0) { /* Handle errors with more specifity as required. */ slab_rebalance_signal = 0; } } else if (slab_rebalance_signal && slab_rebal.slab_start != NULL) { /* If we have a decision to continue, continue it */ was_busy = slab_rebalance_move(); } else if (settings.slab_automove && slab_automove_decision(&src, &dest) == 1) { /* Blind to the return codes. It will retry on its own */ slabs_reassign(src, dest); } if (slab_rebal.done) { slab_rebalance_finish(); } /* Sleep a bit if no work to do, or waiting on busy objects */ if (was_busy || !slab_rebalance_signal) sleep(1); } return NULL; }
/* Slab mover thread. * Sits waiting for a condition to jump off and shovel some memory about */ static void *slab_rebalance_thread(void *arg) { int was_busy = 0; /* So we first pass into cond_wait with the mutex held */ mutex_lock(&slabs_rebalance_lock); while (do_run_slab_rebalance_thread) { if (slab_rebalance_signal == 1) { //标志要移动的内存页的信息,并将slab_rebalance_signal赋值为2 //slab_rebal.done赋值为0,表示没有完成 if (slab_rebalance_start() < 0) {//失败 /* Handle errors with more specifity as required. */ slab_rebalance_signal = 0; } was_busy = 0; } else if (slab_rebalance_signal && slab_rebal.slab_start != NULL) { was_busy = slab_rebalance_move();//进行内存页迁移操作 } if (slab_rebal.done) {//完成内存页重分配操作 slab_rebalance_finish(); } else if (was_busy) {//有worker线程在使用内存页上的item /* Stuck waiting for some items to unlock, so slow down a bit * to give them a chance to free up */ usleep(50);//休眠一会儿,等待worker线程放弃使用item,然后再次尝试 } if (slab_rebalance_signal == 0) {//一开始就在这里休眠 /* always hold this lock while we're running */ pthread_cond_wait(&slab_rebalance_cond, &slabs_rebalance_lock); } } return NULL; }
/* Slab mover thread. * Sits waiting for a condition to jump off and shovel some memory about */ static void *slab_rebalance_thread(void *arg) { int was_busy = 0; /* So we first pass into cond_wait with the mutex held */ mutex_lock(&slabs_rebalance_lock); while (do_run_slab_rebalance_thread) { if (slab_rebalance_signal == 1) { if (slab_rebalance_start() < 0) //确定src中删除开始的slab开始的指针。 { /* Handle errors with more specifity as required. */ slab_rebalance_signal = 0; } was_busy = 0; } else if (slab_rebalance_signal && slab_rebal.slab_start != NULL) { /* 开始删除src的那个slab item(hash结构,lru链表),每次删除1个item,函数在while结构中会被重复执行,直到那个slab中item被完全 删除成功,每次删除一个也是为了控制锁的持有时间,毕竟这个锁持有时间越长,就会导致hash结构插入操作等待锁的时间变长 */ was_busy = slab_rebalance_move(); } if (slab_rebal.done) //如果已经删除完毕,开始把slab_rebal中的空间给dest,这个空间来源于上部删除的src的空间 { slab_rebalance_finish(); } else if (was_busy) { /* Stuck waiting for some items to unlock, so slow down a bit * to give them a chance to free up */ usleep(50); } if (slab_rebalance_signal == 0) { /* always hold this lock while we're running */ pthread_cond_wait(&slab_rebalance_cond, &slabs_rebalance_lock); } } return NULL; }