source: trunk/kernel/libk/remote_queuelock.c @ 626

Last change on this file since 626 was 623, checked in by alain, 6 years ago

Introduce three new types of vsegs (KCODE,KDATA,KDEV)
to map the kernel vsegs in the process VSL and GPT.
This now used by both the TSAR and the I86 architectures.

File size: 6.6 KB
Line 
1/*
2 * remote_queuelock.c - remote kernel lock with waiting queue implementation.
3 *
4 * Authors   Alain Greiner     (2016,2017,2018)
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_atomic.h>
27#include <thread.h>
28#include <scheduler.h>
29#include <busylock.h>
30#include <remote_queuelock.h>
31
32//////////////////////////////////////////////////////////////////////////////
33//                Extern global variables
34//////////////////////////////////////////////////////////////////////////////
35
36extern char * lock_type_str[];          // allocated in kernel_init.c
37
38
39/////////////////////////////////////////////
40void remote_queuelock_init( xptr_t   lock_xp,
41                            uint32_t type )
42{
43    // get remote lock cluster and local pointer
44    cxy_t                lock_cxy = GET_CXY( lock_xp );
45    remote_queuelock_t * lock_ptr = GET_PTR( lock_xp );
46
47    // initialise taken field
48    hal_remote_s32( XPTR( lock_cxy , &lock_ptr->taken ), 0 );
49
50    // initialise xroot field
51    xlist_root_init( XPTR( lock_cxy , &lock_ptr->xroot ) );
52
53    // initialise busylock field
54    remote_busylock_init( XPTR( lock_cxy , &lock_ptr->lock ) , type );
55
56#if DEBUG_QUEUELOCK_TYPE
57thread_t * this = CURRENT_THREAD;
58if( DEBUG_QUEUELOCK_TYPE == type )
59printk("\n[%s] thread[%x,%x] initialise lock %s [%x,%x]\n",
60__FUNCTION__, this->process->pid, this->trdid,
61lock_type_str[type], lock_cxy, lock_ptr );
62#endif
63
64}  // end remote_queuelock_init()
65
66///////////////////////////////////////////////
67void remote_queuelock_acquire( xptr_t lock_xp )
68{
69    thread_t * this = CURRENT_THREAD;
70
71    // check calling thread can yield
72    thread_assert_can_yield( this , __FUNCTION__ );
73
74    // get lock cluster and local pointer
75    cxy_t                lock_cxy = GET_CXY( lock_xp );
76    remote_queuelock_t * lock_ptr = GET_PTR( lock_xp );
77
78#if DEBUG_QUEUELOCK_TYPE
79uint32_t lock_type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
80#endif
81
82    // build extended pointer on busylock protecting queuelock
83    xptr_t busylock_xp = XPTR( lock_cxy , &lock_ptr->lock );
84
85    // get busylock
86    remote_busylock_acquire( busylock_xp );
87
88    // block and deschedule if lock already taken
89    while( hal_remote_l32( XPTR( lock_cxy, &lock_ptr->taken ) ) )
90    {
91
92#if DEBUG_QUEUELOCK_TYPE
93if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
94printk("\n[%s] thread[%x,%x] BLOCK on q_lock %s [%x,%x]\n",
95__FUNCTION__, this->process->pid, this->trdid, 
96lock_type_str[lock_type], lock_cxy, lock_ptr );
97#endif
98        // get pointer on calling thread
99        thread_t * this = CURRENT_THREAD;
100
101        // block calling thread
102        thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_LOCK );
103
104        // register calling thread in waiting list
105        xlist_add_last( XPTR( lock_cxy  , &lock_ptr->xroot ),
106                        XPTR( local_cxy , &this->wait_xlist ) );
107
108        // release busylock
109        remote_busylock_release( busylock_xp );
110
111        // deschedule calling thread
112        sched_yield("wait remote_queuelock");
113
114        // get busylock
115        remote_busylock_acquire( busylock_xp );
116    }
117
118#if DEBUG_QUEUELOCK_TYPE
119if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
120printk("\n[%s] thread[%x,%x] ACQUIRE q_lock %s [%x,%x]\n",
121__FUNCTION__, this->process->pid, this->trdid, 
122lock_type_str[lock_type], lock_cxy, lock_ptr );
123#endif
124
125    // update remote_queuelock state
126    hal_remote_s32( XPTR( lock_cxy , &lock_ptr->taken ) , 1 );
127
128    // release busylock
129    remote_busylock_release( busylock_xp );
130
131    hal_fence();
132
133}  // end remote_queuelock_acquire()
134
135////////////////////////////////////////////////
136void remote_queuelock_release( xptr_t  lock_xp )
137{
138    // memory barrier before lock release
139    hal_fence();
140
141    // get lock cluster and local pointer
142    cxy_t                lock_cxy = GET_CXY( lock_xp );
143    remote_queuelock_t * lock_ptr = GET_PTR( lock_xp );
144
145    // build extended pointer on busylock protecting queuelock
146    xptr_t busylock_xp = XPTR( lock_cxy , &lock_ptr->lock );
147
148    // get busylock
149    remote_busylock_acquire( busylock_xp );
150
151#if DEBUG_QUEUELOCK_TYPE
152thread_t * this      = CURRENT_THREAD;
153uint32_t   lock_type = hal_remote_l32( XPTR( lock_cxy , &lock_ptr->lock.type ) );
154if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
155printk("\n[%s] thread[%x,%x] RELEASE q_lock %s (%x,%x)\n",
156__FUNCTION__, this->process->pid, this->trdid,
157lock_type_str[lock_type], lock_cxy, lock_ptr );
158#endif
159
160    // update remote_queuelock state
161    hal_remote_s32( XPTR( lock_cxy , &lock_ptr->taken ) , 0 );
162
163    // unblock first waiting thread if waiting list not empty
164    if( xlist_is_empty( XPTR( lock_cxy, &lock_ptr->xroot ) ) == false )
165    {
166        // get extended pointer on first waiting thread
167        xptr_t root_xp   = XPTR( lock_cxy , &lock_ptr->xroot );
168        xptr_t     thread_xp  = XLIST_FIRST( root_xp , thread_t , wait_xlist );
169        cxy_t      thread_cxy = GET_CXY( thread_xp );
170        thread_t * thread_ptr = GET_PTR( thread_xp );
171
172#if DEBUG_QUEUELOCK_TYPE
173if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
174{
175    trdid_t     trdid   = hal_remote_l32( XPTR( thread_cxy , &thread_ptr->trdid ) );
176    process_t * process = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->process ) );
177    pid_t       pid     = hal_remote_l32( XPTR( thread_cxy , &process->pid ) );
178    printk("\n[%s] thread[%x,%x] UNBLOCK thread[%x,%x] / q_lock %s [%x,%x]\n",
179    __FUNCTION__, this->process->pid, this->trdid, trdid, pid, 
180    lock_type_str[lock_type], lock_cxy, lock_ptr );
181}
182#endif
183
184        // remove this thread from waiting queue
185        xlist_unlink( XPTR( thread_cxy , &thread_ptr->wait_xlist ) );
186
187        // unblock this waiting thread
188        thread_unblock( thread_xp , THREAD_BLOCKED_LOCK );
189    }
190
191    // release busylock
192    remote_busylock_release( busylock_xp );
193
194}  // end remote_queuelock_release()
195
196
197
Note: See TracBrowser for help on using the repository browser.