Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-only */
0002 /*
0003  * vlock.S - simple voting lock implementation for ARM
0004  *
0005  * Created by:  Dave Martin, 2012-08-16
0006  * Copyright:   (C) 2012-2013  Linaro Limited
0007  *
0008  * This algorithm is described in more detail in
0009  * Documentation/arm/vlocks.rst.
0010  */
0011 
0012 #include <linux/linkage.h>
0013 #include "vlock.h"
0014 
0015 /* Select different code if voting flags  can fit in a single word. */
0016 #if VLOCK_VOTING_SIZE > 4
0017 #define FEW(x...)
0018 #define MANY(x...) x
0019 #else
0020 #define FEW(x...) x
0021 #define MANY(x...)
0022 #endif
0023 
0024 @ voting lock for first-man coordination
0025 
0026 .macro voting_begin rbase:req, rcpu:req, rscratch:req
0027     mov \rscratch, #1
0028     strb    \rscratch, [\rbase, \rcpu]
0029     dmb
0030 .endm
0031 
0032 .macro voting_end rbase:req, rcpu:req, rscratch:req
0033     dmb
0034     mov \rscratch, #0
0035     strb    \rscratch, [\rbase, \rcpu]
0036     dsb st
0037     sev
0038 .endm
0039 
0040 /*
0041  * The vlock structure must reside in Strongly-Ordered or Device memory.
0042  * This implementation deliberately eliminates most of the barriers which
0043  * would be required for other memory types, and assumes that independent
0044  * writes to neighbouring locations within a cacheline do not interfere
0045  * with one another.
0046  */
0047 
0048 @ r0: lock structure base
0049 @ r1: CPU ID (0-based index within cluster)
0050 ENTRY(vlock_trylock)
0051     add r1, r1, #VLOCK_VOTING_OFFSET
0052 
0053     voting_begin    r0, r1, r2
0054 
0055     ldrb    r2, [r0, #VLOCK_OWNER_OFFSET]   @ check whether lock is held
0056     cmp r2, #VLOCK_OWNER_NONE
0057     bne trylock_fail            @ fail if so
0058 
0059     @ Control dependency implies strb not observable before previous ldrb.
0060 
0061     strb    r1, [r0, #VLOCK_OWNER_OFFSET]   @ submit my vote
0062 
0063     voting_end  r0, r1, r2      @ implies DMB
0064 
0065     @ Wait for the current round of voting to finish:
0066 
0067  MANY(  mov r3, #VLOCK_VOTING_OFFSET            )
0068 0:
0069  MANY(  ldr r2, [r0, r3]                    )
0070  FEW(   ldr r2, [r0, #VLOCK_VOTING_OFFSET]          )
0071     cmp r2, #0
0072     wfene
0073     bne 0b
0074  MANY(  add r3, r3, #4                  )
0075  MANY(  cmp r3, #VLOCK_VOTING_OFFSET + VLOCK_VOTING_SIZE    )
0076  MANY(  bne 0b                      )
0077 
0078     @ Check who won:
0079 
0080     dmb
0081     ldrb    r2, [r0, #VLOCK_OWNER_OFFSET]
0082     eor r0, r1, r2          @ zero if I won, else nonzero
0083     bx  lr
0084 
0085 trylock_fail:
0086     voting_end  r0, r1, r2
0087     mov r0, #1              @ nonzero indicates that I lost
0088     bx  lr
0089 ENDPROC(vlock_trylock)
0090 
0091 @ r0: lock structure base
0092 ENTRY(vlock_unlock)
0093     dmb
0094     mov r1, #VLOCK_OWNER_NONE
0095     strb    r1, [r0, #VLOCK_OWNER_OFFSET]
0096     dsb st
0097     sev
0098     bx  lr
0099 ENDPROC(vlock_unlock)