1 /*
2 * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12 #include <common/types.h>
13 #include <common/errno.h>
14 #include <common/macro.h>
15 #include <common/lock.h>
16 #include <common/kprint.h>
17 #include <arch/sync.h>
18
19 #include "ticket.h"
20
lock_init(struct lock * l)21 int lock_init(struct lock *l)
22 {
23 struct lock_impl *lock = (struct lock_impl *)l;
24 BUG_ON(!lock);
25 /* Initialize ticket lock */
26 lock->owner = 0;
27 lock->next = 0;
28 smp_wmb();
29 return 0;
30 }
31
lock(struct lock * l)32 void lock(struct lock *l)
33 {
34 struct lock_impl *lock = (struct lock_impl *)l;
35 u32 lockval = 0, newval = 0, ret = 0;
36
37 BUG_ON(!lock);
38 asm volatile(
39
40 " prfm pstl1strm, %3\n"
41 "1: ldaxr %w0, %3\n"
42 " add %w1, %w0, #0x1\n"
43 " stxr %w2, %w1, %3\n"
44 " cbnz %w2, 1b\n"
45 "2: ldar %w2, %4\n"
46 " cmp %w0, %w2\n"
47 " b.ne 2b\n"
48 : "=&r"(lockval), "=&r"(newval), "=&r"(ret), "+Q"(lock->next)
49 : "Q"(lock->owner)
50 : "memory");
51 }
52
53 // clang-format off
try_lock(struct lock * l)54 int try_lock(struct lock *l)
55 {
56 struct lock_impl *lock = (struct lock_impl *)l;
57 u32 lockval = 0, newval = 0, ret = 0, ownerval = 0;
58
59 BUG_ON(!lock);
60 asm volatile(
61
62 " prfm pstl1strm, %4\n"
63 "1: ldaxr %w0, %4\n"
64 " ldar %w3, %5\n"
65 " add %w1, %w0, #0x1\n"
66 " cmp %w0, %w3\n"
67 " b.ne 2f\n" /* fail */
68 " stxr %w2, %w1, %4\n"
69 " cbnz %w2, 1b\n" /* retry */
70 " mov %w2, #0x0\n" /* success */
71 " dmb ish\n" /* store -> load/store barrier */
72 " b 3f\n"
73 "2: mov %w2, #0xffffffffffffffff\n" /* fail */
74 "3:\n"
75 : "=&r"(lockval), "=&r" (newval), "=&r"(ret),
76 "=&r"(ownerval), "+Q" (lock->next)
77 : "Q" (lock->owner)
78 : "memory");
79 return ret;
80 }
81 // clang-format on
82
unlock(struct lock * l)83 void unlock(struct lock *l)
84 {
85 struct lock_impl *lock = (struct lock_impl *)l;
86
87 BUG_ON(!lock);
88 smp_mb(); /* load, store -> store barrier may use stlr here */
89 lock->owner = lock->owner + 1;
90 }
91
is_locked(struct lock * l)92 int is_locked(struct lock *l)
93 {
94 struct lock_impl *lock = (struct lock_impl *)l;
95
96 return lock->owner < lock->next;
97 }
98