@@ -52,6 +52,11 @@ struct debug_percpu_free {
5252 int obj_free ;
5353};
5454
55+ struct obj_pool {
56+ struct hlist_head objects ;
57+ unsigned int cnt ;
58+ } ____cacheline_aligned ;
59+
5560static DEFINE_PER_CPU (struct debug_percpu_free , percpu_obj_pool ) ;
5661
5762static struct debug_bucket obj_hash [ODEBUG_HASH_SIZE ];
@@ -60,8 +65,8 @@ static struct debug_obj obj_static_pool[ODEBUG_POOL_SIZE] __initdata;
6065
6166static DEFINE_RAW_SPINLOCK (pool_lock );
6267
63- static HLIST_HEAD ( obj_pool ) ;
64- static HLIST_HEAD ( obj_to_free ) ;
68+ static struct obj_pool pool_global ;
69+ static struct obj_pool pool_to_free ;
6570
6671/*
6772 * Because of the presence of percpu free pools, obj_pool_free will
@@ -71,12 +76,9 @@ static HLIST_HEAD(obj_to_free);
7176 * can be off.
7277 */
7378static int __data_racy obj_pool_min_free = ODEBUG_POOL_SIZE ;
74- static int __data_racy obj_pool_free = ODEBUG_POOL_SIZE ;
7579static int obj_pool_used ;
7680static int __data_racy obj_pool_max_used ;
7781static bool obj_freeing ;
78- /* The number of objs on the global free list */
79- static int obj_nr_tofree ;
8082
8183static int __data_racy debug_objects_maxchain __read_mostly ;
8284static int __data_racy __maybe_unused debug_objects_maxchecked __read_mostly ;
@@ -124,6 +126,21 @@ static const char *obj_states[ODEBUG_STATE_MAX] = {
124126 [ODEBUG_STATE_NOTAVAILABLE ] = "not available" ,
125127};
126128
129+ static __always_inline unsigned int pool_count (struct obj_pool * pool )
130+ {
131+ return READ_ONCE (pool -> cnt );
132+ }
133+
134+ static inline bool pool_global_should_refill (void )
135+ {
136+ return READ_ONCE (pool_global .cnt ) < debug_objects_pool_min_level ;
137+ }
138+
139+ static inline bool pool_global_must_refill (void )
140+ {
141+ return READ_ONCE (pool_global .cnt ) < (debug_objects_pool_min_level / 2 );
142+ }
143+
127144static void free_object_list (struct hlist_head * head )
128145{
129146 struct hlist_node * tmp ;
@@ -146,11 +163,8 @@ static void fill_pool_from_freelist(void)
146163 /*
147164 * Reuse objs from the global obj_to_free list; they will be
148165 * reinitialized when allocating.
149- *
150- * obj_nr_tofree is checked locklessly; the READ_ONCE() pairs with
151- * the WRITE_ONCE() in pool_lock critical sections.
152166 */
153- if (!READ_ONCE ( obj_nr_tofree ))
167+ if (!pool_count ( & pool_to_free ))
154168 return ;
155169
156170 /*
@@ -171,12 +185,12 @@ static void fill_pool_from_freelist(void)
171185 * Recheck with the lock held as the worker thread might have
172186 * won the race and freed the global free list already.
173187 */
174- while (obj_nr_tofree && (obj_pool_free < debug_objects_pool_min_level )) {
175- obj = hlist_entry (obj_to_free .first , typeof (* obj ), node );
188+ while (pool_to_free . cnt && (pool_global . cnt < debug_objects_pool_min_level )) {
189+ obj = hlist_entry (pool_to_free . objects .first , typeof (* obj ), node );
176190 hlist_del (& obj -> node );
177- WRITE_ONCE (obj_nr_tofree , obj_nr_tofree - 1 );
178- hlist_add_head (& obj -> node , & obj_pool );
179- WRITE_ONCE (obj_pool_free , obj_pool_free + 1 );
191+ WRITE_ONCE (pool_to_free . cnt , pool_to_free . cnt - 1 );
192+ hlist_add_head (& obj -> node , & pool_global . objects );
193+ WRITE_ONCE (pool_global . cnt , pool_global . cnt + 1 );
180194 }
181195 clear_bit (0 , & state );
182196}
@@ -190,12 +204,11 @@ static void fill_pool(void)
190204 * - One other CPU is already allocating
191205 * - the global pool has not reached the critical level yet
192206 */
193- if (READ_ONCE (obj_pool_free ) > (debug_objects_pool_min_level / 2 ) &&
194- atomic_read (& cpus_allocating ))
207+ if (!pool_global_must_refill () && atomic_read (& cpus_allocating ))
195208 return ;
196209
197210 atomic_inc (& cpus_allocating );
198- while (READ_ONCE ( obj_pool_free ) < debug_objects_pool_min_level ) {
211+ while (pool_global_should_refill () ) {
199212 struct debug_obj * new , * last = NULL ;
200213 HLIST_HEAD (head );
201214 int cnt ;
@@ -212,9 +225,9 @@ static void fill_pool(void)
212225 break ;
213226
214227 guard (raw_spinlock_irqsave )(& pool_lock );
215- hlist_splice_init (& head , & last -> node , & obj_pool );
228+ hlist_splice_init (& head , & last -> node , & pool_global . objects );
216229 debug_objects_allocated += cnt ;
217- WRITE_ONCE (obj_pool_free , obj_pool_free + cnt );
230+ WRITE_ONCE (pool_global . cnt , pool_global . cnt + cnt );
218231 }
219232 atomic_dec (& cpus_allocating );
220233}
@@ -268,10 +281,10 @@ alloc_object(void *addr, struct debug_bucket *b, const struct debug_obj_descr *d
268281 }
269282
270283 raw_spin_lock (& pool_lock );
271- obj = __alloc_object (& obj_pool );
284+ obj = __alloc_object (& pool_global . objects );
272285 if (obj ) {
273286 obj_pool_used ++ ;
274- WRITE_ONCE (obj_pool_free , obj_pool_free - 1 );
287+ WRITE_ONCE (pool_global . cnt , pool_global . cnt - 1 );
275288
276289 /*
277290 * Looking ahead, allocate one batch of debug objects and
@@ -283,22 +296,21 @@ alloc_object(void *addr, struct debug_bucket *b, const struct debug_obj_descr *d
283296 for (i = 0 ; i < ODEBUG_BATCH_SIZE ; i ++ ) {
284297 struct debug_obj * obj2 ;
285298
286- obj2 = __alloc_object (& obj_pool );
299+ obj2 = __alloc_object (& pool_global . objects );
287300 if (!obj2 )
288301 break ;
289- hlist_add_head (& obj2 -> node ,
290- & percpu_pool -> free_objs );
302+ hlist_add_head (& obj2 -> node , & percpu_pool -> free_objs );
291303 percpu_pool -> obj_free ++ ;
292304 obj_pool_used ++ ;
293- WRITE_ONCE (obj_pool_free , obj_pool_free - 1 );
305+ WRITE_ONCE (pool_global . cnt , pool_global . cnt - 1 );
294306 }
295307 }
296308
297309 if (obj_pool_used > obj_pool_max_used )
298310 obj_pool_max_used = obj_pool_used ;
299311
300- if (obj_pool_free < obj_pool_min_free )
301- obj_pool_min_free = obj_pool_free ;
312+ if (pool_global . cnt < obj_pool_min_free )
313+ obj_pool_min_free = pool_global . cnt ;
302314 }
303315 raw_spin_unlock (& pool_lock );
304316
@@ -329,7 +341,7 @@ static void free_obj_work(struct work_struct *work)
329341 if (!raw_spin_trylock_irqsave (& pool_lock , flags ))
330342 return ;
331343
332- if (obj_pool_free >= debug_objects_pool_size )
344+ if (pool_global . cnt >= debug_objects_pool_size )
333345 goto free_objs ;
334346
335347 /*
@@ -339,12 +351,12 @@ static void free_obj_work(struct work_struct *work)
339351 * may be gearing up to use more and more objects, don't free any
340352 * of them until the next round.
341353 */
342- while (obj_nr_tofree && obj_pool_free < debug_objects_pool_size ) {
343- obj = hlist_entry (obj_to_free .first , typeof (* obj ), node );
354+ while (pool_to_free . cnt && pool_global . cnt < debug_objects_pool_size ) {
355+ obj = hlist_entry (pool_to_free . objects .first , typeof (* obj ), node );
344356 hlist_del (& obj -> node );
345- hlist_add_head (& obj -> node , & obj_pool );
346- WRITE_ONCE (obj_pool_free , obj_pool_free + 1 );
347- WRITE_ONCE (obj_nr_tofree , obj_nr_tofree - 1 );
357+ hlist_add_head (& obj -> node , & pool_global . objects );
358+ WRITE_ONCE (pool_to_free . cnt , pool_to_free . cnt - 1 );
359+ WRITE_ONCE (pool_global . cnt , pool_global . cnt + 1 );
348360 }
349361 raw_spin_unlock_irqrestore (& pool_lock , flags );
350362 return ;
@@ -355,9 +367,9 @@ static void free_obj_work(struct work_struct *work)
355367 * list. Move remaining free objs to a temporary list to free the
356368 * memory outside the pool_lock held region.
357369 */
358- if (obj_nr_tofree ) {
359- hlist_move_list (& obj_to_free , & tofree );
360- WRITE_ONCE (obj_nr_tofree , 0 );
370+ if (pool_to_free . cnt ) {
371+ hlist_move_list (& pool_to_free . objects , & tofree );
372+ WRITE_ONCE (pool_to_free . cnt , 0 );
361373 }
362374 raw_spin_unlock_irqrestore (& pool_lock , flags );
363375
@@ -400,45 +412,45 @@ static void __free_object(struct debug_obj *obj)
400412
401413free_to_obj_pool :
402414 raw_spin_lock (& pool_lock );
403- work = (obj_pool_free > debug_objects_pool_size ) && obj_cache &&
404- (obj_nr_tofree < ODEBUG_FREE_WORK_MAX );
415+ work = (pool_global . cnt > debug_objects_pool_size ) && obj_cache &&
416+ (pool_to_free . cnt < ODEBUG_FREE_WORK_MAX );
405417 obj_pool_used -- ;
406418
407419 if (work ) {
408- WRITE_ONCE (obj_nr_tofree , obj_nr_tofree + 1 );
409- hlist_add_head (& obj -> node , & obj_to_free );
420+ WRITE_ONCE (pool_to_free . cnt , pool_to_free . cnt + 1 );
421+ hlist_add_head (& obj -> node , & pool_to_free . objects );
410422 if (lookahead_count ) {
411- WRITE_ONCE (obj_nr_tofree , obj_nr_tofree + lookahead_count );
423+ WRITE_ONCE (pool_to_free . cnt , pool_to_free . cnt + lookahead_count );
412424 obj_pool_used -= lookahead_count ;
413425 while (lookahead_count ) {
414426 hlist_add_head (& objs [-- lookahead_count ]-> node ,
415- & obj_to_free );
427+ & pool_to_free . objects );
416428 }
417429 }
418430
419- if ((obj_pool_free > debug_objects_pool_size ) &&
420- (obj_nr_tofree < ODEBUG_FREE_WORK_MAX )) {
431+ if ((pool_global . cnt > debug_objects_pool_size ) &&
432+ (pool_to_free . cnt < ODEBUG_FREE_WORK_MAX )) {
421433 int i ;
422434
423435 /*
424436 * Free one more batch of objects from obj_pool.
425437 */
426438 for (i = 0 ; i < ODEBUG_BATCH_SIZE ; i ++ ) {
427- obj = __alloc_object (& obj_pool );
428- hlist_add_head (& obj -> node , & obj_to_free );
429- WRITE_ONCE (obj_pool_free , obj_pool_free - 1 );
430- WRITE_ONCE (obj_nr_tofree , obj_nr_tofree + 1 );
439+ obj = __alloc_object (& pool_global . objects );
440+ hlist_add_head (& obj -> node , & pool_to_free . objects );
441+ WRITE_ONCE (pool_global . cnt , pool_global . cnt - 1 );
442+ WRITE_ONCE (pool_to_free . cnt , pool_to_free . cnt + 1 );
431443 }
432444 }
433445 } else {
434- WRITE_ONCE (obj_pool_free , obj_pool_free + 1 );
435- hlist_add_head (& obj -> node , & obj_pool );
446+ WRITE_ONCE (pool_global . cnt , pool_global . cnt + 1 );
447+ hlist_add_head (& obj -> node , & pool_global . objects );
436448 if (lookahead_count ) {
437- WRITE_ONCE (obj_pool_free , obj_pool_free + lookahead_count );
449+ WRITE_ONCE (pool_global . cnt , pool_global . cnt + lookahead_count );
438450 obj_pool_used -= lookahead_count ;
439451 while (lookahead_count ) {
440452 hlist_add_head (& objs [-- lookahead_count ]-> node ,
441- & obj_pool );
453+ & pool_global . objects );
442454 }
443455 }
444456 }
@@ -453,7 +465,7 @@ static void __free_object(struct debug_obj *obj)
453465static void free_object (struct debug_obj * obj )
454466{
455467 __free_object (obj );
456- if (!READ_ONCE (obj_freeing ) && READ_ONCE ( obj_nr_tofree )) {
468+ if (!READ_ONCE (obj_freeing ) && pool_count ( & pool_to_free )) {
457469 WRITE_ONCE (obj_freeing , true);
458470 schedule_delayed_work (& debug_obj_work , ODEBUG_FREE_WORK_DELAY );
459471 }
@@ -622,13 +634,13 @@ static void debug_objects_fill_pool(void)
622634 if (unlikely (!obj_cache ))
623635 return ;
624636
625- if (likely (READ_ONCE ( obj_pool_free ) >= debug_objects_pool_min_level ))
637+ if (likely (! pool_global_should_refill () ))
626638 return ;
627639
628640 /* Try reusing objects from obj_to_free_list */
629641 fill_pool_from_freelist ();
630642
631- if (likely (READ_ONCE ( obj_pool_free ) >= debug_objects_pool_min_level ))
643+ if (likely (! pool_global_should_refill () ))
632644 return ;
633645
634646 /*
@@ -1040,7 +1052,7 @@ static void __debug_check_no_obj_freed(const void *address, unsigned long size)
10401052 debug_objects_maxchecked = objs_checked ;
10411053
10421054 /* Schedule work to actually kmem_cache_free() objects */
1043- if (!READ_ONCE (obj_freeing ) && READ_ONCE ( obj_nr_tofree )) {
1055+ if (!READ_ONCE (obj_freeing ) && pool_count ( & pool_to_free )) {
10441056 WRITE_ONCE (obj_freeing , true);
10451057 schedule_delayed_work (& debug_obj_work , ODEBUG_FREE_WORK_DELAY );
10461058 }
@@ -1066,12 +1078,12 @@ static int debug_stats_show(struct seq_file *m, void *v)
10661078 seq_printf (m , "max_checked :%d\n" , debug_objects_maxchecked );
10671079 seq_printf (m , "warnings :%d\n" , debug_objects_warnings );
10681080 seq_printf (m , "fixups :%d\n" , debug_objects_fixups );
1069- seq_printf (m , "pool_free :%d\n" , READ_ONCE ( obj_pool_free ) + obj_percpu_free );
1081+ seq_printf (m , "pool_free :%d\n" , pool_count ( & pool_global ) + obj_percpu_free );
10701082 seq_printf (m , "pool_pcp_free :%d\n" , obj_percpu_free );
10711083 seq_printf (m , "pool_min_free :%d\n" , obj_pool_min_free );
10721084 seq_printf (m , "pool_used :%d\n" , obj_pool_used - obj_percpu_free );
10731085 seq_printf (m , "pool_max_used :%d\n" , obj_pool_max_used );
1074- seq_printf (m , "on_free_list :%d\n" , READ_ONCE ( obj_nr_tofree ));
1086+ seq_printf (m , "on_free_list :%d\n" , pool_count ( & pool_to_free ));
10751087 seq_printf (m , "objs_allocated:%d\n" , debug_objects_allocated );
10761088 seq_printf (m , "objs_freed :%d\n" , debug_objects_freed );
10771089 return 0 ;
@@ -1330,7 +1342,9 @@ void __init debug_objects_early_init(void)
13301342 raw_spin_lock_init (& obj_hash [i ].lock );
13311343
13321344 for (i = 0 ; i < ODEBUG_POOL_SIZE ; i ++ )
1333- hlist_add_head (& obj_static_pool [i ].node , & obj_pool );
1345+ hlist_add_head (& obj_static_pool [i ].node , & pool_global .objects );
1346+
1347+ pool_global .cnt = ODEBUG_POOL_SIZE ;
13341348}
13351349
13361350/*
@@ -1354,21 +1368,23 @@ static bool __init debug_objects_replace_static_objects(struct kmem_cache *cache
13541368 hlist_add_head (& obj -> node , & objects );
13551369 }
13561370
1357- debug_objects_allocated += i ;
1371+ debug_objects_allocated = ODEBUG_POOL_SIZE ;
1372+ pool_global .cnt = ODEBUG_POOL_SIZE ;
13581373
13591374 /*
13601375 * Replace the statically allocated objects list with the allocated
13611376 * objects list.
13621377 */
1363- hlist_move_list (& objects , & obj_pool );
1378+ hlist_move_list (& objects , & pool_global . objects );
13641379
13651380 /* Replace the active object references */
13661381 for (i = 0 ; i < ODEBUG_HASH_SIZE ; i ++ , db ++ ) {
13671382 hlist_move_list (& db -> list , & objects );
13681383
13691384 hlist_for_each_entry (obj , & objects , node ) {
1370- new = hlist_entry (obj_pool .first , typeof (* obj ), node );
1385+ new = hlist_entry (pool_global . objects .first , typeof (* obj ), node );
13711386 hlist_del (& new -> node );
1387+ pool_global .cnt -- ;
13721388 /* copy object data */
13731389 * new = * obj ;
13741390 hlist_add_head (& new -> node , & db -> list );
0 commit comments