source: trunk/kernel/libk/queuelock.c @ 623

Last change on this file since 623 was 623, checked in by alain, 3 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: 4.8 KB
Line 
1/*
2 * queuelock.c - local 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 <queuelock.h>
31
32//////////////////////////////////////////////////////////////////////////////
33//                Extern global variables
34//////////////////////////////////////////////////////////////////////////////
35
36extern char * lock_type_str[];          // allocated in kernel_init.c
37
38
39////////////////////////////////////////
40void queuelock_init( queuelock_t * lock,
41                     uint32_t      type )
42{
43    lock->taken = 0;
44    list_root_init( &lock->root );
45    busylock_init( &lock->lock , type );
46
47#if DEBUG_QUEUELOCK_TYPE
48thread_t * this = CURRENT_THREAD;
49if( DEBUG_QUEUELOCK_TYPE == type )
50printk("\n[%s] thread[%x,%x] initialise lock %s [%x,%x]\n",
51__FUNCTION__, this->process->pid, this->trdid,
52lock_type_str[type], local_cxy, lock );
53#endif
54
55}
56
57////////////////////////////////////////////
58void queuelock_acquire( queuelock_t * lock )
59{
60    thread_t * this = CURRENT_THREAD;
61
62    // check calling thread can yield
63    thread_assert_can_yield( this , __FUNCTION__ );
64
65    // get busylock protecting access to queuelock state
66    busylock_acquire( &lock->lock );
67
68#if DEBUG_QUEUELOCK_TYPE
69uint32_t   lock_type = lock->lock.type;
70#endif
71
72    // block and deschedule if lock already taken
73    while( lock->taken )
74    {
75
76#if DEBUG_QUEUELOCK_TYPE
77if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
78printk("\n[%s ] thread[%x,%x] BLOCK on q_lock %s [%x,%x]\n",
79__FUNCTION__, this->process->pid, this->trdid,
80lock_type_str[lock_type], local_cxy, lock );
81#endif
82        // get pointer on calling thread
83        thread_t * this = CURRENT_THREAD;
84
85        // register calling thread in waiting queue
86        list_add_last( &lock->root , &this->wait_list );
87
88        // block calling thread
89        thread_block( XPTR( local_cxy , this ) , THREAD_BLOCKED_LOCK );
90       
91        // release busylock
92        busylock_release( &lock->lock );
93
94        // deschedule
95        sched_yield("reader wait queuelock");
96       
97        // get busylock
98        busylock_acquire( &lock->lock );
99    }
100
101#if DEBUG_QUEUELOCK_TYPE
102if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
103printk("\n[%s] thread[%x,%x] ACQUIRE q_lock %s [%x,%x]\n",
104__FUNCTION__, this->process->pid, this->trdid,
105lock_type_str[lock_type], local_cxy, lock );
106#endif
107
108    // update queuelock state
109    lock->taken = 1;
110
111    // release busylock
112    busylock_release( &lock->lock );
113
114}  // end queuelock_acquire()
115
116////////////////////////////////////////////
117void queuelock_release( queuelock_t * lock )
118{
119    // memory barrier before lock release
120    hal_fence();
121
122    // get busylock protecting access to queuelock state
123    busylock_acquire( &lock->lock );
124
125#if DEBUG_QUEUELOCK_TYPE
126uint32_t   lock_type = lock->lock.type;
127thread_t * this      = CURRENT_THREAD;
128if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
129printk("\n[%s] thread[%x,%x] RELEASE q_lock %s [%x,%x]\n",
130__FUNCTION__, this->process->pid, this->trdid,
131lock_type_str[lock_type], local_cxy, lock );
132#endif
133
134    // update queuelock state
135    lock->taken = 0;
136
137    // unblock first waiting thread if waiting list not empty
138    if( list_is_empty( &lock->root ) == false )
139    {
140        // get first waiting thread
141        thread_t * thread = LIST_FIRST( &lock->root , thread_t , wait_list );
142
143#if DEBUG_QUEUELOCK_TYPE
144if( (DEBUG_QUEUELOCK_TYPE == lock_type) || (DEBUG_QUEUELOCK_TYPE == 1000) )
145printk("\n[%s] thread[%x,%x] UNBLOCK thread [%x,%x] / q_lock %s [%x,%x]\n",
146__FUNCTION__, this->process->pid, this->trdid, thread->process->pid, thread->trdid,
147lock_type_str[lock_type], local_cxy, lock );
148#endif
149        // remove this waiting thread from waiting list
150        list_unlink( &thread->wait_list );
151
152        // unblock this waiting thread
153        thread_unblock( XPTR( local_cxy , thread ) , THREAD_BLOCKED_LOCK );
154    }
155
156    // release busylock
157    busylock_release( &lock->lock );
158
159}  // end queuelock_release()
160
161
162
Note: See TracBrowser for help on using the repository browser.