xnu-1504.7.4.tar.gz
[apple/xnu.git] / iokit / Kernel / IOSharedDataQueue.cpp
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
40 OSDefineMetaClassAndStructors(IOSharedDataQueue, IODataQueue)
41
42 IOSharedDataQueue *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
56 IOSharedDataQueue *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
70 Boolean IOSharedDataQueue::initWithCapacity(UInt32 size)
71 {
72 IODataQueueAppendix * appendix;
73
74 if (!super::init()) {
75 return false;
76 }
77
78 dataQueue = (IODataQueueMemory *)IOMallocAligned(round_page(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
95 void IOSharedDataQueue::free()
96 {
97 if (dataQueue) {
98 IOFreeAligned(dataQueue, round_page(dataQueue->queueSize + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE));
99 dataQueue = NULL;
100 }
101
102 super::free();
103 }
104
105 IOMemoryDescriptor *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
117 IODataQueueEntry * 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
147 Boolean 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
210 OSMetaClassDefineReservedUnused(IOSharedDataQueue, 0);
211 OSMetaClassDefineReservedUnused(IOSharedDataQueue, 1);
212 OSMetaClassDefineReservedUnused(IOSharedDataQueue, 2);
213 OSMetaClassDefineReservedUnused(IOSharedDataQueue, 3);
214 OSMetaClassDefineReservedUnused(IOSharedDataQueue, 4);
215 OSMetaClassDefineReservedUnused(IOSharedDataQueue, 5);
216 OSMetaClassDefineReservedUnused(IOSharedDataQueue, 6);
217 OSMetaClassDefineReservedUnused(IOSharedDataQueue, 7);