summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/lib/rwlock.S
blob: 03f3bfe598e270d6d2398149dd6f95a69b5581c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/* $Id: rwlock.S,v 1.3 2000/03/16 16:44:38 davem Exp $
 * rwlocks.S: These things are too big to do inline.
 *
 * Copyright (C) 1999 David S. Miller (davem@redhat.com)
 */

	.text
	.align	64

	.globl	rwlock_impl_begin, rwlock_impl_end

	/* The non-contention read lock usage is 2 cache lines. */

	.globl	__read_lock, __read_unlock
rwlock_impl_begin:
__read_lock: /* %o0 = lock_ptr */
	ldsw		[%o0], %g5
	brlz,pn		%g5, __read_wait_for_writer
4:	 add		%g5, 1, %g7
	cas		[%o0], %g5, %g7
	cmp		%g5, %g7
	bne,pn		%icc, __read_lock
	 membar		#StoreLoad | #StoreStore
99:	retl
	 nop
__read_unlock: /* %o0 = lock_ptr */
	lduw		[%o0], %g5
	sub		%g5, 1, %g7
	cas		[%o0], %g5, %g7
	cmp		%g5, %g7
	be,pt		%xcc, 99b
	 membar		#StoreLoad | #StoreStore
	b,a,pt		%xcc, __read_unlock

__read_wait_for_writer:
	ldsw		[%o0], %g5
	brlz,pt		%g5, __read_wait_for_writer
	 membar		#LoadLoad
	b,a,pt		%xcc, 4b
__write_wait_for_writer:
	ldsw		[%o0], %g5
	brlz,pt		%g5, __write_wait_for_writer
	 membar		#LoadLoad
	b,a,pt		%xcc, 4f

	/* Similarly, 2 cache lines for non-contention write locks. */

	.align		64
	.globl		__write_unlock
__write_unlock: /* %o0 = lock_ptr */
	sethi		%hi(0x80000000), %g2
1:	lduw		[%o0], %g5
	andn		%g5, %g2, %g7
	cas		[%o0], %g5, %g7
	cmp		%g5, %g7
	be,pt		%icc, 99b
	 membar		#StoreLoad | #StoreStore
	b,a,pt		%xcc, 1b

	.globl		__write_lock
__write_lock: /* %o0 = lock_ptr */
	sethi		%hi(0x80000000), %g2
1:	ldsw		[%o0], %g5
4:	brnz,pn		%g5, 5f
	 or		%g5, %g2, %g7
	cas		[%o0], %g5, %g7
	cmp		%g5, %g7
	be,pt		%icc, 99b
	 membar		#StoreLoad | #StoreStore

	b,a,pt		%xcc, 1b
5:	brlz		%g5, __write_wait_for_writer
	or		%g5, %g2, %g7
	cas		[%o0], %g5, %g7
	cmp		%g5, %g7
	bne,pn		%icc, 5b
8:	 ldsw		[%o0], %g5
	cmp		%g5, %g2
	be,pn		%icc, 99b
	 membar		#LoadLoad
	b,a,pt		%xcc, 99b
rwlock_impl_end: