Hello Everyone,
I'm encountering an issue while setting up a timer event in DriverKit and would appreciate any guidance.
Here's my current implementation:
void DRV_MAIN_CLASS_NAME::SetupEventTimer()
{
// 1. Create dispatch queue
kern_return_t ret = IODispatchQueue::Create("TimerQueue", 0, 0, &ivars->dispatchQueue);
if (ret != kIOReturnSuccess) {
LogErr("Failed to create dispatch queue: 0x%x", ret);
return;
}
// 2. Create timer source
ret = IOTimerDispatchSource::Create(ivars->dispatchQueue, &ivars->dispatchSource);
if (ret != kIOReturnSuccess) {
LogErr("Failed to create timer: 0x%x", ret);
OSSafeReleaseNULL(ivars->dispatchQueue);
return;
}
/*!
* @brief Create an instance of OSAction.
* @discussion Methods to allocate an OSAction instance are generated for each method defined in a class with
* a TYPE attribute, so there should not be any need to directly call OSAction::Create().
* @param target OSObject to receive the callback. This object will be retained until the OSAction is
* canceled or freed.
* @param targetmsgid Generated message ID for the target method.
* @param msgid Generated message ID for the method invoked by the receiver of the OSAction
* to generate the callback.
* @param referenceSize Size of additional state structure available to the creator of the OSAction
* with GetReference.
* @param action Created OSAction with +1 retain count to be released by the caller.
* @return kIOReturnSuccess on success. See IOReturn.h for error codes.
*/
// 3: Create an OSAction for the TimerOccurred method
// THIS IS WHERE I NEED HELP
OSAction* timerAction = nullptr;
ret = OSAction::Create(this, 0, 0, 0, &timerAction);
if (ret != kIOReturnSuccess) {
LogErr("Failed to create OSAction: 0x%x", ret);
goto cleanup;
}
// 4. Set handler
ret = ivars->dispatchSource->SetHandler(timerAction);
if (ret != kIOReturnSuccess) {
LogErr("Failed to set handler: 0x%x", ret);
goto cleanup;
}
// 5. Schedule timer (1 second)
uint64_t deadline = mach_absolute_time() + NSEC_PER_SEC;
ivars->dispatchSource->WakeAtTime(0, deadline, 0);
cleanup:
if (ret != kIOReturnSuccess) {
OSSafeReleaseNULL(timerAction);
OSSafeReleaseNULL(ivars->dispatchSource);
OSSafeReleaseNULL(ivars->dispatchQueue);
}
}
Problem:
The code runs but the OSAction callback binding seems incorrect (Step 3).
According to the OSAction documentation, I need to use the TYPE macro to properly bind the callback method. But I try to use
TYPE(DRV_MAIN_CLASS_NAME::TimerOccurred)
kern_return_t TimerOccurred() LOCALONLY;
TYPE(TimerOccurred)
kern_return_t TimerOccurred() LOCALONLY;
kern_return_t TimerOccurred() TYPE(DRV_MAIN_CLASS_NAME::TimerOccurred) LOCALONLY;
All results in Out-of-line definition of 'TimerOccurred' does not match any declaration in 'DRV_MAIN_CLASS_NAME'
Questions:
- What is the correct way to declare a timer callback method using TYPE?
- How to get the values
targetmsgid
&msgid
generated by Xcode?
Any help would be greatly appreciated!
Best Regards, Charles
According to the OSAction documentation, I need to use the TYPE macro to properly bind the callback method.
So, fair warning, DriverKit is not well documented and it can often be quite difficult to find the correct syntax based on the class reference. This issues are then complicated by the fact that some of that parts that are documented are ACTUALLY internal components that we never actually intended you to call.
That's what the discussion here is referring to:
Use the custom constructor method generated by the TYPE macro, instead of this method. For more information on custom constructor methods for action objects, see TYPE.
It's not just that you're not "supposed" to call "Create", it's that Create only really exists so that the TYPE method can call it.
As a side note, I would strongly encourage you to file bugs anytime you run into this kind of issue. Improving all of this is likely to be a long term project, but every bug you file makes that process more likely. Please post the bug number back here if you file one on this issue.
Moving to the specific issue:
- What is the correct way to declare a timer callback method using TYPE?
In my experience the best tool you've got is looking through the sample code we have provided (and yes, that's not great either) to find an example of whatever you're trying to do. In this case, the sample "Creating an audio device driver" from AudioDriverKit shows how you use IOTimerDispatchSource. Search that sample for "ZtsTimerOccurred" and you'll see what you need to do.
- How to get the values targetmsgid & msgid generated by Xcode?
You don't need those, this is all sorted out by the "TYPE(...)" macro.
__
Kevin Elliott
DTS Engineer, CoreOS/Hardware