source: trunk/kernel/syscalls/sys_display.c

Last change on this file was 683, checked in by alain, 6 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.