Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to make a function atomic in C?

Is there a way to make a function atomic in C.

I am not looking for a portable solution.(platforms looking for - Win,Linux)

like image 894
FL4SOF Avatar asked Apr 01 '09 07:04

FL4SOF


People also ask

What is an atomic function in C?

Atomics as part of the C language are an optional feature that is available since C11. Their purpose is to ensure race-free access to variables that are shared between different threads. Without atomic qualification, the state of a shared variable would be undefined if two threads access it concurrently.

Is ++ atomic in C?

On objects without an atomic type, standard never defines ++ as an atomic operation.

Is += an atomic operation?

For the change in value to be visible across cores, a += (for instance) would have to load the value, add the increment and then store it. This means that the operation will not be atomic. To ensure atomicity you'd need to put appropriate locking around the operation.

What is atomic type in C?

The type sig_atomic_t is always an integer data type, but which one it is, and how many bits it contains, may vary from machine to machine. Data Type: sig_atomic_t. This is an integer data type. Objects of this type are always accessed atomically. In practice, you can assume that int is atomic.


6 Answers

Maybe.

It depends entirely on your definition of "atomic".

  • In a single core, deeply embedded environment without an operating system involved you can usually disable and enable interrupts. This can be used to allow a function to be atomic against interrupt handler code. But if you have a multi-master bus, a DMA engine, or some other hardware device that can write memory independently, then even masking interrupts might not provide a strong enough guarantee in some circumstances.

  • In an RTOS (real time operating system) environment, the OS kernel usually provides low level synchronization primitives such as critical sections. A critical section is a block of code that behaves "essentially" atomically, at least with respect to all other critical sections. It is usually fundamental to the OS's implementation of other synchronization primitives.

  • In a multi-core environment, a low level primitive called a spinlock is often available. It is used to guard against entry to a block of code that must be atomic with respect to other users of the same spinlock object, and operates by blocking the waiting CPU core in a tight loop until the lock is released (hence the name).

  • In many threading environments, more complex primitives such as events, semaphores, mutexes, and queues are provided by the threading framework. These cooperate with the thread scheduler such that threads waiting for something to happen don't run at all until the condition is met. These can be used to make a function's actions atomic with respect to other threads sharing the same synchronization object.

A general rule would be to use the highest level capabilities available in your environment that are suited to the task. In the best case, an existing thread safe object such as a message queue can be used to avoid needing to do anything special in your code at all.

like image 52
RBerteig Avatar answered Sep 22 '22 07:09

RBerteig


If you want to make sure your function won't be interrupted by signal, use sigprocmask() to mask and unmask signals, although some signals cannot be blocked (like SIGKILL) and behaviour for blocking some signals (like SIGSEGV) is undefined.

See man sigprocmask for details.

like image 42
qrdl Avatar answered Sep 22 '22 07:09

qrdl


Not portably, at least. For some systems, you can probably approach it, by doing things like turning of machine interrupts, to prevent the kernel from pre-empting your function. But it will be very hard, especially for non-embedded systems.

like image 44
unwind Avatar answered Sep 24 '22 07:09

unwind


You'll need platform-specific support to do that - either through use of special compiler intrinsics for hardware instructions, or by using operating system support. Neither C nor C++ has standardized synchronization stuff.

like image 29
snemarch Avatar answered Sep 26 '22 07:09

snemarch


Define what you mean by 'atomic.' Do you mean 'atomic' in the sense that no other process or thread will be selected for scheduling when you run your function? Or do you mean that any shared objects referenced in your function will not be modified by any other threads while your function runs?

For the former, you can't really control that from userspace. If you're on a single-CPU machine you can possibly guarantee atomicity by raising your process priority to the highest priority possible (from userspace). But even then it's not guaranteed because your scheduling algorithm may still allow another process to run. The only reliable way of doing this is from the operating system. For a single-CPU machine you'd disable interrupts. For a multi-core machine you'd need to lock the bus and wait for all processes running on other CPUs to be taken off.

The question here is: why do you want to guarantee atomicity? In general, the requirement that only your process may be running and not others, ought not to exist in userspace. If you want to make sure certain data structures are only accessed by one thread at a time, then you should use a portable thread library (like pthread for example), and fence off your function as a critical section.

like image 22
FreeMemory Avatar answered Sep 22 '22 07:09

FreeMemory


If by atomic you mean 'only one thread at a time', then you could just protect the function with a Critical Section block (in Windows). In Linux, I use a mutex lock/unlock to more or less emulate a critical section.

like image 33
Marc Bernier Avatar answered Sep 23 '22 07:09

Marc Bernier