+
+bool
+IOWorkLoop::eventSourcePerformsWork(IOEventSource *inEventSource)
+{
+ bool result = true;
+
+ /*
+ * The idea here is to see if the subclass of IOEventSource has overridden checkForWork().
+ * The assumption is that if you override checkForWork(), you need to be
+ * active and not passive.
+ *
+ * We picked a known quantity controlG that does not override
+ * IOEventSource::checkForWork(), namely the IOCommandGate associated with
+ * the workloop to which this event source is getting attached.
+ *
+ * We do a pointer comparison on the offset in the vtable for inNewEvent against
+ * the offset in the vtable for inReferenceEvent. This works because
+ * IOCommandGate's slot for checkForWork() has the address of
+ * IOEventSource::checkForWork() in it.
+ *
+ * Think of OSMemberFunctionCast yielding the value at the vtable offset for
+ * checkForWork() here. We're just testing to see if it's the same or not.
+ *
+ */
+ if (controlG) {
+ void * ptr1;
+ void * ptr2;
+
+ ptr1 = OSMemberFunctionCast(void*, inEventSource, &IOEventSource::checkForWork);
+ ptr2 = OSMemberFunctionCast(void*, controlG, &IOEventSource::checkForWork);
+
+ if (ptr1 == ptr2)
+ result = false;
+ }
+
+ return result;
+}
+
+void
+IOWorkLoop::lockTime(void)
+{
+ uint64_t time;
+ time = mach_absolute_time() - reserved->lockTime;
+ if (time > reserved->lockInterval)
+ {
+ absolutetime_to_nanoseconds(time, &time);
+ if (kTimeLockPanics & reserved->options) panic("IOWorkLoop %p lock time %qd us", this, time / 1000ULL);
+ else OSReportWithBacktrace("IOWorkLoop %p lock time %qd us", this, time / 1000ULL);
+ }
+}
+
+void
+IOWorkLoop::setMaximumLockTime(uint64_t interval, uint32_t options)
+{
+ IORecursiveLockLock(gateLock);
+ reserved->lockInterval = interval;
+ reserved->options = (reserved->options & ~kTimeLockPanics) | (options & kTimeLockPanics);
+ IORecursiveLockUnlock(gateLock);
+}