Resource locking

The documentation mentions that KeEnterCriticalRegion() must be called
before ExAcquireResourceExclusiveLite() or a bugcheck will occur, however,
no mention is made when to leave the critical region.

I assume that KeLeaveCriticalRegion() is called after
ExAcquireResourceExclusiveLite(). Also, since the other resource call
descriptions do not mention this I don’t need to worry about it.

Are these valid conclusion?


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

You are correct, you call KeLeaveCiriticalRegion() after you release the
resource.

Mark J. Cariddi
Consulting Associate
Open Systems Resources, Inc.
http://www.osr.com/

-----Original Message-----
From: Stanislaw Kowalczyk [mailto:xxxxx@relicore.com]
Sent: Tuesday, January 22, 2002 3:35 PM
To: NT Developers Interest List
Subject: [ntdev] Resource locking

The documentation mentions that KeEnterCriticalRegion() must be called
before ExAcquireResourceExclusiveLite() or a bugcheck will occur, however,
no mention is made when to leave the critical region.

I assume that KeLeaveCriticalRegion() is called after
ExAcquireResourceExclusiveLite(). Also, since the other resource call
descriptions do not mention this I don’t need to worry about it.

Are these valid conclusion?


You are currently subscribed to ntdev as: xxxxx@osr.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

KeLeaveCriticalRegion is indeed always called after
ExAcquireResourceExclusiveLite, however it also must not be called before
the call to ExReleaseResourceLite, if the call to
ExAcquireResourceExclusiveLite was successful. In other words you must be at
APC_LEVEL for the entire time your thread holds the exclusive lock.

-----Original Message-----
From: Stanislaw Kowalczyk [mailto:xxxxx@relicore.com]
Sent: Tuesday, January 22, 2002 3:35 PM
To: NT Developers Interest List
Subject: [ntdev] Resource locking

The documentation mentions that KeEnterCriticalRegion() must
be called before ExAcquireResourceExclusiveLite() or a
bugcheck will occur, however, no mention is made when to
leave the critical region.

I assume that KeLeaveCriticalRegion() is called after
ExAcquireResourceExclusiveLite(). Also, since the other
resource call descriptions do not mention this I don’t need
to worry about it.

Are these valid conclusion?


You are currently subscribed to ntdev as:
xxxxx@stratus.com To unsubscribe send a blank email to
leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

KeEnterCriticalRegion does not raise to APC_LEVEL, it decrements the
KernelApcDisable field in the thread structure. The relevant code (from
ntddk.h or ntifs.h):

#define KeEnterCriticalRegion() KeGetCurrentThread()->KernelApcDisable -= 1

There is a function version of this as well, but the results are the same.

There are two types of kernel APCs - normal and special. At IRQL
PASSIVE_LEVEL if KernelApcDisable is non-zero, normal kernel APCs are
disabled but special kernel APCs are enabled. When this value returns to
zero, any pending kernel APCs are delivered (again, provided the thread is
running at IRQL PASSIVE_LEVEL.)

To block all APCs (including special APCs) you must raise to APC_LEVEL
explicitly using KeRaiseIrql, or implicitly using some function that raises
to that level (such as the function ExAcquireFastMutex) or above.

The purpose of disabling kernel APCs around lock ownership is to avoid
deadlocks. Thus, special kernel APC code should not be acquiring ERESOURCES
(or other recursive locks) so that driver developers can specify locking
hierarchies without worrying about arbitrary re-entrancy.

So, the rule is that you enter the critical region before acquiring the
ERESOURCE and exit it when you release the ERESOURCE. At one point I
brought the “lax” check in driver verifier to the appropriate developer’s
attention and he assured me that he would tighten the check up; I do not
know if this has been tightened up in XP or .NET Server.

FYI - the same rules apply to kernel mutexes, the difference here is that
the OS handles placing you in the critical section when you acquire the
kernel mutex. The relevant text from the DDK documentation:

“Since KeWaitForMutexObject initiates a wait on a mutex object, a special
consideration applies. APC delivery is the same for mutexes as for all other
dispatcher objects during the wait to acquire the mutex. However, once
KeWaitForMutexObject returns with STATUS_SUCCESS and the thread actually
holds the mutex, only special kernel-mode APCs are delivered. Delivery of
all other APCs, both kernel-mode and user-mode, is disabled. This
restriction on the delivery of APCs persists until the mutex is released.”

The DDK documentation should be clearer on this point (that the critical
section should be held across the entire lifetime of the ERESOURCE
ownership) than it is and I’ll file a bug report against it.

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

