HOMECOURSESSTUDENTSDONATIONSVIDEOSEVENTSTUTORIALSLINKSNEWSCONTACT


TUTORIALS 》 Linux user-space Atomic Operations via GCC Atomic builtins

Atomic operations provide instructions that execute atomically without interruption. We all know the existence and significance of ATOMIC operations in Linux Kernel context (refer: atomic.h source). This is a part of kernel space can not work on user-space.

User space Atomic Operations :: GCC Atomic builtins: Not many are aware of the feasibility of Linux user-space Atomic operations. If you investigate you find what is known as GCC inbuilts. For example: /usr/include/glib-2.0/glib/gatomic.h
/usr/include/glib-2.0/glib/gatomic.h

So you got what is called as Built-in functions for atomic memory access. You can refer the official GCC online doc on the same: 5.44 Built-in functions for atomic memory access. You can get deep if you do a grep of one of these APIs in /usr/include as shown below:
$ grep sync_fetch_and_add * -R


Article: Atomic Operations - Where did atomic.h go?!? There is an author who did abstraction of these GCC Atomic builtins and wrote high-level abstraction to use the same with ease. Here is his article titled Atomic Operations - Where did atomic.h go?!?

Here is the copy-paste of his source (atomic.h) for quick reference:

//Source: http://golubenco.org/atomic-operations.html
#ifndef _ATOMIC_H
#define _ATOMIC_H

/* Check GCC version, just to be safe */
#if !defined(__GNUC__) || (__GNUC__ < 4) || (__GNUC_MINOR__ < 1)
# error atomic.h works only with GCC newer than version 4.1
#endif /* GNUC >= 4.1 */

/**
 * Atomic type.
 */
typedef struct {
	volatile int counter;
} atomic_t;

#define ATOMIC_INIT(i)  { (i) }

/**
 * Read atomic variable
 * @param v pointer of type atomic_t
 *
 * Atomically reads the value of @v.
 */
#define atomic_read(v) ((v)->counter)

/**
 * Set atomic variable
 * @param v pointer of type atomic_t
 * @param i required value
 */
#define atomic_set(v,i) (((v)->counter) = (i))

/**
 * Add to the atomic variable
 * @param i integer value to add
 * @param v pointer of type atomic_t
 */
static inline void atomic_add( int i, atomic_t *v )
{
	(void)__sync_add_and_fetch(&v->counter, i);
}

/**
 * Subtract the atomic variable
 * @param i integer value to subtract
 * @param v pointer of type atomic_t
 *
 * Atomically subtracts @i from @v.
 */
static inline void atomic_sub( int i, atomic_t *v )
{
	(void)__sync_sub_and_fetch(&v->counter, i);
}

/**
 * Subtract value from variable and test result
 * @param i integer value to subtract
 * @param v pointer of type atomic_t
 *
 * Atomically subtracts @i from @v and returns
 * true if the result is zero, or false for all
 * other cases.
 */
static inline int atomic_sub_and_test( int i, atomic_t *v )
{
	return !(__sync_sub_and_fetch(&v->counter, i));
}

/**
 * Increment atomic variable
 * @param v pointer of type atomic_t
 *
 * Atomically increments @v by 1.
 */
static inline void atomic_inc( atomic_t *v )
{
	(void)__sync_fetch_and_add(&v->counter, 1);
}

/**
 * @brief decrement atomic variable
 * @param v: pointer of type atomic_t
 *
 * Atomically decrements @v by 1.  Note that the guaranteed
 * useful range of an atomic_t is only 24 bits.
 */
static inline void atomic_dec( atomic_t *v )
{
	(void)__sync_fetch_and_sub(&v->counter, 1);
}

/**
 * @brief Decrement and test
 * @param v pointer of type atomic_t
 *
 * Atomically decrements @v by 1 and
 * returns true if the result is 0, or false for all other
 * cases.
 */
static inline int atomic_dec_and_test( atomic_t *v )
{
	return !(__sync_sub_and_fetch(&v->counter, 1));
}

