Hold a lock while making an OS call ?

Hi

I have beleow (probably philosophical) question.

  1. Can I hold my own lock when I am make calls into OS?
    I think I read soemwhere that it is not advised to hold a lock and call into OS/dispatch routine etc?
    Why not?

In general, I am not able to realize why it is a problem to hold a lock and call into OS (I guess drivers have-to/do this all the time)
In particular, the OS routine here is ScsiPortWmiDispatchFunction().

  1. Also, is it guarenteed that ScsiPortWmiDispatchFunction() calls back one of the functions SET in SCSI_WMILIB_CONTEXT ***on the SAME CORE (irrespective of IRQL) on which ScsiPortWmiDispatchFunction() was called by my driver***

WDK
ScsiPortWmiDispatchFunction confirms that the SRB is a WMI request and determines whether the block specified by the request is valid for the miniport driver.
***If these conditions are met, ScsiPortWmiDispatchFunction processes the SRB by calling the appropriate HwScsiWmiXxx entry point in the miniport driver’s SCSI_WMILIB_CONTEXT structure.***
If the miniport driver does not define an entry point for an optional HwScsiWmiXxx routine, the port driver handles the request.

Do you mean using SpinLock? If you do, it is a bad design to call an OS function holding SpinLock. If you acquire SpinLock you rise your function in Dispatch Level. And if you call an OS function holding SpinLock a result could be unpredictable. Using SpinLock intended to synchronize your data but not any OS functions.

Igor Sharovar

Igor
Thanks.

Yes I meant SLock.
Why is it bad if I call OS at DISPATCH_LEVEL, unless WDK has explicitly said not do on per function basis?

I guess OS even supports/encourages this right?
For instance when I call NdisSendNetBufferLists(), I pass a hint whether I am at DISPATCH_LEVEL –> I acquired a SLock etc ?

WDK - NdisSendNetBufferLists()
SendFlags
Flags that define attributes for the send operation. The flags can be combined with an OR operation. To clear all the flags, set this member to zero. This function supports the following flags:
NDIS_SEND_FLAGS_DISPATCH_LEVEL
Specifies that the current IRQL is DISPATCH_LEVEL. For more information about this flag, see Dispatch IRQL Tracking.

How do you know who your calling can be called at DISPATCH_LEVEL and
How do you know that you won’t be called back into your driver and
acquire the same lock? You never call another routine at
DISPATCH_LEVEL unless explicitly told to.

–Mark Cariddi
OSR, Open Systems REsources, Inc…

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@yahoo.com
Sent: Friday, September 25, 2009 5:03 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Hold a lock while making an OS call ?

Igor
Thanks.

Yes I meant SLock.
Why is it bad if I call OS at DISPATCH_LEVEL, unless WDK has explicitly
said not do on per function basis?

I guess OS even supports/encourages this right?
For instance when I call NdisSendNetBufferLists(), I pass a hint whether
I am at DISPATCH_LEVEL –> I acquired a SLock etc ?

WDK - NdisSendNetBufferLists()
SendFlags
Flags that define attributes for the send operation. The flags can be
combined with an OR operation. To clear all the flags, set this member
to zero. This function supports the following flags:
NDIS_SEND_FLAGS_DISPATCH_LEVEL
Specifies that the current IRQL is DISPATCH_LEVEL. For more information
about this flag, see Dispatch IRQL Tracking.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

>>

  1. How do you know who your calling can be called at DISPATCH_LEVEL and
  2. How do you know that you won’t be called back into your driver and
    acquire the same lock?
    <<

O.k.

But for closure, assuming [1] is fine for OS and if I/OS ensured that [2] cannot happen, I can still call with lock held. yeah I guess so right…?

xxxxx@yahoo.com wrote:

  1. Also, is it guarenteed that ScsiPortWmiDispatchFunction() calls back one of the functions SET in SCSI_WMILIB_CONTEXT ***on the SAME CORE (irrespective of IRQL) on which ScsiPortWmiDispatchFunction() was called by my driver***

Unless you have set the thread affinity, Windows makes no guarantees at
all about switching cores. Unless you know that you are completely
uninterruptible, you could get a core switch between any two instructions.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

