source: trunk/kernel/kern/printk.c @ 669

Last change on this file since 669 was 669, checked in by alain, 3 years ago

1) Introduce up to 4 command lines arguments in the KSH "load" command.
These arguments are transfered to the user process through the
argc/argv mechanism, using the user space "args" vseg.

2) Introduce the named and anonymous "pipes", for inter-process communication
through the pipe() and mkfifo() syscalls.

3) Introduce the "chat" application to validate the two above mechanisms.

4) Improve printk() and assert() fonctions in printk.c.

File size: 18.1 KB
Line 
1/*
2 * printk.c - Kernel Log & debug messages API implementation.
3 *
4 * authors  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_irqmask.h>
26#include <hal_special.h>
27#include <dev_txt.h>
28#include <remote_busylock.h>
29#include <cluster.h>
30#include <thread.h>
31#include <chdev.h>
32#include <printk.h>
33#include <shared_syscalls.h>
34
35///////////////////////////////////////////////////////////////////////////////////
36//      Extern
37///////////////////////////////////////////////////////////////////////////////////
38
39extern chdev_directory_t  chdev_dir;  // defined in chdev.h / allocated in kernel_init.c
40
41//////////////////////////////////////////////////////////////////////////////////////
42// This static function is called by printk(), nolock_printk(), and snprintk(),
43// functions to build a string from a printf-like format, and stores it
44// in the buffer defined by the <string> and <length> arguments.
45// It does NOT add a terminating NUL character in the <string> buffer.
46// If success, it returns the number of bytes actually copied in the string buffer.
47// It returns -2 in case of illegal format, it returns -1 if the formated string
48// exceeds the length argument.
49//////////////////////////////////////////////////////////////////////////////////////
50// @ string    : buffer allocated by caller.
51// @ length    : buffer size in bytes
52// @ format    : printf like format.
53// @ args      : va_list of arguments.
54// @ return string length if success / -1 if buffer too small / -2 if illegal format.
55//////////////////////////////////////////////////////////////////////////////////////
56static int32_t format_to_string( char       * string,
57                                 uint32_t     length,
58                                 const char * format, 
59                                 va_list    * args ) 
60{
61
62#define TO_STRING(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0);
63
64    uint32_t   ps = 0;        // index in string buffer
65
66format_to_string_text:
67
68    // handle one character per iteration
69    while ( *format != 0 ) 
70    {
71        if (*format == '%')   // copy argument to string
72        {
73            format++;
74            goto format_to_string_arguments;
75        }
76        else                  // copy one char to string
77        {
78            TO_STRING( *format );
79            format++;
80        }
81    }
82
83    TO_STRING( 0 );
84    return ps;
85
86format_to_string_arguments:
87
88    {
89        char              buf[30];    // buffer to display one number
90        char *            pbuf;       // pointer on first char to display
91        uint32_t          len = 0;    // number of char to display
92        static const char HexaTab[] = "0123456789ABCDEF";
93        uint32_t          i;
94       
95        switch (*format) 
96        {
97            case ('c'):             // char conversion
98            {
99                int val = va_arg( *args , int );
100                buf[0] = (char)val;
101                pbuf   = buf;
102                len    = 1;
103                break;
104            }
105            case ('d'):             // up to 10 digits decimal signed integer
106            {
107                int32_t val = va_arg( *args , int32_t );
108                if (val < 0) 
109                {
110                    TO_STRING( '-' );
111                    val = -val;
112                }
113                for(i = 0; i < 10; i++) 
114                {
115                    buf[9 - i] = HexaTab[val % 10];
116                    if (!(val /= 10)) break;
117                }
118                len =  i + 1;
119                pbuf = &buf[9 - i];
120                break;
121            }
122            case ('u'):             // up to 10 digits decimal unsigned integer
123            {
124                uint32_t val = va_arg( *args , uint32_t );
125                for(i = 0; i < 10; i++) 
126                {
127                    buf[9 - i] = HexaTab[val % 10];
128                    if (!(val /= 10)) break;
129                }
130                len =  i + 1;
131                pbuf = &buf[9 - i];
132                break;
133            }
134            case ('x'):             // up to 8 digits hexad after "0x"
135            case ('X'):             // exactly 8 digits hexa after "0x"
136            {
137                uint32_t val = va_arg( *args , uint32_t );
138                TO_STRING( '0' );
139                TO_STRING( 'x' );
140                for(i = 0 ; i < 8 ; i++) 
141                {
142                    buf[7 - i] = HexaTab[val & 0xF];
143                    if( (*format == 'x') && ((val >> 4) == 0) )  break;
144                    val = val >> 4;
145                }
146                len =  i + 1;
147                pbuf = &buf[7 - i];
148                break;
149            }
150            case ('l'):             // up to 16 digits hexa after "0x"
151            case ('L'):             // exactly 16 digits hexa after "0x"
152            {
153                uint64_t val = (((uint64_t)va_arg( *args, uint32_t)) << 32) |
154                               ((uint64_t)va_arg( *args, uint32_t));
155                TO_STRING( '0' );
156                TO_STRING( 'x' );
157                for(i = 0 ; i < 16 ; i++) 
158                {
159                    buf[15 - i] = HexaTab[val & 0xF];
160                    if( (*format == 'l') && ((val >> 4) == 0) )  break;
161                    val = val >> 4;
162                }
163                len =  i + 1;
164                pbuf = &buf[15 - i];
165                break;
166            }
167            case ('s'):             /* string */
168            {
169                char* str = va_arg( *args , char* );
170                while (str[len]) { len++; }
171                pbuf = str;
172                break;
173            }
174            default:       // unsupported argument type
175            {
176                return -2;
177            }
178        }  // end switch on  argument type
179
180        format++;
181
182        // copy argument sub-string to the string buffer
183        for( i = 0 ; i < len ; i++ )
184        {
185            TO_STRING( pbuf[i] );
186        }
187       
188        goto format_to_string_text;
189    }
190}   // end format_to_string()
191
192//////////////////////////////////
193void printk( char * format , ... )
194{
195    char          buffer[CONFIG_PRINTK_BUF_SIZE];
196    va_list       args;
197    int32_t       length;
198
199    // build args va_list
200    va_start( args , format );
201
202    // get pointers on TXT0 chdev
203    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
204    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
205    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
206
207    // get extended pointer on remote TXT0 lock
208    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
209
210    // get TXT0 lock
211    remote_busylock_acquire( lock_xp );
212
213    // build a string from format
214    length = format_to_string( buffer,
215                      CONFIG_PRINTK_BUF_SIZE,
216                      format,
217                      &args );
218    va_end( args );
219
220    if( length > 0  )        // call TXT driver to display formated string on TXT0
221    {
222        dev_txt_sync_write( buffer , length );
223    }
224    else if( length == -2 )  // illegal format => display a warning on TXT0
225    {
226        thread_t * this = CURRENT_THREAD;
227
228        nolock_printk("\n[PANIC] from printk : illegal format\n"
229                      "thread[%x,%x] on core[%x,%d] at cycle %l\n",
230                      this->process->pid, this->trdid,
231                      local_cxy, this->core->lid, hal_get_cycles() );
232    }
233    else                     // format too long => display a warning on TXT0
234    {
235        thread_t * this = CURRENT_THREAD;
236
237        nolock_printk("\n[PANIC] from printk : formated string too long\n"
238                      "thread[%x,%x] on core[%x,%d] at cycle %l\n",
239                      this->process->pid, this->trdid,
240                      local_cxy, this->core->lid, hal_get_cycles() );
241    }
242
243    // release TXT0 lock
244    remote_busylock_release( lock_xp );
245
246}   // end printk()
247
248/////////////////////////////////////////
249void nolock_printk( char * format , ... )
250{
251    char          buffer[CONFIG_PRINTK_BUF_SIZE];
252    va_list       args;
253    int32_t       length;
254
255    // build args va_list
256    va_start( args , format );
257
258    // build a string from format
259    length = format_to_string( buffer,
260                      CONFIG_PRINTK_BUF_SIZE,
261                      format,
262                      &args );
263    va_end( args );
264
265    if( length > 0  )        // call TXT driver to display formated string on TXT0
266    {
267        dev_txt_sync_write( buffer , length );
268    }
269    else if( length == -2 )  // illegal format => display a warning on TXT0
270    {
271        thread_t * this = CURRENT_THREAD;
272
273        nolock_printk("\n[PANIC] from print : illegal format\n"
274                      "thread[%x,%x] on core[%x,%d] at cycle %l\n",
275                      this->process->pid, this->trdid,
276                      local_cxy, this->core->lid, hal_get_cycles() );
277    }
278    else                  // buffer too small => display a warning on TXT0
279    {
280        thread_t * this = CURRENT_THREAD;
281
282        nolock_printk("\n[PANIC] from printk : formated string too long\n"
283                      "thread[%x,%x] on core[%x,%d] at cycle %l\n",
284                      this->process->pid, this->trdid,
285                      local_cxy, this->core->lid, hal_get_cycles() );
286    }
287
288}   // end nolock_printk()
289
290//////////////////////////////////////
291void assert( const char   * func_name,
292             bool_t         expr,
293             char         * format , ... )
294{
295    if( expr == false )
296    {
297        thread_t * this  = CURRENT_THREAD;
298        trdid_t    trdid = this->trdid;
299        pid_t      pid   = this->process->pid;
300        uint32_t   lid   = this->core->lid;
301        uint32_t   cycle = (uint32_t)hal_get_cycles();
302
303        char       buffer[CONFIG_PRINTK_BUF_SIZE];
304        va_list    args;
305
306        va_start( args , format );
307
308        // build a string from format
309        int32_t   length = format_to_string( buffer,
310                                             CONFIG_PRINTK_BUF_SIZE,
311                                             format,
312                                             &args );
313        va_end( args );
314
315        if( length > 0  )  // display panic message on TXT0, including formated string
316        {
317            printk("\n[ASSERT] in %s / core[%x,%d] / thread[%x,%x] / cycle %d\n       %s\n",
318            func_name, local_cxy, lid, pid, trdid, cycle, buffer );
319        }
320        else              // display minimal panic message on TXT0
321        {
322            printk("\n[ASSERT] in %s / core[%x,%d] / thread[%x,%x] / cycle %d\n",
323            func_name, local_cxy, lid, pid, trdid, cycle );
324        }
325    }
326}   // end assert( __FUNCTION__,)
327   
328//////////////////////////////////////
329int32_t snprintk( char       * buffer,
330                  uint32_t     size,
331                  char       * format, ... )
332{
333    va_list       args;
334    int32_t       string_length;
335
336    // build args va_list
337    va_start( args , format );
338
339    // build a string from format
340    string_length = format_to_string( buffer , size , format , &args );
341    va_end( args );
342
343    if( (string_length < 0) || (string_length == (int32_t)size) )  // failure
344    {
345        return -1;
346    }
347    else                                                           // success
348    {
349        // add NUL character
350        buffer[string_length] = 0;
351
352        return string_length;
353    }
354}   // end snprintk()
355
356////////////////////////////////
357void puts( const char * string ) 
358{
359    uint32_t   n = 0;
360
361    // compute string length
362    while ( string[n] > 0 ) n++;
363
364    // get pointers on TXT0 chdev
365    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
366    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
367    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
368
369    if( txt0_xp != XPTR_NULL )
370    {
371        // get extended pointer on remote TXT0 lock
372        xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
373
374        // display string on TTY0
375        remote_busylock_acquire( lock_xp );
376        dev_txt_sync_write( string , n );
377        remote_busylock_release( lock_xp );
378    }
379}   // end puts()
380
381///////////////////////////////////////
382void nolock_puts( const char * string ) 
383{
384    uint32_t   n = 0;
385
386    // compute string length
387    while ( string[n] > 0 ) n++;
388
389    // display string on TTY0
390    dev_txt_sync_write( string , n );
391 
392}   // end nolock_puts()
393
394
395
396/////////////////////////
397void putx( uint32_t val )
398{
399    static const char HexaTab[] = "0123456789ABCDEF";
400
401    char      buf[10];
402    uint32_t  c;
403
404    buf[0] = '0';
405    buf[1] = 'x';
406
407    // build buffer
408    for (c = 0; c < 8; c++) 
409    { 
410        buf[9 - c] = HexaTab[val & 0xF];
411        val = val >> 4;
412    }
413
414    // get pointers on TXT0 chdev
415    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
416    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
417    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
418
419    if( txt0_xp != XPTR_NULL )
420    {
421        // get extended pointer on remote TXT0 chdev lock
422        xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
423
424        // display buf on TTY0
425        remote_busylock_acquire( lock_xp );
426        dev_txt_sync_write( buf , 10 );
427        remote_busylock_release( lock_xp );
428    }
429}   // end putx()
430
431////////////////////////////////
432void nolock_putx( uint32_t val )
433{
434    static const char HexaTab[] = "0123456789ABCDEF";
435
436    char      buf[10];
437    uint32_t  c;
438
439    buf[0] = '0';
440    buf[1] = 'x';
441
442    // build buffer
443    for (c = 0; c < 8; c++) 
444    { 
445        buf[9 - c] = HexaTab[val & 0xF];
446        val = val >> 4;
447    }
448
449    // display buf on TTY0
450    dev_txt_sync_write( buf , 10 );
451
452}   // end nilock_putx()
453
454////////////////////////
455void putd( int32_t val )
456{
457    static const char HexaTab[] = "0123456789ABCDEF";
458
459    char      buf[10];
460    uint32_t  i;
461
462    // get pointers on TXT0 chdev
463    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
464    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
465    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
466
467    // get extended pointer on remote TXT0 chdev lock
468    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
469
470    if( txt0_xp != XPTR_NULL )
471    {
472        // get TXT0 lock
473        remote_busylock_acquire( lock_xp );
474
475        if (val < 0) 
476        {
477            val = -val;
478            dev_txt_sync_write( "-" , 1 );
479        }
480
481        for(i = 0; i < 10 ; i++) 
482        {
483            buf[9 - i] = HexaTab[val % 10];
484            if (!(val /= 10)) break;
485        }
486
487        // display buf on TTY0
488        dev_txt_sync_write( &buf[9-i] , i+1 );
489
490        // release TXT0 lock
491        remote_busylock_release( lock_xp );
492    }
493}   // end putd()
494
495///////////////////////////////
496void nolock_putd( int32_t val )
497{
498    static const char HexaTab[] = "0123456789ABCDEF";
499
500    char      buf[10];
501    uint32_t  i;
502
503    if (val < 0) 
504    {
505        val = -val;
506        dev_txt_sync_write( "-" , 1 );
507    }
508
509    for(i = 0; i < 10 ; i++) 
510    {
511        buf[9 - i] = HexaTab[val % 10];
512        if (!(val /= 10)) break;
513    }
514
515    // display buf on TTY0
516    dev_txt_sync_write( &buf[9-i] , i+1 );
517
518}   // end nolock_putd()
519
520/////////////////////////
521void putl( uint64_t val )
522{
523    static const char HexaTab[] = "0123456789ABCDEF";
524
525    char      buf[18];
526    uint32_t  c;
527
528    buf[0] = '0';
529    buf[1] = 'x';
530
531    // build buffer
532    for (c = 0; c < 16; c++) 
533    { 
534        buf[17 - c] = HexaTab[(unsigned int)val & 0xF];
535        val = val >> 4;
536    }
537
538    // get pointers on TXT0 chdev
539    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
540    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
541    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
542
543    if( txt0_xp != XPTR_NULL )
544    {
545        // get extended pointer on remote TXT0 chdev lock
546        xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
547
548        // display string on TTY0
549        remote_busylock_acquire( lock_xp );
550        dev_txt_sync_write( buf , 18 );
551        remote_busylock_release( lock_xp );
552    }
553}   // end putl()
554
555////////////////////////////////
556void nolock_putl( uint64_t val )
557{
558    static const char HexaTab[] = "0123456789ABCDEF";
559
560    char      buf[18];
561    uint32_t  c;
562
563    buf[0] = '0';
564    buf[1] = 'x';
565
566    // build buffer
567    for (c = 0; c < 16; c++) 
568    { 
569        buf[17 - c] = HexaTab[(unsigned int)val & 0xF];
570        val = val >> 4;
571    }
572
573    // display string on TTY0
574    dev_txt_sync_write( buf , 18 );
575
576}   // end nolock_putl()
577
578/////////////////////////////
579void putb( char     * string,
580           uint8_t  * buffer,
581           uint32_t   size )
582{
583    uint32_t line;
584    uint32_t byte;
585    uint32_t nlines;
586
587    nlines = size >> 4;
588    if( size & 0xF ) nlines++;
589
590    // get pointers on TXT0 chdev
591    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
592    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
593    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
594
595    // get extended pointer on remote TXT0 chdev lock
596    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
597
598    if( txt0_xp != XPTR_NULL )
599    {
600        // get TXT0 lock
601        remote_busylock_acquire( lock_xp );
602
603        // display string on TTY0
604        nolock_printk("\n***** %s *****\n", string );
605
606        for ( line = 0 , byte = 0 ; line < nlines ; line++ )
607        {
608            nolock_printk(" %X | %b %b %b %b | %b %b %b %b | %b %b %b %b | %b %b %b %b |\n",
609            buffer + byte,
610            buffer[byte+ 0],buffer[byte+ 1],buffer[byte+ 2],buffer[byte+ 3],
611            buffer[byte+ 4],buffer[byte+ 5],buffer[byte+ 6],buffer[byte+ 7],
612            buffer[byte+ 8],buffer[byte+ 9],buffer[byte+10],buffer[byte+11],
613            buffer[byte+12],buffer[byte+13],buffer[byte+14],buffer[byte+15] );
614
615            byte += 16;
616        }
617
618        // release TXT0 lock
619        remote_busylock_release( lock_xp );
620    }
621}   // end putb()
622
623
624
625// Local Variables:
626// tab-width: 4
627// c-basic-offset: 4
628// c-file-offsets:((innamespace . 0)(inline-open . 0))
629// indent-tabs-mode: nil
630// End:
631// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
632
Note: See TracBrowser for help on using the repository browser.