Re: How to properly initialize shared memory on Unix?




Chris Thomasson wrote:
You need to be sure that the "operations" effects on shared memory are
visible, before the updates to the "4-byte value" become visible... You
would use a memory barrier instruction (e.g., membar #StoreLoad|#StoreStore)
after the operations. Of course, when a crash occurs you might not be so be
sure that the membar instruction was even executed...

Agree with you on memory/compiler barriers. As David said, mutex (and
most of other synchronization primitives) enforce memory barrier,
that's for sure. But it does not necessary enforce the compiler
optimization barrier (which may also reorder writes). In most compilers
there are intristic functions which enforce compiler and/or memory
barriers. Well, anyway a combination is necessary, to ensure that the
"state consistent" flag is updated last, after everything else is
stored to the memory, and neither CPU nor optimizer reorder this flag
write. Repeating the pseudo-code provided by one of you earlier:

.............
writing to the shared memory
write or full memory barrier
write the consistency flag
unlock the mutex

Once again, in my case the data structures allow committing the
transaction by a single value, which is extremily simplifies my life
:-) if the value is not written, it's like nothing happened.

David Hopwood wrote:
That isn't sufficient. Since the compiler may reorder the write to
the 4-byte value before previous writes, you really do need the memory
barriers (even on architectures with fairly strong memory ordering such
as x86 and SPARC).

Thanks. After I read more on compiler and memory barriers, I've got
much better understanding of the picture. I've tried to play with VC++
compiler and its optimizer. Unfortunately, barrier support is poorly
documented. I found several barrier functionsin MSDN, but some of them
are missing, others are only defined for AMD64, and finally I found
those that work, it's just that they require defining bizzare #pragmas
or asm {} insertions :-) On other platforms (Linux, AIX, Solaris) I
also found the barrier functions but did not try them. HP-UX docs say
volatile is enough for their platform :-)

Alexander Terekhov wrote:
David Hopwood wrote:
Even for POSIX, a platform would be severely broken if a crash could cause
the state of a *shared* mutex to become undefined.
In a sense, the state is indeed undefined. A watchdog process should
emergently recycle the whole crew and stuff (hoping that the platform
is smart enough to reclaim all its internal shared mutex resources
(if any) that it might hold... at last when corresponding shared
memory is reclaimed).

That's quite unfortunate (difficult to use) in a case when the shared
memory is used from a shared library which is opened from multiple
independent processes, and there is no a single master process. If one
of the processes crashes, and leaves the mutex locked, it becames
difficult to decide when to unlock it. One of potential solutions I
thought of would be having a process id of the locking process stored
in the shared memory, and if there is a timeout, another process could
test if that process is alive.
Once again, comparing Windows mutexes and POSIX semaphore-based
mutexes, I don't see any bad in auto-unlock feature (assuming
consistency of my memory structures may be controlled by some flag,
which is anyway necessary).

BTW, ACE library implements SystemV mutexes (semaphores) with this
auto-unlock semantic. They have a very nice implementation there, with
workaround for a race condition on initialization, and even reference
counting :-)

Could somebody advice me where to look for a cross-platform sources for
memory barriers?...

Sincerely,

Andrew

.



Relevant Pages

  • Re: WaitForSingleObject() will not deadlock
    ... Whatever memory values a thread can see when it creates a new thread can ... that later locks the same mutex. ... standardized multithreading library designed to run efficiently on existing ... A C compiler is not required to do this, and it can still be a conforming C ...
    (microsoft.public.vc.mfc)
  • Re: WaitForSingleObject() will not deadlock
    ... Whatever memory values a thread can see when it creates a new thread can ... data written after the mutex is ... standardized multithreading library designed to run efficiently on existing ... A C compiler is not required to do this, and it can still be a conforming C ...
    (microsoft.public.vc.mfc)
  • Re: Broken ARM atomic ops wrt memory barriers (was : [PATCH] Add cmpxchg support for ARMv6+ systems)
    ... I would not remove the "memory" constraint in here. ... If you don't already know that smp_mbis always a compiler barrier then ... this statement may be re-ordered after it, and no accesses after the ...
    (Linux-Kernel)
  • [PATCH] Document Linuxs memory barriers
    ... The attached patch documents the Linux kernel's memory barriers. ... Linux kernel memory barrier functions. ... +Older and less complex CPUs will perform memory accesses in exactly the order ... +In all cases there are variants on a LOCK operation and an UNLOCK operation. ...
    (Linux-Kernel)
  • Re: [PATCH 0/24] make atomic_read() behave consistently across all architectures
    ... piece of memory has changed" which is what the barrier() does. ... implicit (compiler, possibly "light-weight" of the kind referred above) ...
    (Linux-Kernel)

Loading