source: trunk/kernel/libk/remote_busylock.c @ 656

Last change on this file since 656 was 624, checked in by alain, 5 years ago

Fix several bugs to use the instruction MMU in kernel mode
in replacement of the instruction address extension register,
and remove the "kentry" segment.

This version is running on the tsar_generic_iob" platform.

One interesting bug: the cp0_ebase defining the kernel entry point
(for interrupts, exceptions and syscalls) must be initialized
early in kernel_init(), because the VFS initialisation done by
kernel_ini() uses RPCs, and RPCs uses Inter-Processor-Interrup.

File size: 4.7 KB
Line 
1/*
2 * remote_busylock.c - remote kernel busy-waiting lock implementation.
3 *
4 * Authors     Alain Greiner (2016,2017,2018,2019)
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_kernel_types.h>
26#include <hal_irqmask.h>
27#include <hal_special.h>
28#include <hal_remote.h>
29#include <thread.h>
30#include <remote_busylock.h>
31
32//////////////////////////////////////////////////////////////////////////////
33//                Extern global variables
34//////////////////////////////////////////////////////////////////////////////
35
36extern char               * lock_type_str[];    // allocated in kernel_init.c
37extern chdev_directory_t    chdev_dir;          // allocated in kernel_init.c
38
39
40////////////////////////////////////////////
41void remote_busylock_init( xptr_t   lock_xp,
42                           uint32_t type )
43{
44    // get remote lock cluster and local pointer
45    cxy_t        lock_cxy = GET_CXY( lock_xp );
46    busylock_t * lock_ptr = GET_PTR( lock_xp );
47
48    hal_remote_s32( XPTR( lock_cxy , &lock_ptr->ticket  ) , 0 );
49    hal_remote_s32( XPTR( lock_cxy , &lock_ptr->current ) , 0 );
50    hal_remote_s32( XPTR( lock_cxy , &lock_ptr->type    ) , type );
51
52#if DEBUG_BUSYLOCK
53    xlist_entry_init( XPTR( lock_cxy , &lock_ptr->xlist ) ); 
54#endif
55
56}
57
58////////////////////////////////////////////////
59void remote_busylock_acquire( xptr_t   lock_xp )
60{
61    reg_t      save_sr;
62    thread_t * this = CURRENT_THREAD;
63
64    // get remote lock cluster and local pointer
65    cxy_t        lock_cxy = GET_CXY( lock_xp );
66    busylock_t * lock_ptr = GET_PTR( lock_xp );
67
68    // enter critical section
69    hal_disable_irq( &save_sr );
70 
71    // get one ticket
72    uint32_t ticket = hal_remote_atomic_add( XPTR( lock_cxy , &lock_ptr->ticket ) , 1 );
73
74    // poll current until success
75    xptr_t current_xp = XPTR( lock_cxy , &lock_ptr->current );
76    while( hal_remote_l32( current_xp ) != ticket ) asm volatile ("nop");
77
78    // increment thread locks counter
79    this->busylocks++;
80
81    // save SR in lock descriptor
82    hal_remote_s32( XPTR( lock_cxy , &lock_ptr->save_sr ) , save_sr );
83
84    // memory barrier to update busylock and thread state
85    hal_fence();
86   
87#if DEBUG_BUSYLOCK
88uint32_t type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->type ) );
89if( type != LOCK_CHDEV_TXT0 )
90{
91    // update thread list of busyslocks
92    xptr_t root_xp = XPTR( local_cxy , &this->busylocks_root );
93    xlist_add_last( root_xp , XPTR( lock_cxy  , &lock_ptr->xlist ) );
94}
95#endif
96
97#if( DEBUG_BUSYLOCK & 1 )
98if( (type != LOCK_CHDEV_TXT0) && 
99    (this->process->pid == DEBUG_BUSYLOCK_PID) &&
100    (this->trdid == DEBUG_BUSYLOCK_TRDID) )
101{
102    printk("\n[%s] thread[%x,%x] ACQUIRE lock %s\n",
103    __FUNCTION__, this->process->pid, this->trdid, lock_type_str[type] );
104}
105#endif
106
107}  // end remote_busylock_acquire()
108
109///////////////////////////////////////////////
110void remote_busylock_release( xptr_t  lock_xp )
111{
112    thread_t * this = CURRENT_THREAD;
113
114    // memory barrier to update the protected object
115    hal_fence();
116
117    // get remote lock cluster and local pointer
118    cxy_t        lock_cxy = GET_CXY( lock_xp );
119    busylock_t * lock_ptr = GET_PTR( lock_xp );
120
121    // update lock state
122    hal_remote_atomic_add( XPTR( lock_cxy , &lock_ptr->current ) , 1 );
123
124    // decrement thread locks counter
125    this->busylocks--;
126
127    // memory barrier to update busylock and thread state
128    hal_fence();
129
130#if DEBUG_BUSYLOCK
131uint32_t type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->type ) );
132if( type != LOCK_CHDEV_TXT0 ) 
133{
134    // remove lock from thread list of busyslocks
135    xlist_unlink( XPTR( lock_cxy  , &lock_ptr->xlist ) );
136}
137#endif
138
139#if( DEBUG_BUSYLOCK & 1 )
140if( (type != LOCK_CHDEV_TXT0) && 
141    (this->process->pid == DEBUG_BUSYLOCK_PID) &&
142    (this->trdid == DEBUG_BUSYLOCK_TRDID) )
143{
144    printk("\n[%s] thread[%x,%x] RELEASE lock %s\n",
145    __FUNCTION__, this->process->pid, this->trdid, lock_type_str[type] );
146}
147#endif
148                                 
149    // exit critical section
150    hal_restore_irq( hal_remote_l32( XPTR( lock_cxy , &lock_ptr->save_sr ) ) );
151 
152}  // end remote_busylock_release()
153
154
Note: See TracBrowser for help on using the repository browser.