See the new NTFSD FAQ on the OSR Web Site!
-----Original Message-----
From: Roddy, Mark [mailto:xxxxx@stratus.com]
Sent: Tuesday, January 22, 2002 3:34 PM
To: NT Developers Interest List
Subject: [ntdev] RE: Resource locking

KeLeaveCriticalRegion is indeed always called after
ExAcquireResourceExclusiveLite, however it also must not be called before
the call to ExReleaseResourceLite, if the call to
ExAcquireResourceExclusiveLite was successful. In other words you must be at
APC_LEVEL for the entire time your thread holds the exclusive lock.

-----Original Message-----
From: Stanislaw Kowalczyk [mailto:xxxxx@relicore.com]
Sent: Tuesday, January 22, 2002 3:35 PM
To: NT Developers Interest List
Subject: [ntdev] Resource locking

The documentation mentions that KeEnterCriticalRegion() must
be called before ExAcquireResourceExclusiveLite() or a
bugcheck will occur, however, no mention is made when to
leave the critical region.

I assume that KeLeaveCriticalRegion() is called after
ExAcquireResourceExclusiveLite(). Also, since the other
resource call descriptions do not mention this I don’t need
to worry about it.

Are these valid conclusion?


You are currently subscribed to ntdev as:
xxxxx@stratus.com To unsubscribe send a blank email to
leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: xxxxx@osr.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

Thanks for clearing things up.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Tony Mason
Sent: Tuesday, January 22, 2002 4:11 PM
To: NT Developers Interest List
Subject: [ntdev] RE: Resource locking

KeEnterCriticalRegion does not raise to APC_LEVEL, it decrements the
KernelApcDisable field in the thread structure. The relevant code (from
ntddk.h or ntifs.h):

#define KeEnterCriticalRegion() KeGetCurrentThread()->KernelApcDisable -= 1

There is a function version of this as well, but the results are the same.

There are two types of kernel APCs - normal and special. At IRQL
PASSIVE_LEVEL if KernelApcDisable is non-zero, normal kernel APCs are
disabled but special kernel APCs are enabled. When this value returns to
zero, any pending kernel APCs are delivered (again, provided the thread is
running at IRQL PASSIVE_LEVEL.)

To block all APCs (including special APCs) you must raise to APC_LEVEL
explicitly using KeRaiseIrql, or implicitly using some function that raises
to that level (such as the function ExAcquireFastMutex) or above.

The purpose of disabling kernel APCs around lock ownership is to avoid
deadlocks. Thus, special kernel APC code should not be acquiring ERESOURCES
(or other recursive locks) so that driver developers can specify locking
hierarchies without worrying about arbitrary re-entrancy.

So, the rule is that you enter the critical region before acquiring the
ERESOURCE and exit it when you release the ERESOURCE. At one point I
brought the “lax” check in driver verifier to the appropriate developer’s
attention and he assured me that he would tighten the check up; I do not
know if this has been tightened up in XP or .NET Server.

FYI - the same rules apply to kernel mutexes, the difference here is that
the OS handles placing you in the critical section when you acquire the
kernel mutex. The relevant text from the DDK documentation:

“Since KeWaitForMutexObject initiates a wait on a mutex object, a special
consideration applies. APC delivery is the same for mutexes as for all other
dispatcher objects during the wait to acquire the mutex. However, once
KeWaitForMutexObject returns with STATUS_SUCCESS and the thread actually
holds the mutex, only special kernel-mode APCs are delivered. Delivery of
all other APCs, both kernel-mode and user-mode, is disabled. This
restriction on the delivery of APCs persists until the mutex is released.”

The DDK documentation should be clearer on this point (that the critical
section should be held across the entire lifetime of the ERESOURCE
ownership) than it is and I’ll file a bug report against it.

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

See the new NTFSD FAQ on the OSR Web Site!
-----Original Message-----
From: Roddy, Mark [mailto:xxxxx@stratus.com]
Sent: Tuesday, January 22, 2002 3:34 PM
To: NT Developers Interest List
Subject: [ntdev] RE: Resource locking

KeLeaveCriticalRegion is indeed always called after
ExAcquireResourceExclusiveLite, however it also must not be called before
the call to ExReleaseResourceLite, if the call to
ExAcquireResourceExclusiveLite was successful. In other words you must be at
APC_LEVEL for the entire time your thread holds the exclusive lock.

