In the previous article, the basic principles of synchronization and semaphores in ARMv8 were introduced: An Overview of ARMv8 Memory Types and Attributes.
This article continues to explore this topic by detailing the exclusive-related instructions: Load-Exclusive/Store-Exclusive usage.
1. Local Monitor and Global Monitor
The article on An Overview of ARMv8 Memory Types and Attributes provides a detailed description of local monitors and global monitors.
1. Local Monitor
If memory is marked as Non-shareable, it means that the memory cannot be shared and can only be accessed by a single processor. Therefore, the read-write consistency issues for this type of memory only need to be maintained by the local monitor. The local monitor maintains the exclusive state only within the processor, and since it does not involve sharing the exclusive state across multiple processors, there is no need to mark the actual memory. In hardware implementation, the exclusive state can be marked on the memory address to achieve read-write consistency for a single processor. It can also maintain multi-thread read-write consistency within a single processor by tracking exclusive instructions (Load-Exclusive/Store-Exclusive).
2. Global Monitor
For shareable memory, which can be accessed by multiple processors simultaneously, a Global Monitor is needed to maintain read-write consistency by marking the shared memory’s physical memory for exclusive access: defining a mutex semaphore to ensure multiple reads and single writes during multi-processor concurrency.
According to the ARMv8 manual, the global monitor can exist within the processor or as a secondary monitor within the memory interface. In specific design implementations, the local monitor and global monitor can even be combined into a single unit, providing both local monitor and global monitor functionalities.
The following diagram illustrates one implementation architecture of Exclusive: the local monitors are located within each processor (in the Cortex-A series, such as A53, A55, and A73, the local monitors are all located in the L1 cache), and multiple processors share a global monitor:

