Synch transfer fix
[SCSI2SD-V6.git] / src / firmware / spinlock.c
1 //      Copyright (C) 2016 Michael McMaster <michael@codesrc.com>
2 //
3 //      This file is part of SCSI2SD.
4 //
5 //      SCSI2SD is free software: you can redistribute it and/or modify
6 //      it under the terms of the GNU General Public License as published by
7 //      the Free Software Foundation, either version 3 of the License, or
8 //      (at your option) any later version.
9 //
10 //      SCSI2SD is distributed in the hope that it will be useful,
11 //      but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //      GNU General Public License for more details.
14 //
15 //      You should have received a copy of the GNU General Public License
16 //      along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.
17
18 #include "spinlock.h"
19
20 int s2s_spin_trylock(s2s_lock_t* lock)
21 {
22         if (__LDREXW(lock) == 0)
23         {
24                 // Try to set lock
25                 int status = __STREXW(1, lock);
26                 if (status == 0)
27                 {
28                         // got lock
29                         // Do not start any other memory access
30                         // until memory barrier is completed
31                         __DMB();
32                         return 1;
33                 }
34         }
35
36         return 0;
37 }
38
39 void s2s_spin_lock(s2s_lock_t* lock)
40 {
41         int status = 0;
42         do
43         {
44                 // Wait until lock is free
45                 while (__LDREXW(lock) != 0);
46
47                 // Try to set lock
48                 status = __STREXW(1, lock);
49         } while (status!=0); //retry until lock successfully
50
51         // Do not start any other memory access
52         // until memory barrier is completed
53         __DMB();
54 }
55
56 void s2s_spin_unlock(s2s_lock_t* lock)
57 {
58         // Ensure memory operations completed before releasing
59         __DMB();
60         *lock = 0;
61 }