static struct obj_pool pool_global;
static struct obj_pool pool_to_free;
+static HLIST_HEAD(pool_boot);
+
/*
* Because of the presence of percpu free pools, obj_pool_free will
* under-count those in the percpu free pools. Similarly, obj_pool_used
percpu_pool->obj_free--;
goto init_obj;
}
+ } else {
+ obj = __alloc_object(&pool_boot);
+ goto init_obj;
}
raw_spin_lock(&pool_lock);
struct debug_obj *objs[ODEBUG_BATCH_SIZE];
struct debug_percpu_free *percpu_pool;
int lookahead_count = 0;
- unsigned long flags;
bool work;
- local_irq_save(flags);
- if (!obj_cache)
- goto free_to_obj_pool;
+ guard(irqsave)();
+
+ if (unlikely(!obj_cache)) {
+ hlist_add_head(&obj->node, &pool_boot);
+ return;
+ }
/*
* Try to free it into the percpu pool first.
if (percpu_pool->obj_free < ODEBUG_POOL_PERCPU_SIZE) {
hlist_add_head(&obj->node, &percpu_pool->free_objs);
percpu_pool->obj_free++;
- local_irq_restore(flags);
return;
}
percpu_pool->obj_free--;
}
-free_to_obj_pool:
raw_spin_lock(&pool_lock);
work = (pool_global.cnt > debug_objects_pool_size) && obj_cache &&
(pool_to_free.cnt < ODEBUG_FREE_WORK_MAX);
}
}
raw_spin_unlock(&pool_lock);
- local_irq_restore(flags);
}
/*
for (i = 0; i < ODEBUG_HASH_SIZE; i++)
raw_spin_lock_init(&obj_hash[i].lock);
+ /* Keep early boot simple and add everything to the boot list */
for (i = 0; i < ODEBUG_POOL_SIZE; i++)
- hlist_add_head(&obj_static_pool[i].node, &pool_global.objects);
-
- pool_global.cnt = ODEBUG_POOL_SIZE;
+ hlist_add_head(&obj_static_pool[i].node, &pool_boot);
}
/*
pool_global.cnt = ODEBUG_POOL_SIZE;
/*
- * Replace the statically allocated objects list with the allocated
- * objects list.
+ * Move the allocated objects to the global pool and disconnect the
+ * boot pool.
*/
hlist_move_list(&objects, &pool_global.objects);
+ pool_boot.first = NULL;
/* Replace the active object references */
for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) {