Sign in to follow this  
janta

What is a "fence" ?

Recommended Posts

Yes, a fence like in MSDN's InterlockedIncrement documentation:
Quote:
This function generates a full memory barrier (or fence) to ensure that memory operations are completed in order.
In fact I have found some code where there is somthing like:
{
    LONG l1 = 0, l2 = 0;
    InterlockedExchange(&l1, l2);
}
(please note the brackets, and that l1 and l2 are stack object with local scope.) At first I thought that would be legacy code, as it seems to have no side effect at all, but I fugured that InterlockExchange might have some sort of important side effect... Anyone could enlight me ? Regards JA

Share this post


Link to post
Share on other sites


And no, I'm not making a joke. Barrier in this instance is correctly described as a "fence" in the sense that it is an enclosure meant to restrict entry or exit from an area, in this case the area being a space in memory. We might stretch this to call it a metaphor - if a developer doesn't understand the usage of the word "barrier" in that part of the documentation, then the supplementary usage of the world "fence" should clear it up for any speaker of the english language.

Share this post


Link to post
Share on other sites
I understand that on a general purpose a fence is to protect sth or prevent smn from acessing something.
So in our programming world, such a fence is supposed to prevent who from acessing what particular memory ? Couls you give an axample of a situation in which this might be of use. On my side, I got the following:


bool WorkerSleep()
{
while (/* some condition */)
WaitForSingleObject( newJob, 5 );

LONG l1 = 0, l2 = 0;
InterlockedExchange(&l1, l2);

return someGlobal == 0;
}


I admit I dont really get the point.

Share this post


Link to post
Share on other sites
Quote:
Original post by janta
I admit I dont really get the point.


Picture, if you will, what would happen if you've got, say, a dual-core CPU and both cores are trying to access the same piece of memory.

If you've set up a memory barrier, it will force a mutual exclusion on that region of memory. More than that: the CPU cores will not be cacheing that chunk of RAM, either.

Memory barriers are the key to lock-free threading semantics. they allow much faster interprocessor synchronization, at the expense of increased difficulty in getting things right.

Share this post


Link to post
Share on other sites
Two CPUs:

CPU1 :: REG1 :: CACHE1 :: RAM :: CACHE2 :: REG2 :: CPU2

CPU 1 goes and modifies a global varibale, then sends a signal.

CPU 2 notices the single, and then reads the global variable.

The problem is, what if CPU1 had the global variable in his cache, and it hadn't synced to RAM yet? Well, then, CPU2 gets the old value. Oh crap, the world just exploded.

But, if you do some operations, dirty data in all cache's are dumped to RAM. Now when you read the global variable, you the right one.

That may be what is going on. Naturally the above would be highly implementation and architecture sensative.

Share this post


Link to post
Share on other sites
Quote:
Original post by Bregma
If you've set up a memory barrier, it will force a mutual exclusion on that region of memory. More than that: the CPU cores will not be cacheing that chunk of RAM, either.

That sounds quite clear to me. Still, I wonder:
1/ What control do you have over what region of memory is being put under such protection ?
2/ What control do you have over when that protection will end (or will it last until the memory is "released by the process" ?)

- JA

Share this post


Link to post
Share on other sites
Quote:
Original post by janta
Quote:
Original post by Bregma
If you've set up a memory barrier, it will force a mutual exclusion on that region of memory. More than that: the CPU cores will not be cacheing that chunk of RAM, either.

That sounds quite clear to me. Still, I wonder:
1/ What control do you have over what region of memory is being put under such protection ?
2/ What control do you have over when that protection will end (or will it last until the memory is "released by the process" ?)


Generally speaking, barriers are implemented as atomic operations on small addressible chunks of memory (such as a "word," a unit of storage that can be loaded and manipulated in a single CPU instruction).

A classic implementation would be a test-and-set instruction, or an atomic swap instruction (the contents of a memory address and a register are swapped and status bits set depending on the value in memory).

Additional requirements are that the instruction cannot be interrupted (eg. what if a page fault occurs between the fetch and the write of a swap? or a timer goes off?) and that some sort of hardware interlock occurs during the transaction, so one CPU has effectively 'seized the bus' obtaining guranteed mutual access to memory for the duration of the operation.

It may also be necessary to force CPUs to invalidate their lookaside registers to force an actual memory access for such an instruction. It's all pretty architecture-specific.


Share this post


Link to post
Share on other sites
The "Fence" used above looks like it was simply preventing cacheing.

In other words, any read to the memory "Fenced" after the moment of "Fencing" would return data that had been written _after_ the "Fencing".

Which data after the fencing -- no guarantees. But it won't give you data that never existed in memory pre-"Fencing".

If you want to do this yourself, there are better ways to do it. For example, most modern processors have a Compare-And-Set operation that can't be fooled by cache's, as far as I know. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this