The so-called atomic operation means that the operation will never be interrupted by any other task or event before execution is completed. That is to say, its smallest execution unit cannot have a smaller execution unit than it, so here the atom actually uses the concept of material particles in physics.
Atomic operations require hardware support, so they are architecture-related. Their APIs and atomic types are defined in the kernel source code tree include/ASM/atomic. in the H file, they are all implemented in assembly language, because the C language cannot implement such operations.
Atomic operations are mainly used to count resources. Many reference counting (refcnt) is implemented through atomic operations. The atomic type is defined as follows:
Typedef struct
{
Volatile int counter;
}
Atomic_t;
The volatile modifier field tells GCC not to optimize the data of this type, and its access is to the memory instead of the register.
Atomic operation APIs include:
This function performs atomic read operations on atomic variables. It returns the value of atomic variable v.
Atomic_read (atomic_t * V );
This function sets the V value of the atomic type to I.
Atomic_set (atomic_t * V, int I );
This function is used to add value to variable V of the atomic type.
Void atomic_add (int I, atomic_t * V );
This function deducts I from variable V of the atomic type.
Atomic_sub (int I, atomic_t * V );
This function deducts I from the variable V of the atomic type, and determines whether the result is 0. If it is 0, true is returned. Otherwise, false is returned.
Int atomic_sub_and_test (int I, atomic_t * V );
This function increases the value of V to 1.
Void atomic_inc (atomic_t * V );
This function is used to subtract 1 from the V atom variable of the atomic type.
Void atomic_dec (atomic_t * V );
This function subtract 1 from the V atom variable of the atomic type and determines whether the result is 0. If it is 0, true is returned. Otherwise, false is returned.
Int atomic_dec_and_test (atomic_t * V );
This function increases the value of V to 1 and determines whether the result is 0. If the value is 0, the system returns true. Otherwise, the system returns false.
Int atomic_inc_and_test (atomic_t * V );
This function increases I on the V atom of the atomic type variable and determines whether the result is negative. If yes, it returns true; otherwise, it returns false.
Int atomic_add_negative (int I, atomic_t * V );
This function adds I to the V atom variable of the atomic type and returns a pointer to v.
Int atomic_add_return (int I, atomic_t * V );
This function deducts I from variable V of the atomic type and returns a pointer to v.
Int atomic_sub_return (int I, atomic_t * V );
This function increases the value of V to 1 and returns a pointer to v.
Int atomic_inc_return (atomic_t * V );
This function reduces the value of V atom by 1 and returns a pointer to v.
Int atomic_dec_return (atomic_t * V );
Atomic operations are usually used to implement reference counting of resources. In the IP Fragment processing of the TCP/IP protocol stack, reference counting is used, and the fragmentation queue structure struct ipq describes an IP fragment, the refcnt field refers to the reference counter. Its type is atomic_t. When an IP fragment is created (in the ip_frag_create function), use the atomic_set function to set it to 1. When the IP fragment is referenced, use the atomic_inc function to add 1 to the reference count.
When you do not need to reference the IP fragment, you can use the ipq_put function to release the IP Fragment. ipq_put uses the atomic_dec_and_test function to reduce the reference count by 1 and determine whether the reference count is 0, if yes, the IP fragmentation will be released. The ipq_kill function deletes IP fragments from the ipq queue and reduces the reference count of the deleted IP fragments by 1 (implemented by using the atomic_dec function)
This operation is often used to condition variables such as wait_event (queue, condition)
Static atomic_t io_port_available = atomic_init (1 );
Atomic_dec_and_test (& io_port_available)
If the condition is not met, restore: atomic_inc (& io_port_available );
Then congestion and judgment if (wait_event_interruptible (io_port_wait, atomic_read (& io_port_available )))
Determine whether congestion is terminated
One Party holding the atomic operation can perform the following operations:
Atomic_inc (& io_port_available);/* release the device */
Wake_up_interruptible_sync (& io_port_wait);/* awake other UID's */
Atomic_t atomic operation