/**
 * @brief Increment and test
 * @param v pointer of type atomic_t
 *
 * Atomically increments @v by 1
 * and returns true if the result is zero, or false for all
 * other cases.
 */
static inline int atomic_inc_and_test( atomic_t *v )
{
	return !(__sync_add_and_fetch(&v->counter, 1));
}

/**
 * @brief add and test if negative
 * @param v pointer of type atomic_t
 * @param i integer value to add
 *
 * Atomically adds @i to @v and returns true
 * if the result is negative, or false when
 * result is greater than or equal to zero.
 */
static inline int atomic_add_negative( int i, atomic_t *v )
{
	return (__sync_add_and_fetch(&v->counter, i) < 0);
}

#endif

You can download the above source (atomic.h) HERE.

Ramin (one of my students), who solely did this entire study/research and to confirm the GCC Atomic built-ins and the atomic.h abstraction layer, wrote the below sample code to test some of the APIs/features:

//Author : Ramin Farajpour Cami

#include "atomic.h"
#include <stdio.h>

int main(){

	atomic_t v;                   /* define v */
	atomic_t u = ATOMIC_INIT(0);  /* define u and initialize it to zero */

	atomic_set(&v, 4);     /* v = 4 (atomically) */
	printf("%d\n", atomic_read(&v));

	atomic_add(2, &v);     /* v = v + 2 = 6 (atomically) */
	printf("%d\n", atomic_read(&v));

	atomic_inc(&v);        /* v = v + 1 = 7 (atomically) */
	printf("%d\n", atomic_read(&v));

	return 0;
}

You can download the above source (main.c) HERE.

You can now compile and test the same as shown below:

[email protected]:/backups/Ramin/atomic_t$ ls
atomic.h  main.c
[email protected]:/backups/Ramin/atomic_t$ gcc -o main main.c
[email protected]:/backups/Ramin/atomic_t$ ls
atomic.h  main  main.c
[email protected]:/backups/Ramin/atomic_t$ ./main 
4
6
7
[email protected]:/backups/Ramin/atomic_t$

Run-time performance of various synchronization mechanism: A random find by Saravanan (one of my students), found an article where the author Alexander Demin, a Russian programmer, did interesting research on performance of various synchronization mechanisms. You can read his detailed article/research titled: Comparing the performance of atomic, spinlock and mutex. And here is his benchmarks:
MethodTime (sec.)
No synchronization0.070
LOCK0.481
Atomic0.457
Spinlock0.541
Mutex22.667

So this way you can use Atomic variables either directly or via abstraction layer in regular user-space Linux C programming. You can further experiment atomic operations in your concurrent multi-threaded applications where synchronization and data-integrity is critical.


Featured Video:



Suggested Topics:


☆ Tutorials :: Arduino UNO Projects ↗


☆ Tutorials :: Network Software Development ↗


☆ Tutorials :: Research and Projects ↗


☆ Tutorials :: Linux (user-space), Systems Architecture ↗


☆ Tutorials :: Linux Kernel Software Development ↗


☆ Tutorials :: Linux Kernel Internals (PDFs) - by Ramin Farajpour ↗


☆ Tutorials :: Software Development (Programming) Tools ↗


☆ Tutorials :: Embedded Projects ↗

Join The Linux Channel :: Facebook Group ↗

Visit The Linux Channel :: on Youtube ↗


💗 Help shape the future: Sponsor/Donate


Recommended Topics:
Featured Video:
Watch on Youtube - x226 Linux Kernel Tasklets | Big-Picture | vs User-Space pth... ↗

Raspberry Pi OS with PIXEL ↗
Saturday' 13-Mar-2021

Programming Language Performance and Overheads ↗
Saturday' 13-Mar-2021
A detailed Youtube video series of various programming language performance and overheads - a big picture

