* locking hierarchy based on lockdep
@ 2006-11-06 18:32 Jason Baron
2006-11-06 20:05 ` Ingo Molnar
0 siblings, 1 reply; 13+ messages in thread
From: Jason Baron @ 2006-11-06 18:32 UTC (permalink / raw)
To: linux-kernel; +Cc: mingo, arjan
hi,
So based on Ingo and Arjan's lockdep, i thought it would be interesting to
generate a 'locking hierarchy' for the entire kernel. That is for each
lock we assign a number, such that if a < b than lock a must be taken
before lock b. I've done this by doing a depth first search on the lockdep
structures already present in the kernel. This is not a unique ordering
nor is it entirely correct, in the sense that if a path is not traversed
by the kernel, the ordering produced might not be correct. Ideas for this
list might be a starting point for Documenting the locking hierarchy or
even producing a prescriptive lock checker for the kernel, which would
have a lower runtime overhead...other ideas?
I've implemented this as a /proc file, but Ingo suggested that it might be
better for us to simply produce an adjaceny list, and then generate a
locking hierarchy or anything else of interest off of that list....In any
case below is a patch that generates the hierarchy in a /proc file and
i've included a list from a booted kernel...this patch isn't meant as
'this should be merged' but rather as a starting point for a diccussion,
if people are interested.
thanks,
-jason
--- linux-2.6.18/include/linux/lockdep.h.bak 2006-11-01 09:27:23.000000000 -0500
+++ linux-2.6.18/include/linux/lockdep.h 2006-11-02 07:15:07.000000000 -0500
@@ -112,6 +119,7 @@ struct lock_class {
const char *name;
int name_version;
+ struct list_head lock_ordering_entry;
};
/*
@@ -132,6 +140,7 @@ struct lock_list {
struct list_head entry;
struct lock_class *class;
struct stack_trace trace;
+ int distance;
};
/*
--- linux-2.6.18/kernel/lockdep.c.bak 2006-11-01 08:57:22.000000000 -0500
+++ linux-2.6.18/kernel/lockdep.c 2006-11-02 07:14:40.000000000 -0500
@@ -48,7 +48,7 @@
* to use a raw spinlock - we really dont want the spinlock
* code to recurse back into the lockdep code.
*/
-static raw_spinlock_t hash_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
+raw_spinlock_t hash_lock = (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED;
static int lockdep_initialized;
@@ -454,7 +454,7 @@ static void print_lock_dependencies(stru
* Add a new dependency to the head of the list:
*/
static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
- struct list_head *head, unsigned long ip)
+ struct list_head *head, unsigned long ip, int distance)
{
struct lock_list *entry;
/*
@@ -466,6 +466,7 @@ static int add_lock_to_list(struct lock_
return 0;
entry->class = this;
+ entry->distance = distance;
save_trace(&entry->trace);
/*
@@ -856,7 +857,7 @@ check_deadlock(struct task_struct *curr,
*/
static int
check_prev_add(struct task_struct *curr, struct held_lock *prev,
- struct held_lock *next)
+ struct held_lock *next, int distance)
{
struct lock_list *entry;
int ret;
@@ -934,8 +935,11 @@ check_prev_add(struct task_struct *curr,
* L2 added to its dependency list, due to the first chain.)
*/
list_for_each_entry(entry, &prev->class->locks_after, entry) {
- if (entry->class == next->class)
+ if (entry->class == next->class) {
+ if (distance == 1)
+ entry->distance = 1;
return 2;
+ }
}
/*
@@ -943,7 +947,8 @@ check_prev_add(struct task_struct *curr,
* to the previous lock's dependency list:
*/
ret = add_lock_to_list(prev->class, next->class,
- &prev->class->locks_after, next->acquire_ip);
+ &prev->class->locks_after, next->acquire_ip, distance);
+
if (!ret)
return 0;
/*
@@ -953,7 +958,7 @@ check_prev_add(struct task_struct *curr,
if (ret == 2)
return 2;
ret = add_lock_to_list(next->class, prev->class,
- &next->class->locks_before, next->acquire_ip);
+ &next->class->locks_before, next->acquire_ip, distance);
/*
* Debugging printouts:
@@ -999,13 +1004,14 @@ check_prevs_add(struct task_struct *curr
goto out_bug;
for (;;) {
+ int distance = curr->lockdep_depth - depth + 1;
hlock = curr->held_locks + depth-1;
/*
* Only non-recursive-read entries get new dependencies
* added:
*/
if (hlock->read != 2) {
- check_prev_add(curr, hlock, next);
+ check_prev_add(curr, hlock, next, distance);
/*
* Stop after the first non-trylock entry,
* as non-trylock entries have added their
@@ -2702,3 +2708,45 @@ void debug_show_held_locks(struct task_s
EXPORT_SYMBOL_GPL(debug_show_held_locks);
+//create a list of the lock ordering
+
+LIST_HEAD(ordering_list_head);
+
+void dfs_lock_sort(struct lock_class *class) {
+
+ struct lock_list *entry;
+
+ class->version = 1;
+
+ list_for_each_entry(entry, &class->locks_after, entry) {
+ if (entry->class->version == 0 && entry->distance == 1)
+ dfs_lock_sort(entry->class);
+ }
+
+ class->version = 2;
+ list_add(&class->lock_ordering_entry, &ordering_list_head);
+
+}
+
+
+struct list_head *generate_lock_ordering() {
+
+ struct lock_class *class;
+
+ //first mark everything not visisted.
+ list_for_each_entry(class, &all_lock_classes, lock_entry) {
+ class->version = 0;
+ }
+
+ INIT_LIST_HEAD(&ordering_list_head);
+
+ list_for_each_entry(class, &all_lock_classes, lock_entry) {
+ if (class->version == 0)
+ dfs_lock_sort(class);
+ }
+
+ return &ordering_list_head;
+
+}
+
+
--- linux-2.6.18/kernel/lockdep_proc.c.bak 2006-11-01 08:57:32.000000000 -0500
+++ linux-2.6.18/kernel/lockdep_proc.c 2006-11-02 08:14:14.000000000 -0500
@@ -16,6 +16,7 @@
#include <linux/seq_file.h>
#include <linux/kallsyms.h>
#include <linux/debug_locks.h>
+#include <asm/uaccess.h>
#include "lockdep_internals.h"
@@ -326,6 +327,43 @@ static struct file_operations proc_lockd
.release = seq_release,
};
+static int lockdep_ordering_show(struct seq_file *m, void *v)
+{
+
+ struct list_head *tmp_head;
+ struct lock_class *class;
+ unsigned long flags;
+ int i = 0;
+
+ raw_local_irq_save(flags);
+ __raw_spin_lock(&hash_lock);
+
+ tmp_head = generate_lock_ordering();
+
+ list_for_each_entry(class, tmp_head, lock_ordering_entry) {
+ seq_printf(m, "%i: %s\n", i, class->name);
+ i++;
+ }
+
+ __raw_spin_unlock(&hash_lock);
+ raw_local_irq_restore(flags);
+
+ return 0;
+
+}
+
+static int lockdep_ordering_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, lockdep_ordering_show, NULL);
+}
+
+static struct file_operations proc_lockdep_ordering_operations = {
+ .open = lockdep_ordering_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
static int __init lockdep_proc_init(void)
{
struct proc_dir_entry *entry;
@@ -338,6 +376,10 @@ static int __init lockdep_proc_init(void
if (entry)
entry->proc_fops = &proc_lockdep_stats_operations;
+ entry = create_proc_entry("lockdep_ordering", S_IRUSR, NULL);
+ if (entry)
+ entry->proc_fops = &proc_lockdep_ordering_operations;
+
return 0;
}
--- linux-2.6.18/kernel/lockdep_internals.h.bak 2006-11-02 08:18:24.000000000 -0500
+++ linux-2.6.18/kernel/lockdep_internals.h 2006-11-02 07:15:27.000000000 -0500
@@ -30,6 +30,8 @@
#define MAX_STACK_TRACE_ENTRIES 262144UL
extern struct list_head all_lock_classes;
+extern raw_spinlock_t hash_lock;
+extern struct list_head *generate_lock_ordering(void);
extern void
get_usage_chars(struct lock_class *class, char *c1, char *c2, char *c3, char *c4);
> cat /proc/lockdep_ordering
0: entries_lock
1: &undo_list->lock
2: slock-AF_INET
3: &fbc->lock
4: dst_lock
5: ip6_frag_lock
6: ipfrag_lock
7: allocated_ptys.lock
8: slock-AF_INET6
9: tcp_death_row.death_lock
10: fib6_gc_lock
11: i8253_beep_lock
12: &ids->mutex
13: &atkbd->event_mutex
14: vt_activate_queue.lock
15: &tty->atomic_read_lock
16: &entry->access
17: &im->lock
18: log_wait.lock
19: acpi_bus_event_queue.lock
20: acpi_system_event_lock
21: &type->s_umount_key
22: hci_dev_list_lock
23: old_style_rw_init
24: &list->lock
25: &d->lock
26: af_callback_keys + sk->sk_family
27: old_style_rw_init
28: hci_cb_list_lock
29: sk_lock-AF_BLUETOOTH
30: slock-AF_BLUETOOTH
31: old_style_rw_init
32: hci_task_lock
33: &ps->lock
34: hci_notifier.lock
35: &ep->lock
36: &ep->sem
37: &file->f_ep_lock
38: &type->s_umount_key
39: &type->s_lock_key
40: cache_list_lock
41: &key->sem
42: key_construction_sem
43: old_style_spin_init
44: key_serial_lock
45: key_user_lock
46: task_capability_lock
47: inet_peer_unused_lock
48: &rcu_bh_ctrlblk.lock
49: peer_pool_lock
50: &txdr->tx_lock
51: &adapter->tx_queue_lock
52: &adapter->stats_lock
53: af_callback_keys + sk->sk_family
54: sk_lock-AF_PACKET
55: &po->bind_lock
56: sk_lock-AF_INET
57: af_callback_keys + sk->sk_family
58: slock-AF_INET
59: inet_peer_idlock
60: rt_peer_lock
61: ip_conntrack_lock
62: ip6_ra_lock
63: ipv6_sk_ac_lock
64: sk_lock-AF_INET6
65: tcp_hashinfo.lhash_wait.lock
66: &newsk->sk_dst_lock
67: slock-AF_PACKET
68: ipv6_sk_mc_lock
69: af_callback_keys + sk->sk_family
70: tcp_hashinfo.lhash_lock
71: &sk->sk_dst_lock
72: udp_hash_lock
73: &xt[i].mutex
74: &table->lock
75: nf_sockopt_mutex
76: slock-AF_INET6
77: tcp_lock
78: &queue->syn_wait_lock
79: &tcp_hashinfo.bhash[i].lock
80: &tcp_hashinfo.ehash[i].lock
81: addrconf_hash_lock
82: addrconf_verify_lock
83: inet6_proto_lock
84: raw_v6_lock
85: inetsw6_lock
86: &policy->lock
87: disable_ratelimit_lock
88: performance_mutex
89: &type->s_umount_key
90: &type->s_lock_key
91: disks_mutex
92: all_mddevs_lock
93: cm_sbs_mutex
94: registration_lock
95: parportlist_lock
96: &tmp->waitlist_lock
97: &tmp->cad_lock
98: &tmp->pardevice_lock
99: topology_lock
100: ports_lock
101: full_list_lock
102: &card->power_lock
103: &ctl->read_lock
104: &card->files_lock
105: (struct lock_class_key *)id
106: ops_mutex
107: &chip->reg_lock
108: list_mutex
109: &card->ctl_files_rwlock
110: &card->controls_rwsem
111: &ac97->reg_mutex
112: idecd_ref_mutex
113: snd_card_mutex
114: register_lock
115: &grp->list_mutex
116: &grp->list_mutex
117: &grp->list_lock
118: register_mutex
119: &client->ports_mutex
120: &client->ports_lock
121: register_mutex
122: clients_lock
123: rng_mutex
124: cdrom_lock
125: register_mutex
126: sound_oss_mutex
127: sound_loader_lock
128: sg_dev_arr_lock
129: core_lists
130: i2c_adapter_idr.lock
131: snd_ioctl_rwsem
132: old_style_spin_init
133: sound_mutex
134: register_mutex
135: strings
136: info_mutex
137: fdc_wait.lock
138: command_done.lock
139: floppy_hlt_lock
140: dma_spin_lock
141: floppy_usage_lock
142: floppy_lock
143: &s->s_vfs_rename_mutex
144: sysfs_rename_sem
145: old_style_spin_init
146: &dev->up_mutex
147: &u->readlock
148: sk_lock-AF_NETLINK
149: slock-AF_NETLINK
150: kauditd_wait.lock
151: audit_backlog_wait.lock
152: &list->lock
153: audit_cmd_mutex
154: simple_transaction_lock
155: sk_lock-AF_UNIX
156: slock-AF_UNIX
157: &u->lock
158: &u->lock
159: &af_unix_sk_receive_queue_lock_key
160: af_callback_keys + sk->sk_family
161: unix_table_lock
162: init_signals.wait_chldexit.lock
163: &s->lock
164: load_mutex
165: sel_mutex
166: sel_netif_lock
167: audit_filter_mutex
168: &bdev->bd_mount_mutex
169: &type->s_umount_key
170: &journal->j_barrier
171: _event_lock
172: &md->map_lock
173: _hash_lock
174: old_style_spin_init
175: &dio->bio_lock
176: &bdev->bd_mutex
177: &p->lock
178: swapon_mutex
179: swap_lock
180: _lock
181: old_style_spin_init
182: _lock
183: &shost->free_list_lock
184: &shost->scan_mutex
185: sd_index_lock
186: sd_index_idr.lock
187: host_cmd_pool_mutex
188: (reboot_notifier_list).rwsem
189: old_style_spin_init
190: (module_notify_list).rwsem
191: old_style_spin_init
192: af_callback_keys + sk->sk_family
193: module_mutex
194: (munmap_notifier).rwsem
195: old_style_spin_init
196: policy_rwlock
197: &bdev->bd_mutex
198: open_lock
199: &new->reconfig_mutex
200: _minor_lock
201: _minor_idr.lock
202: &bdev->bd_mutex
203: sd_ref_mutex
204: &namespace_sem
205: &tty->atomic_write_lock
206: redirect_lock
207: uts_sem
208: old_style_spin_init
209: &mm->mmap_sem
210: &new->lock
211: &futex_queues[i].lock
212: &futex_queues[i].lock
213: &mm->mmap_sem
214: __pte_lockptr(new)
215: &per_cpu(flush_state, i).tlbstate_lock
216: __pte_lockptr(new)
217: tty_mutex
218: (console_sem).wait.lock
219: rif_lock
220: packet_sklist_lock
221: xfrm_km_lock
222: afinfo_lock
223: llc_sap_list_lock
224: leds_list_lock
225: triggers_list_lock
226: usb_bus_list_lock
227: &ehci->lock
228: (usb_notifier_list).rwsem
229: old_style_spin_init
230: mon_lock
231: deviceconndiscwq.lock
232: &type->s_umount_key
233: &type->s_lock_key
234: hcd_root_hub_lock
235: &uhci->lock
236: &retval->lock
237: &new_driver->dynids.lock
238: &urb->lock
239: hcd_data_lock
240: &type->s_umount_key
241: &type->s_lock_key
242: pin_fs_lock
243: tune_lock
244: block_subsys_lock
245: serial_mutex
246: port_mutex
247: &state->mutex
248: &tty->read_lock
249: &irq_lists[i].lock
250: probing_active
251: &blocking_pool.lock
252: cpufreq_driver_lock
253: &drv->dynids.lock
254: elv_list_lock
255: crypto_alg_sem
256: old_style_spin_init
257: &type->s_lock_key
258: &type->s_umount_key
259: nf_hook_lock
260: &type->s_umount_key
261: &type->s_lock_key
262: nls_lock
263: &type->s_umount_key
264: &type->s_umount_key
265: &type->s_lock_key
266: &type->s_umount_key
267: &type->s_umount_key
268: &type->s_umount_key
269: pdflush_lock
270: die_chain.lock
271: kprobe_mutex
272: serial_lock
273: audit_freelist_lock
274: &type->s_umount_key
275: uidhash_lock
276: tcp_cong_list_lock
277: raw_v4_lock
278: bdev_lock
279: xfrm_policy_afinfo_lock
280: xfrm_state_afinfo_lock
281: ptype_lock
282: neigh_tbl_lock
283: inetsw_lock
284: inet_proto_lock
285: cpufreq_governor_mutex
286: serio_mutex
287: &s->rwsem
288: device_state_lock
289: &serio->drv_mutex
290: psmouse_mutex
291: input_devices_poll_wait.lock
292: &dev->mutex
293: &ps2dev->cmd_mutex
294: i8042_lock
295: &serio->lock
296: serio_event_lock
297: serio_wait.lock
298: &type->s_umount_key
299: genl_mutex
300: qdisc_mod_lock
301: &dma_list_mutex
302: hub_event_lock
303: khubd_wait.lock
304: notify_lock
305: &dev->queue_lock
306: pnp_lock
307: acpi_link_lock
308: acpi_prt_lock
309: pci_lock
310: pci_bus_sem
311: old_style_spin_init
312: &k->k_lock
313: acpi_device_lock
314: acpi_gbl_gpe_lock
315: chrdevs_lock
316: sysrq_key_table_lock
317: pci_config_lock
318: init_mm.mmap_sem
319: old_style_spin_init
320: bus_type_sem
321: old_style_spin_init
322: &(per_cpu(listener_array, i).sem)
323: (task_exit_notifier).rwsem
324: old_style_spin_init
325: &fs->lock
326: net_todo_run_mutex
327: rtnl_mutex
328: rt6_lock
329: fib6_walker_lock
330: &ifa->lock
331: &in_dev->mc_tomb_lock
332: &in_dev->mc_list_lock
333: (inetaddr_chain).rwsem
334: &rt_hash_locks[i]
335: rt_flush_lock
336: fib_info_lock
337: fib_hash_lock
338: old_style_spin_init
339: &nlk->cb_lock
340: &mc->mca_lock
341: &dev->_xmit_lock
342: &idev->mc_lock
343: &ndev->lock
344: addrconf_lock
345: &list->lock
346: lweventlist_lock
347: sysctl_lock
348: &tbl->lock
349: &hh->hh_lock
350: &n->lock
351: &list->lock
352: dev_base_lock
353: qdisc_tree_lock
354: &dev->queue_lock
355: sequence_lock
356: nl_table_wait.lock
357: nl_table_lock
358: &nonblocking_pool.lock
359: net_family_lock
360: proto_list_lock
361: &type->s_umount_key
362: binfmt_lock
363: &k->list_lock
364: workqueue_mutex
365: &rcu_ctrlblk.lock
366: &inode->i_mutex
367: &inode->i_mutex
368: &p->pi_lock
369: cpu_add_remove_lock
370: (cpu_chain).rwsem
371: old_style_spin_init
372: panic_notifier_list.lock
373: &sighand->siglock
374: &base->lock_key
375: &base->lock_key
376: &base->lock_key
377: &base->lock_key
378: vector_lock
379: init_task.file_lock
380: pidmap_lock
381: acpi_gbl_hardware_lock
382: smp_alt
383: &inode->i_mutex
384: cdev_lock
385: &inode->inotify_mutex
386: &ih->mutex
387: &dev->ev_mutex
388: &sbi->s_next_gen_lock
389: (kernel_sem).wait.lock
390: &ei->xattr_sem
391: mb_cache_spinlock
392: &type->s_umount_key
393: &type->s_lock_key
394: proc_subdir_lock
395: proc_inum_lock
396: proc_inum_idr.lock
397: files_lock
398: &type->s_umount_key
399: &type->s_lock_key
400: &type->s_umount_key
401: old_style_rw_init
402: &type->s_umount_key
403: &sysfs_inode_imutex_key
404: fasync_lock
405: &inode->i_alloc_sem
406: &ei->truncate_mutex
407: &fbc->lock
408: &sbi->s_rsv_window_lock
409: &inode->i_lock
410: &f->f_owner.lock
411: &bgl->locks[i].lock
412: &type->s_lock_key
413: &inode->i_data.private_lock
414: &journal->j_revoke_lock
415: &tsk->delays->lock
416: &md->io_lock
417: &host_set->lock
418: &shost->default_lock
419: &journal->j_state_lock
420: &transaction->t_handle_lock
421: modlist_lock
422: &journal->j_list_lock
423: &info->lock
424: &inode->i_data.tree_lock
425: &sbinfo->stat_lock
426: &zone->lru_lock
427: &inode->i_data.i_mmap_lock
428: &anon_vma->lock
429: &mm->page_table_lock
430: &type->s_umount_key
431: &type->s_lock_key
432: &s->s_dquot.dqonoff_mutex
433: dq_list_lock
434: &sbsec->isec_lock
435: dcache_lock
436: rename_lock
437: vfsmount_lock
438: &dentry->d_lock
439: &dentry->d_lock
440: inode_lock
441: sb_lock
442: sb_security_lock
443: unnamed_dev_lock
444: &idp->lock
445: file_systems_lock
446: shrinker_rwsem
447: old_style_spin_init
448: root_session_keyring.sem
449: keyring_serialise_link_sem
450: old_style_spin_init
451: &candidate->lock
452: old_style_spin_init
453: old_style_spin_init
454: keyring_name_lock
455: callback_mutex
456: init_task.alloc_lock
457: cpu_bitmask_lock
458: mtrr_mutex
459: set_atomicity_lock
460: pgd_lock
461: kthread_stop_lock
462: kretprobe_lock
463: vmlist_lock
464: tasklist_lock
465: &sig->stats_lock
466: init_sighand.siglock
467: &sighand->siglock
468: &newf->file_lock
469: &p->alloc_lock
470: cfq_exit_lock
471: ide_lock
472: random_read_wait.lock
473: &input_pool.lock
474: random_write_wait.lock
475: &q->__queue_lock
476: congestion_wqh[1].lock
477: base_lock_keys + cpu
478: base_lock_keys + cpu
479: &cwq->lock
480: &sdev->list_lock
481: base_lock_keys + cpu
482: &avc_cache.slots_lock[i]
483: notif_lock
484: &sem->wait_lock
485: cache_chain_mutex
486: call_lock
487: &ptr->list_lock
488: &on_slab_key
489: &parent->list_lock
490: kclist_lock
491: &zone->lock
492: &port_lock_key
493: &q->lock
494: logbuf_lock
495: vga_lock
496: tty_ldisc_lock
497: tty_ldisc_wait.lock
498: base_lock_keys + cpu
499: &irq_desc_lock_class
500: rtc_lock
501: old_style_seqlock_init
502: clocksource_lock
503: &rq->rq_lock_key
504: &rq->rq_lock_key
505: &rq->rq_lock_key
506: &rq->rq_lock_key
507: resource_lock
508: ioapic_lock
509: i8259A_lock
510: index_init_lock
511: init_mm.page_table_lock
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: locking hierarchy based on lockdep
2006-11-06 18:32 locking hierarchy based on lockdep Jason Baron
@ 2006-11-06 20:05 ` Ingo Molnar
2006-11-06 20:21 ` Roland Dreier
2006-11-07 23:39 ` Jason Baron
0 siblings, 2 replies; 13+ messages in thread
From: Ingo Molnar @ 2006-11-06 20:05 UTC (permalink / raw)
To: Jason Baron; +Cc: linux-kernel, arjan
* Jason Baron <jbaron@redhat.com> wrote:
> I've implemented this as a /proc file, but Ingo suggested that it
> might be better for us to simply produce an adjaceny list, and then
> generate a locking hierarchy or anything else of interest off of that
> list.... [...]
this would certainly be the simplest thing to do - we could extend
/proc/lockdep with the list of 'immediately after' locks separated by
commas. (that list already exists: it's the lock_class.locks_after list)
i like your idea of using lockdep to document locking hierarchies.
Ingo
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: locking hierarchy based on lockdep
2006-11-06 20:05 ` Ingo Molnar
@ 2006-11-06 20:21 ` Roland Dreier
2006-11-06 20:22 ` Jason Baron
2006-11-07 23:39 ` Jason Baron
1 sibling, 1 reply; 13+ messages in thread
From: Roland Dreier @ 2006-11-06 20:21 UTC (permalink / raw)
To: Ingo Molnar; +Cc: Jason Baron, linux-kernel, arjan
> i like your idea of using lockdep to document locking hierarchies.
Yes, it's definitely a cool idea. I think the current implementation
is not that useful, since it jams all the unrelated kernel locks into
a single ordered list, when in fact many locks simply have no ordering
relationship at all because they're never both taken. This makes the
list hard to read and in fact loses the information of which locks
have been taken together.
- R.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: locking hierarchy based on lockdep
2006-11-06 20:21 ` Roland Dreier
@ 2006-11-06 20:22 ` Jason Baron
2006-11-06 20:37 ` Roland Dreier
0 siblings, 1 reply; 13+ messages in thread
From: Jason Baron @ 2006-11-06 20:22 UTC (permalink / raw)
To: Roland Dreier; +Cc: Ingo Molnar, linux-kernel, arjan
On Mon, 6 Nov 2006, Roland Dreier wrote:
> > i like your idea of using lockdep to document locking hierarchies.
>
> Yes, it's definitely a cool idea. I think the current implementation
> is not that useful, since it jams all the unrelated kernel locks into
> a single ordered list, when in fact many locks simply have no ordering
> relationship at all because they're never both taken. This makes the
> list hard to read and in fact loses the information of which locks
> have been taken together.
>
> - R.
>
interesting...perhaps if we layered say the directory structure on the
list too like by the top level kernel directories drivers, kernel, mm,
net, etc. it might be more readable.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: locking hierarchy based on lockdep
2006-11-06 20:22 ` Jason Baron
@ 2006-11-06 20:37 ` Roland Dreier
2006-11-06 20:40 ` Jason Baron
0 siblings, 1 reply; 13+ messages in thread
From: Roland Dreier @ 2006-11-06 20:37 UTC (permalink / raw)
To: Jason Baron; +Cc: Ingo Molnar, linux-kernel, arjan
> interesting...perhaps if we layered say the directory structure on the
> list too like by the top level kernel directories drivers, kernel, mm,
> net, etc. it might be more readable.
I'm not sure that you need to do something manual or ad hoc like that,
although it might be necessary in the end. I'd be curious to see how
the list of locks partitions up if you just divide it up into groups
of locks that have some relationship. I guess the question is, if you
draw the graph whose nodes are locks and whose edges connect locks
that are held together, how many connected pieces does that graph have?
- R.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: locking hierarchy based on lockdep
2006-11-06 20:37 ` Roland Dreier
@ 2006-11-06 20:40 ` Jason Baron
0 siblings, 0 replies; 13+ messages in thread
From: Jason Baron @ 2006-11-06 20:40 UTC (permalink / raw)
To: Roland Dreier; +Cc: Ingo Molnar, linux-kernel, arjan
On Mon, 6 Nov 2006, Roland Dreier wrote:
> > interesting...perhaps if we layered say the directory structure on the
> > list too like by the top level kernel directories drivers, kernel, mm,
> > net, etc. it might be more readable.
>
> I'm not sure that you need to do something manual or ad hoc like that,
> although it might be necessary in the end. I'd be curious to see how
> the list of locks partitions up if you just divide it up into groups
> of locks that have some relationship. I guess the question is, if you
> draw the graph whose nodes are locks and whose edges connect locks
> that are held together, how many connected pieces does that graph have?
>
> - R.
>
ok, so grouping the list by sections of connected components-that's a nice
idea, and would probably make for an interesting list.
-jason
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: locking hierarchy based on lockdep
2006-11-06 20:05 ` Ingo Molnar
2006-11-06 20:21 ` Roland Dreier
@ 2006-11-07 23:39 ` Jason Baron
2006-11-07 23:53 ` Ingo Molnar
2006-11-08 13:08 ` Pavel Machek
1 sibling, 2 replies; 13+ messages in thread
From: Jason Baron @ 2006-11-07 23:39 UTC (permalink / raw)
To: Ingo Molnar; +Cc: linux-kernel, arjan, rdreier
On Mon, 6 Nov 2006, Ingo Molnar wrote:
>
> * Jason Baron <jbaron@redhat.com> wrote:
>
> > I've implemented this as a /proc file, but Ingo suggested that it
> > might be better for us to simply produce an adjaceny list, and then
> > generate a locking hierarchy or anything else of interest off of that
> > list.... [...]
>
> this would certainly be the simplest thing to do - we could extend
> /proc/lockdep with the list of 'immediately after' locks separated by
> commas. (that list already exists: it's the lock_class.locks_after list)
>
> i like your idea of using lockdep to document locking hierarchies.
>
> Ingo
>
hi,
So below is patch that does what you suggest, although i had to add the
concept of 'distance' to the patch since the locks_after list loses this
dependency info afaict. i also wrote a user space program to sort the
locks into cluster of interelated locks and then sorted within these
clusters...the results show one large clump of locks...perhaps there are a
few locks that time them all together like scheduler locks...but i
couldn't figure out which ones to exclude to make the list look really
pretty (also, there could be a bug in my program :). Anyways i'm including
my test program and its output too...
thanks,
-jason
--- linux-2.6.18/include/linux/lockdep.h.bak 2006-11-01 09:27:23.000000000 -0500
+++ linux-2.6.18/include/linux/lockdep.h 2006-11-06 10:32:14.000000000 -0500
@@ -132,6 +132,7 @@ struct lock_list {
struct list_head entry;
struct lock_class *class;
struct stack_trace trace;
+ int distance;
};
/*
--- linux-2.6.18/kernel/lockdep.c.bak 2006-11-01 08:57:22.000000000 -0500
+++ linux-2.6.18/kernel/lockdep.c 2006-11-06 10:33:16.000000000 -0500
@@ -454,7 +454,7 @@ static void print_lock_dependencies(stru
* Add a new dependency to the head of the list:
*/
static int add_lock_to_list(struct lock_class *class, struct lock_class *this,
- struct list_head *head, unsigned long ip)
+ struct list_head *head, unsigned long ip, int distance)
{
struct lock_list *entry;
/*
@@ -466,6 +466,7 @@ static int add_lock_to_list(struct lock_
return 0;
entry->class = this;
+ entry->distance = distance;
save_trace(&entry->trace);
/*
@@ -856,7 +857,7 @@ check_deadlock(struct task_struct *curr,
*/
static int
check_prev_add(struct task_struct *curr, struct held_lock *prev,
- struct held_lock *next)
+ struct held_lock *next, int distance)
{
struct lock_list *entry;
int ret;
@@ -934,8 +935,11 @@ check_prev_add(struct task_struct *curr,
* L2 added to its dependency list, due to the first chain.)
*/
list_for_each_entry(entry, &prev->class->locks_after, entry) {
- if (entry->class == next->class)
+ if (entry->class == next->class) {
+ if (distance == 1)
+ entry->distance = 1;
return 2;
+ }
}
/*
@@ -943,7 +947,8 @@ check_prev_add(struct task_struct *curr,
* to the previous lock's dependency list:
*/
ret = add_lock_to_list(prev->class, next->class,
- &prev->class->locks_after, next->acquire_ip);
+ &prev->class->locks_after, next->acquire_ip, distance);
+
if (!ret)
return 0;
/*
@@ -953,7 +958,7 @@ check_prev_add(struct task_struct *curr,
if (ret == 2)
return 2;
ret = add_lock_to_list(next->class, prev->class,
- &next->class->locks_before, next->acquire_ip);
+ &next->class->locks_before, next->acquire_ip, distance);
/*
* Debugging printouts:
@@ -999,13 +1004,14 @@ check_prevs_add(struct task_struct *curr
goto out_bug;
for (;;) {
+ int distance = curr->lockdep_depth - depth + 1;
hlock = curr->held_locks + depth-1;
/*
* Only non-recursive-read entries get new dependencies
* added:
*/
if (hlock->read != 2) {
- check_prev_add(curr, hlock, next);
+ check_prev_add(curr, hlock, next, distance);
/*
* Stop after the first non-trylock entry,
* as non-trylock entries have added their
@@ -2701,4 +2707,3 @@ void debug_show_held_locks(struct task_s
}
EXPORT_SYMBOL_GPL(debug_show_held_locks);
-
--- linux-2.6.18/kernel/lockdep_proc.c.bak 2006-11-01 08:57:32.000000000 -0500
+++ linux-2.6.18/kernel/lockdep_proc.c 2006-11-07 09:47:09.000000000 -0500
@@ -77,12 +77,29 @@ static unsigned long count_backward_deps
return ret;
}
+static void print_name(struct seq_file *m, struct lock_class *class)
+{
+ char str[128];
+ const char *name = class->name;
+
+ if (!name) {
+ name = __get_key_name(class->key, str);
+ seq_printf(m, "%s", name);
+ } else{
+ seq_printf(m, "%s", name);
+ if (class->name_version > 1)
+ seq_printf(m, "#%d", class->name_version);
+ if (class->subclass)
+ seq_printf(m, "/%d", class->subclass);
+ }
+}
+
static int l_show(struct seq_file *m, void *v)
{
unsigned long nr_forward_deps, nr_backward_deps;
struct lock_class *class = m->private;
- char str[128], c1, c2, c3, c4;
- const char *name;
+ char c1, c2, c3, c4;
+ struct lock_list *entry;
seq_printf(m, "%p", class->key);
#ifdef CONFIG_DEBUG_LOCKDEP
@@ -97,17 +114,17 @@ static int l_show(struct seq_file *m, vo
get_usage_chars(class, &c1, &c2, &c3, &c4);
seq_printf(m, " %c%c%c%c", c1, c2, c3, c4);
- name = class->name;
- if (!name) {
- name = __get_key_name(class->key, str);
- seq_printf(m, ": %s", name);
- } else{
- seq_printf(m, ": %s", name);
- if (class->name_version > 1)
- seq_printf(m, "#%d", class->name_version);
- if (class->subclass)
- seq_printf(m, "/%d", class->subclass);
+ seq_printf(m, ": ");
+ print_name(m, class);
+ seq_printf(m, ": ");
+
+ list_for_each_entry(entry, &class->locks_after, entry) {
+ if (entry->distance == 1) {
+ print_name(m, entry->class);
+ seq_puts(m, ",");
+ }
}
+
seq_puts(m, "\n");
return 0;
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MAX_LOCKS 1000
#define STR_LEN 64
struct node {
struct link *graph_list;
int component;
struct node *ordered_list;
int visited;
char name[STR_LEN];
};
struct link {
struct link *next_link;
struct node *endpoint;
int backlink;
};
int num_nodes = 0;
int num_components = 0;
struct node nodes[MAX_LOCKS];
struct node *ordered_list_array[MAX_LOCKS];
struct link *alloc_link() {
struct link *new_link;
new_link = malloc(sizeof(struct link));
memset(new_link, 0, sizeof(struct link));
return new_link;
}
void add_link(struct node *start_node, struct node *end_node, int backlink) {
//first check if we have it already:
struct link *new_link;
struct link *next_link = start_node->graph_list;
while (next_link) {
if (next_link->endpoint == end_node) {
printf("ERROR: duplicate link add attempted!\n");
exit(-1);
}
next_link = next_link->next_link;
}
next_link = start_node->graph_list;
new_link = alloc_link();
new_link->backlink = backlink;
new_link->endpoint = end_node;
new_link->next_link = next_link;
start_node->graph_list = new_link;
}
void show_graph() {
int i;
struct link *next_link;
printf("num_nodes: %i\n", num_nodes);
printf("num_components: %i\n", num_components);
for(i=0; i<num_nodes; i++) {
printf("node %i: name: %s component: %i\n", i, nodes[i].name, nodes[i].component);
next_link = nodes[i].graph_list;
while(next_link != NULL) {
printf(" link: %s back: %i\n" , next_link->endpoint->name, next_link->backlink);
next_link = next_link->next_link;
}
}
}
struct node *find_node(char *nodename) {
int i;
for(i=0; i<num_nodes; i++) {
if(strcmp(nodes[i].name, nodename) == 0)
return &nodes[i];
}
return NULL;
}
struct node *register_node(char *nodename) {
struct node *node;
node = find_node(nodename);
if(node)
return node;
strcpy(nodes[num_nodes++].name, nodename);
return &nodes[num_nodes-1];
}
void create_graph(char *filename) {
char *line;
ssize_t read;
size_t len = 0;
FILE *fp;
char *pos;
char *lock_name, *start_name, node_name[STR_LEN];
struct node *start_node, *end_node;
if ((fp = fopen(filename, "r")) == NULL) {
perror("Couldn't open file\n");
exit(-1);
}
/* ignore the first line */
read = getline(&line, &len, fp);
while ((read = getline(&line, &len, fp)) != -1) {
pos = strstr(line, ":");
pos++;
pos = strstr(pos, ":");
pos++;
pos = strstr(pos, ":");
pos += 2;
start_name = pos;
pos = strstr(pos, ":");
memcpy(node_name, start_name, pos - start_name);
node_name[pos - start_name] = '\0';
//printf("node name: %s\n", node_name);
start_node = register_node(node_name);
start_name = pos += 2;
while((pos = strstr(start_name, ",")) != NULL) {
memcpy(node_name, start_name, pos - start_name);
node_name[pos - start_name] = '\0';
//printf("link name: %s\n", node_name);
end_node = register_node(node_name);
add_link(start_node, end_node, 0);
//add back link
add_link(end_node, start_node, 1);
start_name = pos+1;
}
}
}
void dfs_visit_component(struct node *node) {
struct link *next_link;
node->visited = 1;
node->component = num_components;
next_link = node->graph_list;
while (next_link) {
if (next_link->endpoint->visited == 0)
dfs_visit_component(next_link->endpoint);
next_link = next_link->next_link;
}
}
void label_connected_components() {
int i;
for (i=0;i<num_nodes;i++) {
nodes[i].visited = 0;
nodes[i].component = -1;
}
for (i=0;i<num_nodes;i++) {
if (nodes[i].visited == 0) {
dfs_visit_component(&nodes[i]);
num_components++;
}
}
}
void dfs_order_components(struct node *node, int component) {
struct link *next_link;
struct node *next_node;
//sanity check:
if (node->component != component) {
printf("Error component mismatch\n");
exit(-1);
}
node->visited = 1;
next_link = node->graph_list;
while (next_link) {
if (next_link->endpoint->visited == 0 && (next_link->endpoint->component == component) && (next_link->backlink == 0)) {
dfs_order_components(next_link->endpoint, component);
}
next_link = next_link->next_link;
}
node->ordered_list = ordered_list_array[component];
ordered_list_array[component] = node;
}
void order_components() {
int i,j;
for (i=0;i<num_nodes;i++) {
nodes[i].visited = 0;
}
for(i=0;i<num_components;i++) {
for(j=0;j<num_nodes;j++) {
if (nodes[j].visited == 0 && nodes[j].component == i)
dfs_order_components(&nodes[j], i);
}
}
}
void show_ordered_list_array() {
int i, j;
struct node *node;
for(i=0;i<num_components;i++) {
j = 0;
node = ordered_list_array[i];
while(node) {
printf("%i: %s\n", j, node->name);
j++;
node = node->ordered_list;
}
printf("\n");
}
}
int main(int argc, char **argv)
{
if (argc != 2) {
printf("usage: %s: <filename>\n", *argv);
exit(-1);
}
create_graph(argv[1]);
label_connected_components();
order_components();
show_ordered_list_array();
}
0: fib6_gc_lock
1: &ids->mutex
2: slock-AF_INET6/1
3: &atkbd->event_mutex
4: &tty->atomic_read_lock
5: (console_sem).wait.lock
6: &im->lock
7: &type->s_umount_key#21
8: &ep->sem
9: &file->f_ep_lock
10: &type->s_umount_key#20
11: &type->s_lock_key#11
12: &key->sem
13: key_construction_sem
14: old_style_spin_init#20
15: sk_lock-AF_PACKET
16: &po->bind_lock
17: sk_lock-AF_INET
18: af_callback_keys + sk->sk_family#4
19: tcp_hashinfo.lhash_wait.lock
20: ip_conntrack_lock
21: sk_lock-AF_INET6
22: nf_sockopt_mutex
23: &xt[i].mutex
24: &table->lock
25: udp_hash_lock
26: &sk->sk_dst_lock
27: tcp_hashinfo.lhash_lock
28: af_callback_keys + sk->sk_family#3
29: ipv6_sk_mc_lock
30: slock-AF_PACKET
31: &newsk->sk_dst_lock
32: slock-AF_INET6
33: &tcp_hashinfo.ehash[i].lock
34: &tcp_hashinfo.bhash[i].lock
35: &queue->syn_wait_lock
36: tcp_lock
37: addrconf_hash_lock
38: addrconf_verify_lock
39: &s->rwsem
40: &type->s_umount_key#19
41: disks_mutex
42: cm_sbs_mutex
43: registration_lock
44: parportlist_lock
45: &tmp->pardevice_lock
46: topology_lock
47: &card->power_lock
48: &card->controls_rwsem
49: &ac97->reg_mutex
50: rng_mutex
51: fdc_wait.lock
52: command_done.lock
53: floppy_lock
54: &grp->list_mutex
55: &grp->list_mutex/1
56: &grp->list_lock
57: register_mutex#4
58: core_lists
59: i2c_adapter_idr.lock
60: register_mutex#3
61: clients_lock
62: register_mutex#2
63: sound_oss_mutex
64: sound_loader_lock
65: sound_mutex
66: register_mutex
67: strings
68: info_mutex
69: &s->s_vfs_rename_mutex
70: &dev->up_mutex
71: &u->readlock
72: audit_cmd_mutex
73: &u->lock
74: &af_unix_sk_receive_queue_lock_key
75: &u->lock/1
76: af_callback_keys + sk->sk_family#2
77: unix_table_lock
78: &s->lock
79: load_mutex
80: sel_mutex
81: sel_netif_lock
82: audit_filter_mutex
83: &bdev->bd_mount_mutex
84: _event_lock
85: &type->s_umount_key#18
86: &journal->j_barrier
87: &md->map_lock
88: _hash_lock
89: old_style_spin_init#16
90: &dio->bio_lock
91: &p->lock
92: swapon_mutex
93: swap_lock
94: &shost->scan_mutex
95: sd_index_lock
96: sd_index_idr.lock
97: host_cmd_pool_mutex
98: module_mutex
99: &bdev->bd_mutex
100: &bdev->bd_mutex/1
101: sd_ref_mutex
102: &bdev->bd_mutex/2
103: _minor_lock
104: _minor_idr.lock
105: idecd_ref_mutex
106: &new->reconfig_mutex
107: open_lock
108: &namespace_sem
109: &tty->atomic_write_lock
110: uts_sem
111: old_style_spin_init#10
112: &mm->mmap_sem
113: &mm->mmap_sem/1
114: &mm->page_table_lock
115: __pte_lockptr(new)
116: __pte_lockptr(new)/1
117: &per_cpu(flush_state
118: i).tlbstate_lock
119: &futex_queues[i].lock
120: &futex_queues[i].lock/1
121: &new->lock
122: tty_mutex
123: log_wait.lock
124: usb_bus_list_lock
125: hcd_data_lock
126: &urb->lock
127: device_state_lock
128: &new_driver->dynids.lock
129: &retval->lock
130: &uhci->lock
131: hcd_root_hub_lock
132: (usb_notifier_list).rwsem
133: &type->s_umount_key#17
134: &type->s_lock_key#8
135: deviceconndiscwq.lock
136: mon_lock
137: old_style_spin_init#13
138: &ehci->lock
139: &type->s_umount_key#16
140: &type->s_lock_key#7
141: pin_fs_lock
142: block_subsys_lock
143: serial_mutex
144: port_mutex
145: &state->mutex
146: probing_active
147: &irq_lists[i].lock
148: &tty->read_lock
149: &blocking_pool.lock
150: cpufreq_driver_lock
151: elv_list_lock
152: &type->s_umount_key#15
153: &type->s_umount_key#14
154: &type->s_lock_key#5
155: &type->s_umount_key#13
156: &type->s_umount_key#12
157: &type->s_lock_key#4
158: &type->s_umount_key#11
159: &type->s_umount_key#10
160: &type->s_umount_key#9
161: pdflush_lock
162: kprobe_mutex
163: serial_lock
164: audit_freelist_lock
165: &type->s_umount_key#8
166: bdev_lock
167: ptype_lock
168: serio_mutex
169: serio_event_lock
170: serio_wait.lock
171: &serio->drv_mutex
172: &dev->mutex
173: psmouse_mutex
174: &ps2dev->cmd_mutex/1
175: &serio->lock
176: i8042_lock
177: input_devices_poll_wait.lock
178: &type->s_umount_key#7
179: hub_event_lock
180: khubd_wait.lock
181: pci_bus_sem
182: old_style_spin_init#8
183: &k->k_lock
184: chrdevs_lock
185: init_mm.mmap_sem
186: old_style_spin_init#7
187: bus_type_sem
188: old_style_spin_init#6
189: &(per_cpu(listener_array, i).sem)
190: net_todo_run_mutex
191: rtnl_mutex
192: sequence_lock
193: qdisc_tree_lock
194: dev_base_lock
195: sysctl_lock
196: lweventlist_lock
197: addrconf_lock
198: &ndev->lock
199: &idev->mc_lock
200: &mc->mca_lock
201: &nlk->cb_lock
202: &list->lock
203: &dev->_xmit_lock
204: &dev->queue_lock#2
205: (inetaddr_chain).rwsem
206: fib_hash_lock
207: &tbl->lock
208: &n->lock
209: &list->lock#3
210: old_style_spin_init#19
211: &in_dev->mc_list_lock
212: &in_dev->mc_tomb_lock
213: rt_flush_lock
214: &rt_hash_locks[i]
215: fib_info_lock
216: &ifa->lock
217: rt6_lock
218: fib6_walker_lock
219: nl_table_wait.lock
220: nl_table_lock
221: &nonblocking_pool.lock
222: &type->s_umount_key#6
223: &k->list_lock
224: workqueue_mutex
225: &inode->i_mutex/1
226: cdev_lock
227: &inode->i_mutex/2
228: &sbi->s_next_gen_lock
229: &p->pi_lock
230: cpu_add_remove_lock
231: (cpu_chain).rwsem
232: old_style_spin_init#4
233: &sighand->siglock
234: &base->lock_key#2
235: &base->lock_key
236: &base->lock_key#4
237: &base->lock_key#3
238: pidmap_lock
239: smp_alt
240: &inode->i_mutex
241: &ei->xattr_sem
242: mb_cache_spinlock
243: (kernel_sem).wait.lock
244: &inode->inotify_mutex
245: &ih->mutex
246: &dev->ev_mutex
247: &type->s_umount_key#5
248: &type->s_lock_key#3
249: proc_subdir_lock
250: files_lock
251: proc_inum_lock
252: proc_inum_idr.lock
253: &type->s_umount_key#4
254: &type->s_lock_key#2
255: &type->s_umount_key#3
256: &type->s_umount_key#2
257: &sysfs_inode_imutex_key
258: &inode->i_alloc_sem
259: &inode->i_data.i_mmap_lock
260: &anon_vma->lock
261: &info->lock
262: &sbinfo->stat_lock
263: &type->s_lock_key#9
264: &journal->j_state_lock
265: modlist_lock
266: &transaction->t_handle_lock
267: &ei->truncate_mutex
268: &md->io_lock
269: cfq_exit_lock
270: ide_lock
271: &input_pool.lock
272: random_write_wait.lock
273: random_read_wait.lock
274: &q->__queue_lock
275: &sdev->list_lock
276: base_lock_keys + cpu#4
277: congestion_wqh[1].lock
278: &host_set->lock
279: &shost->default_lock
280: base_lock_keys + cpu#3
281: base_lock_keys + cpu#2
282: &tsk->delays->lock
283: &journal->j_revoke_lock
284: &bgl->locks[i].lock
285: &inode->i_lock
286: &f->f_owner.lock
287: &zone->lru_lock
288: &sbi->s_rsv_window_lock
289: &inode->i_data.private_lock
290: &journal->j_list_lock
291: &inode->i_data.tree_lock
292: fasync_lock
293: &type->s_umount_key
294: inode_lock
295: dcache_lock
296: vfsmount_lock
297: rename_lock
298: &dentry->d_lock
299: &dentry->d_lock/1
300: &sbsec->isec_lock
301: &s->s_dquot.dqonoff_mutex
302: dq_list_lock
303: &type->s_lock_key
304: sb_lock
305: unnamed_dev_lock
306: &idp->lock
307: sb_security_lock
308: root_session_keyring.sem
309: old_style_spin_init
310: keyring_serialise_link_sem
311: &candidate->lock
312: old_style_spin_init#21
313: old_style_spin_init#2
314: keyring_name_lock
315: callback_mutex
316: init_task.alloc_lock
317: cpu_bitmask_lock
318: cache_chain_mutex
319: &ptr->list_lock
320: &p->alloc_lock
321: &sem->wait_lock
322: notif_lock
323: &avc_cache.slots_lock[i]
324: &newf->file_lock
325: tasklist_lock
326: init_sighand.siglock
327: &sighand->siglock/1
328: &sig->stats_lock
329: &parent->list_lock
330: &on_slab_key
331: vmlist_lock
332: &cwq->lock
333: kthread_stop_lock
334: kretprobe_lock
335: pgd_lock
336: mtrr_mutex
337: call_lock
338: set_atomicity_lock
339: &zone->lock
340: &port_lock_key
341: &q->lock
342: logbuf_lock
343: vga_lock
344: tty_ldisc_lock
345: tty_ldisc_wait.lock
346: base_lock_keys + cpu
347: &irq_desc_lock_class
348: old_style_seqlock_init
349: clocksource_lock
350: &rq->rq_lock_key
351: &rq->rq_lock_key#2
352: &rq->rq_lock_key#3
353: &rq->rq_lock_key#4
354: resource_lock
355: ioapic_lock
356: i8259A_lock
357: init_mm.page_table_lock
0: index_init_lock
0: rtc_lock
0: kclist_lock
0: shrinker_rwsem
1: old_style_spin_init#3
0: file_systems_lock
0: old_style_rw_init
0: acpi_gbl_hardware_lock
0: init_task.file_lock
0: vector_lock
0: panic_notifier_list.lock
0: &rcu_ctrlblk.lock
0: binfmt_lock
0: proto_list_lock
0: net_family_lock
0: &fs->lock
0: (task_exit_notifier).rwsem
1: old_style_spin_init#5
0: pci_config_lock
0: sysrq_key_table_lock
0: acpi_gbl_gpe_lock
0: acpi_device_lock
0: tune_lock
1: pci_lock
0: acpi_prt_lock
0: acpi_link_lock
0: pnp_lock
0: &dev->queue_lock
0: notify_lock
0: &dma_list_mutex
0: qdisc_mod_lock
0: genl_mutex
0: cpufreq_governor_mutex
0: inet_proto_lock
0: inetsw_lock
0: neigh_tbl_lock
0: xfrm_state_afinfo_lock
0: xfrm_policy_afinfo_lock
0: raw_v4_lock
0: tcp_cong_list_lock
0: uidhash_lock
0: die_chain.lock
0: nls_lock
0: nf_hook_lock
0: &type->s_lock_key#6
0: crypto_alg_sem
1: old_style_spin_init#9
0: &drv->dynids.lock
0: triggers_list_lock
0: leds_list_lock
0: llc_sap_list_lock
0: afinfo_lock
0: xfrm_km_lock
0: packet_sklist_lock
0: rif_lock
0: redirect_lock
0: policy_rwlock
0: (munmap_notifier).rwsem
1: old_style_spin_init#11
0: af_callback_keys + sk->sk_family
0: (module_notify_list).rwsem
1: old_style_spin_init#12
0: (reboot_notifier_list).rwsem
1: old_style_spin_init#14
0: &shost->free_list_lock
0: _lock
0: old_style_spin_init#15
0: _lock#2
0: &per_cpu(flush_state, i).tlbstate_lock
0: init_signals.wait_chldexit.lock
0: slock-AF_UNIX
0: sk_lock-AF_UNIX
0: simple_transaction_lock
0: &list->lock#2
0: audit_backlog_wait.lock
0: kauditd_wait.lock
0: slock-AF_NETLINK
0: sk_lock-AF_NETLINK
0: sysfs_rename_sem
1: old_style_spin_init#17
0: snd_ioctl_rwsem
1: old_style_spin_init#18
0: &client->ports_mutex
1: &client->ports_lock
0: sg_dev_arr_lock
0: floppy_usage_lock
0: dma_spin_lock
0: floppy_hlt_lock
0: register_lock
0: snd_card_mutex
0: cdrom_lock
0: &card->ctl_files_rwlock
0: list_mutex
0: &chip->reg_lock
0: ops_mutex
0: (struct lock_class_key *)id
0: &card->files_lock
0: &ctl->read_lock
0: full_list_lock
0: ports_lock
0: &tmp->cad_lock
0: &tmp->waitlist_lock
0: all_mddevs_lock
0: &type->s_lock_key#10
0: &policy->lock
1: performance_mutex
0: disable_ratelimit_lock
0: inetsw6_lock
0: raw_v6_lock
0: inet6_proto_lock
0: ipv6_sk_ac_lock
0: ip6_ra_lock
0: slock-AF_INET
0: af_callback_keys + sk->sk_family#5
0: &adapter->stats_lock
0: &adapter->tx_queue_lock
0: &txdr->tx_lock
0: &rcu_bh_ctrlblk.lock
0: task_capability_lock
0: key_user_lock
0: key_serial_lock
0: &hh->hh_lock
0: cache_list_lock
0: &ep->lock
0: &fbc->lock
0: &ps->lock
0: hci_notifier.lock
0: hci_task_lock
0: sk_lock-AF_BLUETOOTH
1: old_style_rw_init#2
0: slock-AF_BLUETOOTH
0: hci_cb_list_lock
0: old_style_rw_init#3
0: af_callback_keys + sk->sk_family#6
0: &d->lock
0: &list->lock#4
0: old_style_rw_init#4
0: hci_dev_list_lock
0: acpi_system_event_lock
0: acpi_bus_event_queue.lock
0: &fbc->lock#2
0: &entry->access
0: vt_activate_queue.lock
0: i8253_beep_lock
0: allocated_ptys.lock
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: locking hierarchy based on lockdep
2006-11-07 23:39 ` Jason Baron
@ 2006-11-07 23:53 ` Ingo Molnar
2006-11-08 18:04 ` Jason Baron
2006-11-08 13:08 ` Pavel Machek
1 sibling, 1 reply; 13+ messages in thread
From: Ingo Molnar @ 2006-11-07 23:53 UTC (permalink / raw)
To: Jason Baron; +Cc: linux-kernel, arjan, rdreier
* Jason Baron <jbaron@redhat.com> wrote:
> > this would certainly be the simplest thing to do - we could extend
> > /proc/lockdep with the list of 'immediately after' locks separated by
> > commas. (that list already exists: it's the lock_class.locks_after list)
>
> So below is patch that does what you suggest, although i had to add
> the concept of 'distance' to the patch since the locks_after list
> loses this dependency info afaict. i also wrote a user space program
> to sort the locks into cluster of interelated locks and then sorted
> within these clusters...the results show one large clump of
> locks...perhaps there are a few locks that time them all together like
> scheduler locks...but i couldn't figure out which ones to exclude to
> make the list look really pretty (also, there could be a bug in my
> program :). Anyways i'm including my test program and its output
> too...
nice!
small detail: i'm wondering why 'distance' is needed explicitly? The
dependency graph as it is represented by locks_after should be a full
representation of all locking dependencies. What is the intended
definition of 'distance' - the distance from the root of the dependency
tree? (Maybe i'm misunderstanding what you are trying to achieve.)
Ingo
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: locking hierarchy based on lockdep
2006-11-07 23:39 ` Jason Baron
2006-11-07 23:53 ` Ingo Molnar
@ 2006-11-08 13:08 ` Pavel Machek
1 sibling, 0 replies; 13+ messages in thread
From: Pavel Machek @ 2006-11-08 13:08 UTC (permalink / raw)
To: Jason Baron; +Cc: Ingo Molnar, linux-kernel, arjan, rdreier
Hi!
> > * Jason Baron <jbaron@redhat.com> wrote:
> >
> > > I've implemented this as a /proc file, but Ingo suggested that it
> > > might be better for us to simply produce an adjaceny list, and then
> > > generate a locking hierarchy or anything else of interest off of that
> > > list.... [...]
> >
> > this would certainly be the simplest thing to do - we could extend
> > /proc/lockdep with the list of 'immediately after' locks separated by
> > commas. (that list already exists: it's the lock_class.locks_after list)
> >
> > i like your idea of using lockdep to document locking hierarchies.
> >
> > Ingo
> >
>
> hi,
>
> So below is patch that does what you suggest, although i had to add the
> concept of 'distance' to the patch since the locks_after list loses this
> dependency info afaict. i also wrote a user space program to sort the
> locks into cluster of interelated locks and then sorted within these
> clusters...the results show one large clump of locks...perhaps there are a
> few locks that time them all together like scheduler locks...but i
> couldn't figure out which ones to exclude to make the list look really
> pretty (also, there could be a bug in my program :). Anyways i'm including
> my test program and its output too...
Perhaps presenting it as a tree is worth it?
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: locking hierarchy based on lockdep
2006-11-07 23:53 ` Ingo Molnar
@ 2006-11-08 18:04 ` Jason Baron
2006-11-09 9:15 ` Ingo Molnar
0 siblings, 1 reply; 13+ messages in thread
From: Jason Baron @ 2006-11-08 18:04 UTC (permalink / raw)
To: Ingo Molnar; +Cc: linux-kernel, arjan, rdreier
On Wed, 8 Nov 2006, Ingo Molnar wrote:
>
> * Jason Baron <jbaron@redhat.com> wrote:
>
> > > this would certainly be the simplest thing to do - we could extend
> > > /proc/lockdep with the list of 'immediately after' locks separated by
> > > commas. (that list already exists: it's the lock_class.locks_after list)
> >
> > So below is patch that does what you suggest, although i had to add
> > the concept of 'distance' to the patch since the locks_after list
> > loses this dependency info afaict. i also wrote a user space program
> > to sort the locks into cluster of interelated locks and then sorted
> > within these clusters...the results show one large clump of
> > locks...perhaps there are a few locks that time them all together like
> > scheduler locks...but i couldn't figure out which ones to exclude to
> > make the list look really pretty (also, there could be a bug in my
> > program :). Anyways i'm including my test program and its output
> > too...
>
> nice!
>
> small detail: i'm wondering why 'distance' is needed explicitly? The
> dependency graph as it is represented by locks_after should be a full
> representation of all locking dependencies. What is the intended
> definition of 'distance' - the distance from the root of the dependency
> tree? (Maybe i'm misunderstanding what you are trying to achieve.)
>
'distance' is associated with a link, and is meant to represent the number
of intervening locks. So a distance of 1 b/w say lock a and b is to say
there is no intervening lock, whereas 2 would mean there is 1
intervening lock etc.
The reason i added this was that in my algorithm to order locks, say i
come to lock a, which has lock b and lock c in its 'after' list. I don't
know at that point if lock b needs to come before c, or maybe that c has
to come before b.
You are right though, i think that the data in the locks after lists is
sufficient to re-create the entire graph, since its acyclic, but by simply
printing out nodes of distance '1', the algorithm is greatly simplified.
Otherwise, i'd have to first reconstruct the graph...
Also, i was only looking for a link to be label as distance 1, or not...so
we only need to associate 1 bit of information with each link, if you are
concerned about struture bloat.
thanks,
-jason
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: locking hierarchy based on lockdep
2006-11-08 18:04 ` Jason Baron
@ 2006-11-09 9:15 ` Ingo Molnar
2006-11-09 18:58 ` Jason Baron
0 siblings, 1 reply; 13+ messages in thread
From: Ingo Molnar @ 2006-11-09 9:15 UTC (permalink / raw)
To: Jason Baron; +Cc: linux-kernel, arjan, rdreier
* Jason Baron <jbaron@redhat.com> wrote:
> You are right though, i think that the data in the locks after lists
> is sufficient to re-create the entire graph, since its acyclic, but by
> simply printing out nodes of distance '1', the algorithm is greatly
> simplified. Otherwise, i'd have to first reconstruct the graph...
but ... the locks_after list should really only include locks that are
taken immediately after. I.e. there should only be 'distance 1' locks.
Ingo
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: locking hierarchy based on lockdep
2006-11-09 9:15 ` Ingo Molnar
@ 2006-11-09 18:58 ` Jason Baron
2006-11-10 9:27 ` Ingo Molnar
0 siblings, 1 reply; 13+ messages in thread
From: Jason Baron @ 2006-11-09 18:58 UTC (permalink / raw)
To: Ingo Molnar; +Cc: linux-kernel, arjan, rdreier
On Thu, 9 Nov 2006, Ingo Molnar wrote:
>
> * Jason Baron <jbaron@redhat.com> wrote:
>
> > You are right though, i think that the data in the locks after lists
> > is sufficient to re-create the entire graph, since its acyclic, but by
> > simply printing out nodes of distance '1', the algorithm is greatly
> > simplified. Otherwise, i'd have to first reconstruct the graph...
>
> but ... the locks_after list should really only include locks that are
> taken immediately after. I.e. there should only be 'distance 1' locks.
>
hmmm...that's not how i read the lockdep code...and the little piece of
code that i added to add a distance measurement to links, found mostly
distance 1 links but there were a number of 2 and 3 links as well (i don't
think i saw any greater than 3).
thanks.
-Jason
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: locking hierarchy based on lockdep
2006-11-09 18:58 ` Jason Baron
@ 2006-11-10 9:27 ` Ingo Molnar
0 siblings, 0 replies; 13+ messages in thread
From: Ingo Molnar @ 2006-11-10 9:27 UTC (permalink / raw)
To: Jason Baron; +Cc: linux-kernel, arjan, rdreier
* Jason Baron <jbaron@redhat.com> wrote:
> > but ... the locks_after list should really only include locks that
> > are taken immediately after. I.e. there should only be 'distance 1'
> > locks.
>
> hmmm...that's not how i read the lockdep code...and the little piece
> of code that i added to add a distance measurement to links, found
> mostly distance 1 links but there were a number of 2 and 3 links as
> well (i don't think i saw any greater than 3).
hm, indeed, the current code does this. In theory we should not need to
add every lock to every held lock's dependency, because all the
dependency-conflict discovery algorithms can walk the full graph. The
"necessary minimum" would be to only add it to the previous non-trylock
held lock's dependency list.
ok, i like your latest patch as-is - it's simpler than to complicate the
current dependency logic. the 'distance' field is only added to the list
entry structure, so while it increases that structure's size, it at
least doesnt directly increase lock sizes.
Acked-by: Ingo Molnar <mingo@elte.hu>
Ingo
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2006-11-10 9:28 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-11-06 18:32 locking hierarchy based on lockdep Jason Baron
2006-11-06 20:05 ` Ingo Molnar
2006-11-06 20:21 ` Roland Dreier
2006-11-06 20:22 ` Jason Baron
2006-11-06 20:37 ` Roland Dreier
2006-11-06 20:40 ` Jason Baron
2006-11-07 23:39 ` Jason Baron
2006-11-07 23:53 ` Ingo Molnar
2006-11-08 18:04 ` Jason Baron
2006-11-09 9:15 ` Ingo Molnar
2006-11-09 18:58 ` Jason Baron
2006-11-10 9:27 ` Ingo Molnar
2006-11-08 13:08 ` Pavel Machek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox