1e13b1fa5SApple OSS Distributions /*
2e13b1fa5SApple OSS Distributions  * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3e13b1fa5SApple OSS Distributions  *
4e13b1fa5SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5e13b1fa5SApple OSS Distributions  *
6e13b1fa5SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7e13b1fa5SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8e13b1fa5SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9e13b1fa5SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10e13b1fa5SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11e13b1fa5SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12e13b1fa5SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13e13b1fa5SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14e13b1fa5SApple OSS Distributions  *
15e13b1fa5SApple OSS Distributions  * Please obtain a copy of the License at
16e13b1fa5SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17e13b1fa5SApple OSS Distributions  *
18e13b1fa5SApple OSS Distributions  * The Original Code and all software distributed under the License are
19e13b1fa5SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20e13b1fa5SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21e13b1fa5SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22e13b1fa5SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23e13b1fa5SApple OSS Distributions  * Please see the License for the specific language governing rights and
24e13b1fa5SApple OSS Distributions  * limitations under the License.
25e13b1fa5SApple OSS Distributions  *
26e13b1fa5SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27e13b1fa5SApple OSS Distributions  */
28e13b1fa5SApple OSS Distributions 
29e13b1fa5SApple OSS Distributions #include <IOKit/IOSharedDataQueue.h>
30e13b1fa5SApple OSS Distributions #include <IOKit/IODataQueueShared.h>
31e13b1fa5SApple OSS Distributions #include <IOKit/IOLib.h>
32e13b1fa5SApple OSS Distributions #include <IOKit/IOMemoryDescriptor.h>
33e13b1fa5SApple OSS Distributions 
34*a3bb9fccSApple OSS Distributions #ifdef enqueue
35*a3bb9fccSApple OSS Distributions #undef enqueue
36*a3bb9fccSApple OSS Distributions #endif
37*a3bb9fccSApple OSS Distributions 
38e13b1fa5SApple OSS Distributions #ifdef dequeue
39e13b1fa5SApple OSS Distributions #undef dequeue
40e13b1fa5SApple OSS Distributions #endif
41e13b1fa5SApple OSS Distributions 
42e13b1fa5SApple OSS Distributions #define super IODataQueue
43e13b1fa5SApple OSS Distributions 
44e13b1fa5SApple OSS Distributions OSDefineMetaClassAndStructors(IOSharedDataQueue, IODataQueue)
45e13b1fa5SApple OSS Distributions 
46e13b1fa5SApple OSS Distributions IOSharedDataQueue *IOSharedDataQueue::withCapacity(UInt32 size)
47e13b1fa5SApple OSS Distributions {
48e13b1fa5SApple OSS Distributions     IOSharedDataQueue *dataQueue = new IOSharedDataQueue;
49e13b1fa5SApple OSS Distributions 
50e13b1fa5SApple OSS Distributions     if (dataQueue) {
51e13b1fa5SApple OSS Distributions         if  (!dataQueue->initWithCapacity(size)) {
52e13b1fa5SApple OSS Distributions             dataQueue->release();
53e13b1fa5SApple OSS Distributions             dataQueue = 0;
54e13b1fa5SApple OSS Distributions         }
55e13b1fa5SApple OSS Distributions     }
56e13b1fa5SApple OSS Distributions 
57e13b1fa5SApple OSS Distributions     return dataQueue;
58e13b1fa5SApple OSS Distributions }
59e13b1fa5SApple OSS Distributions 
60e13b1fa5SApple OSS Distributions IOSharedDataQueue *IOSharedDataQueue::withEntries(UInt32 numEntries, UInt32 entrySize)
61e13b1fa5SApple OSS Distributions {
62e13b1fa5SApple OSS Distributions     IOSharedDataQueue *dataQueue = new IOSharedDataQueue;
63e13b1fa5SApple OSS Distributions 
64e13b1fa5SApple OSS Distributions     if (dataQueue) {
65e13b1fa5SApple OSS Distributions         if (!dataQueue->initWithEntries(numEntries, entrySize)) {
66e13b1fa5SApple OSS Distributions             dataQueue->release();
67e13b1fa5SApple OSS Distributions             dataQueue = 0;
68e13b1fa5SApple OSS Distributions         }
69e13b1fa5SApple OSS Distributions     }
70e13b1fa5SApple OSS Distributions 
71e13b1fa5SApple OSS Distributions     return dataQueue;
72e13b1fa5SApple OSS Distributions }
73e13b1fa5SApple OSS Distributions 
74e13b1fa5SApple OSS Distributions Boolean IOSharedDataQueue::initWithCapacity(UInt32 size)
75e13b1fa5SApple OSS Distributions {
76e13b1fa5SApple OSS Distributions     IODataQueueAppendix *   appendix;
77*a3bb9fccSApple OSS Distributions     vm_size_t               allocSize;
78e13b1fa5SApple OSS Distributions 
79e13b1fa5SApple OSS Distributions     if (!super::init()) {
80e13b1fa5SApple OSS Distributions         return false;
81e13b1fa5SApple OSS Distributions     }
82e13b1fa5SApple OSS Distributions 
83*a3bb9fccSApple OSS Distributions     _reserved = (ExpansionData *)IOMalloc(sizeof(struct ExpansionData));
84*a3bb9fccSApple OSS Distributions     if (!_reserved) {
85*a3bb9fccSApple OSS Distributions         return false;
86*a3bb9fccSApple OSS Distributions     }
87*a3bb9fccSApple OSS Distributions 
88*a3bb9fccSApple OSS Distributions     if (size > UINT32_MAX - DATA_QUEUE_MEMORY_HEADER_SIZE - DATA_QUEUE_MEMORY_APPENDIX_SIZE) {
89*a3bb9fccSApple OSS Distributions         return false;
90*a3bb9fccSApple OSS Distributions     }
91*a3bb9fccSApple OSS Distributions 
92*a3bb9fccSApple OSS Distributions     allocSize = round_page(size + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE);
93*a3bb9fccSApple OSS Distributions 
94*a3bb9fccSApple OSS Distributions     if (allocSize < size) {
95*a3bb9fccSApple OSS Distributions         return false;
96*a3bb9fccSApple OSS Distributions     }
97*a3bb9fccSApple OSS Distributions 
98*a3bb9fccSApple OSS Distributions     dataQueue = (IODataQueueMemory *)IOMallocAligned(allocSize, PAGE_SIZE);
99e13b1fa5SApple OSS Distributions     if (dataQueue == 0) {
100e13b1fa5SApple OSS Distributions         return false;
101e13b1fa5SApple OSS Distributions     }
102e13b1fa5SApple OSS Distributions 
103e13b1fa5SApple OSS Distributions     dataQueue->queueSize    = size;
104e13b1fa5SApple OSS Distributions     dataQueue->head         = 0;
105e13b1fa5SApple OSS Distributions     dataQueue->tail         = 0;
106e13b1fa5SApple OSS Distributions 
107*a3bb9fccSApple OSS Distributions     if (!setQueueSize(size)) {
108*a3bb9fccSApple OSS Distributions         return false;
109*a3bb9fccSApple OSS Distributions     }
110*a3bb9fccSApple OSS Distributions 
111e13b1fa5SApple OSS Distributions     appendix            = (IODataQueueAppendix *)((UInt8 *)dataQueue + size + DATA_QUEUE_MEMORY_HEADER_SIZE);
112e13b1fa5SApple OSS Distributions     appendix->version   = 0;
113e13b1fa5SApple OSS Distributions     notifyMsg           = &(appendix->msgh);
114e13b1fa5SApple OSS Distributions     setNotificationPort(MACH_PORT_NULL);
115e13b1fa5SApple OSS Distributions 
116e13b1fa5SApple OSS Distributions     return true;
117e13b1fa5SApple OSS Distributions }
118e13b1fa5SApple OSS Distributions 
119e13b1fa5SApple OSS Distributions void IOSharedDataQueue::free()
120e13b1fa5SApple OSS Distributions {
121e13b1fa5SApple OSS Distributions     if (dataQueue) {
122*a3bb9fccSApple OSS Distributions         IOFreeAligned(dataQueue, round_page(getQueueSize() + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE));
123e13b1fa5SApple OSS Distributions         dataQueue = NULL;
124e13b1fa5SApple OSS Distributions     }
125e13b1fa5SApple OSS Distributions 
126*a3bb9fccSApple OSS Distributions     if (_reserved) {
127*a3bb9fccSApple OSS Distributions         IOFree (_reserved, sizeof(struct ExpansionData));
128*a3bb9fccSApple OSS Distributions         _reserved = NULL;
129*a3bb9fccSApple OSS Distributions     }
130*a3bb9fccSApple OSS Distributions 
131e13b1fa5SApple OSS Distributions     super::free();
132e13b1fa5SApple OSS Distributions }
133e13b1fa5SApple OSS Distributions 
134e13b1fa5SApple OSS Distributions IOMemoryDescriptor *IOSharedDataQueue::getMemoryDescriptor()
135e13b1fa5SApple OSS Distributions {
136e13b1fa5SApple OSS Distributions     IOMemoryDescriptor *descriptor = 0;
137e13b1fa5SApple OSS Distributions 
138e13b1fa5SApple OSS Distributions     if (dataQueue != 0) {
139*a3bb9fccSApple OSS Distributions         descriptor = IOMemoryDescriptor::withAddress(dataQueue, getQueueSize() + DATA_QUEUE_MEMORY_HEADER_SIZE + DATA_QUEUE_MEMORY_APPENDIX_SIZE, kIODirectionOutIn);
140e13b1fa5SApple OSS Distributions     }
141e13b1fa5SApple OSS Distributions 
142e13b1fa5SApple OSS Distributions     return descriptor;
143e13b1fa5SApple OSS Distributions }
144e13b1fa5SApple OSS Distributions 
145e13b1fa5SApple OSS Distributions 
146e13b1fa5SApple OSS Distributions IODataQueueEntry * IOSharedDataQueue::peek()
147e13b1fa5SApple OSS Distributions {
148e13b1fa5SApple OSS Distributions     IODataQueueEntry *entry = 0;
149e13b1fa5SApple OSS Distributions 
150e13b1fa5SApple OSS Distributions     if (dataQueue && (dataQueue->head != dataQueue->tail)) {
151e13b1fa5SApple OSS Distributions         IODataQueueEntry *  head        = 0;
152e13b1fa5SApple OSS Distributions         UInt32              headSize    = 0;
153e13b1fa5SApple OSS Distributions         UInt32              headOffset  = dataQueue->head;
154*a3bb9fccSApple OSS Distributions         UInt32              queueSize   = getQueueSize();
155*a3bb9fccSApple OSS Distributions 
156*a3bb9fccSApple OSS Distributions         if (headOffset >= queueSize) {
157*a3bb9fccSApple OSS Distributions             return NULL;
158*a3bb9fccSApple OSS Distributions         }
159e13b1fa5SApple OSS Distributions 
160e13b1fa5SApple OSS Distributions         head         = (IODataQueueEntry *)((char *)dataQueue->queue + headOffset);
161e13b1fa5SApple OSS Distributions         headSize     = head->size;
162e13b1fa5SApple OSS Distributions 
163e13b1fa5SApple OSS Distributions         // Check if there's enough room before the end of the queue for a header.
164e13b1fa5SApple OSS Distributions         // If there is room, check if there's enough room to hold the header and
165e13b1fa5SApple OSS Distributions         // the data.
166e13b1fa5SApple OSS Distributions 
167*a3bb9fccSApple OSS Distributions         if ((headOffset > UINT32_MAX - DATA_QUEUE_ENTRY_HEADER_SIZE) ||
168*a3bb9fccSApple OSS Distributions             (headOffset + DATA_QUEUE_ENTRY_HEADER_SIZE > queueSize) ||
169*a3bb9fccSApple OSS Distributions             (headOffset + DATA_QUEUE_ENTRY_HEADER_SIZE > UINT32_MAX - headSize) ||
170*a3bb9fccSApple OSS Distributions             (headOffset + headSize + DATA_QUEUE_ENTRY_HEADER_SIZE > queueSize)) {
171e13b1fa5SApple OSS Distributions             // No room for the header or the data, wrap to the beginning of the queue.
172*a3bb9fccSApple OSS Distributions             // Note: wrapping even with the UINT32_MAX checks, as we have to support
173*a3bb9fccSApple OSS Distributions             // queueSize of UINT32_MAX
174e13b1fa5SApple OSS Distributions             entry = dataQueue->queue;
175e13b1fa5SApple OSS Distributions         } else {
176e13b1fa5SApple OSS Distributions             entry = head;
177e13b1fa5SApple OSS Distributions         }
178e13b1fa5SApple OSS Distributions     }
179e13b1fa5SApple OSS Distributions 
180e13b1fa5SApple OSS Distributions     return entry;
181e13b1fa5SApple OSS Distributions }
182e13b1fa5SApple OSS Distributions 
183*a3bb9fccSApple OSS Distributions Boolean IOSharedDataQueue::enqueue(void * data, UInt32 dataSize)
184*a3bb9fccSApple OSS Distributions {
185*a3bb9fccSApple OSS Distributions     const UInt32       head      = dataQueue->head;  // volatile
186*a3bb9fccSApple OSS Distributions     const UInt32       tail      = dataQueue->tail;
187*a3bb9fccSApple OSS Distributions     const UInt32       entrySize = dataSize + DATA_QUEUE_ENTRY_HEADER_SIZE;
188*a3bb9fccSApple OSS Distributions     IODataQueueEntry * entry;
189*a3bb9fccSApple OSS Distributions 
190*a3bb9fccSApple OSS Distributions     // Check for overflow of entrySize
191*a3bb9fccSApple OSS Distributions     if (dataSize > UINT32_MAX - DATA_QUEUE_ENTRY_HEADER_SIZE) {
192*a3bb9fccSApple OSS Distributions         return false;
193*a3bb9fccSApple OSS Distributions     }
194*a3bb9fccSApple OSS Distributions     // Check for underflow of (getQueueSize() - tail)
195*a3bb9fccSApple OSS Distributions     if (getQueueSize() < tail) {
196*a3bb9fccSApple OSS Distributions         return false;
197*a3bb9fccSApple OSS Distributions     }
198*a3bb9fccSApple OSS Distributions 
199*a3bb9fccSApple OSS Distributions     if ( tail >= head )
200*a3bb9fccSApple OSS Distributions     {
201*a3bb9fccSApple OSS Distributions         // Is there enough room at the end for the entry?
202*a3bb9fccSApple OSS Distributions         if ((entrySize <= UINT32_MAX - tail) &&
203*a3bb9fccSApple OSS Distributions             ((tail + entrySize) <= getQueueSize()) )
204*a3bb9fccSApple OSS Distributions         {
205*a3bb9fccSApple OSS Distributions             entry = (IODataQueueEntry *)((UInt8 *)dataQueue->queue + tail);
206*a3bb9fccSApple OSS Distributions 
207*a3bb9fccSApple OSS Distributions             entry->size = dataSize;
208*a3bb9fccSApple OSS Distributions             memcpy(&entry->data, data, dataSize);
209*a3bb9fccSApple OSS Distributions 
210*a3bb9fccSApple OSS Distributions             // The tail can be out of bound when the size of the new entry
211*a3bb9fccSApple OSS Distributions             // exactly matches the available space at the end of the queue.
212*a3bb9fccSApple OSS Distributions             // The tail can range from 0 to dataQueue->queueSize inclusive.
213*a3bb9fccSApple OSS Distributions 
214*a3bb9fccSApple OSS Distributions             OSAddAtomic(entrySize, (SInt32 *)&dataQueue->tail);
215*a3bb9fccSApple OSS Distributions         }
216*a3bb9fccSApple OSS Distributions         else if ( head > entrySize )     // Is there enough room at the beginning?
217*a3bb9fccSApple OSS Distributions         {
218*a3bb9fccSApple OSS Distributions             // Wrap around to the beginning, but do not allow the tail to catch
219*a3bb9fccSApple OSS Distributions             // up to the head.
220*a3bb9fccSApple OSS Distributions 
221*a3bb9fccSApple OSS Distributions             dataQueue->queue->size = dataSize;
222*a3bb9fccSApple OSS Distributions 
223*a3bb9fccSApple OSS Distributions             // We need to make sure that there is enough room to set the size before
224*a3bb9fccSApple OSS Distributions             // doing this. The user client checks for this and will look for the size
225*a3bb9fccSApple OSS Distributions             // at the beginning if there isn't room for it at the end.
226*a3bb9fccSApple OSS Distributions 
227*a3bb9fccSApple OSS Distributions             if ( ( getQueueSize() - tail ) >= DATA_QUEUE_ENTRY_HEADER_SIZE )
228*a3bb9fccSApple OSS Distributions             {
229*a3bb9fccSApple OSS Distributions                 ((IODataQueueEntry *)((UInt8 *)dataQueue->queue + tail))->size = dataSize;
230*a3bb9fccSApple OSS Distributions             }
231*a3bb9fccSApple OSS Distributions 
232*a3bb9fccSApple OSS Distributions             memcpy(&dataQueue->queue->data, data, dataSize);
233*a3bb9fccSApple OSS Distributions             OSCompareAndSwap(dataQueue->tail, entrySize, &dataQueue->tail);
234*a3bb9fccSApple OSS Distributions         }
235*a3bb9fccSApple OSS Distributions         else
236*a3bb9fccSApple OSS Distributions         {
237*a3bb9fccSApple OSS Distributions             return false;    // queue is full
238*a3bb9fccSApple OSS Distributions         }
239*a3bb9fccSApple OSS Distributions     }
240*a3bb9fccSApple OSS Distributions     else
241*a3bb9fccSApple OSS Distributions     {
242*a3bb9fccSApple OSS Distributions         // Do not allow the tail to catch up to the head when the queue is full.
243*a3bb9fccSApple OSS Distributions         // That's why the comparison uses a '>' rather than '>='.
244*a3bb9fccSApple OSS Distributions 
245*a3bb9fccSApple OSS Distributions         if ( (head - tail) > entrySize )
246*a3bb9fccSApple OSS Distributions         {
247*a3bb9fccSApple OSS Distributions             entry = (IODataQueueEntry *)((UInt8 *)dataQueue->queue + tail);
248*a3bb9fccSApple OSS Distributions 
249*a3bb9fccSApple OSS Distributions             entry->size = dataSize;
250*a3bb9fccSApple OSS Distributions             memcpy(&entry->data, data, dataSize);
251*a3bb9fccSApple OSS Distributions             OSAddAtomic(entrySize, (SInt32 *)&dataQueue->tail);
252*a3bb9fccSApple OSS Distributions         }
253*a3bb9fccSApple OSS Distributions         else
254*a3bb9fccSApple OSS Distributions         {
255*a3bb9fccSApple OSS Distributions             return false;    // queue is full
256*a3bb9fccSApple OSS Distributions         }
257*a3bb9fccSApple OSS Distributions     }
258*a3bb9fccSApple OSS Distributions 
259*a3bb9fccSApple OSS Distributions     // Send notification (via mach message) that data is available.
260*a3bb9fccSApple OSS Distributions 
261*a3bb9fccSApple OSS Distributions     if ( ( head == tail )                                                   /* queue was empty prior to enqueue() */
262*a3bb9fccSApple OSS Distributions         ||   ( dataQueue->head == tail ) )   /* queue was emptied during enqueue() */
263*a3bb9fccSApple OSS Distributions     {
264*a3bb9fccSApple OSS Distributions         sendDataAvailableNotification();
265*a3bb9fccSApple OSS Distributions     }
266*a3bb9fccSApple OSS Distributions 
267*a3bb9fccSApple OSS Distributions     return true;
268*a3bb9fccSApple OSS Distributions }
269*a3bb9fccSApple OSS Distributions 
270e13b1fa5SApple OSS Distributions Boolean IOSharedDataQueue::dequeue(void *data, UInt32 *dataSize)
271e13b1fa5SApple OSS Distributions {
272e13b1fa5SApple OSS Distributions     Boolean             retVal          = TRUE;
273e13b1fa5SApple OSS Distributions     IODataQueueEntry *  entry           = 0;
274e13b1fa5SApple OSS Distributions     UInt32              entrySize       = 0;
275e13b1fa5SApple OSS Distributions     UInt32              newHeadOffset   = 0;
276e13b1fa5SApple OSS Distributions 
277e13b1fa5SApple OSS Distributions     if (dataQueue) {
278e13b1fa5SApple OSS Distributions         if (dataQueue->head != dataQueue->tail) {
279e13b1fa5SApple OSS Distributions             IODataQueueEntry *  head        = 0;
280e13b1fa5SApple OSS Distributions             UInt32              headSize    = 0;
281e13b1fa5SApple OSS Distributions             UInt32              headOffset  = dataQueue->head;
282*a3bb9fccSApple OSS Distributions             UInt32              queueSize   = getQueueSize();
283*a3bb9fccSApple OSS Distributions 
284*a3bb9fccSApple OSS Distributions             if (headOffset > queueSize) {
285*a3bb9fccSApple OSS Distributions                 return false;
286*a3bb9fccSApple OSS Distributions             }
287e13b1fa5SApple OSS Distributions 
288e13b1fa5SApple OSS Distributions             head         = (IODataQueueEntry *)((char *)dataQueue->queue + headOffset);
289e13b1fa5SApple OSS Distributions             headSize     = head->size;
290e13b1fa5SApple OSS Distributions 
291*a3bb9fccSApple OSS Distributions             // we wrapped around to beginning, so read from there
292e13b1fa5SApple OSS Distributions             // either there was not even room for the header
293*a3bb9fccSApple OSS Distributions             if ((headOffset > UINT32_MAX - DATA_QUEUE_ENTRY_HEADER_SIZE) ||
294*a3bb9fccSApple OSS Distributions                 (headOffset + DATA_QUEUE_ENTRY_HEADER_SIZE > queueSize) ||
295e13b1fa5SApple OSS Distributions                 // or there was room for the header, but not for the data
296*a3bb9fccSApple OSS Distributions                 (headOffset + DATA_QUEUE_ENTRY_HEADER_SIZE > UINT32_MAX - headSize) ||
297*a3bb9fccSApple OSS Distributions                 (headOffset + headSize + DATA_QUEUE_ENTRY_HEADER_SIZE > queueSize)) {
298*a3bb9fccSApple OSS Distributions                 // Note: we have to wrap to the beginning even with the UINT32_MAX checks
299*a3bb9fccSApple OSS Distributions                 // because we have to support a queueSize of UINT32_MAX.
300e13b1fa5SApple OSS Distributions                 entry           = dataQueue->queue;
301e13b1fa5SApple OSS Distributions                 entrySize       = entry->size;
302*a3bb9fccSApple OSS Distributions                 if ((entrySize > UINT32_MAX - DATA_QUEUE_ENTRY_HEADER_SIZE) ||
303*a3bb9fccSApple OSS Distributions                     (entrySize + DATA_QUEUE_ENTRY_HEADER_SIZE > queueSize)) {
304*a3bb9fccSApple OSS Distributions                     return false;
305*a3bb9fccSApple OSS Distributions                 }
306e13b1fa5SApple OSS Distributions                 newHeadOffset   = entrySize + DATA_QUEUE_ENTRY_HEADER_SIZE;
307e13b1fa5SApple OSS Distributions                 // else it is at the end
308e13b1fa5SApple OSS Distributions             } else {
309e13b1fa5SApple OSS Distributions                 entry           = head;
310e13b1fa5SApple OSS Distributions                 entrySize       = entry->size;
311*a3bb9fccSApple OSS Distributions                 if ((entrySize > UINT32_MAX - DATA_QUEUE_ENTRY_HEADER_SIZE) ||
312*a3bb9fccSApple OSS Distributions                     (entrySize + DATA_QUEUE_ENTRY_HEADER_SIZE > UINT32_MAX - headOffset) ||
313*a3bb9fccSApple OSS Distributions                     (entrySize + DATA_QUEUE_ENTRY_HEADER_SIZE + headOffset > queueSize)) {
314*a3bb9fccSApple OSS Distributions                     return false;
315*a3bb9fccSApple OSS Distributions                 }
316e13b1fa5SApple OSS Distributions                 newHeadOffset   = headOffset + entrySize + DATA_QUEUE_ENTRY_HEADER_SIZE;
317e13b1fa5SApple OSS Distributions             }
318e13b1fa5SApple OSS Distributions         }
319e13b1fa5SApple OSS Distributions 
320e13b1fa5SApple OSS Distributions         if (entry) {
321e13b1fa5SApple OSS Distributions             if (data) {
322e13b1fa5SApple OSS Distributions                 if (dataSize) {
323e13b1fa5SApple OSS Distributions                     if (entrySize <= *dataSize) {
324e13b1fa5SApple OSS Distributions                         memcpy(data, &(entry->data), entrySize);
325*a3bb9fccSApple OSS Distributions                         OSCompareAndSwap( dataQueue->head, newHeadOffset, (SInt32 *)&dataQueue->head);
326e13b1fa5SApple OSS Distributions                     } else {
327e13b1fa5SApple OSS Distributions                         retVal = FALSE;
328e13b1fa5SApple OSS Distributions                     }
329e13b1fa5SApple OSS Distributions                 } else {
330e13b1fa5SApple OSS Distributions                     retVal = FALSE;
331e13b1fa5SApple OSS Distributions                 }
332e13b1fa5SApple OSS Distributions             } else {
333*a3bb9fccSApple OSS Distributions                 OSCompareAndSwap( dataQueue->head, newHeadOffset, (SInt32 *)&dataQueue->head);
334e13b1fa5SApple OSS Distributions             }
335e13b1fa5SApple OSS Distributions 
336e13b1fa5SApple OSS Distributions             if (dataSize) {
337e13b1fa5SApple OSS Distributions                 *dataSize = entrySize;
338e13b1fa5SApple OSS Distributions             }
339e13b1fa5SApple OSS Distributions         } else {
340e13b1fa5SApple OSS Distributions             retVal = FALSE;
341e13b1fa5SApple OSS Distributions         }
342e13b1fa5SApple OSS Distributions     } else {
343e13b1fa5SApple OSS Distributions         retVal = FALSE;
344e13b1fa5SApple OSS Distributions     }
345e13b1fa5SApple OSS Distributions 
346e13b1fa5SApple OSS Distributions     return retVal;
347e13b1fa5SApple OSS Distributions }
348e13b1fa5SApple OSS Distributions 
349*a3bb9fccSApple OSS Distributions UInt32 IOSharedDataQueue::getQueueSize()
350*a3bb9fccSApple OSS Distributions {
351*a3bb9fccSApple OSS Distributions     if (!_reserved) {
352*a3bb9fccSApple OSS Distributions         return 0;
353*a3bb9fccSApple OSS Distributions     }
354*a3bb9fccSApple OSS Distributions     return _reserved->queueSize;
355*a3bb9fccSApple OSS Distributions }
356*a3bb9fccSApple OSS Distributions 
357*a3bb9fccSApple OSS Distributions Boolean IOSharedDataQueue::setQueueSize(UInt32 size)
358*a3bb9fccSApple OSS Distributions {
359*a3bb9fccSApple OSS Distributions     if (!_reserved) {
360*a3bb9fccSApple OSS Distributions         return false;
361*a3bb9fccSApple OSS Distributions     }
362*a3bb9fccSApple OSS Distributions     _reserved->queueSize = size;
363*a3bb9fccSApple OSS Distributions     return true;
364*a3bb9fccSApple OSS Distributions }
365e13b1fa5SApple OSS Distributions 
366e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 0);
367e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 1);
368e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 2);
369e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 3);
370e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 4);
371e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 5);
372e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 6);
373e13b1fa5SApple OSS Distributions OSMetaClassDefineReservedUnused(IOSharedDataQueue, 7);
374