Guarding event object

Hello,

Consider foll usage of the variable g_pEvent:

//++++++++

In Dispatch Routine: (User mode app init sends this IOCTL)
g_pEvent = ObReferenceObjectByHandle ( hEvent ) ; // hEvent passed by user mode app

Inside a thread: (this is always running-unless the driver is exiting)
if ( g_pEvent )
{
KeSetEvent ( g_pEvent , … ) ; // Signal the user mode app
}

In Dispatch Routine: (User mode app cleanup sends this IOCTL)
if ( g_pEvent )
{
ObDereferenceObject ( g_pEvent ) ;
g_pEvent = NULL ;
}

//--------

Do I need to guard the usage of g_pEvent by a SpinLock ?

Abhijit

Abhijit wrote:

Hello,

Consider foll usage of the variable g_pEvent:

//++++++++

In Dispatch Routine: (User mode app init sends this IOCTL)
g_pEvent = ObReferenceObjectByHandle ( hEvent ) ; // hEvent passed by
user mode app

Have some error-handling here, before calling ObReferenceObjectByHandle.

If you don’t serialize IOCTL processing you need to protect that sequence.
Like…

***
pTemp = ObReferenceObjectByHandle(…); // needs to run at PASSIVE_LEVEL

KeAcquireSpinLock(…);

if( (g_pEvent != 0) || (pTemp == 0) )
{
KeReleaseSpinLock(…);

if( pTemp )
ObDereferenceObject( pTemp );
// fail request
}
else
{
g_pEvent = pTemp;
KeReleaseSpinLock(…);
// succeed request
}
***

Inside a thread: (this is always running-unless the driver is exiting)
if ( g_pEvent )
{
KeSetEvent ( g_pEvent , … ) ; // Signal the user mode app
}

Protect the whole if-block with the spinlock.
(You need to pass FALSE as the third parameter for KeSetEvent())

In Dispatch Routine: (User mode app cleanup sends this IOCTL)
if ( g_pEvent )
{
ObDereferenceObject ( g_pEvent ) ;
g_pEvent = NULL ;
}

Rewrite like:

***
KeAcquireSpinLock(…);
if( g_pEvent )
{
pTemp = g_pEvent;
g_pEvent = 0;
}
KeReleaseSpinLock(…);

if( pTemp ) ObDereferenceObject( pTemp );
***

(DDK says you may call ObDereferenceObject() at DISPATCH_LEVEL too,
but since it’s not necessary…)

And make sure g_pEvent uses volatile storage-class!

//--------

Do I need to guard the usage of g_pEvent by a SpinLock ?

I strongly suggest you get some good book on multi-threaded
programming; this question doesn’t really have to do with
driver-programming, it’s rather basic multithreaded programming…

Also you might want to rethink that signal-usermode-app-via-event
approach - from what I remember there was a lengthy discussion
about all the nasty things that can happen in some cases - even
“not-so-special” cases.
(completing IRPs is a simple and effective alternative)

Regards,
Paul Groke

It really depends. What does your driver do otherwise to ensure that
#1, #2 and #3 don't occur at the same time (if the answer is that it
trusts the app you should think of a better answer).

for example, if before #3 runs you have code which signals the worker
thread to exit and then waits on the thread object (to detect when the
thread has exited) then you don't need to do anything else to
synchronize #2 and #3.

You also obviously need to protect against multiple calls to the
initialization I/O control or you'll leak event objects, as well as the
race between #1 and #3 (what if #1 runs between the dereference of
g_pEvent and the setting of the event pointer to NULL)?

A spinlock would probably be overkill for this, but you do need some
form of synchronization. Perhaps a mutex?

-p


From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Abhijit
Sent: Tuesday, September 07, 2004 11:08 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] Guarding event object

Hello,

Consider foll usage of the variable g_pEvent:

//++++++++

In Dispatch Routine: (User mode app init sends this IOCTL)
g_pEvent = ObReferenceObjectByHandle ( hEvent ) ; // hEvent
passed by user mode app

Inside a thread: (this is always running-unless the driver is
exiting)
if ( g_pEvent )
{
KeSetEvent ( g_pEvent , .. ) ; // Signal the user mode app
}

In Dispatch Routine: (User mode app cleanup sends this IOCTL)
if ( g_pEvent )
{
ObDereferenceObject ( g_pEvent ) ;
g_pEvent = NULL ;
}

//--------

Do I need to guard the usage of g_pEvent by a SpinLock ?

Abhijit

Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: unknown lmsubst tag
argument: ''
To unsubscribe send a blank email to
xxxxx@lists.osr.com

Peter Wieland wrote:

A spinlock would probably be overkill for this,
but you do need some form of synchronization. Perhaps a mutex?

