Re: [NTDEV] What and When to Use Locks?

If your read accesses pointers in a dynamic collection then you need at
least a read lock. If instead you are reading a fixed length collection it
is possible that you do not need a lock, depending on how you use the data
that can obviously be stale.

“Also, what if my collection is a system-wide one, not just for my driver.”

  • huh? like in a kernel dll? Then you need a locking protocol to go along
    with your shared system wide data. The lock has to obviously be part of the
    dll.

Atomic operations work as documented. They are only useful for maintaining
the coherency of small memory ranges, and only for specific operations:
add/exchange etc. Exchange is not the way to change 0 to 1, increment is.
You can build ‘lockless’ algorithms using them, but generally this is the
wrong approach.

Mark Roddy

Note: The email was trying to reply to an invalid Discussion (292776).

I’m not sure of the context of this conversation, but there are some points I might add

it is not always necessary to use locks or atomic instructions even for data shared between threads (cores) which might be volatile. Correct use of the C volatile qualifier is usually more important (to prevent compiler optimizations that change the meaning of the code), but it depends greatly on the consequences of stale reads or split writes. new developments in transactional memory change this picture again as the CPU can become able to detect conflicting memory access at the hardware level, but consider a variable that contains the current temperature of sensor X. Let’s say that it gets updated by reading a register on a periodic update, but it gets read continually by other threads (cores) in the IO path as part of an algorithm to throttle IO to a hot device. what is the consequence of a single stale read? how about a few thousand stale reads - even as the temperature goes from 37 to 38 degrees Celsius and crosses the ‘critical’ threshold for IO moderation for some hypothetical algorithm

contrast that with the much more common systems programming issues of maintaining a monotonic counter (InterlockedIncrement), object rundown or reference counting (interlocked Increment & decrement), atomic list processing (Interlocked compare exchange) or larger inexpressible changes that require a lock (composed of one or more of these primitives that ensure memory barriers). and this is where transactional memory becomes of much greater interest since it can elide those operations in uncontended cases and structure them within the memory coherency protocol when it can’t elide them.