xref: /xnu-11417.121.6/iokit/IOKit/IOSharedDataQueue.h (revision a1e26a70f38d1d7daa7b49b258e2f8538ad81650)
1*a1e26a70SApple OSS Distributions /*
2*a1e26a70SApple OSS Distributions  * Copyright (c) 1998-2019 Apple Inc. All rights reserved.
3*a1e26a70SApple OSS Distributions  *
4*a1e26a70SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*a1e26a70SApple OSS Distributions  *
6*a1e26a70SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*a1e26a70SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*a1e26a70SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*a1e26a70SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*a1e26a70SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*a1e26a70SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*a1e26a70SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*a1e26a70SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*a1e26a70SApple OSS Distributions  *
15*a1e26a70SApple OSS Distributions  * Please obtain a copy of the License at
16*a1e26a70SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*a1e26a70SApple OSS Distributions  *
18*a1e26a70SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*a1e26a70SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*a1e26a70SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*a1e26a70SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*a1e26a70SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*a1e26a70SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*a1e26a70SApple OSS Distributions  * limitations under the License.
25*a1e26a70SApple OSS Distributions  *
26*a1e26a70SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*a1e26a70SApple OSS Distributions  */
28*a1e26a70SApple OSS Distributions 
29*a1e26a70SApple OSS Distributions #ifndef _IOKIT_IOSHAREDDATAQUEUE_H
30*a1e26a70SApple OSS Distributions #define _IOKIT_IOSHAREDDATAQUEUE_H
31*a1e26a70SApple OSS Distributions 
32*a1e26a70SApple OSS Distributions #define DISABLE_DATAQUEUE_WARNING /* IODataQueue is deprecated, please use IOSharedDataQueue instead */
33*a1e26a70SApple OSS Distributions 
34*a1e26a70SApple OSS Distributions #include <IOKit/IODataQueue.h>
35*a1e26a70SApple OSS Distributions #include <libkern/c++/OSPtr.h>
36*a1e26a70SApple OSS Distributions 
37*a1e26a70SApple OSS Distributions #undef DISABLE_DATAQUEUE_WARNING
38*a1e26a70SApple OSS Distributions 
39*a1e26a70SApple OSS Distributions typedef struct _IODataQueueEntry IODataQueueEntry;
40*a1e26a70SApple OSS Distributions 
41*a1e26a70SApple OSS Distributions /*!
42*a1e26a70SApple OSS Distributions  * @class IOSharedDataQueue : public IODataQueue
43*a1e26a70SApple OSS Distributions  * @abstract A generic queue designed to pass data both from the kernel to a user process and from a user process to the kernel.
44*a1e26a70SApple OSS Distributions  * @discussion The IOSharedDataQueue class is designed to also allow a user process to queue data to kernel code.  IOSharedDataQueue objects are designed to be used in a single producer / single consumer situation.  As such, there are no locks on the data itself.  Because the kernel enqueue and user-space dequeue methods follow a strict set of guidelines, no locks are necessary to maintain the integrity of the data struct.
45*a1e26a70SApple OSS Distributions  *
46*a1e26a70SApple OSS Distributions  * <br>Each data entry can be variable sized, but the entire size of the queue data region (including overhead for each entry) must be specified up front.
47*a1e26a70SApple OSS Distributions  *
48*a1e26a70SApple OSS Distributions  * <br>In order for the IODataQueue instance to notify the user process that data is available, a notification mach port must be set.  When the queue is empty and a new entry is added, a message is sent to the specified port.
49*a1e26a70SApple OSS Distributions  *
50*a1e26a70SApple OSS Distributions  * <br>In order to make the data queue memory available to a user process, the method getMemoryDescriptor() must be used to get an IOMemoryDescriptor instance that can be mapped into a user process.  Typically, the clientMemoryForType() method on an IOUserClient instance will be used to request the IOMemoryDescriptor and then return it to be mapped into the user process.
51*a1e26a70SApple OSS Distributions  */
52*a1e26a70SApple OSS Distributions class IOSharedDataQueue : public IODataQueue
53*a1e26a70SApple OSS Distributions {
54*a1e26a70SApple OSS Distributions 	OSDeclareDefaultStructors(IOSharedDataQueue);
55*a1e26a70SApple OSS Distributions 
56*a1e26a70SApple OSS Distributions 	struct ExpansionData {
57*a1e26a70SApple OSS Distributions 		UInt32 queueSize;
58*a1e26a70SApple OSS Distributions 	};
59*a1e26a70SApple OSS Distributions /*! @var reserved
60*a1e26a70SApple OSS Distributions  *   Reserved for future use.  (Internal use only)  */
61*a1e26a70SApple OSS Distributions 	ExpansionData * _reserved;
62*a1e26a70SApple OSS Distributions 
63*a1e26a70SApple OSS Distributions protected:
64*a1e26a70SApple OSS Distributions 	virtual void free() APPLE_KEXT_OVERRIDE;
65*a1e26a70SApple OSS Distributions 
66*a1e26a70SApple OSS Distributions /*!
67*a1e26a70SApple OSS Distributions  * @function getQueueSize
68*a1e26a70SApple OSS Distributions  * @abstract Returns the size of the data queue.
69*a1e26a70SApple OSS Distributions  * @discussion Use this method to access the size of the data queue. Do not access the value of size directly, as it can get modified from userspace and is not reliable.
70*a1e26a70SApple OSS Distributions  * @result Returns the size of the data queue, or zero in case of failure.
71*a1e26a70SApple OSS Distributions  */
72*a1e26a70SApple OSS Distributions 	UInt32 getQueueSize();
73*a1e26a70SApple OSS Distributions 
74*a1e26a70SApple OSS Distributions /*!
75*a1e26a70SApple OSS Distributions  * @function setQueueSize
76*a1e26a70SApple OSS Distributions  * @abstract Stores the value of the size of the data queue.
77*a1e26a70SApple OSS Distributions  * @discussion Use this method to store the value of the size of the data queue. Do not access the value of size directly, as it can get modified from userspace and is not reliable.
78*a1e26a70SApple OSS Distributions  * @param size The size of the data queue.
79*a1e26a70SApple OSS Distributions  * @result Returns true in case of success, false otherwise.
80*a1e26a70SApple OSS Distributions  */
81*a1e26a70SApple OSS Distributions 	Boolean setQueueSize(UInt32 size);
82*a1e26a70SApple OSS Distributions 
83*a1e26a70SApple OSS Distributions public:
84*a1e26a70SApple OSS Distributions /*!
85*a1e26a70SApple OSS Distributions  * @function withCapacity
86*a1e26a70SApple OSS Distributions  * @abstract Static method that creates a new IOSharedDataQueue instance with the capacity specified in the size parameter.
87*a1e26a70SApple OSS Distributions  * @discussion The actual size of the entire data queue memory region (to be shared into a user process) is equal to the capacity plus the IODataQueueMemory overhead.  This overhead value can be determined from the DATA_QUEUE_MEMORY_HEADER_SIZE macro in <IOKit/IODataQueueShared.h>.  The size of the data queue memory region must include space for the overhead of each IODataQueueEntry.  This entry overhead can be determined from the DATA_QUEUE_ENTRY_HEADER_SIZE macro in <IOKit/IODataQueueShared.h>.<br>  This method allocates a new IODataQueue instance and then calls initWithCapacity() with the given size parameter.  If the initWithCapacity() fails, the new instance is released and zero is returned.
88*a1e26a70SApple OSS Distributions  * @param size The size of the data queue memory region.
89*a1e26a70SApple OSS Distributions  * @result Returns the newly allocated IOSharedDataQueue instance.  Zero is returned on failure.
90*a1e26a70SApple OSS Distributions  */
91*a1e26a70SApple OSS Distributions 	static OSPtr<IOSharedDataQueue> withCapacity(UInt32 size __xnu_data_size);
92*a1e26a70SApple OSS Distributions 
93*a1e26a70SApple OSS Distributions /*!
94*a1e26a70SApple OSS Distributions  * @function withEntries
95*a1e26a70SApple OSS Distributions  * @abstract Static method that creates a new IOSharedDataQueue instance with the specified number of entries of the given size.
96*a1e26a70SApple OSS Distributions  * @discussion This method will create a new IOSharedDataQueue instance with enough capacity for numEntries of entrySize.  It does account for the IODataQueueEntry overhead for each entry.  Note that the numEntries and entrySize are simply used to determine the data region size.  They do not actually restrict the size of number of entries that can be added to the queue.<br>  This method allocates a new IODataQueue instance and then calls initWithEntries() with the given numEntries and entrySize parameters.  If the initWithEntries() fails, the new instance is released and zero is returned.
97*a1e26a70SApple OSS Distributions  * @param numEntries Number of entries to allocate space for.
98*a1e26a70SApple OSS Distributions  * @param entrySize Size of each entry.
99*a1e26a70SApple OSS Distributions  * @result Reeturns the newly allocated IOSharedDataQueue instance.  Zero is returned on failure.
100*a1e26a70SApple OSS Distributions  */
101*a1e26a70SApple OSS Distributions 	static OSPtr<IOSharedDataQueue> withEntries(UInt32 numEntries, UInt32 entrySize __xnu_data_size);
102*a1e26a70SApple OSS Distributions 
103*a1e26a70SApple OSS Distributions /*!
104*a1e26a70SApple OSS Distributions  * @function initWithCapacity
105*a1e26a70SApple OSS Distributions  * @abstract Initializes an IOSharedDataQueue instance with the capacity specified in the size parameter.
106*a1e26a70SApple OSS Distributions  * @discussion The actual size of the entire data queue memory region (to be shared into a user process) is equal to the capacity plus the IODataQueueMemory overhead.  This overhead value can be determined from the DATA_QUEUE_MEMORY_HEADER_SIZE and DATA_QUEUE_MEMORY_APPENDIX_SIZE macro in <IOKit/IODataQueueShared.h>.  The size of the data queue memory region must include space for the overhead of each IODataQueueEntry.  This entry overhead can be determined from the DATA_QUEUE_ENTRY_HEADER_SIZE macro in <IOKit/IODataQueueShared.h>.
107*a1e26a70SApple OSS Distributions  * @param size The size of the data queue memory region.
108*a1e26a70SApple OSS Distributions  * @result Returns true on success and false on failure.
109*a1e26a70SApple OSS Distributions  */
110*a1e26a70SApple OSS Distributions 	virtual Boolean initWithCapacity(UInt32 size) APPLE_KEXT_OVERRIDE;
111*a1e26a70SApple OSS Distributions 
112*a1e26a70SApple OSS Distributions /*!
113*a1e26a70SApple OSS Distributions  * @function getMemoryDescriptor
114*a1e26a70SApple OSS Distributions  * @abstract Returns a memory descriptor covering the IODataQueueMemory region.
115*a1e26a70SApple OSS Distributions  * @discussion The IOMemoryDescriptor instance returned by this method is intended to be mapped into a user process.  This is the memory region that the IODataQueueClient code operates on.
116*a1e26a70SApple OSS Distributions  * @result Returns a newly allocated IOMemoryDescriptor for the IODataQueueMemory region.  Returns zero on failure.
117*a1e26a70SApple OSS Distributions  */
118*a1e26a70SApple OSS Distributions 	virtual OSPtr<IOMemoryDescriptor> getMemoryDescriptor() APPLE_KEXT_OVERRIDE;
119*a1e26a70SApple OSS Distributions 
120*a1e26a70SApple OSS Distributions /*!
121*a1e26a70SApple OSS Distributions  * @function peek
122*a1e26a70SApple OSS Distributions  * @abstract Used to peek at the next entry on the queue.
123*a1e26a70SApple OSS Distributions  * @discussion This function can be used to look at the next entry which allows the entry to be received without having to copy it with dequeue.  In order to do this, call peek to get the entry.  Then call dequeue with a NULL data pointer.  That will cause the head to be moved to the next entry, but no memory to be copied.
124*a1e26a70SApple OSS Distributions  * @result Returns a pointer to the next IODataQueueEntry if one is available.  0 (NULL) is returned if the queue is empty.
125*a1e26a70SApple OSS Distributions  */
126*a1e26a70SApple OSS Distributions 	virtual IODataQueueEntry * peek();
127*a1e26a70SApple OSS Distributions 
128*a1e26a70SApple OSS Distributions /*!
129*a1e26a70SApple OSS Distributions  * @function dequeue
130*a1e26a70SApple OSS Distributions  * @abstract Dequeues the next available entry on the queue and copies it into the given data pointer.
131*a1e26a70SApple OSS Distributions  * @discussion This function will dequeue the next available entry on the queue.  If a data pointer is provided, it will copy the data into the memory region if there is enough space available as specified in the dataSize parameter.  If no data pointer is provided, it will simply move the head value past the current entry.
132*a1e26a70SApple OSS Distributions  * @param data A pointer to the data memory region in which to copy the next entry data on the queue.  If this parameter is 0 (NULL), it will simply move to the next entry.
133*a1e26a70SApple OSS Distributions  * @param dataSize A pointer to the size of the data parameter.  On return, this contains the size of the actual entry data - even if the original size was not large enough.
134*a1e26a70SApple OSS Distributions  * @result Returns true on success and false on failure.  Typically failure means that the queue is empty.
135*a1e26a70SApple OSS Distributions  */
136*a1e26a70SApple OSS Distributions 	virtual Boolean dequeue(void *data, UInt32 *dataSize);
137*a1e26a70SApple OSS Distributions 
138*a1e26a70SApple OSS Distributions /*!
139*a1e26a70SApple OSS Distributions  * @function enqueue
140*a1e26a70SApple OSS Distributions  * @abstract Enqueues a new entry on the queue.
141*a1e26a70SApple OSS Distributions  * @discussion This method adds a new data entry of dataSize to the queue.  It sets the size parameter of the entry pointed to by the tail value and copies the memory pointed to by the data parameter in place in the queue.  Once that is done, it moves the tail to the next available location.  When attempting to add a new entry towards the end of the queue and there isn't enough space at the end, it wraps back to the beginning.<br>  If the queue is empty when a new entry is added, sendDataAvailableNotification() is called to send a message to the user process that data is now available.
142*a1e26a70SApple OSS Distributions  * @param data Pointer to the data to be added to the queue.
143*a1e26a70SApple OSS Distributions  * @param dataSize Size of the data pointed to by data.
144*a1e26a70SApple OSS Distributions  * @result Returns true on success and false on failure.  Typically failure means that the queue is full.
145*a1e26a70SApple OSS Distributions  */
146*a1e26a70SApple OSS Distributions 	virtual Boolean enqueue(void *data, UInt32 dataSize) APPLE_KEXT_OVERRIDE;
147*a1e26a70SApple OSS Distributions 
148*a1e26a70SApple OSS Distributions #ifdef PRIVATE
149*a1e26a70SApple OSS Distributions /* workaround for queue.h redefine, please do not use */
150*a1e26a70SApple OSS Distributions 	__inline__ Boolean
enqueue_tail(void * data,UInt32 dataSize)151*a1e26a70SApple OSS Distributions 	enqueue_tail(void *data, UInt32 dataSize)
152*a1e26a70SApple OSS Distributions 	{
153*a1e26a70SApple OSS Distributions 		return IOSharedDataQueue::enqueue(data, dataSize);
154*a1e26a70SApple OSS Distributions 	}
155*a1e26a70SApple OSS Distributions #endif
156*a1e26a70SApple OSS Distributions 
157*a1e26a70SApple OSS Distributions #if APPLE_KEXT_VTABLE_PADDING
158*a1e26a70SApple OSS Distributions 	OSMetaClassDeclareReservedUnused(IOSharedDataQueue, 0);
159*a1e26a70SApple OSS Distributions 	OSMetaClassDeclareReservedUnused(IOSharedDataQueue, 1);
160*a1e26a70SApple OSS Distributions 	OSMetaClassDeclareReservedUnused(IOSharedDataQueue, 2);
161*a1e26a70SApple OSS Distributions 	OSMetaClassDeclareReservedUnused(IOSharedDataQueue, 3);
162*a1e26a70SApple OSS Distributions 	OSMetaClassDeclareReservedUnused(IOSharedDataQueue, 4);
163*a1e26a70SApple OSS Distributions 	OSMetaClassDeclareReservedUnused(IOSharedDataQueue, 5);
164*a1e26a70SApple OSS Distributions 	OSMetaClassDeclareReservedUnused(IOSharedDataQueue, 6);
165*a1e26a70SApple OSS Distributions 	OSMetaClassDeclareReservedUnused(IOSharedDataQueue, 7);
166*a1e26a70SApple OSS Distributions #endif
167*a1e26a70SApple OSS Distributions };
168*a1e26a70SApple OSS Distributions 
169*a1e26a70SApple OSS Distributions #endif /* _IOKIT_IOSHAREDDATAQUEUE_H */
170