]> git.saurik.com Git - apple/xnu.git/blame - iokit/IOKit/perfcontrol/IOPerfControl.h
xnu-4903.270.47.tar.gz
[apple/xnu.git] / iokit / IOKit / perfcontrol / IOPerfControl.h
CommitLineData
d9a64523
A
1/*
2 * Copyright (c) 2017 Apple Inc. All rights reserved.
3 */
4
5#pragma once
6
7#ifdef KERNEL_PRIVATE
8#ifdef __cplusplus
9
10#include <IOKit/IOService.h>
11
12struct thread_group;
13
0a7de745
A
14enum{
15 kIOPerfControlClientWorkUntracked = 0,
d9a64523
A
16};
17
18/*!
19 * @class IOPerfControlClient : public OSObject
20 * @abstract Class which implements an interface allowing device drivers to participate in performance control.
21 * @discussion TODO
22 */
23class IOPerfControlClient final : public OSObject
24{
0a7de745 25 OSDeclareDefaultStructors(IOPerfControlClient);
d9a64523
A
26
27protected:
0a7de745 28 virtual bool init(IOService *driver, uint64_t maxWorkCapacity);
d9a64523
A
29
30public:
0a7de745
A
31/*!
32 * @function copyClient
33 * @abstract Return a retained reference to a client object, to be released by the driver. It may be
34 * shared with other drivers in the system.
35 * @param driver The device driver that will be using this interface.
36 * @param maxWorkCapacity The maximum number of concurrent work items supported by the device driver.
37 * @returns An instance of IOPerfControlClient.
38 */
39 static IOPerfControlClient *copyClient(IOService *driver, uint64_t maxWorkCapacity);
40
41/*!
42 * @function registerDevice
43 * @abstract Inform the system that work will be dispatched to a device in the future.
44 * @discussion The system will do some one-time setup work associated with the device, and may block the
45 * current thread during the setup. Devices should not be passed to work workSubmit, workSubmitAndBegin,
46 * workBegin, or workEnd until they have been successfully registered. The unregistration process happens
47 * automatically when the device object is deallocated.
48 * @param device The device object. Some platforms require device to be a specific subclass of IOService.
49 * @returns kIOReturnSuccess or an IOReturn error code
50 */
51 virtual IOReturn registerDevice(IOService *driver, IOService *device);
52
53/*!
54 * @function unregisterDevice
55 * @abstract Inform the system that work will be no longer be dispatched to a device in the future.
56 * @discussion This call is optional as the unregistration process happens automatically when the device
57 * object is deallocated. This call may block the current thread and/or acquire locks. It should not be
58 * called until after all submitted work has been ended using workEnd.
59 * @param device The device object. Some platforms require device to be a specific subclass of IOService.
60 */
61 virtual void unregisterDevice(IOService *driver, IOService *device);
62
63/*!
64 * @struct WorkSubmitArgs
65 * @discussion Drivers may submit additional device-specific arguments related to the submission of a work item
66 * by passing a struct with WorkSubmitArgs as its first member. Note: Drivers are responsible for publishing
67 * a header file describing these arguments.
68 */
69 struct WorkSubmitArgs {
70 uint32_t version;
71 uint32_t size;
72 uint64_t submit_time;
73 uint64_t reserved[4];
74 void *driver_data;
75 };
76
77/*!
78 * @function workSubmit
79 * @abstract Tell the performance controller that work was submitted.
80 * @param device The device that will execute the work. Some platforms require device to be a
81 * specific subclass of IOService.
82 * @param args Optional device-specific arguments related to the submission of this work item.
83 * @returns A token representing this work item, which must be passed to workEnd when the work is finished
84 * unless the token equals kIOPerfControlClientWorkUntracked. Failure to do this will result in memory leaks
85 * and a degradation of system performance.
86 */
87 virtual uint64_t workSubmit(IOService *device, WorkSubmitArgs *args = nullptr);
88
89/*!
90 * @struct WorkBeginArgs
91 * @discussion Drivers may submit additional device-specific arguments related to the start of a work item
92 * by passing a struct with WorkBeginArgs as its first member. Note: Drivers are responsible for publishing
93 * a header file describing these arguments.
94 */
95 struct WorkBeginArgs {
96 uint32_t version;
97 uint32_t size;
98 uint64_t begin_time;
99 uint64_t reserved[4];
100 void *driver_data;
101 };
102
103/*!
104 * @function workSubmitAndBegin
105 * @abstract Tell the performance controller that work was submitted and immediately began executing.
106 * @param device The device that is executing the work. Some platforms require device to be a
107 * specific subclass of IOService.
108 * @param submitArgs Optional device-specific arguments related to the submission of this work item.
109 * @param beginArgs Optional device-specific arguments related to the start of this work item.
110 * @returns A token representing this work item, which must be passed to workEnd when the work is finished
111 * unless the token equals kIOPerfControlClientWorkUntracked. Failure to do this will result in memory leaks
112 * and a degradation of system performance.
113 */
114 virtual uint64_t workSubmitAndBegin(IOService *device, WorkSubmitArgs *submitArgs = nullptr,
115 WorkBeginArgs *beginArgs = nullptr);
116
117/*!
118 * @function workBegin
119 * @abstract Tell the performance controller that previously submitted work began executing.
120 * @param device The device that is executing the work. Some platforms require device to be a
121 * specific subclass of IOService.
122 * @param args Optional device-specific arguments related to the start of this work item.
123 */
124 virtual void workBegin(IOService *device, uint64_t token, WorkBeginArgs *args = nullptr);
125
126/*!
127 * @struct WorkEndArgs
128 * @discussion Drivers may submit additional device-specific arguments related to the end of a work item
129 * by passing a struct with WorkEndArgs as its first member. Note: Drivers are responsible for publishing
130 * a header file describing these arguments.
131 */
132 struct WorkEndArgs {
133 uint32_t version;
134 uint32_t size;
135 uint64_t end_time;
136 uint64_t reserved[4];
137 void *driver_data;
138 };
139
140/*!
141 * @function workEnd
142 * @abstract Tell the performance controller that previously started work finished executing.
143 * @param device The device that executed the work. Some platforms require device to be a
144 * specific subclass of IOService.
145 * @param args Optional device-specific arguments related to the end of this work item.
146 * @param done Optional Set to false if the work has not yet completed. Drivers are then responsible for
147 * calling workBegin when the work resumes and workEnd with done set to True when it has completed.
148 */
149 virtual void workEnd(IOService *device, uint64_t token, WorkEndArgs *args = nullptr, bool done = true);
150
151/*!
152 * @struct PerfControllerInterface
153 * @discussion Function pointers necessary to register a performance controller. Not for general driver use.
154 */
155 struct PerfControllerInterface {
156 struct WorkState {
157 uint64_t thread_group_id;
158 void *thread_group_data;
159 void *work_data;
160 uint32_t work_data_size;
161 };
162
163 using RegisterDeviceFunction = IOReturn (*)(IOService *);
164 using WorkCanSubmitFunction = bool (*)(IOService *, WorkState *, WorkSubmitArgs *);
165 using WorkSubmitFunction = void (*)(IOService *, uint64_t, WorkState *, WorkSubmitArgs *);
166 using WorkBeginFunction = void (*)(IOService *, uint64_t, WorkState *, WorkBeginArgs *);
167 using WorkEndFunction = void (*)(IOService *, uint64_t, WorkState *, WorkEndArgs *, bool);
168
169 uint64_t version;
170 RegisterDeviceFunction registerDevice;
171 RegisterDeviceFunction unregisterDevice;
172 WorkCanSubmitFunction workCanSubmit;
173 WorkSubmitFunction workSubmit;
174 WorkBeginFunction workBegin;
175 WorkEndFunction workEnd;
176 };
177
178/*!
179 * @function registerPerformanceController
180 * @abstract Register a performance controller to receive callbacks. Not for general driver use.
181 * @param interface Struct containing callback functions implemented by the performance controller.
182 * @returns kIOReturnSuccess or kIOReturnError if the interface was already registered.
183 */
184 virtual IOReturn registerPerformanceController(PerfControllerInterface interface);
d9a64523
A
185
186private:
0a7de745
A
187 struct WorkTableEntry {
188 struct thread_group *thread_group;
189 bool started;
190 uint8_t perfcontrol_data[32];
191 };
192
193// TODO: size of table should match sum(maxWorkCapacity) of all users
194 static constexpr size_t kWorkTableNumEntries = 1024;
195
196 uint64_t allocateToken(thread_group *thread_group);
197 void deallocateToken(uint64_t token);
198 bool getEntryForToken(uint64_t token, WorkTableEntry &entry);
199 void markEntryStarted(uint64_t token, bool started);
200
201 PerfControllerInterface interface;
202 IOLock *interfaceLock;
203 OSSet *deviceRegistrationList;
204
205// TODO: replace with ltable or pool of objects
206 WorkTableEntry workTable[kWorkTableNumEntries];
207 size_t workTableNextIndex;
208 IOSimpleLock *workTableLock;
d9a64523
A
209};
210
211#endif /* __cplusplus */
212#endif /* KERNEL_PRIVATE */