1/*
2 * Copyright (c) 2012-2016 Apple 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 IOReportUnit 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) APPLE_KEXT_OVERRIDE;
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 channelList - 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 channel_id ID of channel being added
458 @param symChannelName 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 Locking: Caller must ensure that the reporter (data) lock is held.
629 The returned pointer is only valid until unlockReporter() is called.
630*/
631 virtual const IOReportElementValues* getElementValues(int element_index);
632
633/*! @function IOReporter::getFirstElementIndex
634 @abstract Returns the first element index for a channel
635
636 @param channel_id - ID of the channel
637 @param element_index - pointer to the returned element_index
638 @result appropriate IOReturn code
639
640 @discussion
641 For efficiently and thread-safely reading _elements
642
643 Locking: Caller must ensure that the reporter (data) lock is held.
644*/
645 virtual IOReturn getFirstElementIndex(uint64_t channel_id,
646 int *element_index);
647
648/*! @function IOReporter::getChannelIndex
649 @abstract Returns the index of a channel from internal data structures
650
651 @param channel_id - ID of the channel
652 @param channel_index - pointer to the returned element_index
653 @result appropriate IOReturn code
654
655 @discussion
656 For efficiently and thread-safely reading channels
657
658 Locking: Caller must ensure that the reporter (data) lock is held.
659*/
660 virtual IOReturn getChannelIndex(uint64_t channel_id,
661 int *channel_index);
662
663/*! @function IOReporter::getChannelIndices
664 @abstract Returns the index of a channel and its corresponding
665 first element index from internal data structure
666
667 @param channel_id - ID of the channel
668 @param channel_index - pointer to the returned channel_index
669 @param element_index - pointer to the returned element_index
670 @result appropriate IOReturn code
671
672 @discussion
673 For efficiently and thread-safely reading channel elements.
674 It is commonly useful to get access to both channel and element
675 indices togther. This convenience method allows sub-classes to
676 get both indices simultaneously.
677
678 Locking: Caller must ensure that the reporter (data) lock is held.
679*/
680 virtual IOReturn getChannelIndices(uint64_t channel_id,
681 int *channel_index,
682 int *element_index);
683
684/*! @function IOReporter::copyElementValues
685 @abstract Copies the values of an internal element to *elementValues
686
687 @param element_index - Index of the element to return values from
688 @param elementValues - For returning the content of element values
689 @result Returns the content of an element
690
691 @discussion
692 For efficiently and thread-safely reading _elements.
693 May need to find the index of the element first.
694
695 Locking: Caller must ensure that the reporter (data) lock is held.
696*/
697 virtual IOReturn copyElementValues(int element_index,
698 IOReportElementValues *elementValues);
699
700// private methods
701private:
702/*! @function IOReporter::copyChannelIDs
703 @abstract return an an OSArray of the reporter's
704 channel IDs
705
706 @result An OSArray of the repoter's channel ID's as OSNumbers
707
708 @discussion
709 This method is an internal helper function used to prepare a
710 legend entry. It encapsulates the channel IDs in OSNumbers and
711 aggregates them in an OSArray used when building the IOReportLegend
712
713 Locking: Caller must ensure that the reporter (data) lock is held.
714*/
715 OSArray* copyChannelIDs(void);
716
717/*! @function IOReporter::legendWith
718 @abstract Internal method to help create legend entries
719
720 @param channelIDs - OSArray of OSNumber(uint64_t) channels IDs.
721 @param channelNames - parrallel OSArray of OSSymbol(rich names)
722 @param channelType - the type of all channels in this legend
723 @param unit - The unit for the quantity recorded by this reporter object
724
725 @result An IOReportLegendEntry object or NULL on failure
726
727 @discussion
728 This static method is the main legend creation function. It is called by
729 IOReporter sub-classes and is responsible for building an
730 IOReportLegendEntry corresponding to this reporter object.
731 This legend entry may be extended by the sub-class of IOReporter if
732 required.
733
734 Locking: SAFE to call concurrently (no static globals), MAY BLOCK
735*/
736 static IOReportLegendEntry* legendWith(OSArray *channelIDs,
737 OSArray *channelNames,
738 IOReportChannelType channelType,
739 IOReportUnit unit);
740
741// protected instance variables (want to get rid of these)
742protected:
743 IOReportChannelType _channelType;
744 uint64_t _driver_id; // driver reporting data
745
746 // IOHistogramReporter accesses these; need to re-do its instantiation
747 IOReportElement *_elements;
748 int *_enableCounts; // refcount kIOReportEnable/Disable
749 uint16_t _channelDimension; // Max channel size
750 int _nElements;
751 int _nChannels; // Total Channels in this reporter
752 OSArray *_channelNames;
753
754 // MUST be protected because check is a macro!
755 bool _reporterIsLocked;
756 bool _reporterConfigIsLocked;
757
758 // Required for swapping inside addChannel
759 IOReportElement *_swapElements;
760 int *_swapEnableCounts;
761
762// private instance variables
763private:
764 IOReportUnit _unit;
765
766 int _enabled; // 'enabled' if _enabled > 0
767
768 IOLock *_configLock;
769 IOInterruptState _interruptState;
770 IOSimpleLock *_reporterLock;
771
772};
773
774
775/************************************/
776/***** 3. IOReporter Subclasses *****/
777/************************************/
778
779/*!
780 @class IOSimpleReporter
781 @abstract Report simple integers
782 @discussion
783 Each IOSimpleReporter can have an arbitrary number of channels,
784 each publishing a single integer value at any given time.
785*/
786
787class IOSimpleReporter : public IOReporter
788{
789 OSDeclareDefaultStructors(IOSimpleReporter);
790
791public:
792
793/*! @function IOSimpleReporter::with
794 @abstract create an initialized simple reporter
795
796 @param reportingService - IOService associated with all channels
797 @param categories - The category in which the report should be classified
798 @param unit - The unit for the quantity recorded by the reporter object
799 @result On success, an instance of IOSimpleReporter, else NULL
800
801 @discussion
802 Creates an instance of IOSimpleReporter object
803
804 Locking: SAFE to call concurrently (no static globals), MAY BLOCK.
805*/
806 static IOSimpleReporter* with(IOService *reportingService,
807 IOReportCategories categories,
808 IOReportUnit unit);
809
810/*! @function IOSimpleReporter::setValue
811 @abstract Thread safely set a channel's value
812
813 @param channel_id - ID of the channel for which the value needs to be set
814 @param value - New channel value
815 @result Appropriate IOReturn code
816
817 @discussion
818 Updates the value of a channel to the provided value.
819
820 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
821*/
822 IOReturn setValue(uint64_t channel_id,
823 int64_t value);
824
825/*! @function IOSimpleReporter::incrementValue
826 @abstract Thread safely increment a channel's value by a given amount
827
828 @param channel_id - ID of the channel for which the value needs to be incremented
829 @param increment - Amount to be added to the current channel value
830 @result Appropriate IOReturn code
831 @discussion
832 Increments the value of the channel ID by the provided amount.
833
834 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
835*/
836 IOReturn incrementValue(uint64_t channel_id,
837 int64_t increment);
838
839/*! @function IOSimpleReporter::getValue
840 @abstract Thread safely access a channel value
841
842 @param channel_id - ID of the channel to get a value from
843 @result Returns the current value stored in the channel
844 @discussion
845 Accessor method to a channel's current stored value
846
847 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
848*/
849 int64_t getValue(uint64_t channel_id);
850
851protected:
852
853/*! @function IOSimpleReporter::initWith
854 @abstract instance method implementation called by IOSimpleReporter::with
855
856 @discussion
857 See description of parameters above
858
859 Locking: same-instance concurrency UNSAFE
860*/
861 virtual bool initWith(IOService *reportingService,
862 IOReportCategories categories,
863 IOReportUnit unit);
864
865private:
866
867};
868
869
870
871/*!
872 @class IOStateReporter
873 @abstract Report state machine data
874 @discussion
875 Each IOStateReporter can report information for an arbitrary number
876 of similar state machines. All must have the same number of states.
877*/
878class IOStateReporter : public IOReporter
879{
880 OSDeclareDefaultStructors(IOStateReporter);
881
882public:
883
884/*! @function IOStateReporter::with
885 @abstract State reporter static creation method
886
887 @param reportingService - The I/O Kit service for this reporter's channels
888 @param categories - The categories for this reporter's channels
889 @param nstates - Maximum number of states for this reporter's channels
890 @param unit - optional parameter if using override/increment...()
891 @result on success, an IOStateReporter instance, else NULL
892
893 @discussion
894 Creates an instance of IOStateReporter. The default time scale
895 is the current system's notion of mach_absolute_time(). Using a
896 non-default time scale requires the use of
897 override/incrementChannelState() instead of setState().
898 setState() always updates using mach_absolute_time().
899
900 Locking: SAFE to call concurrently (no static globals), MAY BLOCK
901*/
902 static IOStateReporter* with(IOService *reportingService,
903 IOReportCategories categories,
904 int nstates,
905 IOReportUnit unit = kIOReportUnitHWTicks);
906
907/*! @function IOStateReporter::setStateID
908 @abstract Assign a non-default ID to a state
909
910 @param channel_id - ID of channel containing the state in question
911 @param state_index - index of state to give an ID: [0..(nstates-1)]
912 @param state_id - 64-bit state ID, for ASCII, use IOREPORT_MAKEID
913
914 @result Appropriate IOReturn code
915
916 @discussion
917 By default, IOStateReporter identifies its channel states by
918 numbering them from 0 to <nstates - 1>. If setStateID is not
919 called to customize the state IDs, the numbered states will be
920 kept throughout the life of the object and it is safe to reference
921 those states by their indices. Otherwise, after setStateID() has
922 been called, the ordering of states is no longer guaranteed and
923 the client must reference states by their assigned state ID.
924
925 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
926*/
927 IOReturn setStateID(uint64_t channel_id,
928 int state_index,
929 uint64_t state_id);
930
931/*! @function IOStateReporter::setChannelState
932 @abstract Updates the current state of a channel to a new state
933
934 @param channel_id - ID of the channel which is updated to a new state
935 @param new_state_id - ID of the target state for this channel
936 @param last_intransition - deprecated: time of most recent entry
937 @param prev_state_residency - deprecated: time spent in previous state
938 @result Appropriate IOReturn code
939
940 @discussion
941 setChannelState() updates the amount of time spent in the previous
942 state (if any) and increments the number of transitions into the
943 new state. It also sets the target state's last transition time to
944 the current time and enables internal time-keeping for the channel.
945 In this mode, calls like getStateResidencyTime() and updateReport()
946 automatically update a channel's time in state.
947
948 new_state_id identifies the target state as initialized
949 (0..<nstates-1>) or as configured by setStateID().
950
951 Drivers wishing to compute and report their own time in state
952 should use incrementChannelState() or overrideChannelState(). It
953 is not currently possible for a driver to synchronize with the
954 automatic time-keeping enabled by setChannelState(). The
955 4-argument version of setChannelState() is thus impossible to
956 use correctly. In the future, there may be a setChannelState()
957 which accepts a last_intransition parameter and uses it to
958 automatically calculate time in state (ERs -> IOReporting / X).
959
960 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
961*/
962 IOReturn setChannelState(uint64_t channel_id,
963 uint64_t new_state_id,
964 uint64_t last_intransition,
965 uint64_t prev_state_residency) __deprecated;
966
967/*! @function IOStateReporter::setChannelState
968 @abstract Updates the current state of a channel to a new state
969
970 @param channel_id - ID of the channel which is updated to a new state
971 @param new_state_id - ID of the target state for this channel
972 @result Appropriate IOReturn code
973
974 @discussion
975 setChannelState() updates the amount of time spent in the previous
976 state (if any) and increments the number of transitions into the
977 new state. It also sets the target state's last transition time to
978 the current time and enables internal time-keeping for the channel.
979 In this mode, calls like getStateResidencyTime() and updateReport()
980 automatically update a channel's time in state.
981
982 new_state_id identifies the target state as initialized
983 (0..<nstates-1>) or as configured by setStateID().
984
985 Drivers wishing to compute and report their own time in state
986 should use incrementChannelState() or overrideChannelState(). It
987 is not currently possible for a driver to synchronize with the
988 automatic time-keeping enabled by setChannelState(). The
989 4-argument version of setChannelState() is thus impossible to
990 use correctly. In the future, there may be a setChannelState()
991 which accepts a last_intransition parameter and uses it to
992 automatically calculate time in state (ERs -> IOReporting / X).
993
994 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
995*/
996 IOReturn setChannelState(uint64_t channel_id,
997 uint64_t new_state_id);
998
999
1000/*! @function IOStateReporter::setState
1001 @abstract Updates state for single channel reporters
1002
1003 @param new_state_id - New state for the channel
1004 @result Appropriate IOReturn code.
1005
1006 @discussion
1007 setState() is a convenience method for single-channel state
1008 reporter instances. An error will be returned if the reporter
1009 in question has more than one channel.
1010
1011 See further discussion at setChannelState().
1012
1013 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1014*/
1015 IOReturn setState(uint64_t new_state_id);
1016
1017/*! @function IOStateReporter::setState
1018 @abstract Updates state for single channel reporters
1019
1020 @param new_state_id - New state for the channel
1021 @param last_intransition - deprecated: time of most recent entry
1022 @param prev_state_residency - deprecated: spent in previous state
1023 @result Appropriate IOReturn code.
1024
1025 @discussion
1026 setState() is a convenience method for single-channel state
1027 reporter instances. An error will be returned if the reporter
1028 in question has more than one channel.
1029
1030 See further discussion at setChannelState().
1031
1032 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1033*/
1034 IOReturn setState(uint64_t new_state_id,
1035 uint64_t last_intransition,
1036 uint64_t prev_state_residency) __deprecated;
1037
1038/*! @function IOStateReporter::overrideChannelState
1039 @abstract Overrides state data for a channel with passed arguments
1040
1041 @param channel_id - ID of the channel which state is to be updated
1042 @param state_id - state id for the channel
1043 @param time_in_state - time used as new total time in state
1044 @param intransitions - total number of transitions into state
1045 @param last_intransition - mach_absolute_time of most recent entry (opt)
1046 @result Appropriate IOReturn code
1047
1048 @discussion
1049 overrideChannelState() sets a particular state's time in state
1050 and transition count to the values provided. The optional
1051 last_intransition records the last time the channel transitioned
1052 into the given state. Passing 0 for time_in_state and
1053 intransitions will force the current values to 0. Passing 0
1054 for last_intransition for all states will disable the notion
1055 of a channel's "current state."
1056
1057 The most recent last_intransition (amongst all states in a channel)
1058 logically determines the current state. If last_intransition is
1059 not provided for any state, the channel will not report a current
1060 For consistent results, it is important to either never specify
1061 last_intransition or to always specify it.
1062
1063 There is currently a bug in determining current state (13423273).
1064 The IOReportMacros.h macros only update the state's metadata
1065 timestamp and libIOReport only looks at the metadata timestamps
1066 to determine the current state. Until that bug is fixed, whichever
1067 state is updated most recently will be considered the "current"
1068 state by libIOReport.
1069
1070 ::setState()'s automatic "time in state" updates are not supported
1071 when using overrideChannelState(). Clients must not use
1072 overrideChannelState() on any channel that has ::setState() called
1073 on it. Unlike with ::setState(), clients using
1074 overrideChannelState() are responsible for ensuring that data is
1075 up to date for updateReport() calls. The correct way to do this
1076 is for a driver's ::updateReport() method to push the most up to
1077 date values into the reporters before calling
1078 super::updateReport().
1079
1080 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1081*/
1082 IOReturn overrideChannelState(uint64_t channel_id,
1083 uint64_t state_id,
1084 uint64_t time_in_state,
1085 uint64_t intransitions,
1086 uint64_t last_intransition = 0);
1087
1088/*! @function IOStateReporter::incrementChannelState
1089 @abstract Updates state data for a channel with passed arguments
1090
1091 @param channel_id - ID of the channel which state is to be updated
1092 @param state_id - state id for the channel
1093 @param time_in_state - time to be accumulated for time in state
1094 @param intransitions - number of transitions into state to be added
1095 @param last_intransition - mach_absolute_time of most recent entry (opt)
1096 @result Appropriate IOReturn code
1097
1098 @discussion
1099 incrementChannelState() adds time_in_state and intransitions
1100 to the current values stored for a particular state. If provided,
1101 last_intransition overwrites the time the state was most recently
1102 entered. Passing 0 for time_in_state and intransitions will have
1103 no effect. Passing 0 for last_intransition for all states will
1104 disable the notion of a channel's "current state."
1105
1106 The most recent last_intransition (amongst all states in a channel)
1107 logically determines the current state. If last_intransition is
1108 not provided for any state, the channel will not report a current
1109 For consistent results, it is important to either never specify
1110 last_intransition or to always specify it.
1111
1112 There is currently a bug in determining current state (13423273).
1113 The IOReportMacros.h macros only update the state's metadata
1114 timestamp and libIOReport only looks at the metadata timestamps
1115 to determine the current state. Until that bug is fixed, whichever
1116 state is updated most recently will be considered the "current"
1117 state by libIOReport.
1118
1119 ::setState()'s automatic "time in state" updates are not supported
1120 when using incrementChannelState(). Clients must not use
1121 incrementChannelState() on any channel that has ::setState()
1122 called on it. Unlike with ::setState(), clients using
1123 incrementChannelState() are responsible for ensuring that data
1124 is up to date for updateReport() calls. The correct way to do
1125 this is for a driver's ::updateReport() method to push the most
1126 up to date values into the reporters before calling
1127 super::updateReport().
1128
1129 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1130*/
1131 IOReturn incrementChannelState(uint64_t channel_id,
1132 uint64_t state_id,
1133 uint64_t time_in_state,
1134 uint64_t intransitions,
1135 uint64_t last_intransition = 0);
1136
1137/*! @function IOStateReporter::setStateByIndices
1138 @abstract update a channel state without validating channel_id
1139
1140 @param channel_index - 0..<nChannels>, available from getChannelIndex()
1141 @param new_state_index - New state (by index) for the channel
1142 @result Appropriate IOReturn code
1143
1144 @discussion
1145 Similar to setState(), setStateByIndices() sets a channel's state
1146 without searching for the channel or state IDs. It will perform
1147 bounds checking, but relies on the caller to properly indicate
1148 the indices of the channel and state. Clients can rely on channels
1149 being added to IOStateReporter in order: the first channel will
1150 have index 0, the second index 1, etc. Like ::setState(),
1151 "time in state" calculations are handled automatically.
1152
1153 setStateByIndices() is faster than than setChannelState(), but
1154 it should only be used where the latter's performance overhead
1155 might be a problem. For example, many channels in a single
1156 reporter and high-frequency state changes.
1157
1158 Drivers wishing to compute and report their own time in state
1159 should use incrementChannelState() or overrideChannelState(). It
1160 is not currently possible for a driver to synchronize with the
1161 automatic time-keeping enabled by setStateByIndices(). The
1162 4-argument version of setChannelState() is thus impossible to
1163 use correctly. In the future, there may be a setChannelState()
1164 which accepts a last_intransition parameter and uses it to
1165 automatically calculate time in state (ERs -> IOReporting / X).
1166
1167 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1168*/
1169 IOReturn setStateByIndices(int channel_index,
1170 int new_state_index);
1171
1172/*! @function IOStateReporter::setStateByIndices
1173 @abstract update a channel state without validating channel_id
1174
1175 @param channel_index - 0..<nChannels>, available from getChannelIndex()
1176 @param new_state_index - New state (by index) for the channel
1177 @param last_intransition - deprecated: time of most recent entry
1178 @param prev_state_residency - deprecated: time spent in previous state
1179 @result Appropriate IOReturn code
1180
1181 @discussion
1182 Similar to setState(), setStateByIndices() sets a channel's state
1183 without searching for the channel or state IDs. It will perform
1184 bounds checking, but relies on the caller to properly indicate
1185 the indices of the channel and state. Clients can rely on channels
1186 being added to IOStateReporter in order: the first channel will
1187 have index 0, the second index 1, etc. Like ::setState(),
1188 "time in state" calculations are handled automatically.
1189
1190 setStateByIndices() is faster than than setChannelState(), but
1191 it should only be used where the latter's performance overhead
1192 might be a problem. For example, many channels in a single
1193 reporter and high-frequency state changes.
1194
1195 Drivers wishing to compute and report their own time in state
1196 should use incrementChannelState() or overrideChannelState(). It
1197 is not currently possible for a driver to synchronize with the
1198 automatic time-keeping enabled by setStateByIndices(). The
1199 4-argument version of setChannelState() is thus impossible to
1200 use correctly. In the future, there may be a setChannelState()
1201 which accepts a last_intransition parameter and uses it to
1202 automatically calculate time in state (ERs -> IOReporting / X).
1203
1204 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1205*/
1206 IOReturn setStateByIndices(int channel_index,
1207 int new_state_index,
1208 uint64_t last_intransition,
1209 uint64_t prev_state_residency) __deprecated;
1210
1211/*! @function IOStateReporter::getStateInTransitions
1212 @abstract Accessor method for count of transitions into state
1213
1214 @param channel_id - ID of the channel
1215 @param state_id - State of the channel
1216 @result Count of transitions into the requested state.
1217
1218 @discussion
1219 Some clients may need to consume internally the data aggregated by the
1220 reporter object. This method allows a client to retrieve the count of
1221 transitions into the requested state for the channel_id.
1222
1223 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1224*/
1225 uint64_t getStateInTransitions(uint64_t channel_id,
1226 uint64_t state_id);
1227
1228/*! @function IOStateReporter::getStateResidencyTime
1229 @abstract Accessor method for time spent in a given state
1230
1231 @param channel_id - ID of the channel
1232 @param state_id - State of the channel
1233 @result Absolute time spent in specified state
1234
1235 @discussion
1236 Some clients may need to consume internally the data aggregated
1237 by the by the reporter object. This method allows a client to
1238 retrieve the absolute time a particular channel recorded as spent
1239 in a specified state.
1240
1241 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1242*/
1243 uint64_t getStateResidencyTime(uint64_t channel_id,
1244 uint64_t state_id);
1245
1246/*! @function IOStateReporter::getStateLastTransitionTime
1247 @abstract Accessor method for last time a transition occured
1248
1249 @param channel_id - ID of the channel
1250 @param state_id - State of the channel
1251 @result Absolute time for when the last transition occured
1252
1253 @discussion
1254 Some clients may need to consume internally the data aggregated
1255 by the by the reporter object. This method allows a client to
1256 retrieve the absolute time stamp for when the last transition into
1257 a specific state was recorded.
1258
1259 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1260*/
1261 uint64_t getStateLastTransitionTime(uint64_t channel_id, uint64_t state_id);
1262
1263/*! @function [DEPRECATED] IOStateReporter::getStateLastChannelUpdateTime
1264 @abstract Deprecated accessor for last time a channel was auto-updated
1265
1266 @param channel_id - ID of the channel
1267 @result Absolute time for last time the channel was updated
1268
1269 @discussion
1270 If a channel has had ::setState() called on it, calls such as
1271 getStateResidencyTime() or updateReport() will update time in the
1272 current state and update an internal "last channel update time."
1273 Because clients have no way to interlock with those methods, there
1274 is no sensible way to use this method and it will be removed in
1275 a future release.
1276
1277 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1278*/
1279 uint64_t getStateLastChannelUpdateTime(uint64_t channel_id) __deprecated;
1280
1281/*! @function IOStateReporter::free
1282 @abstract Releases the object and all its resources.
1283
1284 @discussion
1285 ::free() assumes that init() has completed. Clients should use
1286 the static ::with() methods to obtain fully-initialized reporter
1287 instances.
1288
1289 Locking: same-instance concurrency UNSAFE
1290*/
1291 virtual void free(void) APPLE_KEXT_OVERRIDE;
1292
1293protected:
1294
1295/*! @function IOStateReporter::initWith
1296 @abstract Instance method implementation called by ::with
1297
1298 @discussion
1299 See description of parameters above
1300*/
1301 virtual bool initWith(IOService *reportingService,
1302 IOReportCategories categories,
1303 int16_t nstates, IOReportUnit unit);
1304
1305
1306/*! @function IOStateReporter::handleSwapPrepare
1307 @abstract _swap* = <IOStateReporter-specific per-channel buffers>
1308 [see IOReporter::handle*Swap* for more info]
1309*/
1310 virtual IOReturn handleSwapPrepare(int newNChannels) APPLE_KEXT_OVERRIDE;
1311
1312/*!
1313 @function IOStateReporter::handleAddChannelSwap
1314 @abstract swap in IOStateReporter's variables
1315*/
1316 virtual IOReturn handleAddChannelSwap(uint64_t channel_id,
1317 const OSSymbol *symChannelName) APPLE_KEXT_OVERRIDE;
1318
1319/*!
1320 @function IOStateReporter::handleSwapCleanup
1321 @abstract clean up unused buffers in _swap*
1322*/
1323 virtual void handleSwapCleanup(int swapNChannels) APPLE_KEXT_OVERRIDE;
1324
1325/*! @function IOStateReporter::updateChannelValues
1326 @abstract Update accounting of time spent in current state
1327
1328 @param channel_index - internal index of the channel
1329 @result appropriate IOReturn code
1330
1331 @discussion
1332 Internal State reporter method to account for the time spent in
1333 the current state when updateReport() is called on the reporter's
1334 channels.
1335
1336 Locking: Caller must ensure that the reporter (data) lock is held.
1337*/
1338 virtual IOReturn updateChannelValues(int channel_index) APPLE_KEXT_OVERRIDE;
1339
1340/*! @function IOStateReporter::setStateByIndices
1341 @abstract update a channel state without validating channel_id
1342
1343 @param channel_index - 0..<nChannels>, available from getChannelIndex()
1344 @param new_state_index - New state for the channel
1345 @param last_intransition - to remove: time of most recent entry
1346 @param prev_state_residency - to remove: time spent in previous state
1347 @result Appropriate IOReturn code
1348
1349 @discussion
1350 Locked version of IOReporter::setStateByIndices(). This method may be
1351 overriden by sub-classes.
1352
1353 Locking: Caller must ensure that the reporter (data) lock is held.
1354*/
1355 virtual IOReturn handleSetStateByIndices(int channel_index,
1356 int new_state_index,
1357 uint64_t last_intransition,
1358 uint64_t prev_state_residency);
1359
1360/*! @function IOStateReporter::setStateID
1361 @abstract Assign a non-default ID to a state
1362
1363 @param channel_id - ID of channel containing the state in question
1364 @param state_index - index of state to give an ID: [0..(nstates-1)]
1365 @param state_id - 64-bit state ID, for ASCII, use IOREPORT_MAKEID
1366
1367 @result Appropriate IOReturn code
1368
1369 @discussion
1370 Locked version of IOReporter::setStateID(). This method may be
1371 overriden by sub-classes
1372
1373 Locking: Caller must ensure that the reporter (data) lock is held.
1374*/
1375 virtual IOReturn handleSetStateID(uint64_t channel_id,
1376 int state_index,
1377 uint64_t state_id);
1378
1379/*! @function IOStateReporter::handleOverrideChannelStateByIndices
1380 @abstract Overrides state data for a channel with passed arguments
1381
1382 @param channel_index - index of the channel which state is to be updated
1383 @param state_index - index of the state id for the channel
1384 @param time_in_state - time used as new total time in state
1385 @param intransitions - total number of transitions into state
1386 @param last_intransition - mach_absolute_time of most recent entry (opt)
1387 @result Appropriate IOReturn code
1388
1389 @discussion
1390 Locked version of IOReporter::overrideChannelState(). This method
1391 may be overriden by sub-classes.
1392
1393 Locking: Caller must ensure that the reporter (data) lock is held.
1394*/
1395 virtual IOReturn handleOverrideChannelStateByIndices(int channel_index,
1396 int state_index,
1397 uint64_t time_in_state,
1398 uint64_t intransitions,
1399 uint64_t last_intransition = 0);
1400
1401/*! @function IOStateReporter::handleIncrementChannelStateByIndices
1402 @abstract Updates state data for a channel with passed arguments
1403
1404 @param channel_index - index of the channel which state is to be updated
1405 @param state_index - index of the state id for the channel
1406 @param time_in_state - time used as new total time in state
1407 @param intransitions - total number of transitions into state
1408 @param last_intransition - mach_absolute_time of most recent entry (opt)
1409 @result Appropriate IOReturn code
1410
1411 @discussion
1412 Locked version of IOReporter::incrementChannelState(). This method
1413 may be overriden by sub-classes.
1414
1415 Locking: Caller must ensure that the reporter (data) lock is held.
1416*/
1417 virtual IOReturn handleIncrementChannelStateByIndices(int channel_index,
1418 int state_index,
1419 uint64_t time_in_state,
1420 uint64_t intransitions,
1421 uint64_t last_intransition = 0);
1422private:
1423
1424 int *_currentStates; // current states (per chonnel)
1425 uint64_t *_lastUpdateTimes; // most recent auto-update
1426
1427 // Required for swapping inside addChannel
1428 int *_swapCurrentStates;
1429 uint64_t *_swapLastUpdateTimes;
1430
1431enum valueSelector {
1432 kInTransitions,
1433 kResidencyTime,
1434 kLastTransitionTime
1435};
1436 uint64_t _getStateValue(uint64_t channel_id,
1437 uint64_t state_id,
1438 enum valueSelector value);
1439
1440 IOReturn _getStateIndices(uint64_t channel_id,
1441 uint64_t state_id,
1442 int *channel_index,
1443 int *state_index);
1444
1445};
1446
1447
1448/*!
1449 @class IOHistogramReporter
1450 @abstract Report histograms of values
1451 @discussion
1452 Each IOHistogramReporter can report one histogram representing
1453 how a given value has changed over time.
1454*/
1455class IOHistogramReporter : public IOReporter
1456{
1457 OSDeclareDefaultStructors(IOHistogramReporter);
1458
1459public:
1460/*! @function IOHistogramReporter::with
1461 @abstract Initializes the IOHistogramReporter instance variables and data structures
1462
1463 @param reportingService - The I/O Kit service for this reporter's channels
1464 @param categories - The categories in which the report should be classified
1465 @param channelID - uint64_t channel identifier
1466 @param channelName - rich channel name as char*
1467 @param unit - The unit for the quantity recorded by the reporter object
1468 @param nSegments - Number of segments to be extracted from the config data structure
1469 @param config - Histograms require the caller to pass a configuration by segments
1470 @result an instance of the IOSimpleReporter object or NULL on error
1471
1472 @discussion
1473 Creates an instance of histogram reporter object.
1474
1475FIXME: need more explanation of the config
1476
1477 IOHistogramReporter currently only supports a single channel.
1478
1479
1480 */
1481 static IOHistogramReporter* with(IOService *reportingService,
1482 IOReportCategories categories,
1483 uint64_t channelID,
1484 const char *channelName,
1485 IOReportUnit unit,
1486 int nSegments,
1487 IOHistogramSegmentConfig *config);
1488
1489/*! @function IOHistogramReporter::addChannel
1490 @abstract Override IOReporter::addChannel(*) to return an error
1491
1492 @result kIOReturnUnsupported - doesn't support adding channels
1493*/
1494 IOReturn addChannel(__unused uint64_t channelID, __unused const char *channelName = NULL) {
1495 return kIOReturnUnsupported;
1496 }
1497
1498/*! @function IOHistogramReporter::overrideBucketValues
1499 @abstract Override values of a bucket at specified index
1500
1501 @param index - index of bucket to override
1502 @param bucket_hits - new bucket hits count
1503 @param bucket_min - new bucket minimum value
1504 @param bucket_max - new bucket maximum value
1505 @param bucket_sum - new bucket sum
1506 @result Appropriate IOReturn code
1507
1508 @discussion
1509 Replaces data in the bucket at the specified index with the data pointed
1510 to by bucket. No sanity check is performed on the data. If the index
1511 is out of bounds, kIOReturnBadArgument is returned.
1512
1513 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1514*/
1515
1516 IOReturn overrideBucketValues(unsigned int index,
1517 uint64_t bucket_hits,
1518 int64_t bucket_min,
1519 int64_t bucket_max,
1520 int64_t bucket_sum);
1521
1522/*! @function IOHistogramReporter::tallyValue
1523 @abstract Add a new value to the histogram
1524
1525 @param value - new value to add to the histogram
1526 @result the index of the affected bucket, or -1 on error
1527
1528 @discussion
1529 The histogram reporter determines in which bucket the value
1530 falls and increments it. The lowest and highest buckets
1531 extend to negative and positive infinity, respectively.
1532
1533 Locking: same-instance concurrency SAFE, WILL NOT BLOCK
1534*/
1535 int tallyValue(int64_t value);
1536
1537/*! @function IOHistogramReporter::free
1538 @abstract Releases the object and all its resources.
1539
1540 @discussion
1541 ::free() assumes that init() has completed. Clients should use
1542 the static ::with() methods to obtain fully-initialized reporter
1543 instances.
1544
1545 Locking: same-instance concurrency UNSAFE
1546*/
1547 virtual void free(void) APPLE_KEXT_OVERRIDE;
1548
1549protected:
1550
1551/*! @function IOHistogramReporter::initWith
1552 @abstract instance method implementation called by ::with
1553
1554 @discussion
1555 See description of parameters above
1556*/
1557 virtual bool initWith(IOService *reportingService,
1558 IOReportCategories categories,
1559 uint64_t channelID,
1560 const OSSymbol *channelName,
1561 IOReportUnit unit,
1562 int nSegments,
1563 IOHistogramSegmentConfig *config);
1564
1565/*! @function IOHistogramReporter::handleCreateLegend
1566 @abstract Builds an IOReporting legend entry representing the channels of this reporter.
1567
1568 @result An IOReportLegendEntry or NULL on failure
1569
1570 @discussion
1571 The returned legend entry may be appended to kIOReportLegendKey
1572 to be published by the caller in the IORegistry. See the
1573 IOReportLegend class for more details.
1574
1575 Locking: same-instance concurrency SAFE, MAY BLOCK
1576*/
1577 IOReportLegendEntry* handleCreateLegend(void) APPLE_KEXT_OVERRIDE;
1578
1579
1580private:
1581
1582 int _segmentCount;
1583 int64_t *_bucketBounds;
1584 int _bucketCount;
1585 IOHistogramSegmentConfig *_histogramSegmentsConfig;
1586};
1587
1588
1589/***********************************/
1590/***** 4. IOReportLegend Class *****/
1591/***********************************/
1592
1593/*!
1594 @class IOReportLegend
1595 @abstract combine legend entries into a complete legend
1596 @discussion
1597 IOReportLegend adds metadata to legend entries and combines them
1598 into a single OSArray that can be published under the
1599 kIOReportLegendKey property in the I/O Kit registry.
1600*/
1601class IOReportLegend : public OSObject
1602{
1603 OSDeclareDefaultStructors(IOReportLegend);
1604
1605public:
1606/*! @function IOReportLegend::with
1607 @abstract Create an instance of IOReportLegend
1608
1609 @param legend - OSArray of the legend possibly already present in registry
1610 @result an instance of IOReportLegend, or NULL on failure
1611
1612 @discussion
1613 An IOReporting legend (an OSArray of legend entries) may be already
1614 present in the IORegistry. Thus the recommended way to publish
1615 new entries is to append to any existing array as follows:
1616 1. call getProperty(kIOReportLegendKey) to get an existing legend.
1617
1618 2a. If it exists
1619 - OSDynamicCast to OSArray
1620 - and pass it to ::with()
1621 IOReportLegend *legendMaker = IOReportLegend::with(legend);
1622 The provided array is retained by IOReportLegend.
1623
1624 2b. If no legend already exists in the registry, pass NULL
1625 IOReportLegend *legend = IOReportLegend::with(NULL);
1626 This latter invocation will cause IOReportLegend to create a new
1627 array internally (also holding one reference).
1628
1629 At the cost of some registry churn, the static
1630 IOReportLegend::addReporterLegend() will handle the above, removing
1631 the need for any direct use of the IOReportLegend class.
1632*/
1633 static IOReportLegend* with(OSArray *legend);
1634
1635/*! @function IOReportLegend::addLegendEntry
1636 @abstract Add a new legend entry
1637
1638 @param legendEntry - entry to be added to the internal legend array
1639 @param groupName - primary group name for this entry
1640 @param subGroupName - secondary group name for this entry
1641 @result appropriate IOReturn code
1642
1643 @discussion
1644 The entry will be retained as an element of the internal array.
1645 Legend entries are available from reporter objects. Entries
1646 represent some number of channels with similar properties (such
1647 as group and sub-group). Multiple legend entries with the same
1648 group names will be aggregated in user space.
1649
1650 Drivers that instantiate their reporter objects in response to
1651 IOService::configureReport(kIOReportDisable) will need to create
1652 temporary reporter objects for the purpose of creating their
1653 legend entries. User-space legends are tracked by 12836893.
1654*/
1655 IOReturn addLegendEntry(IOReportLegendEntry *legendEntry,
1656 const char *groupName,
1657 const char *subGroupName);
1658
1659/*! @function IOReportLegend::addReporterLegend
1660 @abstract Add a legend entry from a reporter object
1661
1662 @param reporter - IOReporter to use to extract and append the legend
1663 @param groupName - primary group name for this entry
1664 @param subGroupName - secondary group name for this entry
1665 @result appropriate IOReturn code
1666
1667 @discussion
1668 An IOReportLegendEntry will be created internally to this method from
1669 the IOReporter object passed in argument. The entry will be released
1670 internally after being appended to the IOReportLegend object.
1671 Legend entries are available from reporter objects. Entries
1672 represent some number of channels with similar properties (such
1673 as group and sub-group). Multiple legend entries with the same
1674 group names will be aggregated in user space.
1675
1676 Drivers that instantiate their reporter objects in response to
1677 IOService::configureReport(kIOReportDisable) will need to create
1678 temporary reporter objects for the purpose of creating their
1679 legend entries. User-space legends are tracked by 12836893.
1680
1681 Locking: same-reportingService and same-IORLegend concurrency UNSAFE
1682*/
1683 IOReturn addReporterLegend(IOReporter *reporter,
1684 const char *groupName,
1685 const char *subGroupName);
1686
1687/*! @function IOReportLegend::addReporterLegend
1688 @abstract Add a legend entry from a reporter object
1689
1690 @param reportingService - IOService data provider into the reporter object
1691 @param reporter - IOReporter to use to extract and append the legend
1692 @param groupName - primary group name for this entry
1693 @param subGroupName - secondary group name for this entry
1694 @result appropriate IOReturn code
1695
1696 @discussion
1697 An IOReportLegendEntry will be created internally to this method from
1698 the IOReporter object passed in argument. The entry will be released
1699 internally after being appended to the IOReportLegend object.
1700 Legend entries are available from reporter objects. Entries
1701 represent some number of channels with similar properties (such
1702 as group and sub-group). Multiple legend entries with the same
1703 group names will be aggregated in user space.
1704
1705 Drivers that instantiate their reporter objects in response to
1706 IOService::configureReport(kIOReportDisable) will need to create
1707 temporary reporter objects for the purpose of creating their
1708 legend entries. User-space legends are tracked by 12836893.
1709
1710 The static version of addReporterLegend adds the reporter's legend
1711 directly to reportingService's kIOReportLegendKey. It is not
1712 possible to safely update kIOReportLegendKey from multiple threads.
1713
1714 Locking: same-reportingService and same-IORLegend concurrency UNSAFE
1715*/
1716 static IOReturn addReporterLegend(IOService *reportingService,
1717 IOReporter *reporter,
1718 const char *groupName,
1719 const char *subGroupName);
1720
1721/*! @function IOReportLegend::getLegend
1722 @abstract Accessor method to get the legend array
1723
1724 @result Returns the OSObject holding the legend to be published by the driver
1725 @discussion
1726 This array will include all legend entries added to the object.
1727*/
1728 OSArray* getLegend(void);
1729
1730/*! @function IOReportLegend::free
1731 @abstract Frees the IOReportLegend object
1732
1733 @discussion
1734 ::free() cleans up the reporter and anything it allocated.
1735
1736 ::free() releases the internal array (which was either passed
1737 to ::with() or created as a result of ::with(NULL)). Assuming
1738 the caller extracted the array with getLegend() and published it
1739 in the I/O Kit registry, its ownership will now be with the
1740 registry.
1741*/
1742 void free(void) APPLE_KEXT_OVERRIDE;
1743
1744
1745
1746protected:
1747
1748private:
1749
1750 OSArray *_reportLegend;
1751
1752 IOReturn initWith(OSArray *legend);
1753
1754/*! @function IOReportLegend::organizeLegend
1755 @abstract Sets up the legend entry, organizing it with group and sub-group names
1756
1757 @param groupName - Primary group name
1758 @param subGroupName - Secondary group name
1759 @result IOReturn code
1760*/
1761 IOReturn organizeLegend(IOReportLegendEntry *legendEntry,
1762 const OSSymbol *groupName,
1763 const OSSymbol *subGroupName);
1764
1765// FUTURE POSSIBILITY (NOT IMPLEMENTED!)
1766/*! @function IOReportLegend::createReporters
1767 @abstract Creates as many IOReporter objects as the legend contains
1768
1769 @param legend - OSArray legend object containing the description of all reporters
1770 the driver is able to address
1771 @param reporter - OSSet of reporter objects created by this call
1772 @result IOReturn code kIOReturnSuccess if successful
1773
1774 @discussion
1775 NOT SUPPORTED at the time of writing
1776 Convenience method to create all the driver's reporter objects from a legend.
1777 Can be used when a legend is made public through the IORegistry but IOReporter
1778 objects have not yet been created to save memory, waiting for observers.
1779 Upon a call to configureReport via the IOService method, a driver could
1780 create all reporter objects on the fly using this function.
1781*/
1782 // For Future IOReporterManager...
1783 // static IOReturn createReporters(requestedChannels, legend);
1784};
1785
1786#endif /* ! _IOKERNEL_REPORTERS_H_ */
1787