2012-08-17 19:07:01 +04:00
/ *
* vlock. S - s i m p l e v o t i n g l o c k i m p l e m e n t a t i o n f o r A R M
*
* Created b y : D a v e M a r t i n , 2 0 1 2 - 0 8 - 1 6
* Copyright : ( C) 2 0 1 2 - 2 0 1 3 L i n a r o L i m i t e d
*
* This p r o g r a m i s f r e e s o f t w a r e ; you can redistribute it and/or modify
* it u n d e r t h e t e r m s o f t h e G N U G e n e r a l P u b l i c L i c e n s e v e r s i o n 2 a s
* published b y t h e F r e e S o f t w a r e F o u n d a t i o n .
*
* This p r o g r a m i s d i s t r i b u t e d i n t h e h o p e t h a t i t w i l l b e u s e f u l ,
* but W I T H O U T A N Y W A R R A N T Y ; without even the implied warranty of
* MERCHANTABILITY o r F I T N E S S F O R A P A R T I C U L A R P U R P O S E . S e e t h e
* GNU G e n e r a l P u b l i c L i c e n s e f o r m o r e d e t a i l s .
*
*
* This a l g o r i t h m i s d e s c r i b e d i n m o r e d e t a i l i n
* Documentation/ a r m / v l o c k s . t x t .
* /
# include < l i n u x / l i n k a g e . h >
# include " v l o c k . h "
/* Select different code if voting flags can fit in a single word. */
# if V L O C K _ V O T I N G _ S I Z E > 4
# define F E W ( x . . . )
# define M A N Y ( x . . . ) x
# else
# define F E W ( x . . . ) x
# define M A N Y ( x . . . )
# endif
@ voting lock for first-man coordination
.macro voting_begin rbase : req, r c p u : r e q , r s c r a t c h : r e q
mov \ r s c r a t c h , #1
strb \ r s c r a t c h , [ \ r b a s e , \ r c p u ]
dmb
.endm
.macro voting_end rbase : req, r c p u : r e q , r s c r a t c h : r e q
dmb
mov \ r s c r a t c h , #0
strb \ r s c r a t c h , [ \ r b a s e , \ r c p u ]
2013-05-14 13:08:07 +04:00
dsb s t
2012-08-17 19:07:01 +04:00
sev
.endm
/ *
* The v l o c k s t r u c t u r e m u s t r e s i d e i n S t r o n g l y - O r d e r e d o r D e v i c e m e m o r y .
* This i m p l e m e n t a t i o n d e l i b e r a t e l y e l i m i n a t e s m o s t o f t h e b a r r i e r s w h i c h
* would b e r e q u i r e d f o r o t h e r m e m o r y t y p e s , a n d a s s u m e s t h a t i n d e p e n d e n t
* writes t o n e i g h b o u r i n g l o c a t i o n s w i t h i n a c a c h e l i n e d o n o t i n t e r f e r e
* with o n e a n o t h e r .
* /
@ r0: lock structure base
@ r1: CPU ID (0-based index within cluster)
ENTRY( v l o c k _ t r y l o c k )
add r1 , r1 , #V L O C K _ V O T I N G _ O F F S E T
voting_ b e g i n r0 , r1 , r2
ldrb r2 , [ r0 , #V L O C K _ O W N E R _ O F F S E T ] @ c h e c k w h e t h e r l o c k i s h e l d
cmp r2 , #V L O C K _ O W N E R _ N O N E
bne t r y l o c k _ f a i l @ fail if so
@ Control dependency implies strb not observable before previous ldrb.
strb r1 , [ r0 , #V L O C K _ O W N E R _ O F F S E T ] @ s u b m i t m y v o t e
voting_ e n d r0 , r1 , r2 @ implies DMB
@ Wait for the current round of voting to finish:
MANY( m o v r3 , #V L O C K _ V O T I N G _ O F F S E T )
0 :
MANY( l d r r2 , [ r0 , r3 ] )
FEW( l d r r2 , [ r0 , #V L O C K _ V O T I N G _ O F F S E T ] )
cmp r2 , #0
wfene
bne 0 b
MANY( a d d r3 , r3 , #4 )
MANY( c m p r3 , #V L O C K _ V O T I N G _ O F F S E T + V L O C K _ V O T I N G _ S I Z E )
MANY( b n e 0 b )
@ Check who won:
dmb
ldrb r2 , [ r0 , #V L O C K _ O W N E R _ O F F S E T ]
eor r0 , r1 , r2 @ zero if I won, else nonzero
bx l r
trylock_fail :
voting_ e n d r0 , r1 , r2
mov r0 , #1 @ nonzero indicates that I lost
bx l r
ENDPROC( v l o c k _ t r y l o c k )
@ r0: lock structure base
ENTRY( v l o c k _ u n l o c k )
dmb
mov r1 , #V L O C K _ O W N E R _ N O N E
strb r1 , [ r0 , #V L O C K _ O W N E R _ O F F S E T ]
2013-05-14 13:08:07 +04:00
dsb s t
2012-08-17 19:07:01 +04:00
sev
bx l r
ENDPROC( v l o c k _ u n l o c k )