1/* 2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#include <IOKit/IOSharedDataQueue.h> 30#include <IOKit/IODataQueueShared.h> 31#include <IOKit/IOLib.h> 32#include <IOKit/IOMemoryDescriptor.h> 33 34#ifdef dequeue 35#undef dequeue 36#endif 37 38#define super IODataQueue 39 40OSDefineMetaClassAndStructors(IOSharedDataQueue, IODataQueue) 41 42IOSharedDataQueue *IOSharedDataQueue::withCapacity(UInt32 size) 43{ 44 IOSharedDataQueue *dataQueue = new IOSharedDataQueue; 45 46 if (dataQueue) { 47 if (!dataQueue->initWithCapacity(size)) { 48 dataQueue->release(); 49 dataQueue = 0; 50 } 51 } 52 53 return dataQueue; 54} 55 56IOSharedDataQueue *IOSharedDataQueue::withEntries(UInt32 numEntries, UInt32 entrySize) 57{ 58 IOSharedDataQueue *dataQueue = new IOSharedDataQueue; 59 60 if (dataQueue) { 61 if (!dataQueue->initWithEntries(numEntries, entrySize)) { 62 dataQueue->release(); 63 dataQueue = 0; 64 } 65 } 66 67 return dataQueue; 68} 69 70Boolean IOSharedDataQueue::initWithCapacity(UInt32 size) 71{ 72 IODataQueueAppendix * appendix; 73 74 if (!super::init()) { 75 return false; 76 } 77 78 dataQueue = (IODataQueueMemory *)IOMallocAligned(round_page_32(size + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE), PAGE_SIZE); 79 if (dataQueue == 0) { 80 return false; 81 } 82 83 dataQueue->queueSize = size; 84 dataQueue->head = 0; 85 dataQueue->tail = 0; 86 87 appendix = (IODataQueueAppendix *)((UInt8 *)dataQueue + size + DATA_QUEUE_MEMORY_HEADER_SIZE); 88 appendix->version = 0; 89 notifyMsg = &(appendix->msgh); 90 setNotificationPort(MACH_PORT_NULL); 91 92 return true; 93} 94 95void IOSharedDataQueue::free() 96{ 97 if (dataQueue) { 98 IOFreeAligned(dataQueue, round_page_32(dataQueue->queueSize + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE)); 99 dataQueue = NULL; 100 } 101 102 super::free(); 103} 104 105IOMemoryDescriptor *IOSharedDataQueue::getMemoryDescriptor() 106{ 107 IOMemoryDescriptor *descriptor = 0; 108 109 if (dataQueue != 0) { 110 descriptor = IOMemoryDescriptor::withAddress(dataQueue, dataQueue->queueSize + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE, kIODirectionOutIn); 111 } 112 113 return descriptor; 114} 115 116 117IODataQueueEntry * IOSharedDataQueue::peek() 118{ 119 IODataQueueEntry *entry = 0; 120 121 if (dataQueue && (dataQueue->head != dataQueue->tail)) { 122 IODataQueueEntry * head = 0; 123 UInt32 headSize = 0; 124 UInt32 headOffset = dataQueue->head; 125 UInt32 queueSize = dataQueue->queueSize; 126 127 head = (IODataQueueEntry *)((char *)dataQueue->queue + headOffset); 128 headSize = head->size; 129 130 // Check if there's enough room before the end of the queue for a header. 131 // If there is room, check if there's enough room to hold the header and 132 // the data. 133 134 if ((headOffset + DATA_QUEUE_ENTRY_HEADER_SIZE > queueSize) || 135 ((headOffset + headSize + DATA_QUEUE_ENTRY_HEADER_SIZE) > queueSize)) 136 { 137 // No room for the header or the data, wrap to the beginning of the queue. 138 entry = dataQueue->queue; 139 } else { 140 entry = head; 141 } 142 } 143 144 return entry; 145} 146 147Boolean IOSharedDataQueue::dequeue(void *data, UInt32 *dataSize) 148{ 149 Boolean retVal = TRUE; 150 IODataQueueEntry * entry = 0; 151 UInt32 entrySize = 0; 152 UInt32 newHeadOffset = 0; 153 154 if (dataQueue) { 155 if (dataQueue->head != dataQueue->tail) { 156 IODataQueueEntry * head = 0; 157 UInt32 headSize = 0; 158 UInt32 headOffset = dataQueue->head; 159 UInt32 queueSize = dataQueue->queueSize; 160 161 head = (IODataQueueEntry *)((char *)dataQueue->queue + headOffset); 162 headSize = head->size; 163 164 // we wraped around to beginning, so read from there 165 // either there was not even room for the header 166 if ((headOffset + DATA_QUEUE_ENTRY_HEADER_SIZE > queueSize) || 167 // or there was room for the header, but not for the data 168 ((headOffset + headSize + DATA_QUEUE_ENTRY_HEADER_SIZE) > queueSize)) { 169 entry = dataQueue->queue; 170 entrySize = entry->size; 171 newHeadOffset = entrySize + DATA_QUEUE_ENTRY_HEADER_SIZE; 172 // else it is at the end 173 } else { 174 entry = head; 175 entrySize = entry->size; 176 newHeadOffset = headOffset + entrySize + DATA_QUEUE_ENTRY_HEADER_SIZE; 177 } 178 } 179 180 if (entry) { 181 if (data) { 182 if (dataSize) { 183 if (entrySize <= *dataSize) { 184 memcpy(data, &(entry->data), entrySize); 185 dataQueue->head = newHeadOffset; 186 } else { 187 retVal = FALSE; 188 } 189 } else { 190 retVal = FALSE; 191 } 192 } else { 193 dataQueue->head = newHeadOffset; 194 } 195 196 if (dataSize) { 197 *dataSize = entrySize; 198 } 199 } else { 200 retVal = FALSE; 201 } 202 } else { 203 retVal = FALSE; 204 } 205 206 return retVal; 207} 208 209 210OSMetaClassDefineReservedUnused(IOSharedDataQueue, 0); 211OSMetaClassDefineReservedUnused(IOSharedDataQueue, 1); 212OSMetaClassDefineReservedUnused(IOSharedDataQueue, 2); 213OSMetaClassDefineReservedUnused(IOSharedDataQueue, 3); 214OSMetaClassDefineReservedUnused(IOSharedDataQueue, 4); 215OSMetaClassDefineReservedUnused(IOSharedDataQueue, 5); 216OSMetaClassDefineReservedUnused(IOSharedDataQueue, 6); 217OSMetaClassDefineReservedUnused(IOSharedDataQueue, 7); 218