source: trunk/kernel/libk/readlock.c @ 35

Last change on this file since 35 was 14, checked in by alain, 8 years ago

Bugs fix.

File size: 3.4 KB
Line 
1/*
2 * readlock.c - kernel readlock synchronization
3 *
4 * Author  Alain Greiner     (2016}
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2.0 of the License.
13 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <kernel_config.h>
25#include <hal_types.h>
26#include <hal_atomic.h>
27#include <hal_special.h>
28#include <hal_irqmask.h>
29#include <thread.h>
30#include <scheduler.h>
31#include <printk.h>
32#include <readlock.h>
33
34///////////////////////////////////////
35void readlock_init( readlock_t * lock )
36{ 
37        lock->taken = 0;
38    lock->count = 0;
39        lock->owner = NULL;
40}
41
42//////////////////////////////////////////
43void readlock_rd_lock( readlock_t * lock )
44{
45        uint32_t           mode;
46    volatile uint32_t  taken;
47        thread_t         * this     = CURRENT_THREAD;
48        bool_t             isAtomic = false;
49
50    // disable IRQs
51        hal_disable_irq( &mode );
52 
53    // loop to take the lock against concurrent write
54        while( isAtomic == false )
55        {
56        // check lock value with a simple read
57        taken = lock->taken;
58                if( taken != 0 )  continue;
59 
60        // try to tomically take the lock
61                isAtomic = hal_atomic_cas( &lock->taken , 0 , 1 );
62        }
63
64    // increment count
65    lock->count++;
66
67    // sync
68    hal_wbflush();
69
70    // release lock to support several parallel read access
71    lock->taken = 0;
72
73    // update calling thread locks count
74        this->local_locks++;
75
76    // enable IRQs
77        hal_restore_irq( mode );
78}
79
80////////////////////////////////////////////
81void readlock_rd_unlock( readlock_t * lock )
82{
83    uint32_t   mode;
84        thread_t * this = CURRENT_THREAD;
85
86    // disable IRQs
87        hal_disable_irq( &mode );
88 
89    hal_atomic_dec( &lock->count );
90        this->local_locks--;
91
92    // enable IRQs
93        hal_restore_irq( mode );
94}
95
96//////////////////////////////////////////
97void readlock_wr_lock( readlock_t * lock )
98{
99        uint32_t           mode;
100    volatile uint32_t  taken;
101    volatile bool_t    isAtomic = false;
102    volatile bool_t    noReader = false;
103        thread_t         * this = CURRENT_THREAD;
104
105    // disable IRQs
106        hal_disable_irq( &mode );
107 
108    // loop to take the lock
109        while( isAtomic == false )
110        {
111        // check lock state with a simple read
112        taken = lock->taken;
113                if( taken != 0 ) continue;
114 
115        // try to atomically take the lock if not already taken
116                isAtomic = hal_atomic_cas( &lock->taken , 0 , 1 );
117        }
118
119    // wait completion of read accesses
120    while( noReader == false )
121    {
122        noReader = ( lock->count == 0 );
123    }
124   
125    lock->owner = this;
126        this->local_locks++;
127
128    // enable IRQs
129        hal_restore_irq( mode );
130}
131
132////////////////////////////////////////////
133void readlock_wr_unlock( readlock_t * lock )
134{
135    uint32_t   mode;
136        thread_t * this = CURRENT_THREAD;
137
138    // disable IRQs
139        hal_disable_irq( &mode );
140 
141    lock->owner = NULL;
142    lock->taken = 0;
143    this->local_locks--;
144
145    // enable IRQs
146        hal_restore_irq( mode );
147}
148
Note: See TracBrowser for help on using the repository browser.