Loading...
iokit/Kernel/IOCommandQueue.cpp xnu-12377.101.15 xnu-792
--- xnu/xnu-12377.101.15/iokit/Kernel/IOCommandQueue.cpp
+++ xnu/xnu-792/iokit/Kernel/IOCommandQueue.cpp
@@ -1,61 +1,40 @@
 /*
- * Copyright (c) 1998-2010 Apple Inc. All rights reserved.
+ * Copyright (c) 1998-2004 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- *
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- *
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- *
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * @APPLE_LICENSE_HEADER_START@
+ * 
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
+ * 
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ * 
+ * @APPLE_LICENSE_HEADER_END@
  */
-
-#define IOKIT_ENABLE_SHARED_PTR
-
-#if !defined(__LP64__)
-
+/*
+Copyright (c) 1998 Apple Computer, Inc.  All rights reserved.
+
+HISTORY
+    1998-7-13	Godfrey van der Linden(gvdl)
+        Created.
+]*/
 #include <IOKit/IOCommandQueue.h>
 #include <IOKit/IOWorkLoop.h>
 #include <IOKit/IOTimeStamp.h>
-#include <IOKit/IOKitDebug.h>
-#include <libkern/c++/OSSharedPtr.h>
 
 #include <mach/sync_policy.h>
 
-#if IOKITSTATS
-
-#define IOStatisticsInitializeCounter() \
-	IOStatistics::setCounterType(reserved->counter, kIOStatisticsCommandQueueCounter)
-
-#define IOStatisticsActionCall() \
-	IOStatistics::countCommandQueueActionCall(reserved->counter)
-
-#else
-
-#define IOStatisticsInitializeCounter()
-#define IOStatisticsActionCall()
-
-#endif /* IOKITSTATS */
-
-#define NUM_FIELDS_IN_COMMAND   4
+#define NUM_FIELDS_IN_COMMAND	4
 typedef struct commandEntryTag {
-	void *f[NUM_FIELDS_IN_COMMAND];
+    void *f[NUM_FIELDS_IN_COMMAND];
 } commandEntryT;
 
 #define super IOEventSource
