• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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