atomic_add atomic_clear atomic_cmpset atomic_fetchadd atomic_load atomic_readandclear atomic_set atomic_subtract atomic_store - atomic operations
For example, the function to atomically add two integers is called
atomic_add_int (.);
Certain architectures also provide operations for types smaller than ``int ''
These must not be used in MI code because the instructions to implement them efficiently may not be available.
The second variant of each operation includes a read memory barrier.
This barrier ensures that the effects of this operation are completed before the
effects of any later data accesses.
As a result, the operation is said to have acquire semantics as it acquires a
pseudo-lock requiring further operations to wait until it has completed.
To denote this, the suffix
``_acq
''
is inserted into the function name immediately prior to the
``_ Aq Fa type
''
suffix.
For example, to subtract two integers ensuring that any later writes will
happen after the subtraction is performed, use
atomic_subtract_acq_int (.);
The third variant of each operation includes a write memory barrier.
This ensures that all effects of all previous data accesses are completed
before this operation takes place.
As a result, the operation is said to have release semantics as it releases
any pending data accesses to be completed before its operation is performed.
To denote this, the suffix
``_rel
''
is inserted into the function name immediately prior to the
``_ Aq Fa type
''
suffix.
For example, to add two long integers ensuring that all previous
writes will happen first, use
atomic_add_rel_long (.);
A practical example of using memory barriers is to ensure that data accesses that are protected by a lock are all performed while the lock is held. To achieve this, one would use a read barrier when acquiring the lock to guarantee that the lock is held before any protected operations are performed. Finally, one would use a write barrier when releasing the lock to ensure that all of the protected operations are completed before the lock is released.
*p += v;
*p &= ~v;
if (*dst == old) {
*dst = new;
return 1;
} else
return 0;
The
atomic_cmpset ();
functions are not implemented for the types
``char
''
``short
''
``8
''
and
``16
''
tmp = *p; *p += v; return tmp;
The
atomic_fetchadd ();
functions are only implemented for the types
``int
''
and
``32
''
and do not have any variants with memory barriers at this time.
return (*addr)
The
atomic_load ();
functions always have acquire semantics.
temp = *addr; *addr = 0; return (temp);
The
atomic_readandclear ();
functions are not implemented for the types
``char
''
``short
''
``ptr
''
``8
''
and
``16
''
and do
not have any variants with memory barriers at this time.
*p |= v;
*p -= v;
*p = v;
The
atomic_store ();
functions always have release semantics.
The type ``64 '' is currently not implemented for any of the atomic operations on the arm i386 and powerpc architectures.
/* Try to obtain mtx_lock once. */
#define _obtain_lock(mp, tid) \
atomic_cmpset_acq_ptr(&(mp)->mtx_lock, MTX_UNOWNED, (tid))
/* Get a sleep lock, deal with recursion inline. */
#define _get_sleep_lock(mp, tid, opts, file, line) do { \
uintptr_t _tid = (uintptr_t)(tid); \
\
if (!_obtain_lock(mp, tid)) { \
if (((mp)->mtx_lock & MTX_FLAGMASK) != _tid) \
_mtx_lock_sleep((mp), _tid, (opts), (file), (line));\
else { \
atomic_set_ptr(&(mp)->mtx_lock, MTX_RECURSE); \
(mp)->mtx_recurse++; \
} \
} \
} while (0)
|
Закладки на сайте Проследить за страницей |
Created 1996-2025 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |