xref: /xnu-11215.1.10/iokit/IOKit/perfcontrol/IOPerfControl.h (revision 8d741a5de7ff4191bf97d57b9f54c2f6d4a15585)
1*8d741a5dSApple OSS Distributions /*
2*8d741a5dSApple OSS Distributions  * Copyright (c) 2017 Apple Inc. All rights reserved.
3*8d741a5dSApple OSS Distributions  */
4*8d741a5dSApple OSS Distributions 
5*8d741a5dSApple OSS Distributions #pragma once
6*8d741a5dSApple OSS Distributions 
7*8d741a5dSApple OSS Distributions #ifdef KERNEL_PRIVATE
8*8d741a5dSApple OSS Distributions #ifdef __cplusplus
9*8d741a5dSApple OSS Distributions 
10*8d741a5dSApple OSS Distributions #include <IOKit/IOService.h>
11*8d741a5dSApple OSS Distributions #include <stdatomic.h>
12*8d741a5dSApple OSS Distributions #include <kern/bits.h>
13*8d741a5dSApple OSS Distributions #include <libkern/c++/OSPtr.h>
14*8d741a5dSApple OSS Distributions 
15*8d741a5dSApple OSS Distributions struct thread_group;
16*8d741a5dSApple OSS Distributions 
17*8d741a5dSApple OSS Distributions enum{
18*8d741a5dSApple OSS Distributions 	kIOPerfControlClientWorkUntracked = 0,
19*8d741a5dSApple OSS Distributions };
20*8d741a5dSApple OSS Distributions 
21*8d741a5dSApple OSS Distributions /*!
22*8d741a5dSApple OSS Distributions  * @class IOPerfControlClient : public OSObject
23*8d741a5dSApple OSS Distributions  * @abstract Class which implements an interface allowing device drivers to participate in performance control.
24*8d741a5dSApple OSS Distributions  * @discussion TODO
25*8d741a5dSApple OSS Distributions  */
26*8d741a5dSApple OSS Distributions class IOPerfControlClient final : public OSObject
27*8d741a5dSApple OSS Distributions {
28*8d741a5dSApple OSS Distributions 	OSDeclareDefaultStructors(IOPerfControlClient);
29*8d741a5dSApple OSS Distributions 
30*8d741a5dSApple OSS Distributions protected:
31*8d741a5dSApple OSS Distributions 	virtual bool init(IOService *driver, uint64_t maxWorkCapacity);
32*8d741a5dSApple OSS Distributions 	virtual void free() APPLE_KEXT_OVERRIDE;
33*8d741a5dSApple OSS Distributions 
34*8d741a5dSApple OSS Distributions public:
35*8d741a5dSApple OSS Distributions /*!
36*8d741a5dSApple OSS Distributions  * @function copyClient
37*8d741a5dSApple OSS Distributions  * @abstract Return a retained reference to a client object, to be released by the driver. It may be
38*8d741a5dSApple OSS Distributions  * shared with other drivers in the system.
39*8d741a5dSApple OSS Distributions  * @param driver The device driver that will be using this interface.
40*8d741a5dSApple OSS Distributions  * @param maxWorkCapacity The maximum number of concurrent work items supported by the device driver.
41*8d741a5dSApple OSS Distributions  * @returns An instance of IOPerfControlClient.
42*8d741a5dSApple OSS Distributions  */
43*8d741a5dSApple OSS Distributions 	static IOPerfControlClient *copyClient(IOService *driver, uint64_t maxWorkCapacity);
44*8d741a5dSApple OSS Distributions 
45*8d741a5dSApple OSS Distributions /*!
46*8d741a5dSApple OSS Distributions  * @function registerDevice
47*8d741a5dSApple OSS Distributions  * @abstract Inform the system that work will be dispatched to a device in the future.
48*8d741a5dSApple OSS Distributions  * @discussion The system will do some one-time setup work associated with the device, and may block the
49*8d741a5dSApple OSS Distributions  * current thread during the setup. Devices should not be passed to work workSubmit, workSubmitAndBegin,
50*8d741a5dSApple OSS Distributions  * workBegin, or workEnd until they have been successfully registered. The unregistration process happens
51*8d741a5dSApple OSS Distributions  * automatically when the device object is deallocated.
52*8d741a5dSApple OSS Distributions  * @param device The device object. Some platforms require device to be a specific subclass of IOService.
53*8d741a5dSApple OSS Distributions  * @returns kIOReturnSuccess or an IOReturn error code
54*8d741a5dSApple OSS Distributions  */
55*8d741a5dSApple OSS Distributions 	virtual IOReturn registerDevice(IOService *driver, IOService *device);
56*8d741a5dSApple OSS Distributions 
57*8d741a5dSApple OSS Distributions /*!
58*8d741a5dSApple OSS Distributions  * @function unregisterDevice
59*8d741a5dSApple OSS Distributions  * @abstract Inform the system that work will be no longer be dispatched to a device in the future.
60*8d741a5dSApple OSS Distributions  * @discussion This call is optional as the unregistration process happens automatically when the device
61*8d741a5dSApple OSS Distributions  * object is deallocated. This call may block the current thread and/or acquire locks. It should not be
62*8d741a5dSApple OSS Distributions  * called until after all submitted work has been ended using workEnd.
63*8d741a5dSApple OSS Distributions  * @param device The device object. Some platforms require device to be a specific subclass of IOService.
64*8d741a5dSApple OSS Distributions  */
65*8d741a5dSApple OSS Distributions 	virtual void unregisterDevice(IOService *driver, IOService *device);
66*8d741a5dSApple OSS Distributions 
67*8d741a5dSApple OSS Distributions /*!
68*8d741a5dSApple OSS Distributions  * @struct WorkSubmitArgs
69*8d741a5dSApple OSS Distributions  * @discussion Drivers may submit additional device-specific arguments related to the submission of a work item
70*8d741a5dSApple OSS Distributions  * by passing a struct with WorkSubmitArgs as its first member. Note: Drivers are responsible for publishing
71*8d741a5dSApple OSS Distributions  * a header file describing these arguments.
72*8d741a5dSApple OSS Distributions  */
73*8d741a5dSApple OSS Distributions 	struct WorkSubmitArgs {
74*8d741a5dSApple OSS Distributions 		uint32_t version;
75*8d741a5dSApple OSS Distributions 		uint32_t size;
76*8d741a5dSApple OSS Distributions 		uint64_t submit_time;
77*8d741a5dSApple OSS Distributions 		uint64_t reserved[4];
78*8d741a5dSApple OSS Distributions 		void *driver_data;
79*8d741a5dSApple OSS Distributions 	};
80*8d741a5dSApple OSS Distributions 
81*8d741a5dSApple OSS Distributions /*!
82*8d741a5dSApple OSS Distributions  * @function workSubmit
83*8d741a5dSApple OSS Distributions  * @abstract Tell the performance controller that work was submitted.
84*8d741a5dSApple OSS Distributions  * @param device The device that will execute the work. Some platforms require device to be a
85*8d741a5dSApple OSS Distributions  * specific subclass of IOService.
86*8d741a5dSApple OSS Distributions  * @param args Optional device-specific arguments related to the submission of this work item.
87*8d741a5dSApple OSS Distributions  * @returns A token representing this work item, which must be passed to workEnd when the work is finished
88*8d741a5dSApple OSS Distributions  * unless the token equals kIOPerfControlClientWorkUntracked. Failure to do this will result in memory leaks
89*8d741a5dSApple OSS Distributions  * and a degradation of system performance.
90*8d741a5dSApple OSS Distributions  */
91*8d741a5dSApple OSS Distributions 	virtual uint64_t workSubmit(IOService *device, WorkSubmitArgs *args = nullptr);
92*8d741a5dSApple OSS Distributions 
93*8d741a5dSApple OSS Distributions /*!
94*8d741a5dSApple OSS Distributions  * @struct WorkBeginArgs
95*8d741a5dSApple OSS Distributions  * @discussion Drivers may submit additional device-specific arguments related to the start of a work item
96*8d741a5dSApple OSS Distributions  * by passing a struct with WorkBeginArgs as its first member. Note: Drivers are responsible for publishing
97*8d741a5dSApple OSS Distributions  * a header file describing these arguments.
98*8d741a5dSApple OSS Distributions  */
99*8d741a5dSApple OSS Distributions 	struct WorkBeginArgs {
100*8d741a5dSApple OSS Distributions 		uint32_t version;
101*8d741a5dSApple OSS Distributions 		uint32_t size;
102*8d741a5dSApple OSS Distributions 		uint64_t begin_time;
103*8d741a5dSApple OSS Distributions 		uint64_t reserved[4];
104*8d741a5dSApple OSS Distributions 		void *driver_data;
105*8d741a5dSApple OSS Distributions 	};
106*8d741a5dSApple OSS Distributions 
107*8d741a5dSApple OSS Distributions /*!
108*8d741a5dSApple OSS Distributions  * @function workSubmitAndBegin
109*8d741a5dSApple OSS Distributions  * @abstract Tell the performance controller that work was submitted and immediately began executing.
110*8d741a5dSApple OSS Distributions  * @param device The device that is executing the work. Some platforms require device to be a
111*8d741a5dSApple OSS Distributions  * specific subclass of IOService.
112*8d741a5dSApple OSS Distributions  * @param submitArgs Optional device-specific arguments related to the submission of this work item.
113*8d741a5dSApple OSS Distributions  * @param beginArgs Optional device-specific arguments related to the start of this work item.
114*8d741a5dSApple OSS Distributions  * @returns A token representing this work item, which must be passed to workEnd when the work is finished
115*8d741a5dSApple OSS Distributions  * unless the token equals kIOPerfControlClientWorkUntracked. Failure to do this will result in memory leaks
116*8d741a5dSApple OSS Distributions  * and a degradation of system performance.
117*8d741a5dSApple OSS Distributions  */
118*8d741a5dSApple OSS Distributions 	virtual uint64_t workSubmitAndBegin(IOService *device, WorkSubmitArgs *submitArgs = nullptr,
119*8d741a5dSApple OSS Distributions 	    WorkBeginArgs *beginArgs = nullptr);
120*8d741a5dSApple OSS Distributions 
121*8d741a5dSApple OSS Distributions /*!
122*8d741a5dSApple OSS Distributions  * @function workBegin
123*8d741a5dSApple OSS Distributions  * @abstract Tell the performance controller that previously submitted work began executing.
124*8d741a5dSApple OSS Distributions  * @param device The device that is executing the work. Some platforms require device to be a
125*8d741a5dSApple OSS Distributions  * specific subclass of IOService.
126*8d741a5dSApple OSS Distributions  * @param args Optional device-specific arguments related to the start of this work item.
127*8d741a5dSApple OSS Distributions  */
128*8d741a5dSApple OSS Distributions 	virtual void workBegin(IOService *device, uint64_t token, WorkBeginArgs *args = nullptr);
129*8d741a5dSApple OSS Distributions 
130*8d741a5dSApple OSS Distributions /*!
131*8d741a5dSApple OSS Distributions  * @struct WorkEndArgs
132*8d741a5dSApple OSS Distributions  * @discussion Drivers may submit additional device-specific arguments related to the end of a work item
133*8d741a5dSApple OSS Distributions  * by passing a struct with WorkEndArgs as its first member. Note: Drivers are responsible for publishing
134*8d741a5dSApple OSS Distributions  * a header file describing these arguments.
135*8d741a5dSApple OSS Distributions  */
136*8d741a5dSApple OSS Distributions 	struct WorkEndArgs {
137*8d741a5dSApple OSS Distributions 		uint32_t version;
138*8d741a5dSApple OSS Distributions 		uint32_t size;
139*8d741a5dSApple OSS Distributions 		uint64_t end_time;
140*8d741a5dSApple OSS Distributions 		uint64_t reserved[4];
141*8d741a5dSApple OSS Distributions 		void *driver_data;
142*8d741a5dSApple OSS Distributions 	};
143*8d741a5dSApple OSS Distributions 
144*8d741a5dSApple OSS Distributions /*!
145*8d741a5dSApple OSS Distributions  * @function workEnd
146*8d741a5dSApple OSS Distributions  * @abstract Tell the performance controller that previously started work finished executing.
147*8d741a5dSApple OSS Distributions  * @param device The device that executed the work. Some platforms require device to be a
148*8d741a5dSApple OSS Distributions  * specific subclass of IOService.
149*8d741a5dSApple OSS Distributions  * @param args Optional device-specific arguments related to the end of this work item.
150*8d741a5dSApple OSS Distributions  * @param done Optional Set to false if the work has not yet completed. Drivers are then responsible for
151*8d741a5dSApple OSS Distributions  * calling workBegin when the work resumes and workEnd with done set to True when it has completed. A workEnd() call
152*8d741a5dSApple OSS Distributions  * without a corresponding workBegin() call is a way to cancel a work item and return token to IOPerfControl.
153*8d741a5dSApple OSS Distributions  */
154*8d741a5dSApple OSS Distributions 	virtual void workEnd(IOService *device, uint64_t token, WorkEndArgs *args = nullptr, bool done = true);
155*8d741a5dSApple OSS Distributions 
156*8d741a5dSApple OSS Distributions /*!
157*8d741a5dSApple OSS Distributions  * @function copyWorkContext
158*8d741a5dSApple OSS Distributions  * @abstract Return a retained reference to an opaque OSObject, to be released by the driver. This object can
159*8d741a5dSApple OSS Distributions  * be used by IOPerfControl to track a work item. This may perform dynamic memory allocation.
160*8d741a5dSApple OSS Distributions  * @returns A pointer to an OSObject
161*8d741a5dSApple OSS Distributions  */
162*8d741a5dSApple OSS Distributions 	OSPtr<OSObject> copyWorkContext();
163*8d741a5dSApple OSS Distributions 
164*8d741a5dSApple OSS Distributions /*!
165*8d741a5dSApple OSS Distributions  * @function workSubmitAndBeginWithContext
166*8d741a5dSApple OSS Distributions  * @abstract Tell the performance controller that work was submitted and immediately began executing
167*8d741a5dSApple OSS Distributions  * @param device The device that is executing the work. Some platforms require device to be a
168*8d741a5dSApple OSS Distributions  * specific subclass of IOService.
169*8d741a5dSApple OSS Distributions  * @param context An OSObject returned by copyWorkContext(). The context object will be used by IOPerfControl to track
170*8d741a5dSApple OSS Distributions  * this work item.
171*8d741a5dSApple OSS Distributions  * @param submitArgs Optional device-specific arguments related to the submission of this work item.
172*8d741a5dSApple OSS Distributions  * @param beginArgs Optional device-specific arguments related to the start of this work item.
173*8d741a5dSApple OSS Distributions  * @returns true if IOPerfControl is tracking this work item, else false.
174*8d741a5dSApple OSS Distributions  * @note The workEndWithContext() call is optional if the corresponding workSubmitWithContext() call returned false.
175*8d741a5dSApple OSS Distributions  */
176*8d741a5dSApple OSS Distributions 	bool workSubmitAndBeginWithContext(IOService *device, OSObject *context, WorkSubmitArgs *submitArgs = nullptr,
177*8d741a5dSApple OSS Distributions 	    WorkBeginArgs *beginArgs = nullptr);
178*8d741a5dSApple OSS Distributions 
179*8d741a5dSApple OSS Distributions /*!
180*8d741a5dSApple OSS Distributions  * @function workSubmitWithContext
181*8d741a5dSApple OSS Distributions  * @abstract Tell the performance controller that work was submitted.
182*8d741a5dSApple OSS Distributions  * @param device The device that will execute the work. Some platforms require device to be a
183*8d741a5dSApple OSS Distributions  * specific subclass of IOService.
184*8d741a5dSApple OSS Distributions  * @param context An OSObject returned by copyWorkContext(). The context object will be used by IOPerfControl to track
185*8d741a5dSApple OSS Distributions  * this work item.
186*8d741a5dSApple OSS Distributions  * @param args Optional device-specific arguments related to the submission of this work item.
187*8d741a5dSApple OSS Distributions  * @returns true if IOPerfControl is tracking this work item, else false.
188*8d741a5dSApple OSS Distributions  */
189*8d741a5dSApple OSS Distributions 	bool workSubmitWithContext(IOService *device, OSObject *context, WorkSubmitArgs *args = nullptr);
190*8d741a5dSApple OSS Distributions 
191*8d741a5dSApple OSS Distributions /*!
192*8d741a5dSApple OSS Distributions  * @function workBeginWithContext
193*8d741a5dSApple OSS Distributions  * @abstract Tell the performance controller that previously submitted work began executing.
194*8d741a5dSApple OSS Distributions  * @param device The device that is executing the work. Some platforms require device to be a
195*8d741a5dSApple OSS Distributions  * specific subclass of IOService.
196*8d741a5dSApple OSS Distributions  * @param context An OSObject returned by copyWorkContext() and provided to the previous call to workSubmitWithContext().
197*8d741a5dSApple OSS Distributions  * @param args Optional device-specific arguments related to the start of this work item.
198*8d741a5dSApple OSS Distributions  * @note The workBeginWithContext() and workEndWithContext() calls are optional if the corresponding workSubmitWithContext() call returned false.
199*8d741a5dSApple OSS Distributions  */
200*8d741a5dSApple OSS Distributions 	void workBeginWithContext(IOService *device, OSObject *context, WorkBeginArgs *args = nullptr);
201*8d741a5dSApple OSS Distributions 
202*8d741a5dSApple OSS Distributions /*!
203*8d741a5dSApple OSS Distributions  * @function workEndWithContext
204*8d741a5dSApple OSS Distributions  * @abstract Tell the performance controller that previously started work finished executing.
205*8d741a5dSApple OSS Distributions  * @param device The device that executed the work. Some platforms require device to be a
206*8d741a5dSApple OSS Distributions  * specific subclass of IOService.
207*8d741a5dSApple OSS Distributions  * @param context An OSObject returned by copyWorkContext() and provided to the previous call to workSubmitWithContext().
208*8d741a5dSApple OSS Distributions  * @param args Optional device-specific arguments related to the end of this work item.
209*8d741a5dSApple OSS Distributions  * @param done Optional Set to false if the work has not yet completed. Drivers are then responsible for
210*8d741a5dSApple OSS Distributions  * calling workBegin when the work resumes and workEnd with done set to True when it has completed.
211*8d741a5dSApple OSS Distributions  * @note The workEndWithContext() call is optional if the corresponding workSubmitWithContext() call returned false. A workEndWithContext()
212*8d741a5dSApple OSS Distributions  * call without a corresponding workBeginWithContext() call is a way to cancel a work item.
213*8d741a5dSApple OSS Distributions  */
214*8d741a5dSApple OSS Distributions 	void workEndWithContext(IOService *device, OSObject *context, WorkEndArgs *args = nullptr, bool done = true);
215*8d741a5dSApple OSS Distributions 
216*8d741a5dSApple OSS Distributions /*!
217*8d741a5dSApple OSS Distributions  * @struct WorkUpdateArgs
218*8d741a5dSApple OSS Distributions  * @discussion Drivers may submit additional device-specific arguments related to a work item by passing a
219*8d741a5dSApple OSS Distributions  * struct with WorkUpdateArgs as its first member. Note: Drivers are responsible for publishing
220*8d741a5dSApple OSS Distributions  * a header file describing these arguments.
221*8d741a5dSApple OSS Distributions  */
222*8d741a5dSApple OSS Distributions 	struct WorkUpdateArgs {
223*8d741a5dSApple OSS Distributions 		uint32_t version;
224*8d741a5dSApple OSS Distributions 		uint32_t size;
225*8d741a5dSApple OSS Distributions 		uint64_t update_time;
226*8d741a5dSApple OSS Distributions 		uint64_t reserved[4];
227*8d741a5dSApple OSS Distributions 		void *driver_data;
228*8d741a5dSApple OSS Distributions 	};
229*8d741a5dSApple OSS Distributions 
230*8d741a5dSApple OSS Distributions /*!
231*8d741a5dSApple OSS Distributions  * @function workUpdateWithContext
232*8d741a5dSApple OSS Distributions  * @abstract Provide and receive additional information from the performance controller. If this call is
233*8d741a5dSApple OSS Distributions  * made at all, it should be between workSubmit and workEnd. The purpose and implementation of this call are
234*8d741a5dSApple OSS Distributions  * device specific, and may do nothing on some devices.
235*8d741a5dSApple OSS Distributions  * @param device The device that submitted the work. Some platforms require device to be a
236*8d741a5dSApple OSS Distributions  * specific subclass of IOService.
237*8d741a5dSApple OSS Distributions  * @param context An OSObject returned by copyWorkContext() and provided to the previous call to workSubmitWithContext().
238*8d741a5dSApple OSS Distributions  * @param args Optional device-specific arguments.
239*8d741a5dSApple OSS Distributions  */
240*8d741a5dSApple OSS Distributions 	void workUpdateWithContext(IOService *device, OSObject *context, WorkUpdateArgs *args = nullptr);
241*8d741a5dSApple OSS Distributions 
242*8d741a5dSApple OSS Distributions /*
243*8d741a5dSApple OSS Distributions  * Callers should always use the CURRENT version so that the kernel can detect both older
244*8d741a5dSApple OSS Distributions  * and newer structure layouts. New callbacks should always be added at the end of the
245*8d741a5dSApple OSS Distributions  * structure, and xnu should expect existing source recompiled against newer headers
246*8d741a5dSApple OSS Distributions  * to pass NULL for unimplemented callbacks.
247*8d741a5dSApple OSS Distributions  */
248*8d741a5dSApple OSS Distributions 
249*8d741a5dSApple OSS Distributions #define PERFCONTROL_INTERFACE_VERSION_NONE (0) /* no interface */
250*8d741a5dSApple OSS Distributions #define PERFCONTROL_INTERFACE_VERSION_1 (1) /* up-to workEnd */
251*8d741a5dSApple OSS Distributions #define PERFCONTROL_INTERFACE_VERSION_2 (2) /* up-to workUpdate */
252*8d741a5dSApple OSS Distributions #define PERFCONTROL_INTERFACE_VERSION_3 (3) /* up-to (un)registerDriverDevice */
253*8d741a5dSApple OSS Distributions #define PERFCONTROL_INTERFACE_VERSION_4 (4) /* up-to workEndWithResources */
254*8d741a5dSApple OSS Distributions #define PERFCONTROL_INTERFACE_VERSION_CURRENT PERFCONTROL_INTERFACE_VERSION_4
255*8d741a5dSApple OSS Distributions 
256*8d741a5dSApple OSS Distributions /*!
257*8d741a5dSApple OSS Distributions  * @struct PerfControllerInterface
258*8d741a5dSApple OSS Distributions  * @discussion Function pointers necessary to register a performance controller. Not for general driver use.
259*8d741a5dSApple OSS Distributions  */
260*8d741a5dSApple OSS Distributions 	struct PerfControllerInterface {
261*8d741a5dSApple OSS Distributions 		enum struct PerfDeviceID : uint32_t{
262*8d741a5dSApple OSS Distributions 			kInvalid = 0,
263*8d741a5dSApple OSS Distributions 			kCPU = 0,
264*8d741a5dSApple OSS Distributions 			kANE = 0x4,
265*8d741a5dSApple OSS Distributions 			kGPU,
266*8d741a5dSApple OSS Distributions 			kMSR,
267*8d741a5dSApple OSS Distributions 			kStorage,
268*8d741a5dSApple OSS Distributions 		};
269*8d741a5dSApple OSS Distributions 
270*8d741a5dSApple OSS Distributions 		struct DriverState {
271*8d741a5dSApple OSS Distributions 			uint32_t has_target_thread_group : 1;
272*8d741a5dSApple OSS Distributions 			uint32_t has_device_info : 1;
273*8d741a5dSApple OSS Distributions 			uint32_t reserved : 30;
274*8d741a5dSApple OSS Distributions 
275*8d741a5dSApple OSS Distributions 			uint64_t target_thread_group_id;
276*8d741a5dSApple OSS Distributions 			void *target_thread_group_data;
277*8d741a5dSApple OSS Distributions 
278*8d741a5dSApple OSS Distributions 			PerfDeviceID device_type;
279*8d741a5dSApple OSS Distributions 			uint32_t instance_id;
280*8d741a5dSApple OSS Distributions 			bool resource_accounting;
281*8d741a5dSApple OSS Distributions 		};
282*8d741a5dSApple OSS Distributions 
283*8d741a5dSApple OSS Distributions 		struct WorkState {
284*8d741a5dSApple OSS Distributions 			uint64_t thread_group_id;
285*8d741a5dSApple OSS Distributions 			void *thread_group_data;
286*8d741a5dSApple OSS Distributions 			void *work_data;
287*8d741a5dSApple OSS Distributions 			uint32_t work_data_size;
288*8d741a5dSApple OSS Distributions 			uint32_t started : 1;
289*8d741a5dSApple OSS Distributions 			uint32_t reserved : 31;
290*8d741a5dSApple OSS Distributions 			const DriverState* driver_state;
291*8d741a5dSApple OSS Distributions 		};
292*8d741a5dSApple OSS Distributions 
293*8d741a5dSApple OSS Distributions 		struct ResourceAccounting {
294*8d741a5dSApple OSS Distributions 			uint64_t mach_time_delta;
295*8d741a5dSApple OSS Distributions 			uint64_t energy_nj_delta;
296*8d741a5dSApple OSS Distributions 		};
297*8d741a5dSApple OSS Distributions 
298*8d741a5dSApple OSS Distributions 		using RegisterDeviceFunction = IOReturn (*)(IOService *);
299*8d741a5dSApple OSS Distributions 		using RegisterDriverDeviceFunction = IOReturn (*)(IOService *, IOService *, DriverState *);
300*8d741a5dSApple OSS Distributions 		using WorkCanSubmitFunction = bool (*)(IOService *, WorkState *, WorkSubmitArgs *);
301*8d741a5dSApple OSS Distributions 		using WorkSubmitFunction = void (*)(IOService *, uint64_t, WorkState *, WorkSubmitArgs *);
302*8d741a5dSApple OSS Distributions 		using WorkBeginFunction = void (*)(IOService *, uint64_t, WorkState *, WorkBeginArgs *);
303*8d741a5dSApple OSS Distributions 		using WorkEndFunction = void (*)(IOService *, uint64_t, WorkState *, WorkEndArgs *, bool);
304*8d741a5dSApple OSS Distributions 		using WorkEndWithResourcesFunction = void (*)(IOService *, uint64_t, WorkState *, WorkEndArgs *, ResourceAccounting *, bool);
305*8d741a5dSApple OSS Distributions 		using WorkUpdateFunction = void (*)(IOService *, uint64_t, WorkState *, WorkUpdateArgs *);
306*8d741a5dSApple OSS Distributions 
307*8d741a5dSApple OSS Distributions 		uint64_t version;
308*8d741a5dSApple OSS Distributions 		RegisterDeviceFunction registerDevice;
309*8d741a5dSApple OSS Distributions 		RegisterDeviceFunction unregisterDevice;
310*8d741a5dSApple OSS Distributions 		WorkCanSubmitFunction workCanSubmit;
311*8d741a5dSApple OSS Distributions 		WorkSubmitFunction workSubmit;
312*8d741a5dSApple OSS Distributions 		WorkBeginFunction workBegin;
313*8d741a5dSApple OSS Distributions 		WorkEndFunction workEnd;
314*8d741a5dSApple OSS Distributions 		WorkUpdateFunction workUpdate;
315*8d741a5dSApple OSS Distributions 		RegisterDriverDeviceFunction registerDriverDevice;
316*8d741a5dSApple OSS Distributions 		RegisterDriverDeviceFunction unregisterDriverDevice;
317*8d741a5dSApple OSS Distributions 		WorkEndWithResourcesFunction workEndWithResources;
318*8d741a5dSApple OSS Distributions 	};
319*8d741a5dSApple OSS Distributions 
320*8d741a5dSApple OSS Distributions 	struct IOPerfControlClientShared {
321*8d741a5dSApple OSS Distributions 		atomic_uint_fast8_t maxDriverIndex;
322*8d741a5dSApple OSS Distributions 		PerfControllerInterface interface;
323*8d741a5dSApple OSS Distributions 		IOLock *interfaceLock;
324*8d741a5dSApple OSS Distributions 		OSSet *deviceRegistrationList;
325*8d741a5dSApple OSS Distributions 	};
326*8d741a5dSApple OSS Distributions 
327*8d741a5dSApple OSS Distributions 	struct IOPerfControlClientData {
328*8d741a5dSApple OSS Distributions 		struct thread_group *target_thread_group;
329*8d741a5dSApple OSS Distributions 		PerfControllerInterface::DriverState driverState;
330*8d741a5dSApple OSS Distributions 		IOService* device;
331*8d741a5dSApple OSS Distributions 	};
332*8d741a5dSApple OSS Distributions /*!
333*8d741a5dSApple OSS Distributions  * @function registerPerformanceController
334*8d741a5dSApple OSS Distributions  * @abstract Register a performance controller to receive callbacks. Not for general driver use.
335*8d741a5dSApple OSS Distributions  * @param interface Struct containing callback functions implemented by the performance controller.
336*8d741a5dSApple OSS Distributions  * @returns kIOReturnSuccess or kIOReturnError if the interface was already registered.
337*8d741a5dSApple OSS Distributions  */
338*8d741a5dSApple OSS Distributions 	virtual IOReturn registerPerformanceController(PerfControllerInterface *interface);
339*8d741a5dSApple OSS Distributions 
340*8d741a5dSApple OSS Distributions /*!
341*8d741a5dSApple OSS Distributions  * @function getClientData
342*8d741a5dSApple OSS Distributions  * @abstract Not for general driver use. Only used by registerPerformanceController(). Allows performanceController to register existing IOPerfControlClient.
343*8d741a5dSApple OSS Distributions  * @returns IOPerfControlData associated with a IOPerfControlClient
344*8d741a5dSApple OSS Distributions  */
345*8d741a5dSApple OSS Distributions 	IOPerfControlClientData *
getClientData()346*8d741a5dSApple OSS Distributions 	getClientData()
347*8d741a5dSApple OSS Distributions 	{
348*8d741a5dSApple OSS Distributions 		return &clientData;
349*8d741a5dSApple OSS Distributions 	}
350*8d741a5dSApple OSS Distributions 
351*8d741a5dSApple OSS Distributions private:
352*8d741a5dSApple OSS Distributions 	struct WorkTableEntry {
353*8d741a5dSApple OSS Distributions 		struct thread_group *thread_group;
354*8d741a5dSApple OSS Distributions 		coalition_t coal;
355*8d741a5dSApple OSS Distributions 		bool started;
356*8d741a5dSApple OSS Distributions 		uint8_t perfcontrol_data[32];
357*8d741a5dSApple OSS Distributions 	};
358*8d741a5dSApple OSS Distributions 
359*8d741a5dSApple OSS Distributions 	static constexpr size_t kMaxWorkTableNumEntries = 1024;
360*8d741a5dSApple OSS Distributions 	static constexpr size_t kWorkTableIndexBits = 24;
361*8d741a5dSApple OSS Distributions 	static constexpr size_t kWorkTableMaxSize = (1 << kWorkTableIndexBits) - 1; // - 1 since
362*8d741a5dSApple OSS Distributions 	// kIOPerfControlClientWorkUntracked takes number 0
363*8d741a5dSApple OSS Distributions 	static constexpr size_t kWorkTableIndexMask = (const size_t)mask(kWorkTableIndexBits);
364*8d741a5dSApple OSS Distributions 
365*8d741a5dSApple OSS Distributions 	uint64_t allocateToken(thread_group *thread_group);
366*8d741a5dSApple OSS Distributions 	void deallocateToken(uint64_t token);
367*8d741a5dSApple OSS Distributions 	WorkTableEntry *getEntryForToken(uint64_t token);
368*8d741a5dSApple OSS Distributions 	void markEntryStarted(uint64_t token, bool started);
369*8d741a5dSApple OSS Distributions 	inline uint64_t tokenToGlobalUniqueToken(uint64_t token);
370*8d741a5dSApple OSS Distributions 	void accountResources(coalition_t coal, PerfControllerInterface::PerfDeviceID device_type, PerfControllerInterface::ResourceAccounting *resources);
371*8d741a5dSApple OSS Distributions 
372*8d741a5dSApple OSS Distributions 	uint8_t driverIndex;
373*8d741a5dSApple OSS Distributions 	IOPerfControlClientShared *shared;
374*8d741a5dSApple OSS Distributions 	WorkTableEntry *workTable;
375*8d741a5dSApple OSS Distributions 	size_t workTableLength;
376*8d741a5dSApple OSS Distributions 	size_t workTableNextIndex;
377*8d741a5dSApple OSS Distributions 	IOSimpleLock *workTableLock;
378*8d741a5dSApple OSS Distributions 
379*8d741a5dSApple OSS Distributions 	IOPerfControlClientData clientData;
380*8d741a5dSApple OSS Distributions };
381*8d741a5dSApple OSS Distributions 
382*8d741a5dSApple OSS Distributions #endif /* __cplusplus */
383*8d741a5dSApple OSS Distributions #endif /* KERNEL_PRIVATE */
384