source: trunk/kernel/kern/printk.c

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

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

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