source: trunk/kernel/kern/chdev.c @ 627

Last change on this file since 627 was 625, checked in by alain, 5 years ago

Fix a bug in the vmm_remove_vseg() function: the physical pages
associated to an user DATA vseg were released to the kernel when
the target process descriptor was in the reference cluster.
This physical pages release should be done only when the page
forks counter value is zero.
All other modifications are cosmetic.

File size: 21.7 KB
Line 
1/*
2 * chdev.c - channel device descriptor operations implementation.
3 *
4 * Authors  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_kernel_types.h>
26#include <hal_special.h>
27#include <hal_remote.h>
28#include <hal_irqmask.h>
29#include <printk.h>
30#include <boot_info.h>
31#include <xlist.h>
32#include <kmem.h>
33#include <scheduler.h>
34#include <thread.h>
35#include <rpc.h>
36#include <chdev.h>
37#include <devfs.h>
38
39//////////////////////////////////////////////////////////////////////////////////////
40// Extern global variables
41//////////////////////////////////////////////////////////////////////////////////////
42
43extern chdev_directory_t    chdev_dir;         // allocated in kernel_init.c
44
45
46#if (DEBUG_SYS_READ & 1)
47extern uint32_t enter_chdev_cmd_read;
48extern uint32_t exit_chdev_cmd_read;
49extern uint32_t enter_chdev_server_read;
50extern uint32_t exit_chdev_server_read;
51#endif
52
53#if (DEBUG_SYS_WRITE & 1)
54extern uint32_t enter_chdev_cmd_write;
55extern uint32_t exit_chdev_cmd_write;
56extern uint32_t enter_chdev_server_write;
57extern uint32_t exit_chdev_server_write;
58#endif
59
60////////////////////////////////////////////
61char * chdev_func_str( uint32_t func_type ) 
62{
63    switch ( func_type ) 
64    {
65        case DEV_FUNC_RAM: return "RAM";
66        case DEV_FUNC_ROM: return "ROM";
67        case DEV_FUNC_FBF: return "FBF";
68        case DEV_FUNC_IOB: return "IOB";
69        case DEV_FUNC_IOC: return "IOC";
70        case DEV_FUNC_MMC: return "MMC";
71        case DEV_FUNC_DMA: return "DMA";
72        case DEV_FUNC_NIC: return "NIC";
73        case DEV_FUNC_TIM: return "TIM";
74        case DEV_FUNC_TXT: return "TXT";
75        case DEV_FUNC_ICU: return "ICU";
76        case DEV_FUNC_PIC: return "PIC";
77        default:           return "undefined";
78    }
79}
80
81/////////////////////////////////////////
82chdev_t * chdev_create( uint32_t    func,
83                        uint32_t    impl,
84                        uint32_t    channel,
85                        uint32_t    is_rx,
86                        xptr_t      base )
87{
88    chdev_t    * chdev;
89    kmem_req_t   req;
90
91    // allocate memory for chdev
92    req.type   = KMEM_DEVICE;
93    req.flags  = AF_ZERO;
94    chdev      = (chdev_t *)kmem_alloc( &req );
95
96    if( chdev == NULL ) return NULL;
97
98    // initialize lock
99    remote_busylock_init( XPTR( local_cxy , &chdev->wait_lock ), LOCK_CHDEV_QUEUE );
100
101    // initialise waiting queue
102    xlist_root_init( XPTR( local_cxy , &chdev->wait_root ) );
103
104    // initialize attributes
105    chdev->func    =  func;
106    chdev->impl    =  impl;
107    chdev->channel =  channel;
108    chdev->is_rx   =  is_rx;
109    chdev->base    =  base; 
110
111    return chdev;
112
113}  // end chdev_create()
114
115///////////////////////////////////
116void chdev_print( chdev_t * chdev )
117{
118    printk("\n - func      = %s"
119           "\n - channel   = %d"
120           "\n - base      = %l"
121           "\n - cmd       = %x"
122           "\n - isr       = %x"
123           "\n - chdev     = %x\n",
124           chdev_func_str(chdev->func),
125           chdev->channel,
126           chdev->base,
127           chdev->cmd,
128           chdev->isr,
129           chdev );
130}
131
132//////////////////////////////////////////////////
133void chdev_register_command( xptr_t     chdev_xp )
134{
135    thread_t * server_ptr;    // local pointer on server thread associated to chdev
136    xptr_t     server_xp;     // extended pointer on server thread
137    core_t   * core_ptr;      // local pointer on core running the server thread
138    uint32_t   server_lid;    // core running the server thread local index
139    xptr_t     lock_xp;       // extended pointer on lock protecting the chdev state
140
141#if (DEBUG_SYS_READ & 1)
142enter_chdev_cmd_read = (uint32_t)hal_get_cycles();
143#endif
144
145#if (DEBUG_SYS_WRITE & 1)
146enter_chdev_cmd_write = (uint32_t)hal_get_cycles();
147#endif
148
149    thread_t * this = CURRENT_THREAD;
150
151    // get chdev cluster and local pointer
152    cxy_t     chdev_cxy = GET_CXY( chdev_xp );
153    chdev_t * chdev_ptr = GET_PTR( chdev_xp );
154
155    // check calling thread can yield
156    thread_assert_can_yield( this , __FUNCTION__ );
157
158    // get local and extended pointers on server thread
159    server_ptr = (thread_t *)hal_remote_lpt( XPTR( chdev_cxy , &chdev_ptr->server) );
160    server_xp  = XPTR( chdev_cxy , server_ptr );
161
162    // get local pointer on core running the server thread
163    core_ptr   = (core_t *)hal_remote_lpt( XPTR( chdev_cxy , &server_ptr->core ) );
164
165    // get server core local index
166    server_lid = hal_remote_l32( XPTR( chdev_cxy , &core_ptr->lid ) );
167
168#if (DEBUG_CHDEV_CMD_RX || DEBUG_CHDEV_CMD_TX)
169bool_t      is_rx        = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->is_rx ) );
170trdid_t     server_trdid = hal_remote_l32( XPTR( chdev_cxy , &server_ptr->trdid ) ); 
171process_t * process_ptr  = hal_remote_lpt( XPTR( chdev_cxy , &server_ptr->process ) );
172pid_t       server_pid   = hal_remote_l32( XPTR( chdev_cxy , &process_ptr->pid ) );
173#endif
174   
175#if DEBUG_CHDEV_CMD_RX
176uint32_t rx_cycle = (uint32_t)hal_get_cycles();
177if( (is_rx) && (DEBUG_CHDEV_CMD_RX < rx_cycle) )
178printk("\n[%s] client thread[%x,%x] enter for RX / server[%x,%x] / cycle %d\n",
179__FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid, rx_cycle );
180#endif
181
182#if DEBUG_CHDEV_CMD_TX
183uint32_t tx_cycle = (uint32_t)hal_get_cycles();
184if( (is_rx == 0) && (DEBUG_CHDEV_CMD_TX < tx_cycle) )
185printk("\n[%s] client thread[%x,%x] enter for TX / server[%x,%x] / cycle %d\n",
186__FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid, tx_cycle );
187#endif
188
189    // build extended pointer on client thread xlist
190    xptr_t  list_xp    = XPTR( local_cxy , &this->wait_list );
191
192    // build extended pointer on chdev waiting queue root
193    xptr_t  root_xp    = XPTR( chdev_cxy , &chdev_ptr->wait_root );
194
195    // build extended pointer on lock protecting chdev waiting queue
196    lock_xp            = XPTR( chdev_cxy , &chdev_ptr->wait_lock );
197
198    // The following actions execute in critical section,
199    // because the lock_acquire / lock_release :
200    // (1) take the lock protecting the chdev state
201    // (2) register client thread in server queue
202    // (3) unblock the server thread and block client thread
203    // (4) send IPI to force server scheduling
204    // (5) release the lock protecting waiting queue
205
206    // 1. take the lock protecting chdev queue
207    remote_busylock_acquire( lock_xp );
208
209    // 2. register client thread in waiting queue
210    xlist_add_last( root_xp , list_xp );
211
212#if (DEBUG_CHDEV_CMD_TX & 1)
213if( (is_rx == 0)  && (DEBUG_CHDEV_CMD_TX < tx_cycle) )
214printk("\n[%s] client thread[%x,%x] registered write request in chdev\n",
215__FUNCTION__, this->process->pid, this->trdid );
216#endif
217 
218#if (DEBUG_CHDEV_CMD_RX & 1)
219if( (is_rx)  && (DEBUG_CHDEV_CMD_RX < rx_cycle) )
220printk("\n[%s] client thread[%x,%x] registered read request in chdev\n",
221__FUNCTION__, this->process->pid, this->trdid );
222#endif
223 
224    // 3. client thread unblocks server thread and blocks itself
225    thread_unblock( server_xp , THREAD_BLOCKED_IDLE );
226    thread_block( XPTR( local_cxy , CURRENT_THREAD ) , THREAD_BLOCKED_IO );
227
228#if (DEBUG_CHDEV_CMD_TX & 1)
229if( (is_rx == 0) && (DEBUG_CHDEV_CMD_TX < tx_cycle) )
230printk("\n[%s] client thread[%x,%x] unblock server thread[%x,%x] and block itsef\n",
231__FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid );
232#endif
233
234#if (DEBUG_CHDEV_CMD_RX & 1)
235if( (is_rx) && (DEBUG_CHDEV_CMD_RX < rx_cycle) )
236printk("\n[%s] client thread[%x,%x] unblock server thread[%x,%x] and block itsef\n",
237__FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid );
238#endif
239
240    // 4. send IPI to core running the server thread when server core != client core
241    if( (server_lid != this->core->lid) || (local_cxy != chdev_cxy) )
242    {
243        dev_pic_send_ipi( chdev_cxy , server_lid ); 
244
245#if (DEBUG_CHDEV_CMD_TX & 1)
246if( (is_rx == 0)  && (DEBUG_CHDEV_CMD_TX < tx_cycle) )
247printk("\n[%s] client thread[%x,%x] sent IPI to TX server thread[%x,%x]\n",
248__FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid );
249#endif
250
251#if (DEBUG_CHDEV_CMD_RX & 1)
252if( (is_rx)  && (DEBUG_CHDEV_CMD_RX < rx_cycle) )
253printk("\n[%s] client thread[%x,%x] sent IPI to RX server thread[%x,%x]\n",
254__FUNCTION__, this->process->pid, this->trdid, server_pid, server_trdid );
255#endif
256
257    }
258 
259    // 5. release lock protecting chdev queue
260    remote_busylock_release( lock_xp );
261
262    // deschedule
263    sched_yield("blocked on I/O");
264
265#if DEBUG_CHDEV_CMD_RX
266rx_cycle = (uint32_t)hal_get_cycles();
267if( (is_rx) && (DEBUG_CHDEV_CMD_RX < rx_cycle) )
268printk("\n[%s] client thread[%x,%x] exit for RX / cycle %d\n",
269__FUNCTION__, this->process->pid, this->trdid, rx_cycle );
270#endif
271
272#if DEBUG_CHDEV_CMD_TX
273tx_cycle = (uint32_t)hal_get_cycles();
274if( (is_rx == 0) && (DEBUG_CHDEV_CMD_TX < tx_cycle) )
275printk("\n[%s] client thread[%x,%x] exit for TX / cycle %d\n",
276__FUNCTION__, this->process->pid, this->trdid, tx_cycle );
277#endif
278
279#if (DEBUG_SYS_READ & 1)
280exit_chdev_cmd_read = (uint32_t)hal_get_cycles();
281#endif
282
283#if (DEBUG_SYS_WRITE & 1)
284exit_chdev_cmd_write = (uint32_t)hal_get_cycles();
285#endif
286
287}  // end chdev_register_command()
288
289/////////////////////////////////////////
290void chdev_server_func( chdev_t * chdev )
291{
292    xptr_t          client_xp;    // extended pointer on waiting thread
293    cxy_t           client_cxy;   // cluster of client thread
294    thread_t      * client_ptr;   // local pointer on client thread
295    thread_t      * server;       // local pointer on server thread
296    xptr_t          root_xp;      // extended pointer on device waiting queue root
297    xptr_t          lock_xp;      // extended pointer on lock ptotecting chdev queue
298
299    server = CURRENT_THREAD;
300
301    // build extended pointer on root of client threads queue
302    root_xp = XPTR( local_cxy , &chdev->wait_root );
303
304    // build extended pointer on lock protecting client threads queue
305    lock_xp = XPTR( local_cxy , &chdev->wait_lock );
306
307        // This infinite loop is executed by the DEV thread
308    // to handle commands registered in the chdev queue.
309    while( 1 )
310    {
311
312#if( DEBUG_CHDEV_SERVER_RX || DEBUG_CHDEV_SERVER_TX )
313uint32_t rx_cycle = (uint32_t)hal_get_cycles();
314if( (chdev->is_rx) && (DEBUG_CHDEV_SERVER_RX < rx_cycle) )
315printk("\n[%s] server thread[%x,%x] check TXT_RX channel %d / cycle %d\n",
316__FUNCTION__ , server->process->pid, server->trdid, chdev->channel, rx_cycle );
317#endif
318
319#if DEBUG_CHDEV_SERVER_TX
320uint32_t tx_cycle = (uint32_t)hal_get_cycles();
321if( (chdev->is_rx == 0) && (DEBUG_CHDEV_SERVER_TX < tx_cycle) )
322printk("\n[%s] thread[%x,%x] check TXT_TX channel %d / cycle %d\n",
323__FUNCTION__ , server->process->pid, server->trdid, chdev->channel, tx_cycle );
324#endif
325
326        // check server thread can yield
327        thread_assert_can_yield( server , __FUNCTION__ );
328
329        // get the lock protecting the waiting queue
330        remote_busylock_acquire( lock_xp );
331
332        // check waiting queue state
333        if( xlist_is_empty( root_xp ) ) // waiting queue empty
334        {
335            // release lock protecting the waiting queue
336            remote_busylock_release( lock_xp );
337
338#if DEBUG_CHDEV_SERVER_RX
339rx_cycle = (uint32_t)hal_get_cycles();
340if( (chdev->is_rx) && (DEBUG_CHDEV_SERVER_RX < rx_cycle) )
341printk("\n[%s] server thread[%x,%x] found RX queue empty => blocks / cycle %d\n",
342__FUNCTION__ , server->process->pid, server->trdid, rx_cycle );
343#endif
344
345#if DEBUG_CHDEV_SERVER_TX
346tx_cycle = (uint32_t)hal_get_cycles();
347if( (chdev->is_rx == 0) && (DEBUG_CHDEV_SERVER_TX < tx_cycle) )
348printk("\n[%s] server thread[%x,%x] found TX queue empty => blocks / cycle %d\n",
349__FUNCTION__ , server->process->pid, server->trdid, tx_cycle );
350#endif
351            // block
352            thread_block( XPTR( local_cxy , server ) , THREAD_BLOCKED_IDLE ); 
353
354            // deschedule
355            sched_yield("I/O queue empty");
356        } 
357        else                            // waiting queue not empty
358        {
359            // release lock protecting the waiting queue
360            remote_busylock_release( lock_xp );
361
362            // get extended pointer on first client thread
363            client_xp = XLIST_FIRST( root_xp , thread_t , wait_list );
364
365            // get client thread cluster and local pointer
366            client_cxy = GET_CXY( client_xp );
367            client_ptr = GET_PTR( client_xp );
368
369#if( DEBUG_CHDEV_SERVER_TX || DEBUG_CHDEV_SERVER_RX )
370process_t * process      = hal_remote_lpt( XPTR( client_cxy , &client_ptr->process ) );
371pid_t       client_pid   = hal_remote_l32( XPTR( client_cxy , &process->pid ) );
372trdid_t     client_trdid = hal_remote_l32( XPTR( client_cxy , &client_ptr->trdid ) );
373#endif
374
375#if DEBUG_CHDEV_SERVER_RX
376rx_cycle = (uint32_t)hal_get_cycles();
377if( (chdev->is_rx) && (DEBUG_CHDEV_SERVER_RX < rx_cycle) )
378printk("\n[%s] server thread[%x,%x] get command from client thread[%x,%x] / cycle %d\n",
379__FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, rx_cycle );
380#endif
381
382#if DEBUG_CHDEV_SERVER_TX
383tx_cycle = (uint32_t)hal_get_cycles();
384if( (chdev->is_rx == 0) && (DEBUG_CHDEV_SERVER_TX < tx_cycle) )
385printk("\n[%s] server thread[%x,%x] get command from client thread[%x,%x] / cycle %d\n",
386__FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, tx_cycle );
387#endif
388
389#if (DEBUG_SYS_READ & 1)
390enter_chdev_server_read = (uint32_t)hal_get_cycles();
391#endif
392
393#if (DEBUG_SYS_WRITE & 1)
394enter_chdev_server_write = (uint32_t)hal_get_cycles();
395#endif
396
397            // call the (blocking) driver command function
398            // to launch I/O operation AND wait completion
399            chdev->cmd( client_xp );
400       
401            // unblock client thread when driver returns
402            thread_unblock( client_xp , THREAD_BLOCKED_IO );
403
404            // get the lock protecting the waiting queue
405            remote_busylock_acquire( lock_xp );
406
407            // remove this client thread from chdev waiting queue
408            xlist_unlink( XPTR( client_cxy , &client_ptr->wait_list ) );
409
410            // release lock protecting the waiting queue
411            remote_busylock_release( lock_xp );
412
413#if DEBUG_CHDEV_SERVER_RX
414rx_cycle = (uint32_t)hal_get_cycles();
415if( (chdev->is_rx) && (DEBUG_CHDEV_SERVER_RX < rx_cycle) )
416printk("\n[%s] thread[%x,%x] completes command for client thread[%x,%x] / cycle %d\n",
417__FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, rx_cycle );
418#endif
419
420#if DEBUG_CHDEV_SERVER_TX
421tx_cycle = (uint32_t)hal_get_cycles();
422if( (chdev->is_rx == 0) && (DEBUG_CHDEV_SERVER_TX < tx_cycle) )
423printk("\n[%s] thread[%x,%x] completes command for client thread[%x,%x] / cycle %d\n",
424__FUNCTION__, server->process->pid, server->trdid, client_pid, client_trdid, tX_cycle );
425#endif
426
427#if (DEBUG_SYS_READ & 1)
428exit_chdev_server_read = (uint32_t)hal_get_cycles();
429#endif
430
431#if (DEBUG_SYS_WRITE & 1)
432exit_chdev_server_write = (uint32_t)hal_get_cycles();
433#endif
434
435        }
436    }  // end while
437}  // end chdev_server_func()
438
439////////////////////////////////////////
440xptr_t chdev_from_file( xptr_t file_xp )
441{
442    cxy_t         file_cxy;
443    vfs_file_t  * file_ptr;
444    uint32_t      inode_type;
445    vfs_inode_t * inode_ptr;
446    chdev_t     * chdev_ptr;
447
448    assert( (file_xp != XPTR_NULL) ,
449    "file_xp == XPTR_NULL\n" );
450
451    // get cluster and local pointer on remote file descriptor
452    // associated inode and chdev are stored in same cluster as the file desc.
453    file_cxy  = GET_CXY( file_xp );
454    file_ptr  = (vfs_file_t *)GET_PTR( file_xp );
455
456    // get inode type from file descriptor
457    inode_type = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) );
458    inode_ptr  = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
459
460    assert( (inode_type == INODE_TYPE_DEV) ,
461    "inode type %d is not INODE_TYPE_DEV\n", inode_type );
462
463    // get chdev local pointer from inode extension
464    chdev_ptr = (chdev_t *)hal_remote_lpt( XPTR( file_cxy , &inode_ptr->extend ) );
465
466    return XPTR( file_cxy , chdev_ptr );
467
468}  // end chdev_from_file()
469
470//////////////////////////////
471void chdev_dir_display( void )
472{
473    uint32_t  i;
474    cxy_t     cxy;
475    chdev_t * ptr;
476    uint32_t  base;
477
478    // get pointers on TXT0 chdev
479    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
480    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
481    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
482
483    // get extended pointer on TXT0 lock
484    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
485
486    // get TXT0 lock
487    remote_busylock_acquire( lock_xp );
488
489    // header
490    nolock_printk("\n***** external chdevs directory *****\n");
491
492    // IOB
493    if (chdev_dir.iob != XPTR_NULL )
494    {
495        cxy  = GET_CXY( chdev_dir.iob );
496        ptr  = GET_PTR( chdev_dir.iob );
497        base = (uint32_t)hal_remote_l64( XPTR( cxy , &ptr->base ) );
498        nolock_printk("  - iob       : cxy = %X / ptr = %X / base = %X\n", cxy, ptr, base);
499    }
500
501    // PIC
502    cxy  = GET_CXY( chdev_dir.pic );
503    ptr  = GET_PTR( chdev_dir.pic );
504    base = (uint32_t)hal_remote_l64( XPTR( cxy , &ptr->base ) );
505    nolock_printk("  - pic       : cxy = %X / ptr = %X / base = %X\n", cxy, ptr, base);
506
507    // TXT
508    for( i = 0 ; i < LOCAL_CLUSTER->nb_txt_channels ; i++ )
509    {
510        cxy = GET_CXY( chdev_dir.txt_rx[i] );
511        ptr = GET_PTR( chdev_dir.txt_rx[i] );
512        base = (uint32_t)hal_remote_l64( XPTR( cxy , &ptr->base ) );
513        nolock_printk("  - txt_rx[%d] : cxy = %X / ptr = %X / base = %X\n", i, cxy, ptr, base);
514
515        cxy = GET_CXY( chdev_dir.txt_tx[i] );
516        ptr = GET_PTR( chdev_dir.txt_tx[i] );
517        base = (uint32_t)hal_remote_l64( XPTR( cxy , &ptr->base ) );
518        nolock_printk("  - txt_tx[%d] : cxy = %X / ptr = %X / base = %X\n", i, cxy, ptr, base);
519    }
520
521    // IOC
522    for( i = 0 ; i < LOCAL_CLUSTER->nb_ioc_channels ; i++ )
523    {
524        cxy = GET_CXY( chdev_dir.ioc[i] );
525        ptr = GET_PTR( chdev_dir.ioc[i] );
526        base = (uint32_t)hal_remote_l64( XPTR( cxy , &ptr->base ) );
527        nolock_printk("  - ioc[%d]    : cxy = %X / ptr = %X / base = %X\n", i, cxy, ptr, base);
528    }
529
530    // FBF
531    for( i = 0 ; i < LOCAL_CLUSTER->nb_fbf_channels ; i++ )
532    {
533        cxy  = GET_CXY( chdev_dir.fbf[i] );
534        ptr  = GET_PTR( chdev_dir.fbf[i] );
535        base = (uint32_t)hal_remote_l64( XPTR( cxy , &ptr->base ) );
536        nolock_printk("  - fbf[%d]    : cxy = %X / ptr = %X / base = %X\n", i, cxy, ptr, base);
537    }
538
539    // NIC
540    for( i = 0 ; i < LOCAL_CLUSTER->nb_nic_channels ; i++ )
541    {
542        cxy = GET_CXY( chdev_dir.nic_rx[i] );
543        ptr = GET_PTR( chdev_dir.nic_rx[i] );
544        base = (uint32_t)hal_remote_l64( XPTR( cxy , &ptr->base ) );
545        nolock_printk("  - nic_rx[%d] : cxy = %X / ptr = %X / base = %X\n", i, cxy, ptr, base);
546
547        cxy = GET_CXY( chdev_dir.nic_tx[i] );
548        ptr = GET_PTR( chdev_dir.nic_tx[i] );
549        base = (uint32_t)hal_remote_l64( XPTR( cxy , &ptr->base ) );
550        nolock_printk("  - nic_tx[%d] : cxy = %X / ptr = %X / base = %X\n", i, cxy, ptr, base);
551    }
552
553    // release lock
554    remote_busylock_release( lock_xp );
555
556}  // end chdev_dir_display()
557
558///////////////////////////////////////////
559void chdev_queue_display( xptr_t chdev_xp )
560{
561    cxy_t       chdev_cxy;          // chdev cluster
562    chdev_t   * chdev_ptr;          // chdev local pointer
563    xptr_t      root_xp;            // extended pointer on waiting queuue root
564    char        name[16];           // local copie of chdev name
565    xptr_t      iter_xp;            // extended pointer on xlist_t field in waiting thread
566    xptr_t      thread_xp;          // extended pointer on thread registered in queue
567    cxy_t       thread_cxy;         // cluster identifier for waiting thread
568    thread_t  * thread_ptr;         // local pointer on waiting thread
569    trdid_t     trdid;              // waiting thread identifier
570    process_t * process;            // waiting thread process descriptor
571    pid_t       pid;                // waiting thread process identifier
572
573    // get cluster and local pointer on chdev
574    chdev_cxy = GET_CXY( chdev_xp );
575    chdev_ptr = GET_PTR( chdev_xp );
576
577    // get extended pointer on root of requests queue
578    root_xp = XPTR( chdev_cxy , &chdev_ptr->wait_root );
579
580    // get chdev name
581    hal_remote_strcpy( XPTR( local_cxy , name ), XPTR( chdev_cxy , chdev_ptr->name ) );
582
583    // get pointers on TXT0 chdev
584    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
585    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
586    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
587
588    // get extended pointer on TXT0 lock
589    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
590
591    // get TXT0 lock
592    remote_busylock_acquire( lock_xp );
593
594    // check queue empty
595    if( xlist_is_empty( root_xp ) )
596    {
597        nolock_printk("\n***** Waiting queue empty for chdev %s\n", name ); 
598    }
599    else
600    {
601        nolock_printk("\n***** Waiting queue for chdev %s\n", name ); 
602
603        // scan the waiting queue
604        XLIST_FOREACH( root_xp , iter_xp )
605        {
606            thread_xp  = XLIST_ELEMENT( iter_xp , thread_t , wait_list );
607            thread_cxy = GET_CXY( thread_xp );
608            thread_ptr = GET_PTR( thread_xp );
609            trdid      = hal_remote_l32 ( XPTR( thread_cxy , &thread_ptr->trdid   ) );
610            process    = hal_remote_lpt( XPTR( thread_cxy , &thread_ptr->process ) );
611                        pid        = hal_remote_l32 ( XPTR( thread_cxy , &process->pid        ) );
612
613            nolock_printk("- thread[%x,%x]\n", pid, trdid );
614        }
615    }
616
617    // release TXT0 lock
618    remote_busylock_release( lock_xp );
619
620}  // end chdev_queue_display()
621
Note: See TracBrowser for help on using the repository browser.