I believe a Spinlock is the most lightweight and fast form of
synchronization
thats available in windows. I’d say a mutex would be overkill :wink:

Of course it depends on what has to be done while the lock is held - if
it’s
just get/set some variables, then I’d always use a spinlock.

Regards,
Paul Groke

On Wed, 2004-09-08 at 09:31, xxxxx@tab.at wrote:

Peter Wieland wrote:

> A spinlock would probably be overkill for this,
> but you do need some form of synchronization. Perhaps a mutex?

I believe a Spinlock is the most lightweight and fast form of
synchronization
thats available in windows. I’d say a mutex would be overkill :wink:

This isn’t really true - a spin lock raises the IRQL, thus monopolizing
the entire CPU until you release it again. FAST_MUTEXes are very fast
(as the name would imply) in most cases, and they’re much nicer to the
rest of the system, if you can use them.

Also, FWIW, in-stack queued spinlocks are also more efficient, if your
target platform supports them.

Someone from Microsoft posted about this recently. I also had an
article in my blog about it a while ago.

-sd


Steve Dispensa
MVP - Windows DDK
www.kernelmustard.com

Hi again Steve :wink:

Steve Dispensa wrote:

On Wed, 2004-09-08 at 09:31, xxxxx@tab.at wrote:
> Peter Wieland wrote:
>
> > A spinlock would probably be overkill for this,
> > but you do need some form of synchronization. Perhaps a mutex?
>
> I believe a Spinlock is the most lightweight and fast form of
> synchronization
> thats available in windows. I’d say a mutex would be overkill :wink:

This isn’t really true - a spin lock raises the IRQL, thus monopolizing
the entire CPU until you release it again. FAST_MUTEXes are very fast
(as the name would imply) in most cases, and they’re much nicer to the
rest of the system, if you can use them.

Ok. Fast mutexes… never really understood those.
Can a fast mutex outperform a spinlock in a case like:

// running at != APC_LEVEL and not inside a critical-region
Lock();
DoSome100CpuCyclesStuff();
Unlock();

Also, FWIW, in-stack queued spinlocks are also more efficient, if your
target platform supports them.

Yeah, right, I always forget about them since I’m doing a win2k driver :frowning:

Someone from Microsoft posted about this recently. I also had an
article in my blog about it a while ago.

-sd

Bye,
Paul Groke

Yep - spinlocks are fast. They also take over the processor, block out
APCs and DPCs, thread switches, etc… To me the side effect of raising
IRQL outweighs the “speed” of using a spinlock in places where
performance requirements or IRQL considerations don’t demand them.

And my guess, based on the IOCTLS listed and their “setup” and
“teardown” type functionality is that this isn’t really part of the
critical path of his driver. If it is then, by all means, use a
spinlock.

-p

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@tab.at
Sent: Wednesday, September 08, 2004 7:31 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Guarding event object

Peter Wieland wrote:

> A spinlock would probably be overkill for this, but you do
need some
> form of synchronization. Perhaps a mutex?

I believe a Spinlock is the most lightweight and fast form of
synchronization thats available in windows. I’d say a mutex
would be overkill :wink:

Of course it depends on what has to be done while the lock is
held - if it’s just get/set some variables, then I’d always
use a spinlock.

Regards,
Paul Groke


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as:
xxxxx@windows.microsoft.com To unsubscribe send a blank
email to xxxxx@lists.osr.com

Fast mutexes are fast to acquire if nobody is waiting, probably at least as
fast as a spinlock. They certainly are not faster or more efficient to
release or to wait for.

=====================
Mark Roddy

-----Original Message-----
From: Steve Dispensa [mailto:xxxxx@positivenetworks.net]
Sent: Wednesday, September 08, 2004 3:10 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Guarding event object

On Wed, 2004-09-08 at 09:31, xxxxx@tab.at wrote:

Peter Wieland wrote:

> A spinlock would probably be overkill for this, but you do need
> some form of synchronization. Perhaps a mutex?

I believe a Spinlock is the most lightweight and fast form of
synchronization thats available in windows. I’d say a mutex would be
overkill :wink:

This isn’t really true - a spin lock raises the IRQL, thus monopolizing the
entire CPU until you release it again. FAST_MUTEXes are very fast (as the
name would imply) in most cases, and they’re much nicer to the rest of the
system, if you can use them.

Also, FWIW, in-stack queued spinlocks are also more efficient, if your
target platform supports them.

Someone from Microsoft posted about this recently. I also had an article in
my blog about it a while ago.

-sd


Steve Dispensa
MVP - Windows DDK
www.kernelmustard.com


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

You are currently subscribed to ntdev as: xxxxx@stratus.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

Look at fast mutex code. Very similar to spinlock, and loses only in cases
of large contention.

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