2. Simple Use of Exclusive Instructions
In AArch32, the exclusive instructions used are LDREX and STREX:
LDREX R1, [R0]STREX R2, R1, [R0]
In AArch64, the exclusive instructions used are LDXR & STXR:
ldxr w0, [x9]stxr w8, w0, [x9]
Below, we will introduce the simple usage of these two instructions using LDREX and STREX as examples:
LDREX R1, [R0] loads a word (4 bytes) of data from the memory address pointed to by R0 into R1. It also initializes the exclusive state of the Exclusive monitor and marks the memory area pointed to by R0 (of one granule size) as Exclusive access.
STREX R2, R1, [R0] is a conditional store instruction whose successful execution depends on the Exclusive monitor. If the Exclusive monitor detects that the conditions for successfully executing the Store-Exclusive instruction are met:
- The Store operation will execute: the value in R1 will be updated to the memory location pointed to by R0.
- The exclusive state in the monitor will be cleared, and the previously marked Exclusive access memory area will also be cleared.
-
The value in the status register R2 will be set to 0, indicating that the STREX instruction executed successfully.
If the conditions for successfully executing the Store-Exclusive instruction are not met, the Store operation will not proceed, and the value in the status register R2 will be set to 1, indicating that the STREX instruction execution failed.
Additionally, LDREX and STREX are instructions for exclusive access to a word (Word, 32 bit) in memory. If the memory area for exclusive access is not a word, there are other instructions:
- LDREXB and STREXB: for exclusive access to a byte (Byte, 8 bit) in memory;
- LDREXH and STREXH: for exclusive access to a half-word (Half Word, 16 bit);
- LDREXD and STREXD: for exclusive access to a double word (Double Word, 64 bit).
They must be used in pairs and cannot be mixed.
3. Exclusive Example Program
1. Atomic Increment Program
The following example demonstrates the process of using LDXR & STXR to implement an atomic increment:
; extern int atom_add(int *val);_atom_add:mov x9, x0 ; Backup x0 for recovery on failure, x9=x0=*valldxr w0, [x9] ; Read an int from the memory of val and mark Exclusiveadd w0, w0, #1 ; w0=w0+1stxr w8, w0, [x9] ; Attempt to write back to val location, store result in w8cbz w8, atom_add_done ; If w8 is 0, it means success, jump to endmov x0, x9 ; Restore the backup of x0, re-execute atom_addb _atom_addatom_add_done:ret
Another increment program (found in the OSAtomicAdd32 function provided by libkern):
;int32_t OSAtomicAdd32(int32_t __theAmount, volatile int32_t *__theValue);ldxr w8, [x1] ; Load the value of __theValue into w8, while marking Exclusive access stateadd w8, w8, w0 ; w8=w8+w0, w0=__theAmountstxr w9, w8, [x1] ; Write w8 back to *__theValue, result saved in w9cbnz w9, _OSAtomicAdd32 ; Check if w9 is 0, if not, jump to function head, re-execute functionmov x0, x8 ; On success, return w8 as return value.ret lr
2. Atomic Lock Program
For an analysis of this atomic lock program, refer to the original article: ARMv8 Exclusive Operations (II) Exclusive Operation Examples | Jun’s World
; void lock(lock_t *ptr)lock: ; is it locked? LDXR W1, [X0] ; Load current value of lock CMP W1, #LOCKED ; Compare with "LOCKED" B.EQ lock ; If LOCKED, try again ; Attempt to lock MOV W1, #LOCKDED STXR W2, W1, [X0] ; Attempt to lock CBNZ W2, lock ; If STXR failed, try again DMB SY ; Ensures accesses to the resource are not made before the lock is acquired RET
4. Analysis of Exclusive Instruction Execution in Multi-Processor Multi-Threading
The article ARMv8 Exclusive Operations (II) Exclusive Operation Examples | Jun’s World analyzed the process of two threads competing for a lock. Extending to multi-threading and multiple CPUs follows the same principle: when performing read and write operations on the same address, only one thread can successfully complete the read and write operation at any one time.
Below, we will illustrate the principle of exclusive access in ARMv8 with a multi-processor and multi-threading example:
As shown in the figure below, a system has two CPUs, CPU0 with two threads: Thread 1 executing Program 1 and Thread 2 executing Program 2. CPU1 has one thread: Thread 3 executing Program 2. The programs in the three threads all access the same address A.
Their execution order is as follows:
- Thread 3 of CPU1 first executes LDREX, locking the memory area starting at address A for exclusive access, while updating the local monitor and global monitor status of CPU1 to Exclusive state.
- Then, Thread 1 of CPU0 also executes LDREX, which will also update the local monitor and global monitor status of CPU0 to Exclusive state. At this point, from the perspective of the global monitor, both CPU0 and CPU1 have marked a segment of memory starting at address A for Exclusive access.
- Next, Thread 2 of CPU0 also executes LDREX, at which point it will find that the local monitor of CPU0 has already marked that segment of memory as exclusive, and the global monitor also has the exclusive marking from CPU0. However, this does not affect the execution of the instruction.
- Next, Thread 1 of CPU0 first executes the STREX instruction, attempting to write a new value to address A. At this time, it finds that the local monitor of CPU0 has marked that segment of memory for exclusive access, and the global monitor also has the exclusive marking from CPU 0, so the STREX instruction will execute successfully. It will also clear the exclusive markings in the local monitor of CPU0 and the global monitor for all processors on that segment of memory.
- Next, when Thread 3 of CPU1 executes STREX, it finds that only the local monitor of CPU1 has the exclusive marking for that segment of memory, while the global monitor does not have the exclusive marking from CPU1. Therefore, the update fails, and the STREX instruction execution fails.
- Similarly, when Thread 2 of CPU0 executes STREX, it will also fail, finding that neither the local monitor nor the global monitor has the exclusive marking for that segment of memory.
-
If Program 2 is the atomic increment program mentioned above, after the STREX instruction fails, it will re-execute LDREX. At this point, the execution order of the three threads is: Thread1 – Thread3 – Thread2.
The core of ARM’s exclusive access mechanism is:
At any one time, multiple observers are allowed to read the same segment of memory and mark it for exclusive access, but only one of those observers is allowed to successfully write to that memory. According to the first write, the first observer that completes the LDREX/STREX instructions on that memory (the one that completes the update first) can succeed, while all others will fail.
This ensures the read-write consistency issue among multiple observers. In practice, the latest value stored in that segment of memory can be re-read using LDREX, processed again, and saved until successful.

This article is reproduced from CSDN, author: SOC Luo Sanpao, the article has obtained the authorization of the original author.