What is a Linux Kernel Module - a Big Picture ↗
Saturday' 13-Mar-2021
Learning Linux Kernel Programming is always fascinating and yet challenging. So generally you may tend to learn Kernel Module programming, since such a module can be dynamically plugged into running Linux Kernel. But this will lead to confusion, and many assume kernel source is mostly a collection of these modules. Which in reality is not. Not just that, when we say Kernel Module, its a vaguely defined term. The term Module (as we know) is nothing but a collection of APIs, bunch of variables and associated data-structures. Which may or may not be a plugable kernel module. If you ask me, I am a fan of wiring Linux Kernel Modules, which may not be necessarily a pluggable kernel module. It all boils down to the address space at which these modules function inside a monolithic Linux Kernel. Which is nothing but Linux Kernel's address space. Hence here is my detailed multi-episode Youtube video series on Linux Kernel modules, a big picture and the significance of the

Linux Kernel Programming | with or without Kernel Modules | Device Drivers ↗
Saturday' 13-Mar-2021
When learning Linux Kernel programming, often I notice my students and viewers gets confused and they start with learning writing Linux Kernel modules. And so they develop the common misconception about Kernel Programming in general. They assume writing code in Linux Kernel means writing kernel modules. Which is absolutely not. Kernel modules are an optional choice and are part of Linux Kernel. But besides modules, Linux Kernel has lot of other mainstream code. Hence if anyone wants to be a Kernel Developer, you should be aware that sometimes you add new code via modules, sometimes without them. And if you ask me, I am not much in favor of writing Kernel modules. Instead in my code, I try to integrate and make them a part of Linux Kernel so that they all get initialized during boot time. Here is an extensive Youtube video of mine on Linux Kernel Programming, with and without Kernel Modules.

Weekly News Digest - Week 03 - June 2020 ↗
Saturday' 13-Mar-2021
The Linux Channel :: Weekly News Digest - Week 03 - June 2020 > KimĪ‡ Micro: A powerful alternative to the Raspberry Pi that supports PCIe cards > Linux Lands And Then Reverts Usage Of Flexible Array Members > AMD Ryzen 4000-Powered Asus Mini PC Challenges Intel's NUC > Aaeon's Raspberry Pi-like Board Bears An Intel 8th Gen Core i7 CPU and 16GB of DDR4 > Linus Torvalds Announces Massive Linux Kernel 5.8 Update > New Cisco Cloud Scale ASIC & 400G Line Card Announced > Key Differences of PoE vs PoE+ vs PoE++ Switches a STH Guide

CEO, CTO Talk ↗
Saturday' 13-Mar-2021

TCP vs UDP an Expert Opinion ↗
Saturday' 13-Mar-2021

Weekly News Digest - Week 5 - February 2018 ↗
Saturday' 13-Mar-2021
> Mini-ITX board fosters flexibility and fights obsolescence > You Can Do Better Than Arduino: Try These Microcontrollers > Open source is 20: How it changed programming and business forever > Since computer technology evolves so rapidly, does it matter if you have 5 or 15 years of experience as e.g. software developer? > Linux Kernel net_device data-structure - possible_net_t nd_net - Network namespace and Linux Containers - Ep7 > New Wave of Mini Satellites Could Boost Climate Research > Here come all the AI deployments; Now how do we manage AI? > Imagination announces neural network acceleration push

How to start Open-Source Project ↗
Saturday' 13-Mar-2021

Weekly News Digest - Week 8 - February 2018 ↗
Saturday' 13-Mar-2021
> Asymmetric Processor Cores > Using QCT Quanta LB6M 10GbE Switch for Container Networking > Using SSE Instead Of WebSockets For Unidirectional Data Flow Over HTTP/2 > Why IPv6 networks create DNS configuration problems > Hypervisor or containers: Which solution is right for you? > Blockchain for 2018 and Beyond: A (growing) list of blockchain use cases > Raw sockets backdoor gives attackers complete control of some Linux servers


Trending Video:
Watch on Youtube - x22f Linux Kernel Network Drivers - Classification ↗

Linux user-space Atomic Operations via GCC Atomic builtins ↗
Saturday' 13-Mar-2021



Recommended Video:
Watch on Youtube - x22c Linux Kernel Programming | likely() & unlikely() ↗