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
RevLine 
[1]1/*
2 * printk.c - Kernel Log & debug messages API implementation.
3 *
[669]4 * authors  Alain Greiner (2016,2017,2018,2019,2020)
[1]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>
[1]25#include <hal_irqmask.h>
[5]26#include <hal_special.h>
[1]27#include <dev_txt.h>
[564]28#include <remote_busylock.h>
[1]29#include <cluster.h>
[446]30#include <thread.h>
[14]31#include <chdev.h>
[5]32#include <printk.h>
[445]33#include <shared_syscalls.h>
[1]34
35///////////////////////////////////////////////////////////////////////////////////
[669]36//      Extern
[14]37///////////////////////////////////////////////////////////////////////////////////
38
[188]39extern chdev_directory_t  chdev_dir;  // defined in chdev.h / allocated in kernel_init.c
[14]40
[669]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 ) 
[23]60{
61
[669]62#define TO_STRING(x) do { string[ps] = (x); ps++; if(ps==length) return -1; } while(0);
[23]63
[669]64    uint32_t   ps = 0;        // index in string buffer
[23]65
[669]66format_to_string_text:
[23]67
[669]68    // handle one character per iteration
[23]69    while ( *format != 0 ) 
70    {
71        if (*format == '%')   // copy argument to string
72        {
73            format++;
[669]74            goto format_to_string_arguments;
[23]75        }
76        else                  // copy one char to string
77        {
[669]78            TO_STRING( *format );
[23]79            format++;
80        }
81    }
82
[669]83    TO_STRING( 0 );
[23]84    return ps;
85
[669]86format_to_string_arguments:
[23]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            {
[669]99                int val = va_arg( *args , int );
100                buf[0] = (char)val;
[23]101                pbuf   = buf;
102                len    = 1;
103                break;
104            }
[623]105            case ('d'):             // up to 10 digits decimal signed integer
106            {
[669]107                int32_t val = va_arg( *args , int32_t );
[23]108                if (val < 0) 
109                {
[669]110                    TO_STRING( '-' );
[23]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            }
[623]122            case ('u'):             // up to 10 digits decimal unsigned integer
[23]123            {
[669]124                uint32_t val = va_arg( *args , uint32_t );
[23]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            }
[669]134            case ('x'):             // up to 8 digits hexad after "0x"
135            case ('X'):             // exactly 8 digits hexa after "0x"
[23]136            {
[669]137                uint32_t val = va_arg( *args , uint32_t );
138                TO_STRING( '0' );
139                TO_STRING( 'x' );
140                for(i = 0 ; i < 8 ; i++) 
[23]141                {
[669]142                    buf[7 - i] = HexaTab[val & 0xF];
143                    if( (*format == 'x') && ((val >> 4) == 0) )  break;
144                    val = val >> 4;
[23]145                }
146                len =  i + 1;
[669]147                pbuf = &buf[7 - i];
[23]148                break;
149            }
[669]150            case ('l'):             // up to 16 digits hexa after "0x"
151            case ('L'):             // exactly 16 digits hexa after "0x"
[246]152            {
[669]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++) 
[246]158                {
[669]159                    buf[15 - i] = HexaTab[val & 0xF];
160                    if( (*format == 'l') && ((val >> 4) == 0) )  break;
161                    val = val >> 4;
[246]162                }
[669]163                len =  i + 1;
164                pbuf = &buf[15 - i];
[246]165                break;
166            }
[23]167            case ('s'):             /* string */
168            {
[669]169                char* str = va_arg( *args , char* );
[23]170                while (str[len]) { len++; }
171                pbuf = str;
172                break;
173            }
174            default:       // unsupported argument type
175            {
[669]176                return -2;
[23]177            }
178        }  // end switch on  argument type
179
180        format++;
181
[669]182        // copy argument sub-string to the string buffer
[23]183        for( i = 0 ; i < len ; i++ )
184        {
[669]185            TO_STRING( pbuf[i] );
[23]186        }
187       
[669]188        goto format_to_string_text;
[23]189    }
[669]190}   // end format_to_string()
[23]191
[337]192//////////////////////////////////
193void printk( char * format , ... )
[1]194{
[669]195    char          buffer[CONFIG_PRINTK_BUF_SIZE];
[1]196    va_list       args;
[669]197    int32_t       length;
[1]198
[669]199    // build args va_list
200    va_start( args , format );
201
[188]202    // get pointers on TXT0 chdev
[407]203    xptr_t    txt0_xp  = chdev_dir.txt_tx[0];
[188]204    cxy_t     txt0_cxy = GET_CXY( txt0_xp );
205    chdev_t * txt0_ptr = GET_PTR( txt0_xp );
206
[564]207    // get extended pointer on remote TXT0 lock
[188]208    xptr_t  lock_xp = XPTR( txt0_cxy , &txt0_ptr->wait_lock );
[14]209
[564]210    // get TXT0 lock
211    remote_busylock_acquire( lock_xp );
[14]212
[669]213    // build a string from format
214    length = format_to_string( buffer,
215                      CONFIG_PRINTK_BUF_SIZE,
216                      format,
217                      &args );
[1]218    va_end( args );
[14]219
[669]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
[564]243    // release TXT0 lock
244    remote_busylock_release( lock_xp );
[1]245
[669]246}   // end printk()
247
[337]248/////////////////////////////////////////
249void nolock_printk( char * format , ... )
[296]250{
[669]251    char          buffer[CONFIG_PRINTK_BUF_SIZE];
[296]252    va_list       args;
[669]253    int32_t       length;
[296]254
[669]255    // build args va_list
[296]256    va_start( args , format );
[669]257
258    // build a string from format
259    length = format_to_string( buffer,
260                      CONFIG_PRINTK_BUF_SIZE,
261                      format,
262                      &args );
[296]263    va_end( args );
264
[669]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 , ... )
[5]294{
[669]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();
[337]302
[669]303        char       buffer[CONFIG_PRINTK_BUF_SIZE];
304        va_list    args;
[491]305
[669]306        va_start( args , format );
[337]307
[669]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 );
[564]314
[669]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;
[337]335
[669]336    // build args va_list
337    va_start( args , format );
[337]338
[669]339    // build a string from format
340    string_length = format_to_string( buffer , size , format , &args );
341    va_end( args );
[337]342
[669]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;
[1]351
[669]352        return string_length;
353    }
354}   // end snprintk()
355
356////////////////////////////////
357void puts( const char * string ) 
[408]358{
359    uint32_t   n = 0;
[23]360
[408]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
[669]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 );
[408]373
[669]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()
[408]380
[669]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
[408]389    // display string on TTY0
390    dev_txt_sync_write( string , n );
[669]391 
392}   // end nolock_puts()
[408]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
[669]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 );
[408]423
[669]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()
[408]430
[669]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
[625]449    // display buf on TTY0
[408]450    dev_txt_sync_write( buf , 10 );
451
[669]452}   // end nilock_putx()
[408]453
[625]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
[669]470    if( txt0_xp != XPTR_NULL )
471    {
472        // get TXT0 lock
473        remote_busylock_acquire( lock_xp );
[625]474
[669]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
[625]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
[669]518}   // end nolock_putd()
[625]519
[408]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
[669]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 );
[408]547
[669]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()
[408]554
[669]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
[408]573    // display string on TTY0
574    dev_txt_sync_write( buf , 18 );
575
[669]576}   // end nolock_putl()
[408]577
[623]578/////////////////////////////
579void putb( char     * string,
580           uint8_t  * buffer,
581           uint32_t   size )
582{
583    uint32_t line;
[662]584    uint32_t byte;
585    uint32_t nlines;
[408]586
[662]587    nlines = size >> 4;
588    if( size & 0xF ) nlines++;
589
[623]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
[669]598    if( txt0_xp != XPTR_NULL )
599    {
600        // get TXT0 lock
601        remote_busylock_acquire( lock_xp );
[623]602
[669]603        // display string on TTY0
604        nolock_printk("\n***** %s *****\n", string );
[623]605
[669]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] );
[623]614
[669]615            byte += 16;
616        }
617
618        // release TXT0 lock
619        remote_busylock_release( lock_xp );
[623]620    }
[669]621}   // end putb()
[623]622
623
624
[1]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.