History

Debugobjects transition check

Implement a basic state machine checker in the debugobjects. This state machine checker detects races and inconsistencies within the "active" life of a debugobject. The checker only keeps track of the current state; all the state machine logic is kept at the object instance level. The checker works by adding a supplementary "unsigned int astate" field to the debug_obj structure. It keeps track of the current "active state" of the object. The only constraints that are imposed on the states by the debugobjects system is that: - activation of an object sets the current active state to 0, - deactivation of an object expects the current active state to be 0. For the rest of the states, the state mapping is determined by the specific object instance. Therefore, the logic keeping track of the state machine is within the specialized instance, without any need to know about it at the debugobject level. The current object active state is changed by calling: debug_object_active_state(addr, descr, expect, next) where "expect" is the expected state and "next" is the next state to move to if the expected state is found. A warning is generated if the expected is not found.

Mathieu Desnoyers committed 16 years ago

Commit a5d8e461 parent d822ed12 files · +67 −3Browse files

Showing the changes to lib/debugobjects.c (1 of 2 files). Show all

Unified · Split

lib/debugobjects.c+56−3
@@ -141,6 +141,7 @@ alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr) · 140 unmodified lines
141141 obj->object = addr;
142142 obj->descr = descr;
143143 obj->state = ODEBUG_STATE_NONE;
144+ obj->astate = 0;
144145 hlist_del(&obj->node);
145146
146147 hlist_add_head(&obj->node, &b->list);
@@ -252,8 +253,10 @@ static void debug_print_object(struct debug_obj *obj, char *msg) · 105 unmodified lines
252253
253254 if (limit < 5 && obj->descr != descr_test) {
254255 limit++;
255− WARN(1, KERN_ERR "ODEBUG: %s %s object type: %s\n", msg,
256− obj_states[obj->state], obj->descr->name);
256+ WARN(1, KERN_ERR "ODEBUG: %s %s (active state %u) "
257+ "object type: %s\n",
258+ msg, obj_states[obj->state], obj->astate,
259+ obj->descr->name);
257260 }
258261 debug_objects_warnings++;
259262 }
@@ -447,7 +450,10 @@ void debug_object_deactivate(void *addr, struct debug_obj_descr *descr) · 187 unmodified lines
447450 case ODEBUG_STATE_INIT:
448451 case ODEBUG_STATE_INACTIVE:
449452 case ODEBUG_STATE_ACTIVE:
450− obj->state = ODEBUG_STATE_INACTIVE;
453+ if (!obj->astate)
454+ obj->state = ODEBUG_STATE_INACTIVE;
455+ else
456+ debug_print_object(obj, "deactivate");
451457 break;
452458
453459 case ODEBUG_STATE_DESTROYED:
@@ -553,6 +559,53 @@ out_unlock: · 99 unmodified lines
553559 raw_spin_unlock_irqrestore(&db->lock, flags);
554560 }
555561
562+/**
563+ * debug_object_active_state - debug checks object usage state machine
564+ * @addr: address of the object
565+ * @descr: pointer to an object specific debug description structure
566+ * @expect: expected state
567+ * @next: state to move to if expected state is found
568+ */
569+void
570+debug_object_active_state(void *addr, struct debug_obj_descr *descr,
571+ unsigned int expect, unsigned int next)
572+{
573+ struct debug_bucket *db;
574+ struct debug_obj *obj;
575+ unsigned long flags;
576+
577+ if (!debug_objects_enabled)
578+ return;
579+
580+ db = get_bucket((unsigned long) addr);
581+
582+ raw_spin_lock_irqsave(&db->lock, flags);
583+
584+ obj = lookup_object(addr, db);
585+ if (obj) {
586+ switch (obj->state) {
587+ case ODEBUG_STATE_ACTIVE:
588+ if (obj->astate == expect)
589+ obj->astate = next;
590+ else
591+ debug_print_object(obj, "active_state");
592+ break;
593+
594+ default:
595+ debug_print_object(obj, "active_state");
596+ break;
597+ }
598+ } else {
599+ struct debug_obj o = { .object = addr,
600+ .state = ODEBUG_STATE_NOTAVAILABLE,
601+ .descr = descr };
602+
603+ debug_print_object(&o, "active_state");
604+ }
605+
606+ raw_spin_unlock_irqrestore(&db->lock, flags);
607+}
608+
556609 #ifdef CONFIG_DEBUG_OBJECTS_FREE
557610 static void __debug_check_no_obj_freed(const void *address, unsigned long size)
558611 {