----- Original Message -----
From:
To: “Windows System Software Devs Interest List”
Sent: Thursday, September 09, 2004 12:11 AM
Subject: Re: [ntdev] Guarding event object

> Hi again Steve :wink:
>
> > Steve Dispensa wrote:
> >
> > On Wed, 2004-09-08 at 09:31, xxxxx@tab.at wrote:
> > > Peter Wieland wrote:
> > >
> > > > A spinlock would probably be overkill for this,
> > > > but you do need some form of synchronization. Perhaps a mutex?
> > >
> > > I believe a Spinlock is the most lightweight and fast form of
> > > synchronization
> > > thats available in windows. I’d say a mutex would be overkill :wink:
> >
> > This isn’t really true - a spin lock raises the IRQL, thus monopolizing
> > the entire CPU until you release it again. FAST_MUTEXes are very fast
> > (as the name would imply) in most cases, and they’re much nicer to the
> > rest of the system, if you can use them.
>
> Ok. Fast mutexes… never really understood those.
> Can a fast mutex outperform a spinlock in a case like:
>
> // running at != APC_LEVEL and not inside a critical-region
> Lock();
> DoSome100CpuCyclesStuff();
> Unlock();
>
> > Also, FWIW, in-stack queued spinlocks are also more efficient, if your
> > target platform supports them.
>
> Yeah, right, I always forget about them since I’m doing a win2k driver :frowning:
>
> > Someone from Microsoft posted about this recently. I also had an
> > article in my blog about it a while ago.
> >
> > -sd
>
> Bye,
> Paul Groke
>
> —
> Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
>
> You are currently subscribed to ntdev as: xxxxx@storagecraft.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com

Yes. I know, it was a question related to multithreaded programming.
My way of asking the question was wrong. I should have asked:
Do I need to guard the usage of g_pEvent by a SpinLock or do I need
to use some other synchronization construct ?
OR still better
Which synchronization mechanism shall I use ?
I was in a dilemma, should I use SpinLock or Mutex and
thought (as usual) to get it from the Gurus here.

Thanks, and sorry for a wrong question.

Abhijit

wrote in message news:xxxxx@ntdev…
> Abhijit wrote:
>
> >Hello,
> >
> > Consider foll usage of the variable g_pEvent:
> >
> > //++++++++
> >
> > 1.
> > In Dispatch Routine: (User mode app init sends this IOCTL)
> > g_pEvent = ObReferenceObjectByHandle ( hEvent ) ; // hEvent passed by
> user mode app
> >
>
> Have some error-handling here, before calling ObReferenceObjectByHandle.
>
> If you don’t serialize IOCTL processing you need to protect that sequence.
> Like…
>
>
> pTemp = ObReferenceObjectByHandle(…); // needs to run at PASSIVE_LEVEL
>
> KeAcquireSpinLock(…);
>
> if( (g_pEvent != 0) || (pTemp == 0) )
> {
> KeReleaseSpinLock(…);
>
> if( pTemp )
> ObDereferenceObject( pTemp );
> // fail request
> }
> else
> {
> g_pEvent = pTemp;
> KeReleaseSpinLock(…);
> // succeed request
> }
>

>
> >
> > 2.
> > Inside a thread: (this is always running-unless the driver is exiting)
> > if ( g_pEvent )
> > {
> > KeSetEvent ( g_pEvent , … ) ; // Signal the user mode app
> > }
> >
>
> Protect the whole if-block with the spinlock.
> (You need to pass FALSE as the third parameter for KeSetEvent())
>
> >
> > 3.
> > In Dispatch Routine: (User mode app cleanup sends this IOCTL)
> > if ( g_pEvent )
> > {
> > ObDereferenceObject ( g_pEvent ) ;
> > g_pEvent = NULL ;
> > }
> >
>
> Rewrite like:
>
>
> KeAcquireSpinLock(…);
> if( g_pEvent )
> {
> pTemp = g_pEvent;
> g_pEvent = 0;
> }
> KeReleaseSpinLock(…);
>
> if( pTemp ) ObDereferenceObject( pTemp );
>

>
> (DDK says you may call ObDereferenceObject() at DISPATCH_LEVEL too,
> but since it’s not necessary…)
>
> And make sure g_pEvent uses volatile storage-class!
>
> > //--------
> >
> > Do I need to guard the usage of g_pEvent by a SpinLock ?
> >
>
> I strongly suggest you get some good book on multi-threaded
> programming; this question doesn’t really have to do with
> driver-programming, it’s rather basic multithreaded programming…
>
> Also you might want to rethink that signal-usermode-app-via-event
> approach - from what I remember there was a lengthy discussion
> about all the nasty things that can happen in some cases - even
> “not-so-special” cases.
> (completing IRPs is a simple and effective alternative)
>
> Regards,
> Paul Groke
>