Re: Named shared memory without synchronization
- From: Dan Schwartz <DanSchwartz@xxxxxxxxxxxxxxxxxxxxxxxxx>
- Date: Fri, 24 Nov 2006 04:44:01 -0800
Thank you for your reply.
"Igor Tandetnik" wrote:
Any reasoning about the behavior of a program in the presence of
multiple threads and such is necessarily specific to a particular
implementation, not the C language in general.
Nevertheless, assuming an x64/x86 architecture (portability being a
secondary issue for me, at least for the time being) implies atomic
operations on the int level, does it not?
Some processors only support loading a register from a word-aligned
memory address with a single machine instruction. Reading an unaligned
word then requires several instructions - reading two aligned words that
the word of interest overlaps, then doing some shifts and bitwise
operations to bring two halves together in the register. The CPU can of
course be interrupted after reading one half and before reading the
other, which could change right under it.
Again, if I assume an x86/x64 architecture I think i can get away with this,
since integers will be aligned by default. I'm not aware of an instance where
this is not true (unless using #pragma pack). Again, correct me if I'm wrong.
So again, as of VC8, any read or write to volatile variable issues a
memory barrier, which allows one to avoid certain "interesting" effects
on some SMP architectures. Earlier compiler versions (and many non-MS
compilers) don't do that, so volatile does not help any for mulithreaded
synchronization.
This is good news to me, since portability is currently a secondary issue
for my app.
If I understand you correctly, using the volatile keyword will ensure (at
least with VC8) that
the solution I suggest (see details below) will also work with dual core
processors (which is not mandatory right now, but nice to have).
Of course the OS-provided synchronization functions (WaitForSingleObjectI'm not trying to achieve synchronization as such (again, see details below).
et al) and Interlocked* functions issue all the necessary memory
barriers, so one doesn't need to worry about such arcane details when
using them.
The only intervening function call was a delay call (see below).The integer seems toThat wouldn't be the case if you were to, say, read it in a tight loop
be fetched again for every access.
without any intervening function calls.
:)In general, after substantialThat's the problem with multithreaded programming: the bugs have the
testing, I haven't found drawbacks to this no-lock strategy.
tendency not to come up during testing. We are talking extremely subtle
effects here: consider the task of debugging a system that only fails
seemingly randomly, approximately once a week, at the customer's site
when running on a 4-way server under heavy load. This task will be yours
if you don't take the time to understand the issues (or else, switch to
a safer implementation utilizing locks or interlocked instructions).
This is exactly what I'm trying to avoid, hence my post here.
My question(s):This depends on exact details of what you are doing. From what little
Is this really a stable solution?
you disclosed, I have my doubts.
If not, does this mean that the same strategy would work for threadWhat strategy? What are you synchonizing? Show some code.
synchronization of an integral global variable?
I don't have the actual "proof-of-concept" code with me. I will post it
later if necessary.
However, I think I can describe it well enough for our purpose:
What I'm trying to achieve is a sort of watchdog behavior, where one process
(the server) will
terminate another (the client) if it does not send an "I'm alive" message
within a predefined
timeout. My suggested solution works as follows:
1. Server names shared memory after the client's executable name.
2. Server defines a pointer (we'll call it x) to an integer in the shared
memory block.
3. Server runs client (createprocess etc...).
4. Client defines a pointer (x) to an integer in the shared memory block
named after its own name
5. Client does his work. Assuming the duration of the client's "main loop"
is at most t seconds,
client resets x (e.g *x=t) every t seconds.
6. Server wakes up every second and does:
if (!((*x)--)) {
terminateprocess(client);
createprocess(client);
}
(note that in reality, the server actually provides watchdog services for
multiple clients, but I don't think it's relevant in the context of this
discussion)
To the best of my understanding, the only two concerns would be:
1. That the integer pointed at by x isn't somehow corrupted by a combined
read/write.
2. That the integer pointed to by x is properly updated when the server
reads it.
From what I gathered from your, as well as Alex's post, if I stick toprimitive types and declare them volatile I'm quite safe.
Given my description, do you share my opinion?
Thanks,
Dan
.
- Follow-Ups:
- Re: Named shared memory without synchronization
- From: Igor Tandetnik
- Re: Named shared memory without synchronization
- From: adebaene
- Re: Named shared memory without synchronization
- References:
- Re: Named shared memory without synchronization
- From: Igor Tandetnik
- Re: Named shared memory without synchronization
- Prev by Date: Generate output list file
- Next by Date: Re: Named shared memory without synchronization
- Previous by thread: Re: Named shared memory without synchronization
- Next by thread: Re: Named shared memory without synchronization
- Index(es):
Relevant Pages
|