The OP seems to be referring to the scsiport environment, which
environment is generally running with a spinlock held internally by
scsiport. The OP cannot acquire or release locks from his miniport
driver, so the question is not relevant to what he is doing.

Mark Roddy

On Fri, Sep 25, 2009 at 6:15 PM, Tim Roberts wrote:
> xxxxx@yahoo.com wrote:
>> 3) Also, is it guarenteed that ScsiPortWmiDispatchFunction() calls back one of the functions SET in SCSI_WMILIB_CONTEXT on the SAME CORE (irrespective of IRQL) on which ScsiPortWmiDispatchFunction() was called by my driver
>>
>
> Unless you have set the thread affinity, Windows makes no guarantees at
> all about switching cores. ?Unless you know that you are completely
> uninterruptible, you could get a core switch between any two instructions.
>
> –
> Tim Roberts, xxxxx@probo.com
> Providenza & Boekelheide, Inc.
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>

> 1) Can I hold my own lock when I am make calls into OS?

I think I read soemwhere that it is not advised to hold a lock and call into OS/dispatch routine etc?
Why not?

A deadlock can occur on any callback from the OS.

Also, this reduces scalability a lot.

In particular, the OS routine here is ScsiPortWmiDispatchFunction().

All ScsiPort’s miniport routines are called under a spinlock held within ScsiPort.

So, you can call this from your miniport context and forget the locks.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

>>
The OP seems to be referring to the scsiport environment, which
environment is generally running with a spinlock held internally by
scsiport.

All ScsiPort’s miniport routines are called under a spinlock held within
ScsiPort.
So, you can call this from your miniport context and forget the locks.
<<
My model is virtual storport miniport. I think the port driver does not hold any locks like before here in thsi model ?

Yes that is quite a different programming environment.

Mark Roddy

On Wed, Oct 7, 2009 at 1:37 PM, wrote:
>>>
> The OP seems to be referring to the scsiport environment, which
> environment is generally running with a spinlock held internally by
> scsiport.
>
> All ScsiPort’s miniport routines are called under a spinlock held within
> ScsiPort.
> So, you can call this from your miniport context and forget the locks.
> <<
> My model is virtual storport miniport. I think the port driver does not hold any locks like before here in thsi model ?
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>

>My model is virtual storport miniport. I think the port driver does not hold any >locks like before here in thsi model ?
You should always be remember that unlike regular miniport driver virtual miniport have full access to kernel API. It means that such driver must follow all rules in using kernel API functions, including using SpinLock.

Igor Sharovar

O.k. my practical problem is below.

a) I use virtaul storport miniport model
b) While doing I/O I acquire my stack SLock and do my processing.
c) This includes acquiring Lock during WMI paths also (DiskMgr etc) where I call ScsiPortWmiDispatchFunction()
d) Had to do (c) becuase otherwise during stress DiskMgr would not even display anything and as soon as I stop the stress, it would display Luns
e) Then realized one should not do (c), becuase of above.

So all I did is release my lock before I call ScsiPortWmiDispatchFunction() and when it calls my callbacks I re-acquire the lock
But I am again back to original issue of DiskMgr WMI calls getting straved in my stack during I/O, i.e DiskMgr never shows up any Luns during heay I/O.

ScsiPortWmiDispatchFunction() seems to be o.k, if I call it with my SLock acquired since
i) Port dirver anyways has no locks now
ii) I ensure when ScsiPortWmiDispatchFunction() calls back into me, I do not attempt to re-acquire the same lock (Also ScsiPortWmiDispatchFunction() calls back on the same core (fine even if it gets preempted/quantumed-out etc before it calls back or even if it calls back on a different core)

I understand 1) is a general idiom (and hence I followed that inspite of my mitigations), but becuase of it I have an issue ?

Anyways will look into my code agian to see if the issue is elsewhere.

> d) Had to do (c) becuase otherwise during stress DiskMgr would not even display anything and as

soon as I stop the stress, it would display Luns

Actually, this is normal. diskmgmt.msc usually works this way under load, on empty OS too.

But I am again back to original issue of DiskMgr WMI calls getting straved in my stack during I/O

Try raising the priority of the thread instead.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

>>
Yes that is quite a different programming environment.
Mark Roddy

My model is virtual storport miniport. I think the port driver does not hold
any locks like before here in thsi model ?