-----Original Message-----
From: Stanislaw Kowalczyk [mailto:xxxxx@relicore.com]
Sent: Tuesday, January 22, 2002 3:35 PM
To: NT Developers Interest List
Subject: [ntdev] Resource locking

The documentation mentions that KeEnterCriticalRegion() must
be called before ExAcquireResourceExclusiveLite() or a
bugcheck will occur, however, no mention is made when to
leave the critical region.

I assume that KeLeaveCriticalRegion() is called after
ExAcquireResourceExclusiveLite(). Also, since the other
resource call descriptions do not mention this I don’t need
to worry about it.

Are these valid conclusion?


You are currently subscribed to ntdev as:
xxxxx@stratus.com To unsubscribe send a blank email to
leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: xxxxx@osr.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: xxxxx@relicore.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

Does this also apply to ExAcquireResourceSharedLite()? Assuming it does.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Tony Mason
Sent: Tuesday, January 22, 2002 4:11 PM
To: NT Developers Interest List
Subject: [ntdev] RE: Resource locking

KeEnterCriticalRegion does not raise to APC_LEVEL, it decrements the
KernelApcDisable field in the thread structure. The relevant code (from
ntddk.h or ntifs.h):

#define KeEnterCriticalRegion() KeGetCurrentThread()->KernelApcDisable -= 1

There is a function version of this as well, but the results are the same.

There are two types of kernel APCs - normal and special. At IRQL
PASSIVE_LEVEL if KernelApcDisable is non-zero, normal kernel APCs are
disabled but special kernel APCs are enabled. When this value returns to
zero, any pending kernel APCs are delivered (again, provided the thread is
running at IRQL PASSIVE_LEVEL.)

To block all APCs (including special APCs) you must raise to APC_LEVEL
explicitly using KeRaiseIrql, or implicitly using some function that raises
to that level (such as the function ExAcquireFastMutex) or above.

The purpose of disabling kernel APCs around lock ownership is to avoid
deadlocks. Thus, special kernel APC code should not be acquiring ERESOURCES
(or other recursive locks) so that driver developers can specify locking
hierarchies without worrying about arbitrary re-entrancy.

So, the rule is that you enter the critical region before acquiring the
ERESOURCE and exit it when you release the ERESOURCE. At one point I
brought the “lax” check in driver verifier to the appropriate developer’s
attention and he assured me that he would tighten the check up; I do not
know if this has been tightened up in XP or .NET Server.

FYI - the same rules apply to kernel mutexes, the difference here is that
the OS handles placing you in the critical section when you acquire the
kernel mutex. The relevant text from the DDK documentation:

“Since KeWaitForMutexObject initiates a wait on a mutex object, a special
consideration applies. APC delivery is the same for mutexes as for all other
dispatcher objects during the wait to acquire the mutex. However, once
KeWaitForMutexObject returns with STATUS_SUCCESS and the thread actually
holds the mutex, only special kernel-mode APCs are delivered. Delivery of
all other APCs, both kernel-mode and user-mode, is disabled. This
restriction on the delivery of APCs persists until the mutex is released.”

The DDK documentation should be clearer on this point (that the critical
section should be held across the entire lifetime of the ERESOURCE
ownership) than it is and I’ll file a bug report against it.

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

See the new NTFSD FAQ on the OSR Web Site!
-----Original Message-----
From: Roddy, Mark [mailto:xxxxx@stratus.com]
Sent: Tuesday, January 22, 2002 3:34 PM
To: NT Developers Interest List
Subject: [ntdev] RE: Resource locking

KeLeaveCriticalRegion is indeed always called after
ExAcquireResourceExclusiveLite, however it also must not be called before
the call to ExReleaseResourceLite, if the call to
ExAcquireResourceExclusiveLite was successful. In other words you must be at
APC_LEVEL for the entire time your thread holds the exclusive lock.

-----Original Message-----
From: Stanislaw Kowalczyk [mailto:xxxxx@relicore.com]
Sent: Tuesday, January 22, 2002 3:35 PM
To: NT Developers Interest List
Subject: [ntdev] Resource locking

The documentation mentions that KeEnterCriticalRegion() must
be called before ExAcquireResourceExclusiveLite() or a
bugcheck will occur, however, no mention is made when to
leave the critical region.

I assume that KeLeaveCriticalRegion() is called after
ExAcquireResourceExclusiveLite(). Also, since the other
resource call descriptions do not mention this I don’t need
to worry about it.

Are these valid conclusion?


You are currently subscribed to ntdev as:
xxxxx@stratus.com To unsubscribe send a blank email to
leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: xxxxx@osr.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: xxxxx@relicore.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

