xref: /xnu-12377.81.4/iokit/DriverKit/IODataQueueDispatchSource.iig (revision 043036a2b3718f7f0be807e2870f8f47d3fa0796)
1/*
2 * Copyright (c) 2019-2019 Apple 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#ifndef _IOKIT_UIODATAQUEUEDISPATCHSOURCE_H
30#define _IOKIT_UIODATAQUEUEDISPATCHSOURCE_H
31
32#include <DriverKit/IODispatchQueue.iig>
33#include <DriverKit/IOMemoryDescriptor.iig>
34
35typedef void (^IODataQueueClientEnqueueEntryBlock)(void *data, size_t dataSize);
36typedef void (^IODataQueueClientDequeueEntryBlock)(const void *data, size_t dataSize);
37
38class NATIVE KERNEL IODataQueueDispatchSource : public IODispatchSource
39{
40public:
41
42    /*!
43     * @brief       Create an IODataQueueDispatchSource for a shared memory data queue.
44     * @param       queueByteCount The size of the queue in bytes.
45     * @param       queue IODispatchQueue the source is attached to. Note that the DataAvailable
46     *              and DataServiced handlers are invoked on the queue set for the target method
47     *              of the OSAction, not this queue.
48     * @param       source Created source with +1 retain count to be released by the caller.
49     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
50     */
51	static kern_return_t
52	Create(
53		uint64_t queueByteCount,
54	    IODispatchQueue * queue,
55	    IODataQueueDispatchSource ** source);
56
57    /*!
58     * @brief Represents the size of the data queue entry header independent of the actual size of the data in the entry.  This is the overhead of each entry in the queue.
59     * @return      Size of the entry header.
60     */
61    static size_t
62    GetDataQueueEntryHeaderSize() LOCALONLY;
63
64	virtual bool
65	init() override;
66
67	virtual void
68	free() override;
69
70    /*!
71     * @brief       As a consumer, set the handler block to run when the queue becomes non-empty.
72     * @param       action OSAction instance specifying the callback method. The OSAction object will be retained
73     *              until SetHandler is called again or the event source is cancelled.
74     *              The DataAvailable handler is invoked on the queue set for the target method of the OSAction.
75     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
76     */
77	virtual kern_return_t
78	SetDataAvailableHandler(
79	OSAction * action TYPE(DataAvailable));
80
81    /*!
82     * @brief       As a producer, set the handler block to run when the queue becomes non-full, after an attempt
83     *              to enqueue data failed.
84     * @param       action OSAction instance specifying the callback method. The OSAction object will be retained
85     *              until SetHandler is called again or the event source is cancelled.
86     *              The DataServiced handler is invoked on the queue set for the target method of the OSAction.
87     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
88     */
89	virtual kern_return_t
90	SetDataServicedHandler(
91	OSAction * action TYPE(DataServiced));
92
93    /*!
94     * @brief       Control the enable state of the interrupt source.
95     * @param       enable Pass true to enable the source or false to disable.
96     * @param       handler Optional block to be executed after the interrupt has been disabled and any pending
97     *              interrupt handlers completed.
98     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
99     */
100	virtual kern_return_t
101	SetEnableWithCompletion(
102		bool enable,
103		IODispatchSourceCancelHandler handler) override LOCAL;
104
105    /*!
106     * @brief       Cancel all callbacks from the event source.
107     * @discussion  After cancellation, the source can only be freed. It cannot be reactivated.
108     * @param       handler Handler block to be invoked after any callbacks have completed.
109     * @return      kIOReturnSuccess on success. See IOReturn.h for error codes.
110     */
111	virtual kern_return_t
112	Cancel(IODispatchSourceCancelHandler handler) override LOCAL;
113
114
115    /*!
116     * @brief       As a consumer, check if the data queue is non-empty.
117     * @return      True if the queue is non-empty.
118     */
119	bool
120	IsDataAvailable(void) LOCALONLY;
121
122    /*!
123     * @brief       As a consumer, get access to the next queue entry without dequeuing it.
124     * @param       callback to invoked if the queue is non-empty with the next entry to be dequeued.
125     * @return      kIOReturnSuccess if the callback was invoked.
126     *              kIOReturnUnderrun if the queue was empty.
127     *              kIOReturnError if the queue was corrupt.
128     */
129	kern_return_t
130	Peek(IODataQueueClientDequeueEntryBlock callback) LOCALONLY;
131
132    /*!
133     * @brief       As a consumer, dequeue the next queue entry.
134     * @param       callback invoked if the queue was non-empty with the entry that was dequeued.
135     * @return      kIOReturnSuccess if the callback was invoked.
136     *              kIOReturnUnderrun if the queue was empty.
137     *              kIOReturnError if the queue was corrupt.
138     */
139	kern_return_t
140	Dequeue(IODataQueueClientDequeueEntryBlock callback) LOCALONLY;
141
142    /*!
143     * @brief       As a producer, enqueue a queue entry.
144     * @param       dataSize size of the data to enqueue.
145     * @param       callback invoked if the queue has enough space to enqueue the data.
146     * @return      kIOReturnSuccess if the callback was invoked.
147     *              kIOReturnOverrun if the queue was full.
148     *              kIOReturnError if the queue was corrupt.
149     */
150	kern_return_t
151	Enqueue(uint32_t dataSize, IODataQueueClientEnqueueEntryBlock callback) LOCALONLY;
152
153    /*!
154     * @brief       As a consumer, dequeue the next queue entry, but don't send any DataServiced notification.
155     * @param       sendDataServiced Flag that indicates a DataServiced notification would have sent.
156     *              It should be initialized to false before a series of calls to this method,
157     *              and if true after those calls, the notification sent with SendDataServiced().
158     * @param       callback invoked if the queue was non-empty with the entry that was dequeued.
159     * @return      kIOReturnSuccess if the callback was invoked.
160     *              kIOReturnUnderrun if the queue was empty.
161     *              kIOReturnError if the queue was corrupt.
162     */
163	kern_return_t
164	DequeueWithCoalesce(bool * sendDataServiced, IODataQueueClientDequeueEntryBlock callback) LOCALONLY;
165
166    /*!
167     * @brief       As a producer, enqueue a queue entry, but don't send any DataAvailable notification.
168     * @param       dataSize size of the data to enqueue
169     * @param       sendDataAvailable Flag that indicates a DataAvailable notification would have been sent.
170     *              It should be initialized to false before a series of calls to this method,
171     *              and if true after those calls, the notification sent with SendDataAvailable().
172     * @param       callback invoked if the queue has enough space to enqueue the data.
173     * @return      kIOReturnSuccess if the callback was invoked.
174     *              kIOReturnOverrun if the queue was full.
175     *              kIOReturnError if the queue was corrupt.
176     */
177	kern_return_t
178	EnqueueWithCoalesce(uint32_t dataSize,  bool * sendDataAvailable, IODataQueueClientEnqueueEntryBlock callback) LOCALONLY;
179
180    /*!
181     * @brief       As a producer, check if the queue has sufficient free space for a queue entry with the specified size.
182     * @param       dataSize  size of the queue entry to check
183     * @return      kIOReturnSuccess if the queue has enough free space
184     *              kIOReturnOverrun if the queue is full
185     *              kIOReturnError if the queue was corrupt
186     */
187	kern_return_t
188	CanEnqueueData(uint32_t dataSize) LOCALONLY;
189
190    /*!
191     * @brief       As a producer, check if the queue has sufficient free space for queue entries with the specified size.
192     * @param       dataSize   size of the queue entry to check
193     * @param       entryCount number of queue entries to check. Entries are assumed to be the same size.
194     * @return      kIOReturnSuccess if the queue has enough free space
195     *              kIOReturnOverrun if the queue is full
196     *              kIOReturnError if the queue was corrupt
197     */
198	kern_return_t
199	CanEnqueueData(uint32_t dataSize, uint32_t entryCount) LOCALONLY;
200
201    /*!
202     * @brief       As a consumer, send the DataServiced notification indicated by DequeueWithCoalesce.
203	 */
204	void
205	SendDataServiced(void) LOCALONLY;
206
207    /*!
208     * @brief       As a producer, send the DataAvailable notification indicated by EnqueueWithCoalesce.
209	 */
210	void
211	SendDataAvailable(void) LOCALONLY;
212
213private:
214	virtual kern_return_t
215	CopyMemory(
216	IOMemoryDescriptor ** memory);
217
218	virtual kern_return_t
219	CopyDataAvailableHandler(
220	OSAction ** action);
221
222	virtual kern_return_t
223	CopyDataServicedHandler(
224	OSAction ** action);
225
226	virtual kern_return_t
227	CheckForWork(bool synchronous) override LOCAL;
228
229	virtual void
230	DataAvailable(
231		OSAction * action TARGET) LOCAL = 0;
232
233	virtual void
234	DataServiced(
235		OSAction * action TARGET) LOCAL = 0;
236};
237
238#endif /* ! _IOKIT_UIODATAQUEUEDISPATCHSOURCE_H */
239