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