Re: Synchronization primitives (was:Re: Where is atomicqueue?)
Re: Synchronization primitives (was:Re: Where is atomicqueue?)
- Subject: Re: Synchronization primitives (was:Re: Where is atomicqueue?)
- From: Army Research Lab <email@hidden>
- Date: Tue, 29 Apr 2008 11:11:53 -0400
- Thread-topic: Synchronization primitives (was:Re: Where is atomicqueue?)
On 4/29/08 10:53 AM, "Steve Sisak" <email@hidden> wrote:
> At 7:25 AM -0400 4/29/08, Army Research Lab wrote:
>> I understand the problems with them; however, the case I plan on supporting
>> generally locks for just long enough to write a value to a shared location,
>> with the values being 32 or 64 bit ints. That was why I got interested in
>> the various atomic functions. I know that they have a much higher
>> likelihood of being optimized than using pthread lock/write/unlock.
>
> If this is all you're interested in, you can implement an atomic
> update of a variable with one of the CompareAndSwap variants. (Note
> that the 64-bit versions are only available to 64-bit code, and the
> values must be on natural alignment, etc.)
>
> int32_t *shared_value = <whatever>
> int32_t new_value;
> int32_t old_value;
>
> do
> {
> old_value = *shared_value;
> new_value = <insert your calculation>;
> }
> while (!OSAtomicCompareAndSwap32Barrier(old_value, new_value, shared_value);
>
> At this point new_value has been successfully written and old_value
> contains the
>
> This is actually the basis for most of the OSAtomic*32 operations.
>
> For 64-bit (or non-32-bit) values on a 32-bit system, you would have
> to protect access using a semaphore, spinlock, etc.
>
>>> I would recommend you restrict yourself to supported interfaces.
>>
>> I don't plan on doing otherwise. If I can't find a supported interface for
>> it, then I'll have to find another way.
>
> You can implement a simple spinlock-like protection mechanism for
> multiple values with compare and swap as well (I'll use the OSAtomic*
> convenience functions and leave how to implement them using compare
> and swap as an exercise),
>
> ------------
>
> #define VALUE1_MASK (1 << 0)
> #define VALUE2_MASK (1 << 1)
>
> int32_t *shared_locks = <whatever>
>
> int32_t old_locks;
>
> do
> {
> old_locks = OSAtomicOr32Barrier(VALUE1_MASK, shared_locks);
>
> // old_locks is the value of *shared_locks before
> // you changed it -- if your bit wasn't set, then
> // YOU changed it and now own the lock -- otherwise
> // someone else set it and you don't
> }
> while (old_locks & VALUE1_MASK);
>
> // do your stuff
>
> old_locks = OSAtomicAnd32Barrier(~VALUE1_MASK, shared_locks);
>
> ------------
>
> to implement non-blocking protection you would do:
>
> old_locks = OSAtomicOr32Barrier(VALUE1_MASK, shared_locks);
>
> if (!(old_locks & VALUE1_MASK))
> {
> // you got the lock -- do your stuff
>
> old_locks = OSAtomicAnd32Barrier(~VALUE1_MASK, shared_locks);
> }
>
> ------------
>
> Read the relevant tecnnotes to determine if you need the barrier
> versions or if you can get away with the non-barrier version.
>
> When in doubt, use the barrier version, which forces all writes
> started before it to complete before it. I think you can use
> non-barrier for the unlock as long as you use barrier for the lock --
> there's probably someone here who can correct me if I'm wrong -- but
> the code above is safe.
>
> You'd use a bit to protect each structure you wanted to update
> atomically and more words as needed.
>
> Hopefully this of use.
>
> -Steve
>
> *Disclaimer, this code was typed in Eudora, not a compiler. YMMV.
Actually it is of quite a bit of use! My concern about the OSAtomic*
functions is that they are all defined in libkern/OSAtomic.h. If I
understand Terry Lambert's earlier reply (sent to the list on Thursday,
April 24, 2008, with the subject 'Re: Where is atomicqueue?'), I should only
expect to be able to use this within the kernel (Note that that earlier
conversation was about atomicqueue, and not about the other functions, so
I'm interpreting what he said, and may be interpreting it incorrectly.
Terry, please forgive me [and correct me!] if I'm wrong).
I want to be able to use this from user space. Are there any functions that
are supported from user space and capable of all that the OSAtomic*
functions are?
Thanks,
Cem Karan
Quoting Terry's earlier post:
"""
Short answer:
(1) It's protected by #ifdef __ppc__, so it's PPC only
(2) It's in a header <libkern/OSAtomic.h>, so you should only _expect_
to be able to use it in the kernel; the fact that there are some
inline functions there notwithstanding
(3) The atual implementaiton is as an external symbol in the Libkern
and System6.0 exports for PPC only
So to get at it you will need to be linked against the kernel (you
will need to be either kernel code or a KEXT), you will need to be
running PPC-only, and you will need to declare an explicit dependency
for your KEXT on an exported symbol set or on the entire kernel.
-- Terry
"""
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden