Re: Locking Primitives



Hi Chris

I've been away, I will try to answer your question, but may have to be brief.

No attempt is made to "repair" any shared memory or do any recovery.
The motivation was to distinguish between failing to get a lock because it
is in use by some thread/process and failing to get a lock because the
process terminated, there is obvioulsy no point in waiting or spinning on a
lock that can never be released.

The shared spinlock data structure contains the PID and TID of the locker,
as well as the date-time-started of the process itself, this handles the fact
that Windows recylces process IDs, the combination of the three values is
unique.

As for the nesting, the spinlock we have allows any function to aquire a
lock, even if some call earlier up the stack has already aquired it. The
spinlock we have support this for read or write mode locks.

These spinlock are ONLY ever aquired by other functions in our library,
never held by caller code (managed code in this case). A managed app will at
some stage call some unmanaged function, that function may set of a sequence
of activities that lock/unlock shared structures, but by the time this
returns to the managed caller, nothing is locked.

This is the intended setting for our spinlock code.

I have dreamt for years of a termination handler, I recall working on VOS
(Stratus' proprietary OS, a derivative of Multics) in which code could (if it
wanted) get an exception raised when the process was stopped, this handler
could then try to cleanup and make a hasty exit before the process stopped, I
dont think Windows offers this, perhaps Server 2008 might, but not checked.

H





"Chris M. Thomasson" wrote:

"Hugo gleaves@xxxxxxxxxxx>" <hugh<underbar> wrote in message
news:694C9DF0-5311-482C-920F-B5583645D468@xxxxxxxxxxxxxxxx
Thank you Chris

Let me peruse your code and see what I find.

I know these issues are not trivial, and we have had great success with
our
(internal use only) spinlock which supports nesting,

What do you mean by nesting? Are you writing about recursive reads and
writes?




read/write and dead locker handling.

Do you mind if I ask how your doing that? ;^)

This is hard to do with custom locks. One time, a long time ago, I created a
scheme in which a client process would mark itself as being within a
critical section. A watchdog process monitored said client process. If the
watchdog noticed that the client died, it would check if was in a critical
section. If it was, it set a piece of state owned by the critical section to
abandoned and forcefully unlocked it. The actual lock structure was based on
a fast-path semaphore. Something like this:

http://groups.google.com/group/comp.programming.threads/browse_frm/thread/6f2a5ca67aa4447

The next locker that came around would notice the abandoned state and
attempt to repair the shared data-structure and revert it back into a
coherent state. If a process dies while it has write access, all bets are
off and you need a robust recover strategy.


I am interested in reading about how you accomplish this.







FWIW, check this read/write strict FIFO spinlock out, it uses atomic
fetch-and-add (e.g., InterlockedExchangeAdd()), in pseudo-code w/ membars
ommited for clarity:
____________________________________________________________
class rwspinlock {
enum constant {
WRITE = 1,
READ = 0x10000
};


atomic_word m_next; // = 0
atomic_word m_cur; // = 0


public:
void rdlock() {
atomic_word ticket = ATOMIC_FAA(&m_next, READ) % READ;
while (ticket != (ATOMIC_LOAD(&m_current) % READ))) backoff();
}


void rdunlock() {
ATOMIC_FAA(&m_current, READ);
}


public:
void wrlock() {
atomic_word ticket = ATOMIC_FAA(&m_next, WRITE);
while (ticket != ATOMIC_LOAD(&m_current)) backoff();
}


void wrunlock() {
ATOMIC_FAA(&m_current, WRITE);
}
};
____________________________________________________________



This AWESOME algorithm was invented by Joe Seigh who can be contacted here:

http://atomic-ptr-plus.sourceforge.net



I believe its the smallest FIFO rw-spinlock in the world. It even works with
wrap and carry out from the writer field into the reader field. Caveat,
number of waiting threads has to be less than field size.


.



Relevant Pages

  • [git pull] core kernel updates for v2.6.29
    ... swiotlb extensions to make it available to 32-bit ... lock debug: sit tight when we are already in a panic ... extern void unblock_signals; ... extern int force_iommu, no_iommu; ...
    (Linux-Kernel)
  • [git pull] core kernel updates for v2.6.29, #2
    ... swiotlb extensions to make it available to 32-bit ... lock debug: sit tight when we are already in a panic ... extern void unblock_signals; ... extern int force_iommu, no_iommu; ...
    (Linux-Kernel)
  • [patch] generic rwsems
    ... This patch converts all architectures to a generic rwsem implementation, ... take a spinlock to take an uncontested rwsem) as a basis. ... better even for architectures that do atomics with hashed spinlocks. ... * lock for reading ...
    (Linux-Kernel)
  • [ANNOUNCE] The -rt git tree
    ... People have also been asking about having an -rt git tree. ... rt/convert-scripts - the scripts to convert spinlocks ... The new lock API. ... where as a spinlock that was declared as raw_spinlock_t would ...
    (Linux-Kernel)
  • Re: Is the following code MT-Safe?
    ... >> void start ... > There is no reason to lock the critical section before starting the thread. ... And the lock won't be released until this exits. ... The assert is part of an _example_, ...
    (microsoft.public.vc.mfc)

Loading