Yes, it also applies to ExAcquireResourceSharedLite() as well.

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

See the new NTFSD FAQ on the OSR Web Site!

-----Original Message-----
From: Stanislaw Kowalczyk [mailto:xxxxx@relicore.com]
Sent: Tuesday, January 22, 2002 4:34 PM
To: NT Developers Interest List
Subject: [ntdev] RE: Resource locking

Does this also apply to ExAcquireResourceSharedLite()? Assuming it does.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Tony Mason
Sent: Tuesday, January 22, 2002 4:11 PM
To: NT Developers Interest List
Subject: [ntdev] RE: Resource locking

KeEnterCriticalRegion does not raise to APC_LEVEL, it decrements the
KernelApcDisable field in the thread structure. The relevant code (from
ntddk.h or ntifs.h):

#define KeEnterCriticalRegion() KeGetCurrentThread()->KernelApcDisable -= 1

There is a function version of this as well, but the results are the same.

There are two types of kernel APCs - normal and special. At IRQL
PASSIVE_LEVEL if KernelApcDisable is non-zero, normal kernel APCs are
disabled but special kernel APCs are enabled. When this value returns to
zero, any pending kernel APCs are delivered (again, provided the thread is
running at IRQL PASSIVE_LEVEL.)

To block all APCs (including special APCs) you must raise to APC_LEVEL
explicitly using KeRaiseIrql, or implicitly using some function that raises
to that level (such as the function ExAcquireFastMutex) or above.

The purpose of disabling kernel APCs around lock ownership is to avoid
deadlocks. Thus, special kernel APC code should not be acquiring ERESOURCES
(or other recursive locks) so that driver developers can specify locking
hierarchies without worrying about arbitrary re-entrancy.

So, the rule is that you enter the critical region before acquiring the
ERESOURCE and exit it when you release the ERESOURCE. At one point I
brought the “lax” check in driver verifier to the appropriate developer’s
attention and he assured me that he would tighten the check up; I do not
know if this has been tightened up in XP or .NET Server.

FYI - the same rules apply to kernel mutexes, the difference here is that
the OS handles placing you in the critical section when you acquire the
kernel mutex. The relevant text from the DDK documentation:

“Since KeWaitForMutexObject initiates a wait on a mutex object, a special
consideration applies. APC delivery is the same for mutexes as for all other
dispatcher objects during the wait to acquire the mutex. However, once
KeWaitForMutexObject returns with STATUS_SUCCESS and the thread actually
holds the mutex, only special kernel-mode APCs are delivered. Delivery of
all other APCs, both kernel-mode and user-mode, is disabled. This
restriction on the delivery of APCs persists until the mutex is released.”

The DDK documentation should be clearer on this point (that the critical
section should be held across the entire lifetime of the ERESOURCE
ownership) than it is and I’ll file a bug report against it.

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

See the new NTFSD FAQ on the OSR Web Site!
-----Original Message-----
From: Roddy, Mark [mailto:xxxxx@stratus.com]
Sent: Tuesday, January 22, 2002 3:34 PM
To: NT Developers Interest List
Subject: [ntdev] RE: Resource locking

KeLeaveCriticalRegion is indeed always called after
ExAcquireResourceExclusiveLite, however it also must not be called before
the call to ExReleaseResourceLite, if the call to
ExAcquireResourceExclusiveLite was successful. In other words you must be at
APC_LEVEL for the entire time your thread holds the exclusive lock.

-----Original Message-----
From: Stanislaw Kowalczyk [mailto:xxxxx@relicore.com]
Sent: Tuesday, January 22, 2002 3:35 PM
To: NT Developers Interest List
Subject: [ntdev] Resource locking

The documentation mentions that KeEnterCriticalRegion() must
be called before ExAcquireResourceExclusiveLite() or a
bugcheck will occur, however, no mention is made when to
leave the critical region.

I assume that KeLeaveCriticalRegion() is called after
ExAcquireResourceExclusiveLite(). Also, since the other
resource call descriptions do not mention this I don’t need
to worry about it.

Are these valid conclusion?


You are currently subscribed to ntdev as:
xxxxx@stratus.com To unsubscribe send a blank email to
leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: xxxxx@osr.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: xxxxx@relicore.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: xxxxx@osr.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

> I assume that KeLeaveCriticalRegion() is called after

ExAcquireResourceExclusiveLite().

No, after releasing all resource locks.
It blocks APCs. They must be blocked if you have resource locks acquired.

Max


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com