@@ -63,260 +42,227 @@
 OSDefineMetaClassAndStructors(IOCommandQueue, IOEventSource)
 
 /*[
- *  Instance Methods
- *
- *  initWithNext:owner:action:size:
- *   - initWithNext: (IOEventSource *) inNext
- *           owner: (id) inOwner
- *           action: (SEL) inAction
- *             size: (int) inSize;
- *
- *  Primary initialiser for the IOCommandQueue class.  Returns an
- *  IOCommandQueue object that is initialised with the next object in
- *  the chain and the owner and action. On return the signalWorkAvailableIMP
- *  has been cached for this function.
- *
- *  If the object fails to initialise for some reason then [self free] will
- *  be called and nil will be returned.
- *
- *  See also: initWithNext:owner:action:(IOEventSource)
- *  ]*/
-bool
-IOCommandQueue::init(OSObject *inOwner,
-    IOCommandQueueAction inAction,
-    int inSize)
-{
-	if (!super::init(inOwner, (IOEventSourceAction) inAction)) {
-		return false;
-	}
-
-	if (KERN_SUCCESS
-	    != semaphore_create(kernel_task, &producerSema, SYNC_POLICY_FIFO, inSize)) {
-		return false;
-	}
-
-	size = inSize + 1; /* Allocate one more entry than needed */
-
-	queue = (void *)kalloc_type(commandEntryT, size, Z_WAITOK_ZERO);
-	if (!queue) {
-		return false;
-	}
-
-	producerLock = IOLockAlloc();
-	if (!producerLock) {
-		return false;
-	}
-
-	producerIndex = consumerIndex = 0;
-
-	IOStatisticsInitializeCounter();
-
-	return true;
-}
-
-OSSharedPtr<IOCommandQueue>
+Instance Methods
+
+initWithNext:owner:action:size:
+    - initWithNext: (IOEventSource *) inNext
+            owner: (id) inOwner
+            action: (SEL) inAction
+              size: (int) inSize;
+
+Primary initialiser for the IOCommandQueue class.  Returns an
+IOCommandQueue object that is initialised with the next object in
+the chain and the owner and action. On return the signalWorkAvailableIMP
+has been cached for this function.
+
+If the object fails to initialise for some reason then [self free] will
+be called and nil will be returned.
+
+See also: initWithNext:owner:action:(IOEventSource)
+]*/
+bool IOCommandQueue::init(OSObject *inOwner,
+                          IOCommandQueueAction inAction,
+                          int inSize)
+{
+    if ( !super::init(inOwner, (IOEventSourceAction) inAction) )
+        return false;
+    
+    if (KERN_SUCCESS
+    !=  semaphore_create(kernel_task, &producerSema, SYNC_POLICY_FIFO, inSize))
+        return false;
+
+    size = inSize + 1; /* Allocate one more entry than needed */
+
+    queue = (void *)kalloc(size * sizeof(commandEntryT));
+    if (!queue)
+        return false;
+
+    producerLock = IOLockAlloc();
+    if (!producerLock)
+        return false;
+
+    producerIndex = consumerIndex = 0;
+
+    return true;
+}
+
+IOCommandQueue *
 IOCommandQueue::commandQueue(OSObject *inOwner,
-    IOCommandQueueAction inAction,
-    int inSize)
-{
-	OSSharedPtr<IOCommandQueue> me = OSMakeShared<IOCommandQueue>();
-
-	if (me && !me->init(inOwner, inAction, inSize)) {
-		me.reset();
-		return nullptr;
-	}
-
-	return me;
+                             IOCommandQueueAction inAction,
+                             int inSize)
+{
+    IOCommandQueue *me = new IOCommandQueue;
+
+    if (me && !me->init(inOwner, inAction, inSize)) {
+        me->free();
+        return 0;
+    }
+
+    return me;
 }
 
 /*[
- *  free
- *   - free
- *
- *  Mandatory free of the object independent of the current retain count.
- *  Returns nil.
- *  ]*/
-void
-IOCommandQueue::free()
-{
-	if (queue) {
-		kfree_type(commandEntryT, size, queue);
-	}
-	if (producerSema) {
-		semaphore_destroy(kernel_task, producerSema);
-	}
-	if (producerLock) {
-		IOLockFree(producerLock);
-	}
-
-	super::free();
+free
+    - free
+
+Mandatory free of the object independent of the current retain count.
+Returns nil.
+]*/
+void IOCommandQueue::free()
+{
+    if (queue)
+        kfree(queue, size * sizeof(commandEntryT));
+    if (producerSema)
+        semaphore_destroy(kernel_task, producerSema);
+    if (producerLock)
+        IOLockFree(producerLock);
+
+    super::free();
 }
 
 #if NUM_FIELDS_IN_COMMAND != 4
 #error IOCommandQueue::checkForWork needs to be updated for new command size
 #endif
 
