diff options
Diffstat (limited to 'lib/debugobjects.c')
-rw-r--r-- | lib/debugobjects.c | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/lib/debugobjects.c b/lib/debugobjects.c index fdcda3dbcd35..2755a3bd16a1 100644 --- a/lib/debugobjects.c +++ b/lib/debugobjects.c | |||
@@ -50,6 +50,9 @@ static int debug_objects_enabled __read_mostly | |||
50 | 50 | ||
51 | static struct debug_obj_descr *descr_test __read_mostly; | 51 | static struct debug_obj_descr *descr_test __read_mostly; |
52 | 52 | ||
53 | static void free_obj_work(struct work_struct *work); | ||
54 | static DECLARE_WORK(debug_obj_work, free_obj_work); | ||
55 | |||
53 | static int __init enable_object_debug(char *str) | 56 | static int __init enable_object_debug(char *str) |
54 | { | 57 | { |
55 | debug_objects_enabled = 1; | 58 | debug_objects_enabled = 1; |
@@ -154,25 +157,51 @@ alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr) | |||
154 | } | 157 | } |
155 | 158 | ||
156 | /* | 159 | /* |
157 | * Put the object back into the pool or give it back to kmem_cache: | 160 | * workqueue function to free objects. |
158 | */ | 161 | */ |
159 | static void free_object(struct debug_obj *obj) | 162 | static void free_obj_work(struct work_struct *work) |
160 | { | 163 | { |
161 | unsigned long idx = (unsigned long)(obj - obj_static_pool); | 164 | struct debug_obj *obj; |
162 | unsigned long flags; | 165 | unsigned long flags; |
163 | 166 | ||
164 | if (obj_pool_free < ODEBUG_POOL_SIZE || idx < ODEBUG_POOL_SIZE) { | 167 | spin_lock_irqsave(&pool_lock, flags); |
165 | spin_lock_irqsave(&pool_lock, flags); | 168 | while (obj_pool_free > ODEBUG_POOL_SIZE) { |
166 | hlist_add_head(&obj->node, &obj_pool); | 169 | obj = hlist_entry(obj_pool.first, typeof(*obj), node); |
167 | obj_pool_free++; | 170 | hlist_del(&obj->node); |
168 | obj_pool_used--; | 171 | obj_pool_free--; |
169 | spin_unlock_irqrestore(&pool_lock, flags); | 172 | /* |
170 | } else { | 173 | * We release pool_lock across kmem_cache_free() to |
171 | spin_lock_irqsave(&pool_lock, flags); | 174 | * avoid contention on pool_lock. |
172 | obj_pool_used--; | 175 | */ |
173 | spin_unlock_irqrestore(&pool_lock, flags); | 176 | spin_unlock_irqrestore(&pool_lock, flags); |
174 | kmem_cache_free(obj_cache, obj); | 177 | kmem_cache_free(obj_cache, obj); |
178 | spin_lock_irqsave(&pool_lock, flags); | ||
175 | } | 179 | } |
180 | spin_unlock_irqrestore(&pool_lock, flags); | ||
181 | } | ||
182 | |||
183 | /* | ||
184 | * Put the object back into the pool and schedule work to free objects | ||
185 | * if necessary. | ||
186 | */ | ||
187 | static void free_object(struct debug_obj *obj) | ||
188 | { | ||
189 | unsigned long flags; | ||
190 | int sched = 0; | ||
191 | |||
192 | spin_lock_irqsave(&pool_lock, flags); | ||
193 | /* | ||
194 | * schedule work when the pool is filled and the cache is | ||
195 | * initialized: | ||
196 | */ | ||
197 | if (obj_pool_free > ODEBUG_POOL_SIZE && obj_cache) | ||
198 | sched = !work_pending(&debug_obj_work); | ||
199 | hlist_add_head(&obj->node, &obj_pool); | ||
200 | obj_pool_free++; | ||
201 | obj_pool_used--; | ||
202 | spin_unlock_irqrestore(&pool_lock, flags); | ||
203 | if (sched) | ||
204 | schedule_work(&debug_obj_work); | ||
176 | } | 205 | } |
177 | 206 | ||
178 | /* | 207 | /* |