source: trunk/kernel/kern/mcs_sync.c @ 8

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

First import

File size: 4.8 KB
Line 
1/*
2 * kern/mcs_sync.c - ticket-based barriers and locks synchronization
3 *
4 * Copyright (c) 2008,2009,2010,2011,2012 Ghassan Almaless
5 * Copyright (c) 2011,2012 UPMC Sorbonne Universites
6 *
7 * This file is part of ALMOS-kernel.
8 *
9 * ALMOS-kernel is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2.0 of the License.
12 *
13 * ALMOS-kernel is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with ALMOS-kernel; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <config.h>
24#include <types.h>
25#include <mcs_sync.h>
26#include <thread.h>
27#include <cpu.h>
28#include <kdmsg.h>
29
30#define mcs_barrier_flush(_ptr)                                         \
31        do{                                                             \
32                cpu_invalid_dcache_line(&(_ptr)->phase);                \
33                cpu_invalid_dcache_line(&(_ptr)->ticket);               \
34                cpu_invalid_dcache_line(&(_ptr)->ticket2);              \
35                cpu_invalid_dcache_line(&(_ptr)->cntr);                 \
36        }while(0);
37
38/////////////////////////////////////////////////
39//FIXME: why all these dcache_invalidate ? [AG]
40/////////////////////////////////////////////////
41
42///////////////////////////////////////////
43void mcs_barrier_init( mcs_barrier_t * ptr,
44                       char          * name,
45                       uint32_t        count )
46{
47        ptr->val.value     = count;
48        ptr->phase.value   = 0;
49        ptr->cntr.value    = count;
50        ptr->ticket.value  = 0;
51        ptr->ticket2.value = 0;
52        ptr->name          = name;
53       
54        cpu_wbflush();
55        cpu_invalid_dcache_line(&ptr->val);
56        mcs_barrier_flush(ptr);
57}
58
59///////////////////////////////////////////
60void mcs_barrier_wait( mcs_barrier_t * ptr)
61{
62        register uint32_t   phase;
63        register uint32_t   order;
64        uint32_t          * current;
65        uint32_t          * next;
66 
67        phase   = ptr->phase.value;
68        current = (phase == 0) ? &ptr->ticket.value : &ptr->ticket2.value;
69        order   = cpu_atomic_add((void*)&ptr->cntr.value, -1);
70
71        if(order == 1)
72        {
73                phase            = ~(phase) & 0x1;
74                next             =  (phase == 0) ? &ptr->ticket.value : &ptr->ticket2.value;
75                ptr->phase.value = phase;
76                ptr->cntr.value  = ptr->val.value;
77                *next            = 0;
78                *current         = 1;
79                cpu_wbflush();
80                mcs_barrier_flush(ptr);
81                return;
82        }
83
84        mcs_barrier_flush(ptr);
85
86        while(cpu_load_word(current) == 0)
87                ;
88
89        cpu_invalid_dcache_line(current);
90}
91
92/////////////////////////////////////
93void mcs_lock_init( mcs_lock_t * ptr,
94                    char       * name )
95{
96        ptr->cntr.value   = 0;
97        ptr->ticket.value = 0;
98        ptr->name         = name;
99       
100        cpu_wbflush();
101        cpu_invalid_dcache_line(&ptr->cntr);
102        cpu_invalid_dcache_line(&ptr->ticket);
103}
104
105////////////////////////////////
106void mcs_lock( mcs_lock_t * ptr, 
107               uint32_t   * irq_state )
108{
109        uint32_t ticket;
110
111        cpu_disable_all_irq( irq_state );
112
113        ticket = cpu_atomic_add( &ptr->ticket.value , 1 );
114
115        while(ticket != cpu_load_word(&ptr->cntr.value))
116                ;
117
118        CURRENT_THREAD->locks_count ++;
119}
120
121//////////////////////////////////
122void mcs_unlock( mcs_lock_t * ptr, 
123                 uint32_t     irq_state )
124{
125        register uint32_t next;
126        volatile uint32_t *val_ptr;
127        register struct thread_s *this;
128
129        this     = CURRENT_THREAD;
130
131        val_ptr  = &ptr->cntr.value;
132        next     = ptr->cntr.value + 1;
133
134        cpu_wbflush();
135        cpu_invalid_dcache_line((void*)val_ptr);
136
137        *val_ptr = next;
138
139        cpu_wbflush();
140        cpu_invalid_dcache_line((void*)val_ptr);
141
142        full_assert(this, this->locks_count > 0);
143        this->locks_count --;
144        cpu_restore_irq(irq_state);
145
146    // pourquoi pas simplement le code ci-dessous ? [AG]
147    // ptr->cntr.value ++;
148        // cpu_wbflush();
149    // CURRENT_THREAD->locks_count --;
150        // cpu_restore_irq( irq_state );
151   
152}
153
154///////////////////////////////////////
155void mcs_lock_remote( mcs_lock_t * ptr,
156                      cid_t        cid, 
157                      uint32_t   * irq_state )
158{
159        uint32_t ticket;
160
161        cpu_disable_all_irq( irq_state );
162
163        ticket = remote_atomic_add( &ptr->ticket.value , cid , 1 );
164
165        while( ticket != remote_lw( &ptr->cntr.value , cid ) )
166                ;
167
168        CURRENT_THREAD->distlocks_count ++;
169}
170
171/////////////////////////////////////////
172void mcs_unlock_remote( mcs_lock_t * ptr, 
173                        cid_t        cid, 
174                        uint32_t     irq_state )
175{
176        register uint32_t next;
177        volatile uint32_t *val_ptr;
178        register struct thread_s *this;
179
180        this     = CURRENT_THREAD;
181        val_ptr  = &ptr->cntr.value;
182        next     = remote_lw((void*)val_ptr, cid) + 1;
183
184        cpu_wbflush();
185        cpu_invalid_dcache_line((void*)val_ptr);
186
187        remote_sw((void*)val_ptr, cid, next);
188
189        cpu_wbflush();
190        cpu_invalid_dcache_line((void*)val_ptr);
191
192        full_assert(this, this->distlocks_count > 0);
193        this->distlocks_count --;
194        cpu_restore_irq(irq_state);
195}
Note: See TracBrowser for help on using the repository browser.