Re: Two Kext Locking Question
Re: Two Kext Locking Question
- Subject: Re: Two Kext Locking Question
- From: Godfrey van der Linden <email@hidden>
- Date: Fri, 28 Jun 2002 11:03:24 -0700
The IOCommandGate is designed to do this, check out the header doc.
However I wrote a paper on designing a PCI device quite a while ago
which should still be available on RobB's How too site.
In simple explanation is that the workloop is the master lock for one
driver stack. In your case kext A will be registering with your
provider's workloop. Now a work loop has lots of event sources
registered with it and each event source has an associated Action.
It is guaranteed that one and only one Action routine can run on a
particular workloop at any time.
So in your example if you find your workloop by just calling
provider->getWorkLoop() in KextA you will automatically be able to
synchronise with the USBs work loop and all completion routines come
out on that context. Then if you need to protect your own driver
against these completion routines and you addEventSource() them to
your providers work loop. Note it is also OK to add
IOTimerEventSources if you have times outs. (Note however the
IOTimerEventSource doesn't currently have a reliable cancel path so
be very careful when you are trying to unload your driver.)
Then In the APIs from your client you wish to synchronise you use the
fGate->runAction(...) function.
Pseudo code follows (check header doc for details).
in your start routine in Kext A
fGate = IOCommandGate::commandGate(this);
IOWorkLoop *wl = getWorkLoop(); // Find my providers work loop.
if (!fGate || !wl)
return false;
if (kIOReturnSuccess != wl->addEventSource(fGate))
return false;
// That's it your now have an IOCommandGate set up in member variable fGate
IOReturn KextA::myClientsAPI(args)
{
return fGate->runAction(&KextA::myClientsAPIGated, args);
}
// Make sure this function is declared as a 'static' function in the header
IOReturn KextA::myClientsAPIGated(IOService *servSelf, void *vArg1,
void *vArg2, /*etc ... */ )
{
KextA *self = (KextA *) servSelf;
UInt32 arg1 = (UInt32) vArg1;
// You can see where this is going I'm sure
// Just remember to either call a member function here or prefix
// all class access with self->
return result;
}
FInally I recommend only cleaning up the fGate at free time and no
earlier. A lot of tear down problems have been due to premature tear
down of the synchroniser.
free()
{
if (fGate)
{
IOWorkLoop *wl = fGate->getWorkLoop();
if (wl)
wl->removeEventSource(fGate);
fGate->release();
fGate = 0;
}
}
Godfrey
At 8:20 -0700 02-6-28, Scott Taggart wrote:
Hi,
I have two kexts: kext A is a USB driver sub-classed from IOService
and Kext B sub-classed from IOEthernetController. B "calls" into
"A" at various times to perform functions such as delivering
outbound frames. I want to "lock" B from entering into A if A has
already been entered (via USB callback, timer, etc.) (i.e., its
"gate/lock" is busy). Can someone please give me the basics of how
I make a given function entry point into A and have it play the "IO
Gate" game (i.e., to make sure it's the only one with the lock).
Function calls and a pointer to some sample code would be a big help.
Thanks,
Scott
_______________________________________________
darwin-kernel mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/darwin-kernel
Do not post admin requests to the list. They will be ignored.