影片培训班学生们赞助商捐赠活动教程链接新闻联系


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:

kiran@WD-1TB2:/backups/Ramin/atomic_t$ ls
atomic.h  main.c
kiran@WD-1TB2:/backups/Ramin/atomic_t$ gcc -o main main.c
kiran@WD-1TB2:/backups/Ramin/atomic_t$ ls
atomic.h  main  main.c
kiran@WD-1TB2:/backups/Ramin/atomic_t$ ./main 
4
6
7
kiran@WD-1TB2:/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


推荐主题:
Featured Video:
在YouTube上观看 - [1640//0] x270 IP Multi-homing | whatever happened to SCTP and now MPTCP - Part 1 ↗

libpcap Library | Linux User-space Network Stack Development ↗
Sunday' 06-Aug-2023
libpcap is a very popular user-space networking library, with which you can capture and or generate packets. libpcap is the underlying framework for many popular packet capture tools such as tcpdump, Wireshark and so on. In fact libpcap is a part of tcpdump project. But besides just using it as a packet capture tool, you can use libpcap in various applications, such as user-space based networking stack development, etc. In some cases libpcap is yet another alternative to raw-sockets and tun/tap interfaces.

The Linux Channel :: Sponsors ↗
Monday' 30-May-2022
Here is a list of all The Linux Channel sponsors/donors (individual/companies).

Inline Programming | Assembly | Scripts | php, python, shell, etc | Rust in Linux Kernel ↗
Friday' 12-May-2023
Inline programming is a technique where code statements are included directly in the text of a program, instead of being contained in separate files or modules. Inline programming can be useful for small or simple tasks, as it can eliminate the need for a separate script or function. One common example of inline programming is using JavaScripts, Php, etc in HTML documents to create dynamic content. Similarly in Linux Kernel we can find lot of instances where we can find inline programming such as inline assembly and now Rust within the Kernel source.

Linux Kernel /sysfs Interface ↗
Saturday' 14-May-2022
/sysfs is one of the most popular kernel to user-space interface which you can leverage to add an interface to your Kernel code such as Kernel modules, Kernel Device Drivers, etc. Although personally I prefer /proc interface than other alternatives such as /sysfs, ioctl() and so on for my personal Kernel modules/stack. So here is my detailed multi-episode Youtube video series on /sysfs Interface.

Rockchip ROC-RK3566-PC from Firefly | OpenWRT ↗
Thursday' 19-Oct-2023
Here is my multi-episode video series on evaluation of Rockchip ROC-RK3566-PC from Firefly with stock OpenWRT firmware.

What is purpose of Kernel Development - Example SMOAD Networks SDWAN Orchestrator Firewall Kernel Engine ↗
Monday' 18-Jul-2022
Often aspiring students may have this question, that what is the purpose of Linux Kernel Development. Since Linux Kernel is very mature and it has almost everything one would need. Usually, we need custom kernel development in the case of any new driver development for new upcoming hardware. And this happens on and on. But at times we may also come across few features/modules/components which are already provided by the Linux Kernel which are not adequate or atleast not the way we exactly intended to use. So, this is the real-world example, sometimes no matter what Linux Kernel provides as a part of stock Kernel/OS features, sometimes we have to write our own custom kernel stack or module(s) which can specifically cater our exact needs.

Linux Kernel Driver Device Trees ↗
Tuesday' 17-Jan-2023
The Linux kernel is the backbone of the Linux operating system. A device tree is a hierarchical tree structure that describes the various devices that are present in a system, including their properties and relationships to one another. The device tree is used by the Linux kernel to identify and initialize the different devices on a system, and to provide a consistent interface for interacting with them.

Linux Kernel vs User-space - Library APIs - Linux Kernel Programming ↗
Friday' 27-Oct-2023
One of the important aspects a beginner who is into Linux Kernel space systems software development has to understand is that unlike user-space C/C++ programming, where you can freely include any library APIs via respective #include files (which are dynamically linked during run-time via those /lib .so files), in the case of Kernel space programming, these library APIs are written within the Kernel source itself. These are the fundamental APIs which we commonly use, such as memcpy(), memcmp(), strlen(), strcpy(), strcpy() and so on. So here is my detailed Youtube video episode on the same with live demo, walk-through and examples.

Porting Sample libpcap C code to Raw Sockets | User-space Network Stack Framework ↗
Monday' 04-Sep-2023
Here is my multi-episode video series where I demonstrate how you can port the my libpcap sample code, discussed in the earlier episode to raw-socket. This code should further help you to design and architect your own user-space Network stack on top of this fundamental framework.

Roadmap - How to become Systems Software Developer ↗
Friday' 13-May-2022
When you are at the beginning of your career or a student, and aspire to become a software developer, one of the avenues to choose is to become a hard-core Systems Software Developer. However it is easier said than done, since there are many aspects to it as you explore further. As a part of systems developer, you can get into core kernel space developer, kernel device drivers developer, embedded developer and get into things like board bring-up, porting, etc, or can become a user-space systems programmer, and so on. So here is my detailed multi-episode Youtube video series on Roadmap - How to become Systems Software Developer.


Trending Video:
在YouTube上观看 - [1950//0] 157 Wireshark - Investigate TCP-Connections with Wireshark Flow Graph feature ↗

Linux Kernel vs User-space - Library APIs - Linux Kernel Programming ↗
Friday' 27-Oct-2023
One of the important aspects a beginner who is into Linux Kernel space systems software development has to understand is that unlike user-space C/C++ programming, where you can freely include any library APIs via respective #include files (which are dynamically linked during run-time via those /lib .so files), in the case of Kernel space programming, these library APIs are written within the Kernel source itself. These are the fundamental APIs which we commonly use, such as memcpy(), memcmp(), strlen(), strcpy(), strcpy() and so on. So here is my detailed Youtube video episode on the same with live demo, walk-through and examples.



Recommended Video:
在YouTube上观看 - [103//0] x271 IP Multi-homing | whatever happened to SCTP and now MPTCP - Part 2 ↗