<<

Stumbled on below.

WDK.HwStartIo
“Storport always calls HwStorStartIo at DISPATCH IRQL by using an internal spin lock to ensure that requests are initiated sequentially. Therefore, the HwStorStartIo routine need not perform its own mutual exclusion. On the other hand, waits or data allocation must never be performed in HwStorStartIo.”

Does above apply only to Storport-miniport (real hw) or VStorport.miniport also ?
I have seen VStorport.HwStartIo being called at PASSIVE_LEVEL Has anyone else noticed that?
Latest OSR VStorport article seem to also suggest that VStorport.HwStartIo is called at DISPATCH_LEVEL ONLY ?

>I have seen VStorport.HwStartIo being called at PASSIVE_LEVEL Has anyone >else noticed that?
It is strange. You should check it again. HwStorStartIo is analog of StartIo in WDM driver and purpose of this function to server request for working with hardware as quickly as possible. If HwStorStartIo would be called on PASSIVE LEVEL it lose its nature.

Igor Sharovar

I believe that the virtual storport locking model is ‘none’, as in do
your own locking. The NtInsider has a long article on virtual storport
complete with sample in the latest edition - so that should cover
this, plus the various presentations by Griswold (sp?) et al at Winhec
and DDC insisted that virtual storport leaves locking up to the
miniport. Doesn’t mean you will always get called at PASSIVE_LEVEL
though - you get called at <= DISPATCH_LEVEL with no locks held.

I’m stilll puzzling over the OP’s problem with WMI requests getting
starved forever. Seems wrong.

Mark Roddy

On Thu, Oct 8, 2009 at 9:30 AM, wrote:
>>I have seen VStorport.HwStartIo being called at PASSIVE_LEVEL Has anyone >else noticed that?
> It is strange. You should check it again. HwStorStartIo is analog of StartIo in WDM driver and purpose of this function to server request for working with hardware as quickly as possible. If HwStorStartIo ?would be called on PASSIVE LEVEL it lose its nature.
>
> Igor Sharovar
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>

Does not apply to virtual storport, which according to several winhec
and ddc presentations, uses a lockless model.

Here:
http://download.microsoft.com/download/5/b/9/5b97017b-e28a-4bae-ba48-174cf47d23cd/STO089_WH06.ppt

for example.

And here:
http://support.microsoft.com/kb/943295

And please see the latest NtInsider.

Mark Roddy

On Thu, Oct 8, 2009 at 12:06 AM, wrote:
>>>
> Yes that is quite a different programming environment.
> Mark Roddy
> …
>> My model is virtual storport miniport. I think the port driver does not hold
> any locks like before here in thsi model ?
> …
> <<
>
> Stumbled on below.
>
> WDK.HwStartIo
> “Storport always calls HwStorStartIo at DISPATCH IRQL by using an internal spin lock to ensure that requests are initiated sequentially. Therefore, the HwStorStartIo routine need not perform its own mutual exclusion. On the other hand, waits or data allocation must never be performed in HwStorStartIo.”
>
> Does above apply only to Storport-miniport (real hw) or VStorport.miniport also ?
> I have seen VStorport.HwStartIo being called at PASSIVE_LEVEL Has anyone else noticed that?
> Latest OSR VStorport article seem to also suggest that VStorport.HwStartIo is called at DISPATCH_LEVEL ONLY ?
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>

>http://download.microsoft.com/download/5/b/9/5b97017b-e28a-4bae-ba48-174cf47d23cd /STO089_WH06.ppt
I can’t load this page…

It is interesting to see where in WDM documentation or others source specified that StartIo for virtual miniport driver could run in <= DISPATCH LEVEL but not on = DISPATCH. The latest OSR article "Writing a Virtual Storport Miniport Driver " says that HwStart run at DISPATCH Level but doesn’t say it could run in PASSIVE Level. In additional to that StartIo for a regular WDM driver run on =DISPATCH LEVEL too. Is virtual miniport StartIo different from others StartIos including other port model drivers and general WDM drivers? I think that StartIo is designed as a high priority queue for serving request and this high priority could be achieved running at DISPATCH LEVEL. But this is only my thought. It is interesting to hear some opinion from Microsoft.

Igor Sharovar

