1/* 2 * Copyright (c) 2012-2014 Apple Computer, 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/* 30 * FILE: IOReporter.h 31 * AUTH: Cyril & Soren (Core OS) 32 * DATE: 2012-2013 (Copyright Apple Inc.) 33 * DESC: IOReporting interfaces for I/O Kit drivers 34 * 35 */ 36 37#ifndef _IOKERNEL_REPORTERS_H_ 38#define _IOKERNEL_REPORTERS_H_ 39 40#include <machine/limits.h> 41 42#include <IOKit/IOLib.h> 43#include <IOKit/IOService.h> 44#include <IOKit/IOLocks.h> 45#include <IOKit/IOBufferMemoryDescriptor.h> 46 47#include <IOKit/IOReportTypes.h> 48#include <IOKit/IOKernelReportStructs.h> 49 50typedef OSDictionary IOReportLegendEntry; 51 52/******************************* 53 TOC: this file contains 54 1. Introduction 55 2a. IOReporter class declaration (public & non-public members) 56 2b. static IOReporter methods unrelated to the class 57 3. IOReporter subclass declarations (public & non-public members) 58 4. IOReportLegend class declaration 59*******************************/ 60 61/*! 62 1. Introduction 63 64 IOReporting is a mechanism for I/O Kit drivers to gather statistics 65 (or other information) and make it available to various "observers," 66 which are generally in user space. Requests for information come 67 through two new IOService methods: ::configureReport(...) and 68 ::updateReport(...). While not required (see IOReportTypes.h), drivers 69 will generally use IOReporter subclass instances to track the requested 70 information and respond to IOReporting requests. Drivers can use these 71 classes to track information, either all the time or between "enable" 72 and "disable" calls to IOService::configureReport(). 73 74 Available information is organized into "channels." A channel is 75 uniquely identified by both driver (registry) ID and a 64-bit channel 76 ID. One way drivers can advertise their channels is by publishing 77 "legends" in the I/O Kit registry. In addition to collecting 78 information and responding to queries, IOReporter objects can produce 79 legend entries describing their channels. The IOReportLegend class 80 helps manage legend entries from multiple reporter objects as well 81 as with grouping channels logically for observers. 82 83 An important basic constraint of the current implementation is that 84 all channels reported by a particular reporter instance must share all 85 traits except channel ID and name. Specifically, the channel type 86 (including report class, categories, & size) and units. Additionally, 87 IOHistogramReporter currently only supports one channel at a time. 88 89 Currently, ::{configure/update}Report() can be called any time between 90 when a driver calls registerService() and when free() is called on 91 your driver. 12960947 tracks improvements / recommendations for 92 correctly handling these calls during termination. 93 94 * Locking 95 IOReporting only imposes concurrent access constraints when multiple 96 threads are accessing the same object. Three levels of constraint apply 97 depending on a method's purpose: 98 1. Allocation/Teardown - same-instance concurrency UNSAFE, MAY BLOCK 99 2. Configuration - same-instance concurrency SAFE, MAY BLOCK 100 3. Update - same-instance concurrency SAFE, WILL NOT BLOCK 101 102 Configuration requires memory management which can block and must 103 be invoked with interrupts ENABLED (for example, NOT in the interrupt 104 context NOR with a spin lock -- like IOSimpleLock -- held). 105 106 Updates can be performed with interrupts disabled, but clients should 107 take into account that IOReporters' non-blocking currenency is achieved 108 with IOSimpleLockLockDisable/UnlockEnableInterrupts(): that is, by 109 disabling interrupts and taking a spin lock. While IOReporting will 110 never hold a lock beyond a call into it, some time may be spent within 111 the call spin-waiting for the lock. Clients holding their own 112 spin locks should carefully consider the impact of IOReporting's 113 (small) additional latency before calling it while holding a spin lock. 114 115 The documentation for each method indicates any concurrency guarantees. 116 */ 117 118 119/*********************************/ 120/*** 2a. IOReporter Base Class ***/ 121/*********************************/ 122 123class IOReporter : public OSObject 124{ 125 OSDeclareDefaultStructors(IOReporter); 126 127protected: 128/*! @function IOReporter::init 129 @abstract base init() method, called by subclass initWith() methods 130 131 @param reportingService - IOService associated with all channels 132 @param channelType - type info for all channels (element_idx = 0) 133 @param unit - description applied for all channels 134 @result true on success, false otherwise 135 136 @discussion 137 init() establishes the parameters of all channels for this reporter 138 instance. Any channels added via addChannel() will be of this type 139 and have this unit. 140 141 IOReporter clients should use the static <subclass>::with() methods 142 below to obtain fully-initialized reporter instances. ::free() 143 expects ::init() to have completed successfully. On failure, any 144 allocations are cleaned up. 145 146 Locking: same-instance concurrency UNSAFE 147*/ 148 virtual bool init(IOService *reportingService, 149 IOReportChannelType channelType, 150 IOReportUnits unit); 151 152public: 153 154/*! @function IOReporter::addChannel 155 @abstract add an additional, similar channel to the reporter 156 157 @param channelID - identifier for the channel to be added 158 @param channelName - an optional human-readble name for the channel 159 @result appropriate IOReturn code 160 161 @discussion 162 The reporter will allocate memory to track a new channel with the 163 provided ID and name (if any). Its other traits (type, etc) will 164 be those provided when the reporter was initialized. If no channel 165 name is provided and the channelID consists solely of ASCII bytes, 166 those bytes (ignoring any NUL bytes) will be used as the 167 human-readable channel name in user space. The IOREPORT_MAKEID() 168 macro in IOReportTypes.h can be used to create ASCII channel IDs. 169 170 Locking: same-instance concurrency SAFE, MAY BLOCK 171*/ 172 IOReturn addChannel(uint64_t channelID, const char *channelName = NULL); 173 174/*! @function IOReporter::createLegend 175 @abstract create a legend entry represending this reporter's channels 176 @result An IOReportLegendEntry object or NULL on failure. 177 @discussion 178 All channels added to the reporter will be represented 179 in the resulting legend entry. 180 181 Legends must be published togethar as an array under the 182 kIOReportLegendKey in the I/O Kit registry. The IOReportLegend 183 class can be used to properly combine legend entries from multiple 184 reporters as well as to put channels into groups of interest to 185 observers. When published, individual legend entries share 186 characteristics such as group and sub-group. Multiple IOReporter 187 instances are required to produce independent legend entries which 188 can then be published with different characteristics. 189 190 Drivers wishing to publish legends should do so as part of their 191 ::start() routine. As superclasses *may* have installed legend 192 entries, any existing existing legend should be retrieved and 193 IOReportLegend used to merge it with the new entries. 194 195 Recommendations for best practices are forthcoming. 196 197 Instead of calling createLegend on your reporter object and then 198 appending it manually to IOReportLegend, one may prefer to call 199 IOReportLegend::appendReporterLegend which creates and appends a 200 reporter's IOReportLegendEntry in a single call. 201 202 Locking: same-instance concurrency SAFE, MAY BLOCK 203*/ 204 IOReportLegendEntry* createLegend(void); 205 206/*! @function IOReporter::configureReport 207 @abstract track IOService::configureReport(), provide sizing info 208 209 @param channelList - channels to configure 210 @param action - enable/disable/size, etc (see IOReportTypes.h) 211 @param result - *incremented* for kIOReportGetDimensions 212 @param destination - action-specific default destination 213 @result appropriate IOReturn code 214 215 @discussion 216 Any time a reporting driver's ::configureReport method is invoked, 217 this method should be invoked on each IOReporter that is being 218 used by that driver to report channels in channelList. 219 220 Any channels in channelList which are not tracked by this reporter 221 are ignored. ::configureReport(kIOReportGetDimensions) expects 222 the full size of all channels, including any reported by 223 superclasses. It is valid to call this routine on multiple 224 reporter objects in succession and they will increment 'result' 225 to provide the correct total. 226 227 In the initial release, this routine is only required to calculate 228 the response to kIOReportGetDimensions, but in the future it will 229 will enable functionality like "triggered polling" via 230 kIOReportNotifyHubOnChange. Internally, it is already keeping 231 track of the number of times each channel has been enabled and 232 disabled. 13073064 tracks adding a method to see whether any 233 channels are currently being observed. 234 235 The static IOReporter::configureAllReports() will call this method 236 on multiple reporters grouped in an OSSet. 237 238 Locking: same-instance concurrency SAFE, MAY BLOCK 239*/ 240 IOReturn configureReport(IOReportChannelList *channelList, 241 IOReportConfigureAction action, 242 void *result, 243 void *destination); 244 245/*! @function IOReporter::updateReport 246 @abstract Produce standard reply to IOService::updateReport() 247 248 @param channelList - channels to update 249 @param action - copy/trace data (see IOReportTypes.h) 250 @param result - action-specific return value (e.g. size of data) 251 @param destination - destination for this update (action-specific) 252 @result appropriate IOReturn code 253 254 @discussion 255 This method searches channelList for channels tracked by this 256 reporter, writes the corresponding data into 'destination', and 257 updates 'result'. It should be possible to pass a given set of 258 IOService::updateReport() arguments to any and all reporters as 259 well as to super::updateReport() and get the right result. 260 261 The static IOReporter::updateAllReports() will call this method 262 on an OSSet of reporters. 263 264 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 265*/ 266 IOReturn updateReport(IOReportChannelList *channelList, 267 IOReportConfigureAction action, 268 void *result, 269 void *destination); 270 271/*! @function IOReporter::free 272 @abstract Releases the object and all its resources. 273 274 @discussion 275 ::free() [called on last ->release()] assumes that init() [called 276 by static ::with() methods] has completed successfully. 277 278 Locking: same-instance concurrency UNSAFE 279*/ 280 virtual void free(void); 281 282 283/*********************************/ 284/*** 2b. Useful Static Methods ***/ 285/*********************************/ 286 287/* The following static functions are intended to simplify the management 288 * of multiple reporters. They may be superseded in the future by an 289 * IOReportManager class. 290 */ 291 292/*! @function IOReporter::configureAllReports 293 @abstract call configureReport() on multiple IOReporter objects 294 295 @param reporters - OSSet of IOReporter objects 296 @param channelList - full list of channels to configure 297 @param action - enable/disable/size, etc 298 @param result - action-specific returned value 299 @param destination - action-specific default destination 300 @result success if all objects successfully complete 301 IOReporter::configureReport() 302 303 @discussion 304 The OSSet must only contain IOReporter instances. The presence 305 of non-IOReporter instances will cause this function to return 306 kIOReturnBadArgument. If any reporter returns an error, the 307 function will immediately return that error. 308 309 Per the IOReporter::configureReport() documentation, each 310 reporter will search channelList for channels it is reporting 311 and provide a partial response. 312*/ 313 static IOReturn configureAllReports(OSSet *reporters, 314 IOReportChannelList *channelList, 315 IOReportConfigureAction action, 316 void *result, 317 void *destination); 318// FIXME: just put the function (inline-ish) here? 319 320/*! @function IOReporter::updateAllReports 321 @abstract call updateReport() on multiple IOReporter objects 322 323 @param reporters - OSSet of IOReporter objects 324 @param channels - full list of channels to update 325 @param action - type/style of update 326 @param result - returned details about what was updated 327 @param destination - destination for this update (action-specific) 328 @result IOReturn code 329 @discussion 330 The OSSet must only contain IOReporter instances. The presence 331 of non-IOReporter instances will cause this function to return 332 kIOReturnBadArgument. If any reporter returns an error, the 333 function will immediately return that error. 334 335 Per the IOReporter::configureReport() documentation, each 336 reporter will search channelList for channels it is reporting 337 and provide a partial response. 338*/ 339 static IOReturn updateAllReports(OSSet *reporters, 340 IOReportChannelList *channelList, 341 IOReportConfigureAction action, 342 void *result, 343 void *destination); 344// FIXME: just put the function (inline-ish) here? 345 346 347 /* Protected (subclass-only) Methods 348 349 General subclassing is not encouraged as we intend to improve 350 internal interfaces. If you need something that might require 351 a subclass, please file a bug against IOReporting/X and we will 352 help you. 353 354 One important concept for sub-classes (not clients) is that report 355 data is stored in IOReportElement structures (see IOReportTypes.h). 356 */ 357protected: 358 359/*! @function IOReporter::lockReporterConfig 360 @function IOReporter::unlockReporterConfig 361 @abstract prevent concurrent reconfiguration of a reporter 362 363 @discussion 364 lockReporterConfig() takes a mutex-based lock intended to prevent 365 concurrent access to the reporter's configuration. It is not 366 intended to prevent updates to the reporter's data. As long as 367 all other requirements are met, it is safe to simultaneously hold 368 both the configuration and data locks on a single reporter. 369 370 lockReporterConfig() is used by routines such as addChannel(). 371 See also lockReporter() and ::handle*Swap*() below. 372*/ 373 void lockReporterConfig(void); 374 void unlockReporterConfig(void); 375 376/*! @function IOReporter::lockReporter 377 @function IOReporter::unlockReporter 378 @abstract prevent concurrent access to a reporter's data 379 380 @discussion 381 This method grabs a lock intended to control access the reporter's 382 reporting data. Sub-classes maninupating internal report values 383 must make sure the reporter is locked (usually by the most generic 384 public interface) before calling getElementValues(), 385 copyElementValues(), or setElementValues(). 386 387 Subclasses should ensure that this lock is taken exactly once 388 before directly accessing reporter data. For example, 389 [virtual] IOFooReporter::handleSetFoo(.) { 390 // assert(lock_held) 391 getElementValues(1..) 392 getElementValues(3..) 393 getElementValues(5..) 394 [calculate] 395 setElementValues(6..) 396 } 397 IOFooReporter::setFoo(.) { // not virtual 398 lockReporter() 399 handleSetFoo(.) 400 unlockReporter() 401 } 402 403 IOReporter::handle*() use lockReporter() similarly. For example, 404 the lock is taken by IOReporter::updateReport() and is already 405 held by the time any ::updateChannelValues() methods are called. 406 407 Subclasses cannot call this routine if the lock is already held. 408 That's why IOReporting generally only calls it from non-virtual 409 public methods. In particular, this method should not be called 410 it from ::handle*() methods which exist to allow override after 411 the lock is taken. 412 413 Because lockReporter() uses a spin lock, it is SAFE to use in the 414 interrupt context. For the same reason, however, it is UNSAFE 415 to perform any blocking blocking operations (including memory 416 allocations) while holding this lock. 417*/ 418 void lockReporter(void); 419 void unlockReporter(void); 420 421/*! 422 @discussion 423 The ::handle*Swap* functions allow subclasses to safely reconfigure 424 their internal state. A non-virtual function handles locking 425 and invokes the functions in order: 426 - lockReporterConfig() // protecting instance vars but not content 427 - prepare / allocate buffers of the new size 428 - if error, bail (unlocking, of course) 429 430 - lockReporter() // protecting data / blocking updates 431 - swap: preserve continuing data / install new buffers 432 - unlockReporter() 433 434 - deallocate now-unused buffers 435 - unlockReporterConfig() 436*/ 437/*! @function IOReporter::handleSwapPrepare 438 @abstract allocate memory in preparation for an instance variable swap 439 440 @param newNChannels target number of channels 441 @result IOReturn code 442 443 @discussion 444 ::handleSwapPrepare() is responsible for allocating appropriately- 445 sized buffers (based on the new number of channels) and storing 446 them in _swap* instance variables. If returning and error, it 447 must deallocate any buffers and set to NULL any _swap* variables. 448 449 Locking: The caller must ensure that the *config* lock is HELD but 450 that the reporter (data) lock is *NOT HELD*. 451*/ 452 virtual IOReturn handleSwapPrepare(int newNChannels); 453 454/*! @function IOReporter::handleAddChannelSwap 455 @abstract update primary instance variables with new buffers 456 457 @param channelID ID of channel being added 458 @param channelName optional channel name, in an allocated object 459 @result IOReturn code 460 461 @discussion 462 handlAddChannelSwap() replaces the primary instance variables 463 with buffers allocated in handlePrepareSwap(). It copies the the 464 existing data into the appropriate portion of the new buffers. 465 Because it is specific to adding one channel, it assumes that the 466 target number of channels is one greater than the current value 467 of _nChannels. 468 469 IOReporter::handleAddChannelSwap() increments _nElements and 470 _nChannels. To ensure that these variables describe the current 471 buffers throughout ::handle*Swap(), subclasses overriding this 472 method should call super::handleAddChannelSwap() after swapping 473 their own instance variables. 474 475 If returning an error, all implementations should leave their 476 instance variables as they found them (*unswapped*). That ensures 477 handleSwapCleanup() cleans up the unused buffers regardless of 478 whether the swap was complete. 479 480 Pseudo-code incorporating these suggestions: 481 res = <err>; swapComplete = false; 482 if (<unexpected>) goto finish 483 tmpBuf = _primaryBuf; _primaryBuf = _swapBuf; _swapBuf = _primaryBuf; 484 ... 485 swapComplete = true; 486 res = super::handle*Swap() 487 ... 488 finish: 489 if (res && swapComplete) // unswap 490 491 Locking: The caller must ensure that BOTH the configuration and 492 reporter (data) locks are HELD. 493*/ 494 virtual IOReturn handleAddChannelSwap(uint64_t channel_id, 495 const OSSymbol *symChannelName); 496 497/*! @function IOReporter::handleSwapCleanup 498 @abstract release and forget unused buffers 499 500 @param swapNChannels channel-relative size of the _swap buffers 501 502 @discussion 503 ::handleSwapCleanup() is responsible for deallocating the buffers 504 no longer used after a swap. It must always be called if 505 SwapPrepare() completes successfully. Because bufers may be 506 swapped in and out of existance, the _swap* variables may be 507 NULL and should be set to NULL when complete. 508 509 Locking: The caller must ensure that the *config* lock is HELD but 510 that the reporter (data) lock is *NOT HELD*. 511*/ 512 virtual void handleSwapCleanup(int swapNChannels); 513 514/*! @function IOReporter::handleConfigureReport 515 @abstract override vector for IOReporter::configureReport() 516 [parameters and result should exactly match] 517 518 @discussion 519 The public base class method takes the reporter lock, calls this 520 function, and then drops the lock. Subclasses should not call 521 this function directly. 522*/ 523 virtual IOReturn handleConfigureReport(IOReportChannelList *channelList, 524 IOReportConfigureAction action, 525 void *result, 526 void *destination); 527 528/*! @function IOReporter::handleUpdateReport 529 @abstract override vector for IOReporter::updateReport() 530 [parameters and result should exactly match] 531 532 @discussion 533 The public base class method takes the reporter lock, calls this 534 function, and then drops the lock. Subclasses should not call 535 this function directly. 536 537 This function may be overriden but the common case should be to 538 simply update reporter's specific values by overriding 539 IOReporter::updateChannelValues(). 540*/ 541 virtual IOReturn handleUpdateReport(IOReportChannelList *channelList, 542 IOReportConfigureAction action, 543 void *result, 544 void *destination); 545 546/* @function IOReporter::handleCreateLegend 547 @abstract override vector for IOReporter::createLegend() 548 [parameters and result should exactly match] 549 550 @discussion 551 The public base class method takes the reporter lock, calls this 552 function, and then drops the lock. Subclasses should not call 553 this function directly. 554*/ 555 virtual IOReportLegendEntry* handleCreateLegend(void); 556 557/*! @function IOReporter::updateChannelValues 558 @abstract update channel values for IOReporter::updateReport() 559 560 @param channel_index - logical (internal) index of the channel 561 @result appropriate IOReturn code 562 563 @discussion 564 Internal reporter method to allow a subclass to update channel 565 data when updateReport() is called. This routine handles the 566 common case of a subclass needing to refresh state in response 567 to IOReporter::updateReport(). It saves the complexity of 568 parsing the full parameters to IOReporter::updateReport(). 569 570 The IOReporter base class implementation does not do anything 571 except return success. 572 573 Locking: IOReporter::updateReport() takes the reporter lock, 574 determines the indices involved, calls this function, and 575 then proceeds to provide values to the caller. If subclasses 576 need to call this routine directly, they must ensure that 577 the reporter (data) lock is held: see 578 IOReporter::lockReporter(). 579*/ 580 virtual IOReturn updateChannelValues(int channel_index); 581 582 583/*! @function IOReporter::updateReportChannel 584 @abstract Internal method to extract channel data to a destination 585 586 @param channel_index - offset into internal elements array 587 @param nElements - incremented by the number of IOReportElements added 588 @param destination - pointer to the destination buffer 589 @result IOReturn code 590 591 @discussion 592 updateReportChannel() is used to extract a single channel's 593 data to the updateReport() destination. 594 595 Locking: Caller must ensure that the reporter (data) lock is held. 596*/ 597 IOReturn updateReportChannel(int channel_index, 598 int *nElements, 599 IOBufferMemoryDescriptor *destination); 600 601 602/*! @function IOReporter::setElementValues 603 @abstract Atomically update a specific member of _elements[]. 604 605 @param element_index - index of the _element in internal array 606 @param values - IORepoterElementValues to replace those at _elements[idx] 607 @param record_time - optional mach_absolute_time to be used for metadata 608 @result IOReturn code 609 610 @discussion 611 element_index can be obtained from getFirstElementIndex(). If 612 record_time is not provided, IOReporter::setElementValues() will 613 fetch the current mach_absolute_time. If the current time is 614 already known, it is more efficient to pass it along. 615 616 Locking: Caller must ensure that the reporter (data) lock is held. 617*/ 618 virtual IOReturn setElementValues(int element_index, 619 IOReportElementValues *values, 620 uint64_t record_time = 0); 621 622/*! @function IOReporter::getElementValues 623 @abstract Internal method to directly access the values of an element 624 625 @param element_index - index of the _element in internal array 626 @result A pointer to the element values requested or NULL on failure 627 628 @discussion 629 630 Locking: Caller must ensure that the reporter (data) lock is held. 631 The returned pointer is only valid until unlockReporter() is called. 632*/ 633 virtual const IOReportElementValues* getElementValues(int element_index); 634 635/*! @function IOReporter::getFirstElementIndex 636 @abstract Returns the first element index for a channel 637 638 @param channel_id - ID of the channel 639 @param element_index - pointer to the returned element_index 640 @result appropriate IOReturn code 641 642 @discussion 643 For efficiently and thread-safely reading _elements 644 645 Locking: Caller must ensure that the reporter (data) lock is held. 646*/ 647 virtual IOReturn getFirstElementIndex(uint64_t channel_id, 648 int *element_index); 649 650/*! @function IOReporter::getChannelIndex 651 @abstract Returns the index of a channel from internal data structures 652 653 @param channel_id - ID of the channel 654 @param element_index - pointer to the returned element_index 655 @result appropriate IOReturn code 656 657 @discussion 658 For efficiently and thread-safely reading channels 659 660 Locking: Caller must ensure that the reporter (data) lock is held. 661*/ 662 virtual IOReturn getChannelIndex(uint64_t channel_id, 663 int *channel_index); 664 665/*! @function IOReporter::getChannelIndices 666 @abstract Returns the index of a channel and its corresponding 667 first element index from internal data structure 668 669 @param channel_id - ID of the channel 670 @param channel_index - pointer to the returned channel_index 671 @param element_index - pointer to the returned element_index 672 @result appropriate IOReturn code 673 674 @discussion 675 For efficiently and thread-safely reading channel elements. 676 It is commonly useful to get access to both channel and element 677 indices togther. This convenience method allows sub-classes to 678 get both indices simultaneously. 679 680 Locking: Caller must ensure that the reporter (data) lock is held. 681*/ 682 virtual IOReturn getChannelIndices(uint64_t channel_id, 683 int *channel_index, 684 int *element_index); 685 686/*! @function IOReporter::copyElementValues 687 @abstract Copies the values of an internal element to *elementValues 688 689 @param element_index - Index of the element to return values from 690 @param elementValues - For returning the content of element values 691 @result Returns the content of an element 692 693 @discussion 694 For efficiently and thread-safely reading _elements. 695 May need to find the index of the element first. 696 697 Locking: Caller must ensure that the reporter (data) lock is held. 698*/ 699 virtual IOReturn copyElementValues(int element_index, 700 IOReportElementValues *elementValues); 701 702// private methods 703private: 704/*! @function IOReporter::copyChannelIDs 705 @abstract return an an OSArray of the reporter's 706 channel IDs 707 708 @param none 709 @result An OSArray of the repoter's channel ID's as OSNumbers 710 711 @discussion 712 This method is an internal helper function used to prepare a 713 legend entry. It encapsulates the channel IDs in OSNumbers and 714 aggregates them in an OSArray used when building the IOReportLegend 715 716 Locking: Caller must ensure that the reporter (data) lock is held. 717*/ 718 OSArray* copyChannelIDs(void); 719 720/*! @function IOReporter::legendWith 721 @abstract Internal method to help create legend entries 722 723 @param channelIDs - OSArray of OSNumber(uint64_t) channels IDs. 724 @param channelNames - parrallel OSArray of OSSymbol(rich names) 725 @param channelType - the type of all channels in this legend 726 @param unit - The unit for the quantity recorded by this reporter object 727 728 @result An IOReportLegendEntry object or NULL on failure 729 730 @discussion 731 This static method is the main legend creation function. It is called by 732 IOReporter sub-classes and is responsible for building an 733 IOReportLegendEntry corresponding to this reporter object. 734 This legend entry may be extended by the sub-class of IOReporter if 735 required. 736 737 Locking: SAFE to call concurrently (no static globals), MAY BLOCK 738*/ 739 static IOReportLegendEntry* legendWith(OSArray *channelIDs, 740 OSArray *channelNames, 741 IOReportChannelType channelType, 742 IOReportUnits unit); 743 744// protected instance variables (want to get rid of these) 745protected: 746 IOReportChannelType _channelType; 747 uint64_t _driver_id; // driver reporting data 748 749 // IOHistogramReporter accesses these; need to re-do its instantiation 750 IOReportElement *_elements; 751 int *_enableCounts; // refcount kIOReportEnable/Disable 752 uint16_t _channelDimension; // Max channel size 753 int _nElements; 754 int _nChannels; // Total Channels in this reporter 755 OSArray *_channelNames; 756 757 // MUST be protected because check is a macro! 758 bool _reporterIsLocked; 759 bool _reporterConfigIsLocked; 760 761 // Required for swapping inside addChannel 762 IOReportElement *_swapElements; 763 int *_swapEnableCounts; 764 765// private instance variables 766private: 767 IOReportUnits _unit; 768 769 int _enabled; // 'enabled' if _enabled > 0 770 771 IOLock *_configLock; 772 IOInterruptState _interruptState; 773 IOSimpleLock *_reporterLock; 774 775}; 776 777 778/************************************/ 779/***** 3. IOReporter Subclasses *****/ 780/************************************/ 781 782/*! 783 @class IOSimpleReporter 784 @abstract Report simple integers 785 @discussion 786 Each IOSimpleReporter can have an arbitrary number of channels, 787 each publishing a single integer value at any given time. 788*/ 789 790class IOSimpleReporter : public IOReporter 791{ 792 OSDeclareDefaultStructors(IOSimpleReporter); 793 794public: 795 796/*! @function IOSimpleReporter::with 797 @abstract create an initialized simple reporter 798 799 @param reportingService - IOService associated with all channels 800 @param categories - The category in which the report should be classified 801 @param unit - The unit for the quantity recorded by the reporter object 802 @result On success, an instance of IOSimpleReporter, else NULL 803 804 @discussion 805 Creates an instance of IOSimpleReporter object 806 807 Locking: SAFE to call concurrently (no static globals), MAY BLOCK. 808*/ 809 static IOSimpleReporter* with(IOService *reportingService, 810 IOReportCategories categories, 811 IOReportUnits unit); 812 813/*! @function IOSimpleReporter::setValue 814 @abstract Thread safely set a channel's value 815 816 @param channel_id - ID of the channel for which the value needs to be set 817 @param value - New channel value 818 @result Appropriate IOReturn code 819 820 @discussion 821 Updates the value of a channel to the provided value. 822 823 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 824*/ 825 IOReturn setValue(uint64_t channel_id, 826 int64_t value); 827 828/*! @function IOSimpleReporter::incrementValue 829 @abstract Thread safely increment a channel's value by a given amount 830 831 @param channel_id - ID of the channel for which the value needs to be incremented 832 @param increment - Amount to be added to the current channel value 833 @result Appropriate IOReturn code 834 @discussion 835 Increments the value of the channel ID by the provided amount. 836 837 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 838*/ 839 IOReturn incrementValue(uint64_t channel_id, 840 int64_t increment); 841 842/*! @function IOSimpleReporter::getValue 843 @abstract Thread safely access a channel value 844 845 @param channel_id - ID of the channel to get a value from 846 @result Returns the current value stored in the channel 847 @discussion 848 Accessor method to a channel's current stored value 849 850 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 851*/ 852 int64_t getValue(uint64_t channel_id); 853 854protected: 855 856/*! @function IOSimpleReporter::initWith 857 @abstract instance method implementation called by IOSimpleReporter::with 858 859 @discussion 860 See description of parameters above 861 862 Locking: same-instance concurrency UNSAFE 863*/ 864 virtual bool initWith(IOService *reportingService, 865 IOReportCategories categories, 866 IOReportUnits unit); 867 868private: 869 870}; 871 872 873 874/*! 875 @class IOStateReporter 876 @abstract Report state machine data 877 @discussion 878 Each IOStateReporter can report information for an arbitrary number 879 of similar state machines. All must have the same number of states. 880*/ 881class IOStateReporter : public IOReporter 882{ 883 OSDeclareDefaultStructors(IOStateReporter); 884 885public: 886 887/*! @function IOStateReporter::with 888 @abstract State reporter static creation method 889 890 @param reportingService - The I/O Kit service for this reporter's channels 891 @param categories - The categories for this reporter's channels 892 @param nstates - Maximum number of states for this reporter's channels 893 @param unit - optional parameter if using override/increment...() 894 @result on success, an IOStateReporter instance, else NULL 895 896 @discussion 897 Creates an instance of IOStateReporter. The default time scale 898 is the current system's notion of mach_absolute_time(). Using a 899 non-default time scale requires the use of 900 override/incrementChannelState() instead of setState(). 901 setState() always updates using mach_absolute_time(). 902 903 Locking: SAFE to call concurrently (no static globals), MAY BLOCK 904*/ 905 static IOStateReporter* with(IOService *reportingService, 906 IOReportCategories categories, 907 int nstates, 908 IOReportUnits unit = kIOReportUnitHWTicks); 909 910/*! @function IOStateReporter::setStateID 911 @abstract Assign a non-default ID to a state 912 913 @param channel_id - ID of channel containing the state in question 914 @param state_index - index of state to give an ID: [0..(nstates-1)] 915 @param state_id - 64-bit state ID, for ASCII, use IOREPORT_MAKEID 916 917 @result Appropriate IOReturn code 918 919 @discussion 920 By default, IOStateReporter identifies its channel states by 921 numbering them from 0 to <nstates - 1>. If setStateID is not 922 called to customize the state IDs, the numbered states will be 923 kept throughout the life of the object and it is safe to reference 924 those states by their indices. Otherwise, after setStateID() has 925 been called, the ordering of states is no longer guaranteed and 926 the client must reference states by their assigned state ID. 927 928 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 929*/ 930 IOReturn setStateID(uint64_t channel_id, 931 int state_index, 932 uint64_t state_id); 933 934/*! @function IOStateReporter::setChannelState 935 @abstract Updates the current state of a channel to a new state 936 937 @param channel_id - ID of the channel which is updated to a new state 938 @param new_state_id - ID of the target state for this channel 939 @param last_intransition - deprecated: time of most recent entry 940 @param prev_state_residency - deprecated: time spent in previous state 941 @result Appropriate IOReturn code 942 943 @discussion 944 setChannelState() updates the amount of time spent in the previous 945 state (if any) and increments the number of transitions into the 946 new state. It also sets the target state's last transition time to 947 the current time and enables internal time-keeping for the channel. 948 In this mode, calls like getStateResidencyTime() and updateReport() 949 automatically update a channel's time in state. 950 951 new_state_id identifies the target state as initialized 952 (0..<nstates-1>) or as configured by setStateID(). 953 954 Drivers wishing to compute and report their own time in state 955 should use incrementChannelState() or overrideChannelState(). It 956 is not currently possible for a driver to synchronize with the 957 automatic time-keeping enabled by setChannelState(). The 958 4-argument version of setChannelState() is thus impossible to 959 use correctly. In the future, there may be a setChannelState() 960 which accepts a last_intransition parameter and uses it to 961 automatically calculate time in state (ERs -> IOReporting / X). 962 963 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 964*/ 965 IOReturn setChannelState(uint64_t channel_id, 966 uint64_t new_state_id); 967 968 IOReturn setChannelState(uint64_t channel_id, 969 uint64_t new_state_id, 970 uint64_t last_intransition, 971 uint64_t prev_state_residency) __deprecated; 972 973/*! @function IOStateReporter::setState 974 @abstract Updates state for single channel reporters 975 976 @param new_state_id - New state for the channel 977 @param last_intransition - deprecated: time of most recent entry 978 @param prev_state_residency - deprecated: spent in previous state 979 @result Appropriate IOReturn code. 980 981 @discussion 982 setState() is a convenience method for single-channel state 983 reporter instances. An error will be returned if the reporter 984 in question has more than one channel. 985 986 See further discussion at setChannelState(). 987 988 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 989*/ 990 IOReturn setState(uint64_t new_state_id); 991 992 IOReturn setState(uint64_t new_state_id, 993 uint64_t last_intransition, 994 uint64_t prev_state_residency) __deprecated; 995 996/*! @function IOStateReporter::overrideChannelState 997 @abstract Overrides state data for a channel with passed arguments 998 999 @param channel_id - ID of the channel which state is to be updated 1000 @param state_id - state id for the channel 1001 @param time_in_state - time used as new total time in state 1002 @param intransitions - total number of transitions into state 1003 @param last_intransition - mach_absolute_time of most recent entry (opt) 1004 @result Appropriate IOReturn code 1005 1006 @discussion 1007 overrideChannelState() sets a particular state's time in state 1008 and transition count to the values provided. The optional 1009 last_intransition records the last time the channel transitioned 1010 into the given state. Passing 0 for time_in_state and 1011 intransitions will force the current values to 0. Passing 0 1012 for last_intransition for all states will disable the notion 1013 of a channel's "current state." 1014 1015 The most recent last_intransition (amongst all states in a channel) 1016 logically determines the current state. If last_intransition is 1017 not provided for any state, the channel will not report a current 1018 For consistent results, it is important to either never specify 1019 last_intransition or to always specify it. 1020 1021 There is currently a bug in determining current state (13423273). 1022 The IOReportMacros.h macros only update the state's metadata 1023 timestamp and libIOReport only looks at the metadata timestamps 1024 to determine the current state. Until that bug is fixed, whichever 1025 state is updated most recently will be considered the "current" 1026 state by libIOReport. 1027 1028 ::setState()'s automatic "time in state" updates are not supported 1029 when using overrideChannelState(). Clients must not use 1030 overrideChannelState() on any channel that has ::setState() called 1031 on it. Unlike with ::setState(), clients using 1032 overrideChannelState() are responsible for ensuring that data is 1033 up to date for updateReport() calls. The correct way to do this 1034 is for a driver's ::updateReport() method to push the most up to 1035 date values into the reporters before calling 1036 super::updateReport(). 1037 1038 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 1039*/ 1040 IOReturn overrideChannelState(uint64_t channel_id, 1041 uint64_t state_id, 1042 uint64_t time_in_state, 1043 uint64_t intransitions, 1044 uint64_t last_intransition = 0); 1045 1046/*! @function IOStateReporter::incrementChannelState 1047 @abstract Updates state data for a channel with passed arguments 1048 1049 @param channel_id - ID of the channel which state is to be updated 1050 @param state_id - state id for the channel 1051 @param time_in_state - time to be accumulated for time in state 1052 @param intransitions - number of transitions into state to be added 1053 @param last_intransition - mach_absolute_time of most recent entry (opt) 1054 @result Appropriate IOReturn code 1055 1056 @discussion 1057 incrementChannelState() adds time_in_state and intransitions 1058 to the current values stored for a particular state. If provided, 1059 last_intransition overwrites the time the state was most recently 1060 entered. Passing 0 for time_in_state and intransitions will have 1061 no effect. Passing 0 for last_intransition for all states will 1062 disable the notion of a channel's "current state." 1063 1064 The most recent last_intransition (amongst all states in a channel) 1065 logically determines the current state. If last_intransition is 1066 not provided for any state, the channel will not report a current 1067 For consistent results, it is important to either never specify 1068 last_intransition or to always specify it. 1069 1070 There is currently a bug in determining current state (13423273). 1071 The IOReportMacros.h macros only update the state's metadata 1072 timestamp and libIOReport only looks at the metadata timestamps 1073 to determine the current state. Until that bug is fixed, whichever 1074 state is updated most recently will be considered the "current" 1075 state by libIOReport. 1076 1077 ::setState()'s automatic "time in state" updates are not supported 1078 when using incrementChannelState(). Clients must not use 1079 incrementChannelState() on any channel that has ::setState() 1080 called on it. Unlike with ::setState(), clients using 1081 incrementChannelState() are responsible for ensuring that data 1082 is up to date for updateReport() calls. The correct way to do 1083 this is for a driver's ::updateReport() method to push the most 1084 up to date values into the reporters before calling 1085 super::updateReport(). 1086 1087 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 1088*/ 1089 IOReturn incrementChannelState(uint64_t channel_id, 1090 uint64_t state_id, 1091 uint64_t time_in_state, 1092 uint64_t intransitions, 1093 uint64_t last_intransition = 0); 1094 1095/*! @function IOStateReporter::setStateByIndices 1096 @abstract update a channel state without validating channel_id 1097 1098 @param channel_index - 0..<nChannels>, available from getChannelIndex() 1099 @param new_state - New state (by index) for the channel 1100 @param last_intransition - deprecated: time of most recent entry 1101 @param prev_state_residency - deprecated: time spent in previous state 1102 @result Appropriate IOReturn code 1103 1104 @discussion 1105 Similar to setState(), setStateByIndices() sets a channel's state 1106 without searching for the channel or state IDs. It will perform 1107 bounds checking, but relies on the caller to properly indicate 1108 the indices of the channel and state. Clients can rely on channels 1109 being added to IOStateReporter in order: the first channel will 1110 have index 0, the second index 1, etc. Like ::setState(), 1111 "time in state" calculations are handled automatically. 1112 1113 setStateByIndices() is faster than than setChannelState(), but 1114 it should only be used where the latter's performance overhead 1115 might be a problem. For example, many channels in a single 1116 reporter and high-frequency state changes. 1117 1118 Drivers wishing to compute and report their own time in state 1119 should use incrementChannelState() or overrideChannelState(). It 1120 is not currently possible for a driver to synchronize with the 1121 automatic time-keeping enabled by setStateByIndices(). The 1122 4-argument version of setChannelState() is thus impossible to 1123 use correctly. In the future, there may be a setChannelState() 1124 which accepts a last_intransition parameter and uses it to 1125 automatically calculate time in state (ERs -> IOReporting / X). 1126 1127 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 1128*/ 1129 IOReturn setStateByIndices(int channel_index, 1130 int new_state_index); 1131 1132 IOReturn setStateByIndices(int channel_index, 1133 int new_state_index, 1134 uint64_t last_intransition, 1135 uint64_t prev_state_residency) __deprecated; 1136 1137/*! @function IOStateReporter::getStateInTransitions 1138 @abstract Accessor method for count of transitions into state 1139 1140 @param channel_id - ID of the channel 1141 @param channel_state - State of the channel 1142 @result Count of transitions into the requested state. 1143 1144 @discussion 1145 Some clients may need to consume internally the data aggregated by the 1146 reporter object. This method allows a client to retrieve the count of 1147 transitions into the requested state for the channel_id. 1148 1149 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 1150*/ 1151 uint64_t getStateInTransitions(uint64_t channel_id, 1152 uint64_t state_id); 1153 1154/*! @function IOStateReporter::getStateResidencyTime 1155 @abstract Accessor method for time spent in a given state 1156 1157 @param channel_id - ID of the channel 1158 @param channel_state - State of the channel 1159 @result Absolute time spent in specified state 1160 1161 @discussion 1162 Some clients may need to consume internally the data aggregated 1163 by the by the reporter object. This method allows a client to 1164 retrieve the absolute time a particular channel recorded as spent 1165 in a specified state. 1166 1167 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 1168*/ 1169 uint64_t getStateResidencyTime(uint64_t channel_id, 1170 uint64_t state_id); 1171 1172/*! @function IOStateReporter::getStateLastTransitionTime 1173 @abstract Accessor method for last time a transition occured 1174 1175 @param channel_id - ID of the channel 1176 @param channel_state - State of the channel 1177 @result Absolute time for when the last transition occured 1178 1179 @discussion 1180 Some clients may need to consume internally the data aggregated 1181 by the by the reporter object. This method allows a client to 1182 retrieve the absolute time stamp for when the last transition into 1183 a specific state was recorded. 1184 1185 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 1186*/ 1187 uint64_t getStateLastTransitionTime(uint64_t channel_id, uint64_t state_id); 1188 1189/*! @function [DEPRECATED] IOStateReporter::getStateLastChannelUpdateTime 1190 @abstract Deprecated accessor for last time a channel was auto-updated 1191 1192 @param channel_id - ID of the channel 1193 @result Absolute time for last time the channel was updated 1194 1195 @discussion 1196 If a channel has had ::setState() called on it, calls such as 1197 getStateResidencyTime() or updateReport() will update time in the 1198 current state and update an internal "last channel update time." 1199 Because clients have no way to interlock with those methods, there 1200 is no sensible way to use this method and it will be removed in 1201 a future release. 1202 1203 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 1204*/ 1205 uint64_t getStateLastChannelUpdateTime(uint64_t channel_id) __deprecated; 1206 1207/*! @function IOStateReporter::free 1208 @abstract Releases the object and all its resources. 1209 1210 @discussion 1211 ::free() assumes that init() has completed. Clients should use 1212 the static ::with() methods to obtain fully-initialized reporter 1213 instances. 1214 1215 Locking: same-instance concurrency UNSAFE 1216*/ 1217 virtual void free(void); 1218 1219protected: 1220 1221/*! @function IOStateReporter::initWith 1222 @abstract Instance method implementation called by ::with 1223 1224 @discussion 1225 See description of parameters above 1226*/ 1227 virtual bool initWith(IOService *reportingService, 1228 IOReportCategories categories, 1229 int16_t nstates, IOReportUnits unit); 1230 1231 1232/*! @function IOStateReporter::handleSwapPrepare 1233 @abstract _swap* = <IOStateReporter-specific per-channel buffers> 1234 1235 @function IOStateReporter::handleAddChannelSwap 1236 @abstract swap in IOStateReporter's variables 1237 1238 @function IOStateReporter::handleSwapCleanup 1239 @abstract clean up unused buffers in _swap* 1240 1241 [see IOReporter::handle*Swap* for more info] 1242*/ 1243 virtual IOReturn handleSwapPrepare(int newNChannels); 1244 virtual IOReturn handleAddChannelSwap(uint64_t channel_id, 1245 const OSSymbol *symChannelName); 1246 virtual void handleSwapCleanup(int swapNChannels); 1247 1248/*! @function IOStateReporter::updateChannelValues 1249 @abstract Update accounting of time spent in current state 1250 1251 @param channel_index - internal index of the channel 1252 @result appropriate IOReturn code 1253 1254 @discussion 1255 Internal State reporter method to account for the time spent in 1256 the current state when updateReport() is called on the reporter's 1257 channels. 1258 1259 Locking: Caller must ensure that the reporter (data) lock is held. 1260*/ 1261 virtual IOReturn updateChannelValues(int channel_index); 1262 1263/*! @function IOStateReporter::setStateByIndices 1264 @abstract update a channel state without validating channel_id 1265 1266 @param channel_index - 0..<nChannels>, available from getChannelIndex() 1267 @param new_state - New state for the channel 1268 @param last_intransition - to remove: time of most recent entry 1269 @param prev_state_residency - to remove: time spent in previous state 1270 @result Appropriate IOReturn code 1271 1272 @discussion 1273 Locked version of IOReporter::setStateByIndices(). This method may be 1274 overriden by sub-classes. 1275 1276 Locking: Caller must ensure that the reporter (data) lock is held. 1277*/ 1278 virtual IOReturn handleSetStateByIndices(int channel_index, 1279 int new_state_index, 1280 uint64_t last_intransition, 1281 uint64_t prev_state_residency); 1282 1283/*! @function IOStateReporter::setStateID 1284 @abstract Assign a non-default ID to a state 1285 1286 @param channel_id - ID of channel containing the state in question 1287 @param state_index - index of state to give an ID: [0..(nstates-1)] 1288 @param state_id - 64-bit state ID, for ASCII, use IOREPORT_MAKEID 1289 1290 @result Appropriate IOReturn code 1291 1292 @discussion 1293 Locked version of IOReporter::setStateID(). This method may be 1294 overriden by sub-classes 1295 1296 Locking: Caller must ensure that the reporter (data) lock is held. 1297*/ 1298 virtual IOReturn handleSetStateID(uint64_t channel_id, 1299 int state_index, 1300 uint64_t state_id); 1301 1302/*! @function IOStateReporter::handleOverrideChannelStateByIndices 1303 @abstract Overrides state data for a channel with passed arguments 1304 1305 @param channel_index - index of the channel which state is to be updated 1306 @param state_index - index of the state id for the channel 1307 @param time_in_state - time used as new total time in state 1308 @param intransitions - total number of transitions into state 1309 @param last_intransition - mach_absolute_time of most recent entry (opt) 1310 @result Appropriate IOReturn code 1311 1312 @discussion 1313 Locked version of IOReporter::overrideChannelState(). This method 1314 may be overriden by sub-classes. 1315 1316 Locking: Caller must ensure that the reporter (data) lock is held. 1317*/ 1318 virtual IOReturn handleOverrideChannelStateByIndices(int channel_index, 1319 int state_index, 1320 uint64_t time_in_state, 1321 uint64_t intransitions, 1322 uint64_t last_intransition = 0); 1323 1324/*! @function IOStateReporter::handleIncrementChannelStateByIndices 1325 @abstract Updates state data for a channel with passed arguments 1326 1327 @param channel_index - index of the channel which state is to be updated 1328 @param state_index - index of the state id for the channel 1329 @param time_in_state - time used as new total time in state 1330 @param intransitions - total number of transitions into state 1331 @param last_intransition - mach_absolute_time of most recent entry (opt) 1332 @result Appropriate IOReturn code 1333 1334 @discussion 1335 Locked version of IOReporter::incrementChannelState(). This method 1336 may be overriden by sub-classes. 1337 1338 Locking: Caller must ensure that the reporter (data) lock is held. 1339*/ 1340 virtual IOReturn handleIncrementChannelStateByIndices(int channel_index, 1341 int state_index, 1342 uint64_t time_in_state, 1343 uint64_t intransitions, 1344 uint64_t last_intransition = 0); 1345private: 1346 1347 int *_currentStates; // current states (per chonnel) 1348 uint64_t *_lastUpdateTimes; // most recent auto-update 1349 1350 // Required for swapping inside addChannel 1351 int *_swapCurrentStates; 1352 uint64_t *_swapLastUpdateTimes; 1353 1354enum valueSelector { 1355 kInTransitions, 1356 kResidencyTime, 1357 kLastTransitionTime 1358}; 1359 uint64_t _getStateValue(uint64_t channel_id, 1360 uint64_t state_id, 1361 enum valueSelector value); 1362 1363 IOReturn _getStateIndices(uint64_t channel_id, 1364 uint64_t state_id, 1365 int *channel_index, 1366 int *state_index); 1367 1368}; 1369 1370 1371/*! 1372 @class IOHistogramReporter 1373 @abstract Report histograms of values 1374 @discussion 1375 Each IOHistogramReporter can report one histogram representing 1376 how a given value has changed over time. 1377*/ 1378class IOHistogramReporter : public IOReporter 1379{ 1380 OSDeclareDefaultStructors(IOHistogramReporter); 1381 1382public: 1383/*! @function IOHistogramReporter::with 1384 @abstract Initializes the IOHistogramReporter instance variables and data structures 1385 1386 @param reportingService - IOService instanciator and data provider into the reporter object 1387 @param categories - The categories in which the report should be classified 1388 @param channelID - uint64_t channel identifier 1389 @param channelName - rich channel name as char* 1390 @param unit - The unit for the quantity recorded by the reporter object 1391 @param nSegments - Number of segments to be extracted from the config data structure 1392 @param config - Histograms require the caller to pass a configuration by segments 1393 @result an instance of the IOSimpleReporter object or NULL on error 1394 1395 @discussion 1396 Creates an instance of histogram reporter object. 1397 1398FIXME: need more explanation of the config 1399 1400 IOHistogramReporter currently only supports a single channel. 1401 1402 1403 */ 1404 static IOHistogramReporter* with(IOService *reportingService, 1405 IOReportCategories categories, 1406 uint64_t channelID, 1407 const char *channelName, 1408 IOReportUnits unit, 1409 int nSegments, 1410 IOHistogramSegmentConfig *config); 1411 1412/*! @function IOHistogramReporter::addChannel 1413 @abstract Override IOReporter::addChannel(*) to return an error 1414 1415 @result kIOReturnUnsupported - doesn't support adding channels 1416*/ 1417 IOReturn addChannel(uint64_t channelID, const char *channelName = NULL) { 1418 return kIOReturnUnsupported; 1419 } 1420 1421/*! @function IOHistogramReporter::tallyValue 1422 @abstract Add a new value to the histogram 1423 1424 @param value - new value to add to the histogram 1425 @result the index of the affected bucket, or -1 on error 1426 1427 @discussion 1428 The histogram reporter determines in which bucket the value 1429 falls and increments it. The lowest and highest buckets 1430 extend to negative and positive infinity, respectively. 1431 1432 Locking: same-instance concurrency SAFE, WILL NOT BLOCK 1433*/ 1434 int tallyValue(int64_t value); 1435 1436/*! @function IOHistogramReporter::free 1437 @abstract Releases the object and all its resources. 1438 1439 @discussion 1440 ::free() assumes that init() has completed. Clients should use 1441 the static ::with() methods to obtain fully-initialized reporter 1442 instances. 1443 1444 Locking: same-instance concurrency UNSAFE 1445*/ 1446 virtual void free(void); 1447 1448protected: 1449 1450/*! @function IOHistogramReporter::initWith 1451 @abstract instance method implementation called by ::with 1452 1453 @discussion 1454 See description of parameters above 1455*/ 1456 virtual bool initWith(IOService *reportingService, 1457 IOReportCategories categories, 1458 uint64_t channelID, 1459 const OSSymbol *channelName, 1460 IOReportUnits unit, 1461 int nSegments, 1462 IOHistogramSegmentConfig *config); 1463 1464/*! @function IOHistogramReporter::handleCreateLegend 1465 @abstract Builds an IOReporting legend entry representing the channels of this reporter. 1466 1467 @result An IOReportLegendEntry or NULL on failure 1468 1469 @discussion 1470 The returned legend entry may be appended to kIOReportLegendKey 1471 to be published by the caller in the IORegistry. See the 1472 IOReportLegend class for more details. 1473 1474 Locking: same-instance concurrency SAFE, MAY BLOCK 1475*/ 1476 IOReportLegendEntry* handleCreateLegend(void); 1477 1478 1479private: 1480 1481 int _segmentCount; 1482 int64_t *_bucketBounds; 1483 int _bucketCount; 1484 IOHistogramSegmentConfig *_histogramSegmentsConfig; 1485}; 1486 1487 1488/***********************************/ 1489/***** 4. IOReportLegend Class *****/ 1490/***********************************/ 1491 1492/*! 1493 @class IOReportLegend 1494 @abstract combine legend entries into a complete legend 1495 @discussion 1496 IOReportLegend adds metadata to legend entries and combines them 1497 into a single OSArray that can be published under the 1498 kIOReportLegendKey property in the I/O Kit registry. 1499*/ 1500class IOReportLegend : public OSObject 1501{ 1502 OSDeclareDefaultStructors(IOReportLegend); 1503 1504public: 1505/*! @function IOReportLegend::with 1506 @abstract Create an instance of IOReportLegend 1507 1508 @param legend - OSArray of the legend possibly already present in registry 1509 @result an instance of IOReportLegend, or NULL on failure 1510 1511 @discussion 1512 An IOReporting legend (an OSArray of legend entries) may be already 1513 present in the IORegistry. Thus the recommended way to publish 1514 new entries is to append to any existing array as follows: 1515 1. call getProperty(kIOReportLegendKey) to get an existing legend. 1516 1517 2a. If it exists 1518 - OSDynamicCast to OSArray 1519 - and pass it to ::with() 1520 IOReportLegend *legendMaker = IOReportLegend::with(legend); 1521 The provided array is retained by IOReportLegend. 1522 1523 2b. If no legend already exists in the registry, pass NULL 1524 IOReportLegend *legend = IOReportLegend::with(NULL); 1525 This latter invocation will cause IOReportLegend to create a new 1526 array internally (also holding one reference). 1527 1528 At the cost of some registry churn, the static 1529 IOReportLegend::addReporterLegend() will handle the above, removing 1530 the need for any direct use of the IOReportLegend class. 1531*/ 1532 static IOReportLegend* with(OSArray *legend); 1533 1534/*! @function IOReportLegend::addLegendEntry 1535 @abstract Add a new legend entry 1536 1537 @param legendEntry - entry to be added to the internal legend array 1538 @param groupName - primary group name for this entry 1539 @param subGroupName - secondary group name for this entry 1540 @result appropriate IOReturn code 1541 1542 @discussion 1543 The entry will be retained as an element of the internal array. 1544 Legend entries are available from reporter objects. Entries 1545 represent some number of channels with similar properties (such 1546 as group and sub-group). Multiple legend entries with the same 1547 group names will be aggregated in user space. 1548 1549 Drivers that instantiate their reporter objects in response to 1550 IOService::configureReport(kIOReportDisable) will need to create 1551 temporary reporter objects for the purpose of creating their 1552 legend entries. User-space legends are tracked by 12836893. 1553*/ 1554 IOReturn addLegendEntry(IOReportLegendEntry *legendEntry, 1555 const char *groupName, 1556 const char *subGroupName); 1557 1558/*! @function IOReportLegend::addReporterLegend 1559 @abstract Add a legend entry from a reporter object 1560 1561 @param reportingService - IOService data provider into the reporter object 1562 @param reporter - IOReporter to use to extract and append the legend 1563 @param groupName - primary group name for this entry 1564 @param subGroupName - secondary group name for this entry 1565 @result appropriate IOReturn code 1566 1567 @discussion 1568 An IOReportLegendEntry will be created internally to this method from 1569 the IOReporter object passed in argument. The entry will be released 1570 internally after being appended to the IOReportLegend object. 1571 Legend entries are available from reporter objects. Entries 1572 represent some number of channels with similar properties (such 1573 as group and sub-group). Multiple legend entries with the same 1574 group names will be aggregated in user space. 1575 1576 Drivers that instantiate their reporter objects in response to 1577 IOService::configureReport(kIOReportDisable) will need to create 1578 temporary reporter objects for the purpose of creating their 1579 legend entries. User-space legends are tracked by 12836893. 1580 1581 The static version of addReporterLegend adds the reporter's 1582 legend directly to reportingService's kIOReportLegendKey. This 1583 will result in serialized getProperty() and setProperty() calls 1584 on reportingService and should be avoided when many reporters 1585 objects are in use. 1586*/ 1587 IOReturn addReporterLegend(IOReporter *reporter, 1588 const char *groupName, 1589 const char *subGroupName); 1590 1591 static IOReturn addReporterLegend(IOService *reportingService, 1592 IOReporter *reporter, 1593 const char *groupName, 1594 const char *subGroupName); 1595 1596/*! @function IOReportLegend::getLegend 1597 @abstract Accessor method to get the legend array 1598 1599 @result Returns the OSObject holding the legend to be published by the driver 1600 @discussion 1601 This array will include all legend entries added to the object. 1602*/ 1603 OSArray* getLegend(void); 1604 1605/*! @function IOReportLegend::free 1606 @abstract Frees the IOReportLegend object 1607 1608 @discussion 1609 ::free() cleans up the reporter and anything it allocated. 1610 1611 ::free() releases the internal array (which was either passed 1612 to ::with() or created as a result of ::with(NULL)). Assuming 1613 the caller extracted the array with getLegend() and published it 1614 in the I/O Kit registry, its ownership will now be with the 1615 registry. 1616*/ 1617 void free(void); 1618 1619 1620 1621protected: 1622 1623private: 1624 1625 OSArray *_reportLegend; 1626 1627 IOReturn initWith(OSArray *legend); 1628 1629/*! @function IOReportLegend::organizeLegend 1630 @abstract Sets up the legend entry, organizing it with group and sub-group names 1631 1632 @param groupName - Primary group name 1633 @param subGroupName - Secondary group name 1634 @result IOReturn code 1635 1636 @discussion 1637*/ 1638 IOReturn organizeLegend(IOReportLegendEntry *legendEntry, 1639 const OSSymbol *groupName, 1640 const OSSymbol *subGroupName); 1641 1642// FUTURE POSSIBILITY (NOT IMPLEMENTED!) 1643/*! @function IOReportLegend::createReporters 1644 @abstract Creates as many IOReporter objects as the legend contains 1645 1646 @param legend - OSArray legend object containing the description of all reporters 1647 the driver is able to address 1648 @param reporter - OSSet of reporter objects created by this call 1649 @result IOReturn code kIOReturnSuccess if successful 1650 1651 @discussion 1652 NOT SUPPORTED at the time of writing 1653 Convenience method to create all the driver's reporter objects from a legend. 1654 Can be used when a legend is made public through the IORegistry but IOReporter 1655 objects have not yet been created to save memory, waiting for observers. 1656 Upon a call to configureReport via the IOService method, a driver could 1657 create all reporter objects on the fly using this function. 1658*/ 1659 // For Future IOReporterManager... 1660 // static IOReturn createReporters(requestedChannels, legend); 1661}; 1662 1663#endif /* ! _IOKERNEL_REPORTERS_H_ */ 1664