-bool
-IOCommandQueue::checkForWork()
-{
-	void        *field0, *field1, *field2, *field3;
-	bool    trace = (gIOKitTrace & kIOTraceCommandGates) ? true : false;
-
-	if (!enabled || consumerIndex == producerIndex) {
-		return false;
-	}
-
-	{
-		commandEntryT *q = (commandEntryT *) queue;
-		int localIndex = consumerIndex;
-
-		field0 = q[localIndex].f[0]; field1 = q[localIndex].f[1];
-		field2 = q[localIndex].f[2]; field3 = q[localIndex].f[3];
-		semaphore_signal(producerSema);
-	}
-
-	if (++consumerIndex >= size) {
-		consumerIndex = 0;
-	}
-
-	if (trace) {
-		IOTimeStampStartConstant(IODBG_CMDQ(IOCMDQ_ACTION),
-		    VM_KERNEL_ADDRHIDE(action), VM_KERNEL_ADDRHIDE(owner));
-	}
-
-	IOStatisticsActionCall();
-	(*(IOCommandQueueAction) action)(owner, field0, field1, field2, field3);
-
-	if (trace) {
-		IOTimeStampEndConstant(IODBG_CMDQ(IOCMDQ_ACTION),
-		    VM_KERNEL_ADDRHIDE(action), VM_KERNEL_ADDRHIDE(owner));
-	}
-
-	return consumerIndex != producerIndex;
+bool IOCommandQueue::checkForWork()
+{
+    void *field0, *field1, *field2, *field3;
+
+    if (!enabled || consumerIndex == producerIndex)
+        return false;
+
+    {
+        commandEntryT *q = (commandEntryT *) queue;
+        int localIndex = consumerIndex;
+
+        field0 = q[localIndex].f[0]; field1 = q[localIndex].f[1];
+        field2 = q[localIndex].f[2]; field3 = q[localIndex].f[3];
+        semaphore_signal(producerSema);
+    }
+
+    if (++consumerIndex >= size)
+        consumerIndex = 0;
+
+    IOTimeStampConstant(IODBG_CMDQ(IOCMDQ_ACTION),
+			(unsigned int) action, (unsigned int) owner);
+
+    (*(IOCommandQueueAction) action)(owner, field0, field1, field2, field3);
+
+    return (consumerIndex != producerIndex);
 }
 
 /*[
- *  enqueueSleep:command:
- *   - (kern_return_t) enqueueSleepRaw: (BOOL) gotoSleep
- *                              field0: (void *) field0 field1: (void *) field1
- *                              field2: (void *) field2 field3: (void *) field3;
- *
- *  Key method that enqueues the four input fields onto the command queue
- *  and calls signalWorkAvailable to indicate that work is available to the
- *  consumer.  This routine is safe against multiple threaded producers.
- *
- *  A family of convenience functions have been provided to assist with the
- *  enqueueing of an method selector and an integer tag.  This relies on the
- *  IODevice rawCommandOccurred... command to forward on the requests.
- *
- *  See also: signalWorkAvailable, checkForWork
- *  ]*/
+enqueueSleep:command:
+    - (kern_return_t) enqueueSleepRaw: (BOOL) gotoSleep
+                               field0: (void *) field0 field1: (void *) field1
+                               field2: (void *) field2 field3: (void *) field3;
+
+Key method that enqueues the four input fields onto the command queue
+and calls signalWorkAvailable to indicate that work is available to the
+consumer.  This routine is safe against multiple threaded producers.
+
+A family of convenience functions have been provided to assist with the
+enqueueing of an method selector and an integer tag.  This relies on the
+IODevice rawCommandOccurred... command to forward on the requests.
+
+See also: signalWorkAvailable, checkForWork
+]*/
 #if NUM_FIELDS_IN_COMMAND != 4
 #error IOCommandQueue::enqueueCommand needs to be updated
 #endif
 
 kern_return_t
 IOCommandQueue::enqueueCommand(bool gotoSleep,
-    void *field0, void *field1,
-    void *field2, void *field3)
-{
-	kern_return_t rtn = KERN_SUCCESS;
-	int retry;
-
-	/* Make sure there is room in the queue before doing anything else */
-
-	if (gotoSleep) {
-		retry = 0;
-		do{
-			rtn = semaphore_wait(producerSema);
-		} while ((KERN_SUCCESS != rtn)
-		    && (KERN_OPERATION_TIMED_OUT != rtn)
-		    && (KERN_SEMAPHORE_DESTROYED != rtn)
-		    && (KERN_TERMINATED != rtn)
-		    && ((retry++) < 4));
-	} else {
-		rtn = semaphore_timedwait(producerSema, MACH_TIMESPEC_ZERO);
-	}
-
-	if (KERN_SUCCESS != rtn) {
-		return rtn;
-	}
-
-	/* Block other producers */
-	IOTakeLock(producerLock);
-
-	/*
-	 * Make sure that we update the current producer entry before we
-	 * increment the producer pointer.  This avoids a nasty race as the
-	 * test for work is producerIndex != consumerIndex and a signal.
-	 */
-	{
-		commandEntryT *q = (commandEntryT *) queue;
-		int localIndex = producerIndex;
-
-		q[localIndex].f[0] = field0; q[localIndex].f[1] = field1;
-		q[localIndex].f[2] = field2; q[localIndex].f[3] = field3;
-	}
-	if (++producerIndex >= size) {
-		producerIndex = 0;
-	}
-
-	/* Clear to allow other producers to go now */
-	IOUnlock(producerLock);
-
-	/*
-	 * Right we have created some new work, we had better make sure that
-	 * we notify the work loop that it has to test producerIndex.
-	 */
-	signalWorkAvailable();
-	return rtn;
-}
-
-int
-IOCommandQueue::performAndFlush(OSObject *target,
-    IOCommandQueueAction inAction)
-{
-	int numEntries;
-	kern_return_t rtn;
-
-	// Set the defaults if necessary
-	if (!target) {
-		target = owner;
-	}
-	if (!inAction) {
-		inAction = (IOCommandQueueAction) action;
-	}
-
-	// Lock out the producers first
-	do {
-		rtn = semaphore_timedwait(producerSema, MACH_TIMESPEC_ZERO);
-	} while (rtn == KERN_SUCCESS);
-
-	// now step over all remaining entries in the command queue
-	for (numEntries = 0; consumerIndex != producerIndex;) {
-		void *field0, *field1, *field2, *field3;
-
-		{
-			commandEntryT *q = (commandEntryT *) queue;
-			int localIndex = consumerIndex;
-
-			field0 = q[localIndex].f[0]; field1 = q[localIndex].f[1];
-			field2 = q[localIndex].f[2]; field3 = q[localIndex].f[3];
-		}
-
-		if (++consumerIndex >= size) {
-			consumerIndex = 0;
-		}
-
-		(*inAction)(target, field0, field1, field2, field3);
-	}
-
-	// finally refill the producer semaphore to size - 1
-	for (int i = 1; i < size; i++) {
-		semaphore_signal(producerSema);
-	}
-
-	return numEntries;
-}
-
-#endif /* !defined(__LP64__) */
+                               void *field0, void *field1,
+                               void *field2, void *field3)
+{
+    kern_return_t rtn = KERN_SUCCESS;
+    int retry;
+
+    /* Make sure there is room in the queue before doing anything else */
+
+    if (gotoSleep) {
+        retry = 0;
+        do
+        rtn = semaphore_wait(producerSema);
+        while(     (KERN_SUCCESS != rtn)
+		&& (KERN_OPERATION_TIMED_OUT != rtn)
+		&& (KERN_SEMAPHORE_DESTROYED != rtn)
+		&& (KERN_TERMINATED != rtn)
+		&& ((retry++) < 4));
+    } else
+        rtn = semaphore_timedwait(producerSema, MACH_TIMESPEC_ZERO);
+
+    if (KERN_SUCCESS != rtn)
+        return rtn;
+
+    /* Block other producers */
+    IOTakeLock(producerLock);
+
+    /*
+     * Make sure that we update the current producer entry before we
+     * increment the producer pointer.  This avoids a nasty race as the
+     * as the test for work is producerIndex != consumerIndex and a signal.
+     */
+    {
+        commandEntryT *q = (commandEntryT *) queue;
+        int localIndex = producerIndex;
+
+        q[localIndex].f[0] = field0; q[localIndex].f[1] = field1;
+        q[localIndex].f[2] = field2; q[localIndex].f[3] = field3;
+    }
+    if (++producerIndex >= size)
+        producerIndex = 0;
+
+    /* Clear to allow other producers to go now */
+    IOUnlock(producerLock);
+
+    /*
+     * Right we have created some new work, we had better make sure that
+     * we notify the work loop that it has to test producerIndex.
+     */
+    signalWorkAvailable();
+    return rtn;
+}
+
+int IOCommandQueue::performAndFlush(OSObject *target,
+                                    IOCommandQueueAction inAction)
+{
+    int numEntries;
+    kern_return_t rtn;
+
+    // Set the defaults if necessary
+    if (!target)
+        target = owner;
+    if (!inAction)
+        inAction = (IOCommandQueueAction) action;
+
+    // Lock out the producers first
+    do {
+        rtn = semaphore_timedwait(producerSema, MACH_TIMESPEC_ZERO);
+    } while (rtn == KERN_SUCCESS);
+
+    // now step over all remaining entries in the command queue
+    for (numEntries = 0; consumerIndex != producerIndex; ) {
+        void *field0, *field1, *field2, *field3;
+
+        {
+            commandEntryT *q = (commandEntryT *) queue;
+            int localIndex = consumerIndex;
+
+            field0 = q[localIndex].f[0]; field1 = q[localIndex].f[1];
+            field2 = q[localIndex].f[2]; field3 = q[localIndex].f[3];
+        }
+
+        if (++consumerIndex >= size)
+            consumerIndex = 0;
+
+        (*inAction)(target, field0, field1, field2, field3);
+    }
+
+    // finally refill the producer semaphore to size - 1
+    for (int i = 1; i < size; i++)
+        semaphore_signal(producerSema);
+
+    return numEntries;
+}