Running at DISPATCH_LEVEL and holding a spinlock are two different
things. I have no idea if virtual storport actually runs at
PASSIVE_LEVEL, but it certainly can receive SRBs at PASSIVE_LEVEL, and
having done so it would have to explicitly raise IRQL to
DISPATCH_LEVEL in order to always invoke HwStartIo with an
=DISPATCH_LEVEL semantics.

Mark Roddy

On Thu, Oct 8, 2009 at 2:42 PM, wrote:
>>http://download.microsoft.com/download/5/b/9/5b97017b-e28a-4bae-ba48-174cf47d23cd /STO089_WH06.ppt
> I can’t load this page…
>
> It is interesting to see where in WDM documentation or others source specified that StartIo for virtual miniport driver could run in <= DISPATCH LEVEL but not on = DISPATCH. The latest OSR article "Writing a Virtual Storport Miniport Driver " says that HwStart run at DISPATCH Level but doesn’t say it could run in PASSIVE Level. In additional to that StartIo for a regular WDM driver run on =DISPATCH LEVEL too. Is virtual miniport StartIo different from others StartIos including other port model drivers and general WDM drivers? I think that StartIo is designed as a high priority queue for serving request and this high priority could be achieved running at DISPATCH LEVEL. But this is only my thought. It is interesting to hear some opinion from Microsoft.
>
> Igor Sharovar
>
>
>
>
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>

>>
It is interesting to see where in WDM documentation or others source specified that StartIo for virtual miniport driver could run in <= DISPATCH LEVEL but not on = DISPATCH. The latest OSR article "Writing a Virtual Storport Miniport Driver " says that HwStart run at DISPATCH Level but doesn’t say it could run in PASSIVE Level.
<<
Yes that’s what I seem to glean so far both from WDK and NTInsider.
Anycase I asked this in the feedback section in that HWStartIo WDK help page. Hope that email reached an human end.

Anyways below is my “VStorport” miniport having its HwStartIo() called at PASSIVE_LEVEL.

—>
*** [c:\src\io.c, 4560]->HwStartIo***
ASSERT(DISPATCH_LEVEL == StartIoEnterIrql) failed !!!
Break instruction exception - code 80000003 (first chance)
Xyzx64!HwStartIo+0xba:
fffffa6009930c3a cc int 3 6: kd\> k Child-SP RetAddr Call Site fffffa6001f32480 fffffa6002a0c45a Xyz!HwStartIo+0xba [c:\src\io.c @ 4560] fffffa6001f32540 fffffa6002a1de99 storport!RaidAdapterPostScatterGatherExecute+0xea fffffa6001f32590 fffffa6002a1ee2f storport!RaidAdapterExecuteXrb+0x29 fffffa6001f325c0 fffffa6002a5e8d1 storport!RaidPnPPassToMiniPort+0x22f fffffa6001f32630 fffffa6002a5eb34 storport!RaUnitQueryCapabilitiesIrp+0x61 fffffa6001f32670 fffffa6002a5f218 storport!RaUnitPnpIrp+0x1e4 fffffa6001f326d0 fffff800032ab59a storport!RaDriverPnpIrp+0x88 fffffa6001f32710 fffff800030b072e nt!IovCallDriver+0x34a fffffa6001f32750 fffff800031e030f nt!IopSynchronousCall+0x10a fffffa6001f327c0 fffff80003277b16 nt!PpIrpQueryCapabilities+0x7f fffffa6001f32850 fffff8000327c2de nt!PiProcessNewDeviceNode+0x76 fffffa6001f329c0 fffff8000327c7ba nt!PipProcessDevNodeTree+0x2de fffffa6001f32c30 fffff80002f73bcd nt!PiProcessReenumeration+0x8a fffffa6001f32c80 fffff80002ea8066 nt!PnpDeviceActionWorker+0x22d fffffa6001f32cf0 fffff800030bede3 nt!ExpWorkerThread+0x11a fffffa6001f32d50 fffff80002ed5536 nt!PspSystemThreadStartup+0x57 fffffa6001f32d80 00000000`00000000 nt!KiStartSystemThread+0x16

6: kd> !irql
Debugger saved IRQL for processor 0x6 – 0 (LOW_LEVEL)

<----