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 - x20f Code with Kiran - Live Coding | Linux Kernel Programming | Kernel Libraries | Part 1 ↗

Multi-Client TCP Server with pthreads Mutex Synchronized - Code-walk of viewer code - Sekhar Pariga ↗
Monday' 28-Sep-2020
Here is a code-walk of a git-hub source submitted by a viewer Sekhar Pariga, which is a Multi-client TCP Server with pthreads Mutex synchronized. Basically it is a Directory Listing Server, that serves ls, cd, pwd of directory functions to connecting TCP clients which are remotely (locally) executed by the server. Server is implemented using multi-thread pthread library, to serve multiple clients simultaneously. Server keeps the each accepted client session details in the queue data structure. Client session queue contains each clients socket-fd and present working directory as a queue node.

Adding your own Kernel Modules into Linux Kernel Source | Linux Kernel Programming ↗
Monday' 28-Sep-2020
Whenever you do custom kernel modules, you can optionally make it a part of existing Linux Kernel source. This does not mean you are submitting your kernel module to the mainline kernel source (i.e kernel.org Linux Kernel Foundation). What I meant is, you can make your kernel module(s) part of Linux Kernel source so that when you compile your kernel you can automatically compile your kernel module(s) too. As well when you create/modify kernel .config configuration file (such as via make menuconfig, etc), you can enable or disable your kernel module(s) too.
To do the same you have to register (and include) your custom Kernel Module's Kconfig and Makefile to the existing Kconfig and Makefile of the Linux Kernel source Here is a detailed multi-episode video of mine which gives the overall idea and the big-picture.

Roadmap - How to become Linux Kernel Developer - Device Drivers Programmer and a Systems Software Expert ↗
Monday' 28-Sep-2020
Many viewers and even sometimes my students ask me how I can become a kernel programmer or just device driver developer and so on. So I shot this video (and an add-on video) where I summarized steps and a roadmap to become a full-fledged Linux Kernel Developer.

Weekly News Digest - Week 03 - July 2020 ↗
Monday' 28-Sep-2020
The Linux Channel :: Weekly News Digest - Week 03 - July 2020
> Linux founder tells Intel to stop inventing 'magic instructions' and 'start fixing real problems'
> QNAP launches its first 2.5GbE network switch - QSW-1105-5T
> Japan's ARM-based Fugaku is the world's fastest supercomputer
> FreeBSD Back To Seeing Progress On 802.11ac WiFi Support, Ath10k Driver
> Sparkfun Launches the ZED-F9R GPS Dead Reckoning Raspberry Pi pHAT for Mobile Robots
> ODROID-N2 Plus SBC Gets Amlogic S922X Rev. C Processor Clocked at up to 2.4 GHz
> Rock Pi E SBC Comes with WiFi, Bluetooth, Two Ethernet Ports, and Optional PoE

Nmap Network Scanning ↗
Monday' 28-Sep-2020

IP-in-IP Tunneling Demystified - VPN Tunnels ↗
Monday' 28-Sep-2020
There can be many ways one can architect VPN Networks. The end objective is to tunnel private IP (typically LAN subnets) within public IP Networks (such as Internet). You can establish such a tunnel in various creative ways, such as Transport Mode, Tunnel Mode, IP-in-IP tunneling, etc. Also you can choose any transport layer protocol of your choice such as send VPN traffic via TCP, or via UDP and so on.

Slow RGB Fade via Arduino UNO ↗
Monday' 28-Sep-2020

PHP installation ↗
Monday' 28-Sep-2020

Layer-2 (L2) Multicast Frame Deep Analysis ↗
Monday' 28-Sep-2020

Management ↗
Monday' 28-Sep-2020


Trending Video:
Watch on Youtube - x20f Code with Kiran - Live Coding | Linux Kernel Programming | Kernel Libraries | Part 1 ↗

Linux Device Drivers, 3rd Edition PDF Book ↗
Monday' 28-Sep-2020
Here is a quick download link for free Linux Device Drivers, 3rd Edition Book PDF Book.



Recommended Video:
Watch on Youtube - x20f Code with Kiran - Live Coding | Linux Kernel Programming | Kernel Libraries | Part 1 ↗