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