2 Copyright © 2017, The AROS Development Team. All rights reserved.
7 #include <aros/atomic.h>
8 #include <aros/types/spinlock_s.h>
9 #include <aros/kernel.h>
10 #include <aros/libcall.h>
12 #define __KERNEL_NO_SPINLOCK_PROTOS__
13 #define __KERNEL_NOLIBBASE__
14 #include <proto/kernel.h>
15 #include <exec_platform.h>
17 #include <kernel_base.h>
18 #include <kernel_debug.h>
22 int Kernel_13_KrnIsSuper();
24 AROS_LH2(spinlock_t
*, KrnSpinTryLock
,
25 AROS_LHA(spinlock_t
*, lock
, A0
),
26 AROS_LHA(ULONG
, mode
, D0
),
27 struct KernelBase
*, KernelBase
, 51, Kernel
)
31 D(bug("[Kernel] %s(0x%p, %08x)\n", __func__
, lock
, mode
));
33 if (mode
== SPINLOCK_MODE_WRITE
)
36 Check if lock->lock equals to SPINLOCK_UNLOCKED. If yes, it will be atomicaly replaced by SPINLOCKF_WRITE and function
37 returns 1. Otherwise it copies value of lock->lock into tmp and returns 0.
39 if (!compare_and_exchange_long((ULONG
*)&lock
->lock
, SPINLOCK_UNLOCKED
, SPINLOCKF_WRITE
, NULL
))
41 D(bug("[Kernel] %s: lock is held (value %08x). Failing to obtain it in WRITE mode...\n", __func__
, lock
->lock
));
44 if (Kernel_13_KrnIsSuper())
50 lock
->s_Owner
= GET_THIS_TASK
;
57 Check if upper 8 bits of lock->lock are all 0, which means spinlock is not in UPDATING state and it is not
58 in the WRITE state. If we manage to obtain it, we set the UPDATING flag. Until we release UPDATING state
59 we are free to do whatever we want with the spinlock
61 while (!compare_and_exchange_byte((UBYTE
*)&lock
->block
[3], 0, SPINLOCKF_UPDATING
>> 24, &tmp
))
64 Obtaining lock in UPDATING mode failed. This can have two reasons - either the lock is in WRITE mode, in
65 which case we fail and return NULL. Eventually the lock can be in UPDATING mode already, in this case we
68 if (tmp
& (SPINLOCKF_WRITE
>> 24))
70 D(bug("[Kernel] %s: lock is held in WRITE mode (value %08x). Failing to obtain it in READ mode...\n", __func__
, lock
->lock
));
75 // Tell CPU we are spinning, it shouldn't take long - someone is just updating the lock in READ mode
76 asm volatile("pause");
78 D(bug("[Kernel] %s: spinning on updating lock ...\n", __func__
));
82 At this point we have the spinlock in UPDATING state. So, update readcount field (no worry with atomic add,
83 spinlock is for our exclusive use here), and then release it just by setting updating flag to 0
85 WARNING: What to do if the 24-bit counter wraps?!
87 lock
->slock
.readcount
++;
88 #if defined(AROS_NO_ATOMIC_OPERATIONS)
89 lock
->slock
.updating
= 0;
91 __AROS_ATOMIC_AND_L(lock
->lock
, ~SPINLOCKF_UPDATING
);
95 D(bug("[Kernel] %s: lock = %08x\n", __func__
, lock
->lock
));