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

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

Introduce the non-standard pthread_parallel_create() system call
and re-write the <fft> and <sort> applications to improve the
intrinsic paralelism in applications.

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