This post is useful for you if you are optimizing your code or using or writing some threading library and you need to write some atomic instructions(Addition, Increment and Decrement). There will be mention of compiler options also for creation of static and dynamic library, so in brief definition of static and dynamic:
1. Static libraries (.a): Library of object code which is linked with, and becomes part of the application.
2. Dynamically linked shared object libraries (.so): There is only one form of this library but it can be used in two ways.
(i) Dynamically linked at run time but statically aware. The libraries must be available during compile/link phase. The shared objects are not included into the executable component but are tied to the execution.
(ii) Dynamically loaded/unloaded and linked during execution (i.e. browser plug-in) using the dynamic linking loader system functions.
For list of option across platforms one can go here : http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html
Linux
For atomic addition if you have to update two variables simultaneously then assembly is the only way. As obvious, assembly will be differ for 32 bit and 64 bit. These instructions are for gcc or g++ compiler.
Atomic Addition ::
32 bit ( __i386__)
__asm__ __volatile__ (
"lock; \n"
"addl %1, %0;\n"
"movl %0, %%eax;\n"
:"=m" (m_value), "=a" (result)
:"ir" (valueToAdd)
);
64 bit (__x86_64__) ::
__asm__ __volatile__ (
" lock;\n"
" addq %1, %0; \n"
" movq %0, %%rax"
: "=m"(m_value), "=a" (result)
: "iA"(valueToAdd)
);
Here m_value is variable to which valueToAdd will be added and result will also be updated simultaneously.
Atomic Increment ::
32 bit (__i386__)
__asm__ __volatile__ (
"lock;\n"
"incl %1;\n"
"movl %1, %%eax;\n"
:"=a" (result)
:"m" (m_value)
);
64bit (__x86_64__)
__asm__ __volatile__ (
"lock;\n"
"incq %1;\n"
"movq %1, %%rax;\n"
:"=a" (result)
:"m" (m_value)
);
Here variable m_value and result both will be Incremented atomically.
Atomic Decrement ::
32 bit (__i386__)
__asm__ __volatile__ (
"lock;\n"
"decl %1;\n"
"movl %1, %%eax;\n"
:"=a" (result)
:"m" (m_value)
);
64bit (__x86_64__)
__asm__ __volatile__ (
"lock;\n"
"decq %1;\n"
"movq %1, %%rax;\n"
:"=a" (result)
:"m" (m_value)
);
Here variable m_value and result both will be Decremented atomically.
Solaris (sparc as well as X86)
Here compiler being used is assumed to be forte. Forte really is rich with provided functions and having rich documentation as well. Using these functions one does not have to worry about sparc or x86 architecture or 32 bit or 64 bit model.
Atomic Addition ::
result =(long) atomic_add_long_nv((unsigned long*)&m_value,valueToAdd);
Here m_value is variable to which valueToAdd will be added and result will also be updated simultaneously.
Atomic Increment ::
result =(long) atomic_inc_ulong_nv((unsigned long*)&m_value);
Here variable m_value and result both will be Decremented atomically.
Atomic Decrement ::
result =(long) atomic_dec_ulong_nv((unsigned long*)&m_value);
Here variable m_value and result both will be Decremented atomically.
There are different variations of above functions for different variable types. Regarding static library creation it should be noted that Solaris 10 has dropped support of static libraries and does not ship static system, threading libraries. While porting any library of application from 32 to 64bit -xport64=full option of CC can be very useful.
AIX
Compiler being used here is xlc or xlC. xlC compiler has got some atomic functions but it is not having many variation. It also provides compiler preprocessor indicator to make some simple statements as atomic.
Atomic Addition ::
#pragma omp atomic
result = fetch_and_addlp((long*)&m_value,valueToAdd) + valueToAdd;
fetch_and_addlp function adds valueToAdd to m_value and returns the original value of m_value atomically. So above line updates the m_value as well as result variable.
Atomic Increment ::
#pragma omp atomic
result = ++m_value ;
Variable m_value and result both will be Incremented atomically.
Atomic Decrement ::
#pragma omp atomic
result = --m_value;
Variable m_value and result both will be Decremented atomically.
While compiling in 32bit applications -bmaxdata:0xD0000000/dsa option allows very large address space model and program can specify maxdata value of upto 3.25GB. For porting applications from 32bit to 64bit -qwarn64 option of xlC is very useful.