]> git.saurik.com Git - apple/xnu.git/blob - iokit/IOKit/IODataQueue.h
xnu-123.5.tar.gz
[apple/xnu.git] / iokit / IOKit / IODataQueue.h
1 /*
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22
23 #ifndef _IOKIT_IODATAQUEUE_H
24 #define _IOKIT_IODATAQUEUE_H
25
26 #include <libkern/c++/OSObject.h>
27 #include <libkern/OSTypes.h>
28 #include <mach/port.h>
29 #include <mach/message.h>
30
31 typedef struct _IODataQueueMemory IODataQueueMemory;
32 class IOMemoryDescriptor;
33
34 struct _notifyMsg {
35 mach_msg_header_t h;
36 };
37
38 /*!
39 * @class IODataQueue : public OSObject
40 * @abstract A generic queue designed to pass data from the kernel to a user process.
41 * @discussion The IODataQueue class is designed to allow kernel code to queue data to a user process. IODataQueue 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.
42 *
43 * <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.
44 *
45 * <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.
46 *
47 * <br>User client code exists in the IOKit framework that facilitates the creation of the receive notification port as well as the listen process for new data available notifications.
48 *
49 * <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.
50 */
51 class IODataQueue : public OSObject
52 {
53 OSDeclareDefaultStructors(IODataQueue)
54
55 protected:
56 IODataQueueMemory * dataQueue;
57
58 void * notifyMsg;
59
60 virtual void free();
61
62 /*!
63 * @function sendDataAvailableNotification
64 * @abstract Sends a dataAvailableNotification message to the specified mach port.
65 * @discussion This method sends a message to the mach port passed to setNotificationPort(). It is used to indicate that data is available in the queue.
66 */
67 virtual void sendDataAvailableNotification();
68
69 public:
70 /*!
71 * @function withCapacity
72 * @abstract Static method that creates a new IODataQueue instance with the capacity specified in the size parameter.
73 * @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.
74 * @param size The size of the data queue memory region.
75 * @result Returns the newly allocated IODataQueue instance. Zero is returned on failure.
76 */
77 static IODataQueue *withCapacity(UInt32 size);
78
79 /*!
80 * @function withEntries
81 * @abstract Static method that creates a new IODataQueue instance with the specified number of entries of the given size.
82 * @discussion This method will create a new IODataQueue 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.
83 * @param numEntries Number of entries to allocate space for.
84 * @param entrySize Size of each entry.
85 * @result Reeturns the newly allocated IODataQueue instance. Zero is returned on failure.
86 */
87 static IODataQueue *withEntries(UInt32 numEntries, UInt32 entrySize);
88
89 /*!
90 * @function initWithCapacity
91 * @abstract Initializes an IODataQueue instance with the capacity specified in the size parameter.
92 * @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>.
93 * @param size The size of the data queue memory region.
94 * @result Returns true on success and false on failure.
95 */
96 virtual Boolean initWithCapacity(UInt32 size);
97
98 /*!
99 * @function initWithEntries
100 * @abstract Initializes an IODataQueue instance with the specified number of entries of the given size.
101 * @discussion This method will initialize an IODataQueue 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.
102 * @param numEntries Number of entries to allocate space for.
103 * @param entrySize Size of each entry.
104 * @result Reeturns true on success and false on failure.
105 */
106 virtual Boolean initWithEntries(UInt32 numEntries, UInt32 entrySize);
107
108 /*!
109 * @function enqueue
110 * @abstract Enqueues a new entry on the queue.
111 * @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.
112 * @param data Pointer to the data to be added to the queue.
113 * @param dataSize Size of the data pointed to by data.
114 * @result Returns true on success and false on failure. Typically failure means that the queue is full.
115 */
116 virtual Boolean enqueue(void *data, UInt32 dataSize);
117
118 /*!
119 * @function setNotificationPort
120 * @abstract Creates a simple mach message targeting the mach port specified in port.
121 * @discussion This message is sent when data is added to an empty queue. It is to notify a user process that new data has become available.
122 * @param port The mach port to target with the notification message.
123 */
124 virtual void setNotificationPort(mach_port_t port);
125
126 /*!
127 * @function getMemoryDescriptor
128 * @abstract Returns a memory descriptor covering the IODataQueueMemory region.
129 * @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.
130 * @result Returns a newly allocated IOMemoryDescriptor for the IODataQueueMemory region. Returns zero on failure.
131 */
132 virtual IOMemoryDescriptor *getMemoryDescriptor();
133 };
134
135 #endif /* _IOKIT_IODATAQUEUE_H */