18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#ifndef __ASM_SPINLOCK_H 78c2ecf20Sopenharmony_ci#define __ASM_SPINLOCK_H 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <asm/spinlock_types.h> 108c2ecf20Sopenharmony_ci#include <asm/processor.h> 118c2ecf20Sopenharmony_ci#include <asm/barrier.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define arch_spin_is_locked(x) ((x)->slock != __ARCH_SPIN_LOCK_UNLOCKED__) 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#ifdef CONFIG_ARC_HAS_LLSC 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic inline void arch_spin_lock(arch_spinlock_t *lock) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci unsigned int val; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci __asm__ __volatile__( 228c2ecf20Sopenharmony_ci "1: llock %[val], [%[slock]] \n" 238c2ecf20Sopenharmony_ci " breq %[val], %[LOCKED], 1b \n" /* spin while LOCKED */ 248c2ecf20Sopenharmony_ci " scond %[LOCKED], [%[slock]] \n" /* acquire */ 258c2ecf20Sopenharmony_ci " bnz 1b \n" 268c2ecf20Sopenharmony_ci " \n" 278c2ecf20Sopenharmony_ci : [val] "=&r" (val) 288c2ecf20Sopenharmony_ci : [slock] "r" (&(lock->slock)), 298c2ecf20Sopenharmony_ci [LOCKED] "r" (__ARCH_SPIN_LOCK_LOCKED__) 308c2ecf20Sopenharmony_ci : "memory", "cc"); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci /* 338c2ecf20Sopenharmony_ci * ACQUIRE barrier to ensure load/store after taking the lock 348c2ecf20Sopenharmony_ci * don't "bleed-up" out of the critical section (leak-in is allowed) 358c2ecf20Sopenharmony_ci * http://www.spinics.net/lists/kernel/msg2010409.html 368c2ecf20Sopenharmony_ci * 378c2ecf20Sopenharmony_ci * ARCv2 only has load-load, store-store and all-all barrier 388c2ecf20Sopenharmony_ci * thus need the full all-all barrier 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_ci smp_mb(); 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* 1 - lock taken successfully */ 448c2ecf20Sopenharmony_cistatic inline int arch_spin_trylock(arch_spinlock_t *lock) 458c2ecf20Sopenharmony_ci{ 468c2ecf20Sopenharmony_ci unsigned int val, got_it = 0; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci __asm__ __volatile__( 498c2ecf20Sopenharmony_ci "1: llock %[val], [%[slock]] \n" 508c2ecf20Sopenharmony_ci " breq %[val], %[LOCKED], 4f \n" /* already LOCKED, just bail */ 518c2ecf20Sopenharmony_ci " scond %[LOCKED], [%[slock]] \n" /* acquire */ 528c2ecf20Sopenharmony_ci " bnz 1b \n" 538c2ecf20Sopenharmony_ci " mov %[got_it], 1 \n" 548c2ecf20Sopenharmony_ci "4: \n" 558c2ecf20Sopenharmony_ci " \n" 568c2ecf20Sopenharmony_ci : [val] "=&r" (val), 578c2ecf20Sopenharmony_ci [got_it] "+&r" (got_it) 588c2ecf20Sopenharmony_ci : [slock] "r" (&(lock->slock)), 598c2ecf20Sopenharmony_ci [LOCKED] "r" (__ARCH_SPIN_LOCK_LOCKED__) 608c2ecf20Sopenharmony_ci : "memory", "cc"); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci smp_mb(); 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci return got_it; 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistatic inline void arch_spin_unlock(arch_spinlock_t *lock) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci smp_mb(); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci WRITE_ONCE(lock->slock, __ARCH_SPIN_LOCK_UNLOCKED__); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* 758c2ecf20Sopenharmony_ci * Read-write spinlocks, allowing multiple readers but only one writer. 768c2ecf20Sopenharmony_ci * Unfair locking as Writers could be starved indefinitely by Reader(s) 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic inline void arch_read_lock(arch_rwlock_t *rw) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci unsigned int val; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* 848c2ecf20Sopenharmony_ci * zero means writer holds the lock exclusively, deny Reader. 858c2ecf20Sopenharmony_ci * Otherwise grant lock to first/subseq reader 868c2ecf20Sopenharmony_ci * 878c2ecf20Sopenharmony_ci * if (rw->counter > 0) { 888c2ecf20Sopenharmony_ci * rw->counter--; 898c2ecf20Sopenharmony_ci * ret = 1; 908c2ecf20Sopenharmony_ci * } 918c2ecf20Sopenharmony_ci */ 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci __asm__ __volatile__( 948c2ecf20Sopenharmony_ci "1: llock %[val], [%[rwlock]] \n" 958c2ecf20Sopenharmony_ci " brls %[val], %[WR_LOCKED], 1b\n" /* <= 0: spin while write locked */ 968c2ecf20Sopenharmony_ci " sub %[val], %[val], 1 \n" /* reader lock */ 978c2ecf20Sopenharmony_ci " scond %[val], [%[rwlock]] \n" 988c2ecf20Sopenharmony_ci " bnz 1b \n" 998c2ecf20Sopenharmony_ci " \n" 1008c2ecf20Sopenharmony_ci : [val] "=&r" (val) 1018c2ecf20Sopenharmony_ci : [rwlock] "r" (&(rw->counter)), 1028c2ecf20Sopenharmony_ci [WR_LOCKED] "ir" (0) 1038c2ecf20Sopenharmony_ci : "memory", "cc"); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci smp_mb(); 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci/* 1 - lock taken successfully */ 1098c2ecf20Sopenharmony_cistatic inline int arch_read_trylock(arch_rwlock_t *rw) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci unsigned int val, got_it = 0; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci __asm__ __volatile__( 1148c2ecf20Sopenharmony_ci "1: llock %[val], [%[rwlock]] \n" 1158c2ecf20Sopenharmony_ci " brls %[val], %[WR_LOCKED], 4f\n" /* <= 0: already write locked, bail */ 1168c2ecf20Sopenharmony_ci " sub %[val], %[val], 1 \n" /* counter-- */ 1178c2ecf20Sopenharmony_ci " scond %[val], [%[rwlock]] \n" 1188c2ecf20Sopenharmony_ci " bnz 1b \n" /* retry if collided with someone */ 1198c2ecf20Sopenharmony_ci " mov %[got_it], 1 \n" 1208c2ecf20Sopenharmony_ci " \n" 1218c2ecf20Sopenharmony_ci "4: ; --- done --- \n" 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci : [val] "=&r" (val), 1248c2ecf20Sopenharmony_ci [got_it] "+&r" (got_it) 1258c2ecf20Sopenharmony_ci : [rwlock] "r" (&(rw->counter)), 1268c2ecf20Sopenharmony_ci [WR_LOCKED] "ir" (0) 1278c2ecf20Sopenharmony_ci : "memory", "cc"); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci smp_mb(); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci return got_it; 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic inline void arch_write_lock(arch_rwlock_t *rw) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci unsigned int val; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci /* 1398c2ecf20Sopenharmony_ci * If reader(s) hold lock (lock < __ARCH_RW_LOCK_UNLOCKED__), 1408c2ecf20Sopenharmony_ci * deny writer. Otherwise if unlocked grant to writer 1418c2ecf20Sopenharmony_ci * Hence the claim that Linux rwlocks are unfair to writers. 1428c2ecf20Sopenharmony_ci * (can be starved for an indefinite time by readers). 1438c2ecf20Sopenharmony_ci * 1448c2ecf20Sopenharmony_ci * if (rw->counter == __ARCH_RW_LOCK_UNLOCKED__) { 1458c2ecf20Sopenharmony_ci * rw->counter = 0; 1468c2ecf20Sopenharmony_ci * ret = 1; 1478c2ecf20Sopenharmony_ci * } 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci __asm__ __volatile__( 1518c2ecf20Sopenharmony_ci "1: llock %[val], [%[rwlock]] \n" 1528c2ecf20Sopenharmony_ci " brne %[val], %[UNLOCKED], 1b \n" /* while !UNLOCKED spin */ 1538c2ecf20Sopenharmony_ci " mov %[val], %[WR_LOCKED] \n" 1548c2ecf20Sopenharmony_ci " scond %[val], [%[rwlock]] \n" 1558c2ecf20Sopenharmony_ci " bnz 1b \n" 1568c2ecf20Sopenharmony_ci " \n" 1578c2ecf20Sopenharmony_ci : [val] "=&r" (val) 1588c2ecf20Sopenharmony_ci : [rwlock] "r" (&(rw->counter)), 1598c2ecf20Sopenharmony_ci [UNLOCKED] "ir" (__ARCH_RW_LOCK_UNLOCKED__), 1608c2ecf20Sopenharmony_ci [WR_LOCKED] "ir" (0) 1618c2ecf20Sopenharmony_ci : "memory", "cc"); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci smp_mb(); 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci/* 1 - lock taken successfully */ 1678c2ecf20Sopenharmony_cistatic inline int arch_write_trylock(arch_rwlock_t *rw) 1688c2ecf20Sopenharmony_ci{ 1698c2ecf20Sopenharmony_ci unsigned int val, got_it = 0; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci __asm__ __volatile__( 1728c2ecf20Sopenharmony_ci "1: llock %[val], [%[rwlock]] \n" 1738c2ecf20Sopenharmony_ci " brne %[val], %[UNLOCKED], 4f \n" /* !UNLOCKED, bail */ 1748c2ecf20Sopenharmony_ci " mov %[val], %[WR_LOCKED] \n" 1758c2ecf20Sopenharmony_ci " scond %[val], [%[rwlock]] \n" 1768c2ecf20Sopenharmony_ci " bnz 1b \n" /* retry if collided with someone */ 1778c2ecf20Sopenharmony_ci " mov %[got_it], 1 \n" 1788c2ecf20Sopenharmony_ci " \n" 1798c2ecf20Sopenharmony_ci "4: ; --- done --- \n" 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci : [val] "=&r" (val), 1828c2ecf20Sopenharmony_ci [got_it] "+&r" (got_it) 1838c2ecf20Sopenharmony_ci : [rwlock] "r" (&(rw->counter)), 1848c2ecf20Sopenharmony_ci [UNLOCKED] "ir" (__ARCH_RW_LOCK_UNLOCKED__), 1858c2ecf20Sopenharmony_ci [WR_LOCKED] "ir" (0) 1868c2ecf20Sopenharmony_ci : "memory", "cc"); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci smp_mb(); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci return got_it; 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic inline void arch_read_unlock(arch_rwlock_t *rw) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci unsigned int val; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci smp_mb(); 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci /* 2008c2ecf20Sopenharmony_ci * rw->counter++; 2018c2ecf20Sopenharmony_ci */ 2028c2ecf20Sopenharmony_ci __asm__ __volatile__( 2038c2ecf20Sopenharmony_ci "1: llock %[val], [%[rwlock]] \n" 2048c2ecf20Sopenharmony_ci " add %[val], %[val], 1 \n" 2058c2ecf20Sopenharmony_ci " scond %[val], [%[rwlock]] \n" 2068c2ecf20Sopenharmony_ci " bnz 1b \n" 2078c2ecf20Sopenharmony_ci " \n" 2088c2ecf20Sopenharmony_ci : [val] "=&r" (val) 2098c2ecf20Sopenharmony_ci : [rwlock] "r" (&(rw->counter)) 2108c2ecf20Sopenharmony_ci : "memory", "cc"); 2118c2ecf20Sopenharmony_ci} 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic inline void arch_write_unlock(arch_rwlock_t *rw) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci smp_mb(); 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci WRITE_ONCE(rw->counter, __ARCH_RW_LOCK_UNLOCKED__); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci#else /* !CONFIG_ARC_HAS_LLSC */ 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic inline void arch_spin_lock(arch_spinlock_t *lock) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci unsigned int val = __ARCH_SPIN_LOCK_LOCKED__; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci /* 2278c2ecf20Sopenharmony_ci * Per lkmm, smp_mb() is only required after _lock (and before_unlock) 2288c2ecf20Sopenharmony_ci * for ACQ and REL semantics respectively. However EX based spinlocks 2298c2ecf20Sopenharmony_ci * need the extra smp_mb to workaround a hardware quirk. 2308c2ecf20Sopenharmony_ci */ 2318c2ecf20Sopenharmony_ci smp_mb(); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci __asm__ __volatile__( 2348c2ecf20Sopenharmony_ci "1: ex %0, [%1] \n" 2358c2ecf20Sopenharmony_ci " breq %0, %2, 1b \n" 2368c2ecf20Sopenharmony_ci : "+&r" (val) 2378c2ecf20Sopenharmony_ci : "r"(&(lock->slock)), "ir"(__ARCH_SPIN_LOCK_LOCKED__) 2388c2ecf20Sopenharmony_ci : "memory"); 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci smp_mb(); 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci/* 1 - lock taken successfully */ 2448c2ecf20Sopenharmony_cistatic inline int arch_spin_trylock(arch_spinlock_t *lock) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci unsigned int val = __ARCH_SPIN_LOCK_LOCKED__; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci smp_mb(); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci __asm__ __volatile__( 2518c2ecf20Sopenharmony_ci "1: ex %0, [%1] \n" 2528c2ecf20Sopenharmony_ci : "+r" (val) 2538c2ecf20Sopenharmony_ci : "r"(&(lock->slock)) 2548c2ecf20Sopenharmony_ci : "memory"); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci smp_mb(); 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci return (val == __ARCH_SPIN_LOCK_UNLOCKED__); 2598c2ecf20Sopenharmony_ci} 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_cistatic inline void arch_spin_unlock(arch_spinlock_t *lock) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci unsigned int val = __ARCH_SPIN_LOCK_UNLOCKED__; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci /* 2668c2ecf20Sopenharmony_ci * RELEASE barrier: given the instructions avail on ARCv2, full barrier 2678c2ecf20Sopenharmony_ci * is the only option 2688c2ecf20Sopenharmony_ci */ 2698c2ecf20Sopenharmony_ci smp_mb(); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci /* 2728c2ecf20Sopenharmony_ci * EX is not really required here, a simple STore of 0 suffices. 2738c2ecf20Sopenharmony_ci * However this causes tasklist livelocks in SystemC based SMP virtual 2748c2ecf20Sopenharmony_ci * platforms where the systemc core scheduler uses EX as a cue for 2758c2ecf20Sopenharmony_ci * moving to next core. Do a git log of this file for details 2768c2ecf20Sopenharmony_ci */ 2778c2ecf20Sopenharmony_ci __asm__ __volatile__( 2788c2ecf20Sopenharmony_ci " ex %0, [%1] \n" 2798c2ecf20Sopenharmony_ci : "+r" (val) 2808c2ecf20Sopenharmony_ci : "r"(&(lock->slock)) 2818c2ecf20Sopenharmony_ci : "memory"); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* 2848c2ecf20Sopenharmony_ci * see pairing version/comment in arch_spin_lock above 2858c2ecf20Sopenharmony_ci */ 2868c2ecf20Sopenharmony_ci smp_mb(); 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci/* 2908c2ecf20Sopenharmony_ci * Read-write spinlocks, allowing multiple readers but only one writer. 2918c2ecf20Sopenharmony_ci * Unfair locking as Writers could be starved indefinitely by Reader(s) 2928c2ecf20Sopenharmony_ci * 2938c2ecf20Sopenharmony_ci * The spinlock itself is contained in @counter and access to it is 2948c2ecf20Sopenharmony_ci * serialized with @lock_mutex. 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci/* 1 - lock taken successfully */ 2988c2ecf20Sopenharmony_cistatic inline int arch_read_trylock(arch_rwlock_t *rw) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci int ret = 0; 3018c2ecf20Sopenharmony_ci unsigned long flags; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci local_irq_save(flags); 3048c2ecf20Sopenharmony_ci arch_spin_lock(&(rw->lock_mutex)); 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci /* 3078c2ecf20Sopenharmony_ci * zero means writer holds the lock exclusively, deny Reader. 3088c2ecf20Sopenharmony_ci * Otherwise grant lock to first/subseq reader 3098c2ecf20Sopenharmony_ci */ 3108c2ecf20Sopenharmony_ci if (rw->counter > 0) { 3118c2ecf20Sopenharmony_ci rw->counter--; 3128c2ecf20Sopenharmony_ci ret = 1; 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci arch_spin_unlock(&(rw->lock_mutex)); 3168c2ecf20Sopenharmony_ci local_irq_restore(flags); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci return ret; 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci/* 1 - lock taken successfully */ 3228c2ecf20Sopenharmony_cistatic inline int arch_write_trylock(arch_rwlock_t *rw) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci int ret = 0; 3258c2ecf20Sopenharmony_ci unsigned long flags; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci local_irq_save(flags); 3288c2ecf20Sopenharmony_ci arch_spin_lock(&(rw->lock_mutex)); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* 3318c2ecf20Sopenharmony_ci * If reader(s) hold lock (lock < __ARCH_RW_LOCK_UNLOCKED__), 3328c2ecf20Sopenharmony_ci * deny writer. Otherwise if unlocked grant to writer 3338c2ecf20Sopenharmony_ci * Hence the claim that Linux rwlocks are unfair to writers. 3348c2ecf20Sopenharmony_ci * (can be starved for an indefinite time by readers). 3358c2ecf20Sopenharmony_ci */ 3368c2ecf20Sopenharmony_ci if (rw->counter == __ARCH_RW_LOCK_UNLOCKED__) { 3378c2ecf20Sopenharmony_ci rw->counter = 0; 3388c2ecf20Sopenharmony_ci ret = 1; 3398c2ecf20Sopenharmony_ci } 3408c2ecf20Sopenharmony_ci arch_spin_unlock(&(rw->lock_mutex)); 3418c2ecf20Sopenharmony_ci local_irq_restore(flags); 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci return ret; 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic inline void arch_read_lock(arch_rwlock_t *rw) 3478c2ecf20Sopenharmony_ci{ 3488c2ecf20Sopenharmony_ci while (!arch_read_trylock(rw)) 3498c2ecf20Sopenharmony_ci cpu_relax(); 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cistatic inline void arch_write_lock(arch_rwlock_t *rw) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci while (!arch_write_trylock(rw)) 3558c2ecf20Sopenharmony_ci cpu_relax(); 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic inline void arch_read_unlock(arch_rwlock_t *rw) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci unsigned long flags; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci local_irq_save(flags); 3638c2ecf20Sopenharmony_ci arch_spin_lock(&(rw->lock_mutex)); 3648c2ecf20Sopenharmony_ci rw->counter++; 3658c2ecf20Sopenharmony_ci arch_spin_unlock(&(rw->lock_mutex)); 3668c2ecf20Sopenharmony_ci local_irq_restore(flags); 3678c2ecf20Sopenharmony_ci} 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_cistatic inline void arch_write_unlock(arch_rwlock_t *rw) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci unsigned long flags; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci local_irq_save(flags); 3748c2ecf20Sopenharmony_ci arch_spin_lock(&(rw->lock_mutex)); 3758c2ecf20Sopenharmony_ci rw->counter = __ARCH_RW_LOCK_UNLOCKED__; 3768c2ecf20Sopenharmony_ci arch_spin_unlock(&(rw->lock_mutex)); 3778c2ecf20Sopenharmony_ci local_irq_restore(flags); 3788c2ecf20Sopenharmony_ci} 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci#endif 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci#endif /* __ASM_SPINLOCK_H */ 383