03-07-2013 01:36 PM
I have process A and process B.
In process A, I want to use lib$movc3 to move a number of pages of memory from one location to another.
However, process B is periodically updating some of these pages of memory. If process B happens to try to update a page that process A is copying using lib$movc3, will the copy be successfully done (i.e. without partial updates by process B)?
Is lib$movc3 atomic?
03-08-2013 06:29 AM
Thanks... Maybe there is one clarification I should make (I'm sure it doesn't make a difference) ... in the scenario presented, Process B is also using lib$movc3 to modify a page of memory.
03-08-2013 06:45 AM - edited 03-08-2013 06:46 AM
The answer is still NO, possibly: "No Way! What were you thinking?"
You need some sort of synchronization method. Probably a LOCK.
Check out the manuals (or help) for SYS$ENQ(w)
For very low frequency (less than 1/second?) and lazy programming you could even consider expoiting an RMS record lock with the WAIT (RAB$V_WAT) option, allthough SYS$ENQ is not all that much harder to program
If you explain more of the context, then perhaps we can provide a better answer.
Things like 'how often', 'how much (data)', 'how many (processes)',...
What changes can be made? threading? implemenation language.
03-08-2013 07:21 AM
Thanks for the difinitive answer :)
I know I could use a lock, but was wondering if I could get away without it for performance purposes.
Just to complete the picture:
We have Global Section A (GS_A) and Global Section B (GS_B)
1- Process A takes the lock on GS_A and copies a list of some memory pages from GS_A to GS_B and releases lock.
2- Process A then copies the pages from GS_B to disk.
3- Goto 1
I wanted to change so that:
Process B takes the lock on GS_A and copies a list of some memory pages from GS_A to GS_B and releases lock. At the same time Process A is copying the pages from GS_B to disk. I do not want to have a lock for the whole GS_B because writing to disk takes too long and Process B can't wait that long.
03-08-2013 07:45 AM
Hmmm.. why use a second process, and (thus) global memory.
Just start an thread in the local process to finish the disk write?
Can probably just use basic AST's to keep everythign alive and synchronized.
If you need that second process/second section, and do not want the copying of the next data to wait for the writing of the current buffer then you'll have to think about granularity. Don't lock the whole section (or do, but under there...) lock pages in the the section. If in use (locked), try for a next one?
I suspect you'll end up using a INSQTI to grab buffers from lists.
It has been done many times before.
Start with a list of free buffers in section B, and an empty work list.
- Grab a buffer from free queue fill it, release to work queue,
- $WAKE process B if work queue was empty
- if free queue was empty, enter self on wait queue node, and $HIBER.
- Grab a buffer from the work queue,
- do the work,
- release to free queue
- if free queue was emtpy then look in wait queue and $wake first entry
- Try to gran a next work buffer, if none then $Hiber.
03-08-2013 09:14 AM
You can also use LIB$BSSI and friends to use a flag in a quadowrd in that shared memory section to implement a semaphore (single bit lock). This is lightweight but the implementation typically is done in a tight CPU bound loop so the wait situation should better be very short.
03-10-2013 04:00 PM
Just to complete the already detailed explanation... even on ancient uniprocessor VAX systems, the only instructions which are atomic are those which are explicitly atomic, ADAWI, BBxxI, INSQTxI etc... Any instruction can be interrupted, for example, for a page fault. Other processes can execute while your process is waiting for the fault to complete. A MOVC instruction can involve many pages, and in extreme cases could incur many page faults and therefore be interrupted many times.
Always take the worst case assumptions about process synchronisation.