source: trunk/kernel/syscalls/sys_display.c @ 684

Last change on this file since 684 was 683, checked in by alain, 4 years ago

All modifications required to support the <tcp_chat> application
including error recovery in case of packet loss.A

File size: 17.4 KB
Line 
1/*
2 * sys_display.c - display the current state of a kernel structure on TXT0
3 *
4 * Author    Alain Greiner (2016,2017,2018,2019,2020)
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 <hal_kernel_types.h>
25#include <hal_uspace.h>
26#include <hal_vmm.h>
27#include <errno.h>
28#include <vmm.h>
29#include <cluster.h>
30#include <thread.h>
31#include <process.h>
32#include <string.h>
33#include <shared_syscalls.h>
34#include <remote_barrier.h>
35#include <vfs.h>
36#include <mapper.h>
37#include <ksocket.h>
38#include <syscalls.h>
39
40/////////////////////////////////////////////////////////////////////////////////
41// This static function returns a printable string for the type of display.
42/////////////////////////////////////////////////////////////////////////////////
43
44#if DEBUG_SYS_DISPLAY
45static char* display_type_str( uint32_t type )
46{
47    if     ( type == DISPLAY_STRING            ) return "STRING"; 
48    else if( type == DISPLAY_VMM               ) return "VMM"; 
49    else if( type == DISPLAY_SCHED             ) return "SCHED"; 
50    else if( type == DISPLAY_CLUSTER_PROCESSES ) return "CLUSTER_PROCESSES"; 
51    else if( type == DISPLAY_VFS               ) return "VFS"; 
52    else if( type == DISPLAY_CHDEV             ) return "CHDEV"; 
53    else if( type == DISPLAY_TXT_PROCESSES     ) return "TXT_PROCESSES"; 
54    else if( type == DISPLAY_DQDT              ) return "DQDT";
55    else if( type == DISPLAY_BUSYLOCKS         ) return "BUSYLOCKS"; 
56    else if( type == DISPLAY_MAPPER            ) return "MAPPER";
57    else if( type == DISPLAY_BARRIER           ) return "BARRIER";
58    else if( type == DISPLAY_FAT               ) return "FAT";
59    else if( type == DISPLAY_SOCKET            ) return "SOCKET";
60    else if( type == DISPLAY_FD                ) return "FD";
61    else if( type == DISPLAY_WINDOWS           ) return "WINDOWS";
62    else                                         return "undefined";
63}
64#endif
65
66/////////////////////////////
67int sys_display( reg_t  type,
68                 reg_t  arg0,
69                 reg_t  arg1,
70                 reg_t  arg2 )
71{
72
73    error_t     error;
74    vseg_t    * vseg;
75
76    thread_t  * this    = CURRENT_THREAD;
77    process_t * process = this->process;
78
79#if (DEBUG_SYS_DISPLAY || CONFIG_INSTRUMENTATION_SYSCALLS)
80uint64_t     tm_start = hal_get_cycles();
81#endif
82
83#if DEBUG_SYS_DISPLAY
84tm_start = hal_get_cycles();
85if( DEBUG_SYS_DISPLAY < tm_start )
86printk("\n[%s] thread[%x,%x] enter / type  %s / arg0 %x / arg1 %x / arg2 %x / cycle = %d\n",
87__FUNCTION__, process->pid, this->trdid, display_type_str(type),
88(uint32_t)arg0, (uint32_t)arg1, (uint32_t)arg2, (uint32_t)tm_start );
89#endif
90
91    switch( type )
92    {
93        ////////////////////
94        case DISPLAY_STRING:
95        {
96            char      kbuf[512];
97            uint32_t  length;
98
99            char    * string = (char *)arg0;
100
101            // check string in user space
102            error = vmm_get_vseg( process , (intptr_t)arg0 , &vseg );
103            if( error )
104            {
105
106#if DEBUG_SYSCALLS_ERROR
107printk("\n[ERROR] in %s for STRING : string buffer %x unmapped\n",
108__FUNCTION__ , (intptr_t)arg0 );
109#endif
110                this->errno = EINVAL;
111                return -1;
112            }
113
114            // ckeck string length
115            length = hal_strlen_from_uspace( string );
116            if( length >= 512 )
117            {
118
119#if DEBUG_SYSCALLS_ERROR
120printk("\n[ERROR] in %s STRING : string length %d too large\n",
121__FUNCTION__ , length );
122#endif
123                this->errno = EINVAL;
124                return -1;
125            }
126
127            // copy string to kernel space
128            hal_strcpy_from_uspace( XPTR( local_cxy , kbuf ),
129                                    string,
130                                    512 );
131
132            // print message on TXT0 kernel terminal
133            printk("\n%s / cycle %d\n", kbuf, (uint32_t)hal_get_cycles() );
134
135            break;
136        }
137        /////////////////
138        case DISPLAY_VMM:
139        {
140            cxy_t cxy      = (cxy_t)arg0;
141            pid_t pid      = (pid_t)arg1;
142            bool_t mapping = (arg2 != 0);
143
144            // check cxy argument
145                if( cluster_is_active( cxy ) == false ) 
146            {
147
148#if DEBUG_SYSCALLS_ERROR
149printk("\n[ERROR] in %s VMM : process %x in cluster %x not found\n",
150__FUNCTION__ , pid , cxy );
151#endif
152                this->errno = EINVAL;
153                return -1;
154            }
155
156            // get extended pointer on process PID in cluster CXY
157            xptr_t process_xp = cluster_get_process_from_pid_in_cxy( cxy , pid );
158                if( process_xp == XPTR_NULL )
159            {
160
161#if DEBUG_SYSCALLS_ERROR
162printk("\n[ERROR] in %s VMM : process %x in cluster %x not found\n",
163__FUNCTION__ , pid , cxy );
164#endif
165                this->errno = EINVAL;
166                return -1;
167            }
168
169            // call kernel function
170                hal_vmm_display( process_xp , mapping );
171
172            break;
173        }
174        ///////////////////
175        case DISPLAY_SCHED:
176        {
177            cxy_t cxy = (cxy_t)arg0;
178            lid_t lid = (lid_t)arg1;
179
180            // check cxy argument
181                if( cluster_is_active( cxy ) == false ) 
182            {
183
184#if DEBUG_SYSCALLS_ERROR
185printk("\n[ERROR] in %s SCHED : illegal cxy argument %x\n",
186__FUNCTION__ , cxy );
187#endif
188                this->errno = EINVAL;
189                return -1;
190            }
191
192            // check lid argument
193            if( lid >= LOCAL_CLUSTER->cores_nr )
194            {
195
196#if DEBUG_SYSCALLS_ERROR
197printk("\n[ERROR] in %s SCHED : illegal lid argument %x\n",
198__FUNCTION__ , lid );
199#endif
200                this->errno = EINVAL;
201                return -1;
202            }
203
204            // call kernel function
205            sched_remote_display( cxy , lid );
206
207            break;
208        }
209        ///////////////////////////////
210        case DISPLAY_CLUSTER_PROCESSES:
211        {
212            cxy_t  cxy   = (cxy_t)arg0;
213            bool_t owned = (bool_t)arg1;
214
215            // check cxy argument
216                if( cluster_is_active( cxy ) == false )
217            {
218
219#if DEBUG_SYSCALLS_ERROR
220printk("\n[ERROR] in %s CLUSTER_PROCESSES : illegal cxy argument %x\n",
221__FUNCTION__ , cxy );
222#endif
223                this->errno = EINVAL;
224                return -1;
225            }
226
227            cluster_processes_display( cxy , owned );
228
229            break;
230        }
231        /////////////////
232        case DISPLAY_VFS:
233        {
234            vfs_display( process->vfs_root_xp );
235
236            break;
237        }
238        ///////////////////
239        case DISPLAY_CHDEV:
240        {
241            chdev_dir_display();
242
243            break;
244        }
245        ///////////////////////////
246        case DISPLAY_TXT_PROCESSES:
247        {
248            uint32_t txt_id = (uint32_t)arg0;
249
250            // check argument
251                if( txt_id >= LOCAL_CLUSTER->nb_txt_channels )
252            {
253
254#if DEBUG_SYSCALLS_ERROR
255printk("\n[ERROR] in %s TXT_PROCESSES : illegal txt_id argument %d\n",
256__FUNCTION__ , txt_id );
257#endif
258                this->errno = EINVAL;
259                return -1;
260            }
261
262            process_txt_display( txt_id );
263
264            break;
265        }
266        //////////////////
267        case DISPLAY_DQDT:
268        {
269            dqdt_display();
270
271            break;
272        }
273        ///////////////////////
274        case DISPLAY_BUSYLOCKS:
275        {
276            pid_t   pid   = (pid_t)arg0;
277            trdid_t trdid = (trdid_t)arg1;
278
279            // get extended pointer on target thread
280            xptr_t thread_xp = thread_get_xptr( pid , trdid );
281
282            if( thread_xp == XPTR_NULL )
283            {
284
285#if DEBUG_SYSCALLS_ERROR
286printk("\n[ERROR] in %s BUSYLOCKS : thread[%x,%x] not found\n",
287__FUNCTION__ , pid, trdid );
288#endif
289                this->errno = EINVAL;
290                return -1;
291            }
292
293            thread_display_busylocks( thread_xp , __FUNCTION__ );
294
295            break;
296        }
297        ////////////////////
298        case DISPLAY_MAPPER:
299        {
300            xptr_t        root_inode_xp;
301            xptr_t        inode_xp;
302            cxy_t         inode_cxy;
303            vfs_inode_t * inode_ptr;
304            xptr_t        mapper_xp;
305            mapper_t    * mapper_ptr;
306            xptr_t        page_xp;
307
308            char          kbuf[CONFIG_VFS_MAX_PATH_LENGTH];
309
310            char     * path    = (char *)arg0;
311            uint32_t   page_id = (uint32_t)arg1;
312            uint32_t   nbytes  = (uint32_t)arg2;
313
314            // check pathname length
315            if( hal_strlen_from_uspace( path ) >= CONFIG_VFS_MAX_PATH_LENGTH )
316            {
317
318#if DEBUG_SYSCALLS_ERROR
319printk("\n[ERROR] in %s MAPPER : pathname too long\n",
320 __FUNCTION__ );
321#endif
322                this->errno = EINVAL;
323                return -1;
324            }
325
326            // check nbytes
327            if( nbytes >= 4096 )
328            {
329
330#if DEBUG_SYSCALLS_ERROR
331printk("\n[ERROR] in %s MAPPER : nbytes cannot be larger than 4096\n",
332 __FUNCTION__ );
333#endif
334                this->errno = EINVAL;
335                return -1;
336            }
337           
338            // copy pathname in kernel space
339            hal_strcpy_from_uspace( XPTR( local_cxy , kbuf ),
340                                    path,
341                                    CONFIG_VFS_MAX_PATH_LENGTH );
342
343            // compute root inode for pathname
344            if( kbuf[0] == '/' )                        // absolute path
345            {
346                // use extended pointer on VFS root inode
347                root_inode_xp = process->vfs_root_xp;
348            }
349            else                                        // relative path
350            {
351                // get cluster and local pointer on reference process
352                xptr_t      ref_xp  = process->ref_xp;
353                process_t * ref_ptr = (process_t *)GET_PTR( ref_xp );
354                cxy_t       ref_cxy = GET_CXY( ref_xp );
355
356                // get extended pointer on CWD inode
357                root_inode_xp = hal_remote_l64( XPTR( ref_cxy , &ref_ptr->cwd_xp ) );
358            }
359
360            // get extended pointer on target inode
361            error = vfs_lookup( root_inode_xp,
362                                kbuf,
363                                0,
364                                &inode_xp,
365                                NULL );
366            if( error )
367                {
368
369#if DEBUG_SYSCALLS_ERROR
370printk("\n[ERROR] in %s for MAPPER : cannot found inode <%s>\n",
371__FUNCTION__ , kbuf );
372#endif
373                        this->errno = ENFILE;
374                        return -1;
375                }
376   
377            // get target inode cluster and local pointer
378            inode_cxy = GET_CXY( inode_xp );
379            inode_ptr = GET_PTR( inode_xp );
380
381            // get extended pointer on target mapper
382            mapper_ptr = hal_remote_lpt( XPTR( inode_cxy , &inode_ptr->mapper ) );
383            mapper_xp  = XPTR( inode_cxy , mapper_ptr );
384
385            // get extended pointer on target page
386            page_xp = mapper_get_page( mapper_xp , page_id );
387
388            if( page_xp == XPTR_NULL )
389                {
390
391#if DEBUG_SYSCALLS_ERROR
392printk("\n[ERROR] in %s MAPPER : cannot get page %d\n",
393__FUNCTION__ , page_id );
394#endif
395                        this->errno = ENFILE;
396                        return -1;
397                }
398
399            // display mapper
400            mapper_display_page( mapper_xp , page_xp , nbytes );
401
402
403            break;
404        }
405        /////////////////////
406        case DISPLAY_BARRIER:
407        {
408            // get target process PID
409            pid_t pid = (pid_t)arg0;
410
411            // get pointers on owner process
412            xptr_t      process_xp  = cluster_get_reference_process_from_pid( pid );
413            process_t * process_ptr = GET_PTR( process_xp );
414            cxy_t       process_cxy = GET_CXY( process_xp );
415
416            if( process_xp == XPTR_NULL )
417            {
418
419#if DEBUG_SYSCALLS_ERROR
420printk("\n[ERROR] in %s BARRIER : process %x not found\n",
421__FUNCTION__ , pid );
422#endif
423                this->errno = EINVAL;
424                return -1;
425            }
426
427            // get extended pointer on root of list of barriers
428            xptr_t root_xp = XPTR( process_cxy , &process_ptr->barrier_root );
429
430            if( xlist_is_empty( root_xp ) )
431            {
432
433#if DEBUG_SYSCALLS_ERROR
434printk("\n[ERROR] in %s BARRIER : no registered barrier in process %x\n",
435__FUNCTION__ , pid );
436#endif
437                this->errno = EINVAL;
438                return -1;
439            }
440
441            // get extended pointer on first registered generic barrier descriptor
442            xptr_t gen_barrier_xp  = XLIST_FIRST( root_xp , generic_barrier_t , list );
443
444            // display barrier state
445            generic_barrier_display( gen_barrier_xp );
446
447            break;
448        }
449        /////////////////
450        case DISPLAY_FAT:
451        {
452            uint32_t  slots = (uint32_t)arg1;
453
454            if( slots > 1024 )
455                {
456
457#if DEBUG_SYSCALLS_ERROR
458printk("\n[ERROR] in %s FAT : nb_slots larger than 1024\n",
459__FUNCTION__ );
460#endif
461                        this->errno = EINVAL;
462                        return -1;
463                }
464
465            if( slots == 0 )  // display fat context in cluster cxy
466            {
467                uint32_t  cxy = (uint32_t)arg0;
468
469                if( cluster_is_active( cxy ) == false ) 
470                {
471
472#if DEBUG_SYSCALLS_ERROR
473printk("\n[ERROR] in %s FAT : illegal cxy argument %x\n",
474__FUNCTION__ , cxy );
475#endif
476                     this->errno = EINVAL;
477                     return -1;
478                }
479
480                fatfs_display_ctx( cxy );
481            }
482            else                  // display nb_slots in page
483            {                       
484                uint32_t min  = (uint32_t)arg0;
485
486                fatfs_display_fat( min , slots );
487            }
488
489            break;
490        }
491        ////////////////////
492        case DISPLAY_SOCKET:
493        {
494            pid_t   pid   = (pid_t)arg0;
495            trdid_t fdid  = (trdid_t)arg1;
496
497            // get extended pointer on owner process descriptor
498            xptr_t owner_xp = cluster_get_owner_process_from_pid( pid );
499
500            if( owner_xp == XPTR_NULL )
501            {
502
503#if DEBUG_SYSCALLS_ERROR
504printk("\n[ERROR] in %s for SOCKET : pid %x not found\n", __FUNCTION__ , pid );
505#endif
506                this->errno = EINVAL;
507                return -1;
508            }
509
510            // get extended pointer on file descriptor
511            xptr_t file_xp = process_fd_get_xptr_from_owner( owner_xp , fdid );
512
513            if( file_xp == XPTR_NULL )
514            {
515
516#if DEBUG_SYSCALLS_ERROR
517printk("\n[ERROR] in %s for SOCKET : fdid %d not found\n", __FUNCTION__ , fdid );
518#endif
519                this->errno = EINVAL;
520                return -1;
521            }
522
523            // get local pointer and cluster for file
524            vfs_file_t * file_ptr = GET_PTR( file_xp );
525            cxy_t        file_cxy = GET_CXY( file_xp );
526
527            // get local pointer on socket descriptor
528            socket_t * socket = hal_remote_lpt( XPTR( file_cxy , &file_ptr->socket ) );
529
530            // display socket descriptor on TXT0
531            socket_display( XPTR( file_cxy , socket ), __FUNCTION__ , NULL );
532
533            break;
534        }
535        ////////////////
536        case DISPLAY_FD:
537        {
538            pid_t   pid   = (pid_t)arg0;
539
540            // get extended pointer on owner process descriptor
541            xptr_t owner_xp = cluster_get_owner_process_from_pid( pid );
542
543            if( owner_xp == XPTR_NULL )
544            {
545
546#if DEBUG_SYSCALLS_ERROR
547printk("\n[ERROR] in %s for FD : pid %x not found\n", __FUNCTION__ , pid );
548#endif
549                this->errno = EINVAL;
550                return -1;
551            }
552
553            // display fd_array on TXT0
554            process_fd_display( owner_xp );
555
556            break;
557        }
558        /////////////////////
559        case DISPLAY_WINDOWS:
560        {
561            pid_t   pid   = (pid_t)arg0;
562
563            if( pid != 0 )  // only one target process
564            {
565                // get extended pointer on owner process descriptor
566                xptr_t owner_xp = cluster_get_owner_process_from_pid( pid );
567
568                if( owner_xp == XPTR_NULL )
569                {
570
571#if DEBUG_SYSCALLS_ERROR
572printk("\n[ERROR] in %s for FD : pid %x not found\n", __FUNCTION__ , pid );
573#endif
574                    this->errno = EINVAL;
575                    return -1;
576                }
577            }
578
579            // display windows state for one, or for all processes
580            dev_fbf_display_windows( pid );
581
582            break;
583        }
584        ////////
585        default: 
586        {
587
588#if DEBUG_SYSCALLS_ERROR
589printk("\n[ERROR] in %s : undefined display type %d\n",
590        __FUNCTION__ , type );
591#endif
592            this->errno = EINVAL;
593            return -1;
594        }
595    }  // end switch on type
596
597#if (DEBUG_SYS_DISPLAY || CONFIG_INSTRUMENTATION_SYSCALLS)
598uint64_t     tm_end = hal_get_cycles();
599#endif
600
601#if DEBUG_SYS_DISPLAY
602if( DEBUG_SYS_DISPLAY < tm_end )
603printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
604__FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end );
605#endif
606
607#if CONFIG_INSTRUMENTATION_SYSCALLS
608hal_atomic_add( &syscalls_cumul_cost[SYS_DISPLAY] , tm_end - tm_start );
609hal_atomic_add( &syscalls_occurences[SYS_DISPLAY] , 1 );
610#endif
611
612    return 0;
613
614}  // end sys_display()
Note: See TracBrowser for help on using the repository browser.