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