source: soft/giet_vm/giet_libs/stdio.c @ 386

Last change on this file since 386 was 382, checked in by alain, 10 years ago

Major evolution of the malloc library, to provide two new services:

  • all allocated blocks are aligned, and the size is a power of 2.
  • the remote-malloc() function allows the application to explicitely define the cluster(x,y).

We keep only the close-fit allocation policy.
These services were required to implement the distributed SBT barrier.

  • Property svn:executable set to *
File size: 19.5 KB
RevLine 
[258]1//////////////////////////////////////////////////////////////////////////////////
2// File     : stdio.c         
3// Date     : 01/04/2010
4// Author   : alain greiner & Joel Porquet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The stdio.c and stdio.h files are part of the GIET_VM nano-kernel.
8// This library contains all user-level functions that contain a system call
9// to access protected or shared ressources.
10///////////////////////////////////////////////////////////////////////////////////
11
12#include <stdarg.h>
13#include <stdio.h>
[267]14#include <giet_config.h>
[258]15
16////////////////////////////////////////////////////////////////////////////////////
[295]17/////////////////////  TTY device related system calls /////////////////////////////
[258]18////////////////////////////////////////////////////////////////////////////////////
[295]19
[352]20///////////////////////////////////////////////////////////////////////
[345]21static int __printf( char* format, unsigned int channel, va_list* args) 
[258]22{
[345]23    int ret;                    // return value from the syscalls
[258]24
[295]25printf_text:
[258]26
[295]27    while (*format) 
[258]28    {
[295]29        unsigned int i;
30        for (i = 0 ; format[i] && (format[i] != '%') ; i++);
31        if (i) 
32        {
33            ret = sys_call(SYSCALL_TTY_WRITE, 
34                           (unsigned int)format,
35                           i, 
36                           channel,
[258]37                           0);
38
[295]39            if (ret != i) goto return_error;
40
41            format += i;
[258]42        }
[295]43        if (*format == '%') 
[258]44        {
[295]45            format++;
46            goto printf_arguments;
[258]47        }
48    }
49
[345]50    return 0;
[295]51
52printf_arguments:
53
[258]54    {
[295]55        char buf[20];
56        char * pbuf;
57        unsigned int len = 0;
58        static const char HexaTab[] = "0123456789ABCDEF";
59        unsigned int i;
[258]60
[295]61        switch (*format++) 
[258]62        {
[295]63            case ('c'):             /* char conversion */
[258]64            {
[345]65                int val = va_arg( *args, int );
[295]66                len = 1;
67                buf[0] = val;
68                pbuf = &buf[0];
69                break;
[258]70            }
[295]71            case ('d'):             /* 32 bits decimal signed integer */
[258]72            {
[345]73                int val = va_arg( *args, int );
[295]74                if (val < 0) 
75                {
76                    val = -val;
77                    ret = sys_call(SYSCALL_TTY_WRITE, 
78                                   (unsigned int)"-",
79                                   1,
80                                   channel,
81                                   0);
82                    if (ret != 1) goto return_error;
83                }
84                for(i = 0; i < 10; i++) 
85                {
86                    buf[9 - i] = HexaTab[val % 10];
87                    if (!(val /= 10)) break;
88                }
89                len =  i + 1;
90                pbuf = &buf[9 - i];
91                break;
[258]92            }
[295]93            case ('u'):             /* 32 bits decimal unsigned integer */
94            {
[345]95                unsigned int val = va_arg( *args, unsigned int );
[295]96                for(i = 0; i < 10; i++) 
97                {
98                    buf[9 - i] = HexaTab[val % 10];
99                    if (!(val /= 10)) break;
100                }
101                len =  i + 1;
102                pbuf = &buf[9 - i];
103                break;
104            }
105            case ('x'):             /* 32 bits hexadecimal integer */
106            {
[345]107                unsigned int val = va_arg( *args, unsigned int );
[295]108                ret = sys_call(SYSCALL_TTY_WRITE,
109                               (unsigned int)"0x",
110                               2,
111                               channel,
112                               0);
113                if (ret != 2) goto return_error;       
114                for(i = 0; i < 8; i++) 
115                {
116                    buf[7 - i] = HexaTab[val % 16];
117                    if (!(val /= 16))  break;
118                }
119                len =  i + 1;
120                pbuf = &buf[7 - i];
121                break;
122            }
123            case ('l'):            /* 64 bits hexadecimal unsigned */
124            {
[345]125                unsigned long long val = va_arg( *args, unsigned long long );
[295]126                ret = sys_call(SYSCALL_TTY_WRITE,
127                               (unsigned int)"0x",
128                               2,
129                               channel,
130                               0);
131                if (ret != 2) goto return_error;
132                for(i = 0; i < 16; i++) 
133                {
134                    buf[15 - i] = HexaTab[val % 16];
135                    if (!(val /= 16))  break;
136                }
137                len =  i + 1;
138                pbuf = &buf[15 - i];
139                break;
140            }
141            case ('s'):             /* string */
142            {
[345]143                char* str = va_arg( *args, char* );
[295]144                while (str[len]) 
145                {
146                    len++;
147                }
148                pbuf = str;
149                break;
150            }
151            default:
152                goto return_error;
[258]153        }
154
[295]155        ret = sys_call(SYSCALL_TTY_WRITE, 
156                       (unsigned int)pbuf,
157                       len,
158                       channel, 
159                       0);
160        if (ret != len)  goto return_error;
161       
162        goto printf_text;
[258]163    }
164
[295]165return_error:
[345]166    return 1;
167} // end __printf()
[295]168
[345]169
170////////////////////////////////////////
171void giet_tty_printf( char* format, ...) 
172{
173    va_list args;
174
175    va_start( args, format );
176    int ret = __printf(format, 0xFFFFFFFF, &args);
[295]177    va_end( args );
[345]178
179    if (ret)
180    {
[382]181        giet_exit("ERROR in giet_tty_printf()");
[345]182    }
[295]183} // end giet_tty_printf()
184
185////////////////////////////////////////
186void giet_shr_printf( char* format, ...) 
[258]187{
[295]188    va_list args;
[345]189    const int channel = 0;
190    volatile unsigned int sr_save;
[258]191
[295]192    sys_call( SYSCALL_TTY_GET_LOCK,
193              channel,
194              (unsigned int)&sr_save,
195              0, 0 );
196
[345]197    va_start( args, format );
198    int ret = __printf(format, channel, &args);
199    va_end( args );
[258]200
[295]201    sys_call( SYSCALL_TTY_RELEASE_LOCK,
202              channel,
203              (unsigned int)&sr_save,
204              0, 0 );
[267]205
[345]206    if (ret)
[258]207    {
[345]208        giet_exit("error in giet_shr_printf()");
[258]209    }
[345]210} // end giet_shr_printf()
[267]211
[295]212/////////////////////////////////
213void giet_tty_getc( char * byte ) 
214{
215    int ret;
216
217    do
[267]218    {
[295]219        ret = sys_call(SYSCALL_TTY_READ, 
220                      (unsigned int)byte,  // buffer address
221                      1,                   // number of characters
222                      0xFFFFFFFF,          // channel index from task context
223                      0);
224        if ( ret < 0 ) giet_exit("error in giet_tty_getc()");
[267]225    }
[295]226    while (ret != 1); 
227}
[267]228
[295]229/////////////////////////////////////
230void giet_tty_gets( char*        buf, 
231                    unsigned int bufsize ) 
232{
233    int           ret;
234    unsigned char byte;
235    unsigned int  index = 0;
236 
237    while (index < (bufsize - 1)) 
238    {
239        do 
240        { 
241            ret = sys_call(SYSCALL_TTY_READ, 
242                           (unsigned int)(&byte),
243                           1,
244                           0xFFFFFFFF,
245                           0);
246            if ( ret < 0 ) giet_exit("error in giet_tty_gets()");
247        } 
248        while (ret != 1);
249
250        if (byte == 0x0A)  /* LF */
251        {
252            break; 
253        }
254        else if ((byte == 0x7F) && (index > 0))  /* DEL */
255        {
256            index--; 
257        }
258        else 
259        {
260            buf[index] = byte;
261            index++;
262        }
263    }
264    buf[index] = 0;
[258]265}
266
[295]267///////////////////////////////////////
268void giet_tty_getw( unsigned int* val ) 
269{
270    unsigned char buf[32];
271    unsigned int  string_byte   = 0x00000000;    // string containing one single byte
272    unsigned int  string_cancel = 0x00082008;    // string containing BS/SPACE/BS
273    unsigned int  save = 0;
274    unsigned int  dec = 0;
275    unsigned int  done = 0;
276    unsigned int  overflow = 0;
277    unsigned int  length = 0;
278    unsigned int  i;
279    unsigned int  channel = 0xFFFFFFFF;
280    int           ret;      // return value from syscalls
281 
282    // get characters
283    while (done == 0) 
284    {
285        // read one character
286        do 
287        { 
288            ret = sys_call( SYSCALL_TTY_READ,
289                            (unsigned int)(&string_byte),
290                            1,
291                            channel, 
292                            0); 
293            if ( ret < 0 ) giet_exit("error in giet_tty_getw()");
294        } 
295        while (ret != 1);
[258]296
[295]297        // analyse character
298        if ((string_byte > 0x2F) && (string_byte < 0x3A))  /* decimal character */
299        {
300            buf[length] = (unsigned char)string_byte;
301            length++;
[258]302
[295]303            // echo
304            ret = sys_call( SYSCALL_TTY_WRITE, 
305                            (unsigned int)(&string_byte),
306                            1, 
307                            channel, 
308                            0 );
309            if ( ret < 0 ) giet_exit("error in giet_tty_gets()");
310        }
311        else if (string_byte == 0x0A)                     /* LF character */
312        {
313            done = 1;
314        }
315        else if ( (string_byte == 0x7F) ||                /* DEL character */
316                  (string_byte == 0x08) )                 /* BS  character */
317        {
318            if ( length > 0 ) 
319            {
320                length--;    // cancel the character
321
322                ret = sys_call( SYSCALL_TTY_WRITE, 
323                                (unsigned int)(&string_cancel),
324                                3, 
325                                channel, 
326                                0 );
[352]327                if ( ret < 0 ) giet_exit("error in giet_tty_getw()");
[295]328            }
329        }
330
331        // test buffer overflow
332        if ( length >= 32 ) 
333        {
334            overflow = 1;
335            done     = 1;
336        }
337    }  // end while characters
338
339    // string to int conversion with overflow detection
340    if ( overflow == 0 )
341    {
342        for (i = 0; (i < length) && (overflow == 0) ; i++) 
343        {
344            dec = dec * 10 + (buf[i] - 0x30);
345            if (dec < save)  overflow = 1; 
346            save = dec;
347        }
348    } 
349
350    // final evaluation
351    if ( overflow == 0 )
352    {
353        // return value
354        *val = dec;
355    }
356    else
357    {
358        // cancel all echo characters
359        for (i = 0; i < length ; i++) 
360        {
361            ret = sys_call( SYSCALL_TTY_WRITE, 
362                            (unsigned int)(&string_cancel),
363                            3, 
364                            channel, 
365                            0 );
[352]366            if ( ret < 0 ) giet_exit("error in giet_tty_getw()");
[295]367        }
368        // echo character '0'
369        string_byte = 0x30;
370        ret = sys_call( SYSCALL_TTY_WRITE, 
371                        (unsigned int)(&string_byte),
372                        1, 
373                        channel, 
374                        0 );
[352]375        if ( ret < 0 ) giet_exit("error in giet_tty_getw()");
[295]376
377        // return 0 value
378        *val = 0;
379    }
380}
381
382
[258]383//////////////////////////////////////////////////////////////////////////////////
384/////////////////////  TIMER related system calls ////////////////////////////////
385//////////////////////////////////////////////////////////////////////////////////
386
[295]387///////////////////////
388void giet_timer_start() 
[258]389{
[295]390    if ( sys_call( SYSCALL_TIMER_START, 0, 0, 0, 0 ) ) 
391       giet_exit("error in giet_timer_start()");
[258]392}
[295]393
394//////////////////////
395void giet_timer_stop() 
[258]396{
[295]397    if ( sys_call( SYSCALL_TIMER_STOP, 0, 0, 0, 0 ) ) 
398        giet_exit("error in giet_timer_stop()");
[258]399}
400
401
402//////////////////////////////////////////////////////////////////////////////////
403///////////////  Frame buffer device related system calls  ///////////////////////
404//////////////////////////////////////////////////////////////////////////////////
405
[295]406////////////////////////////////////////////
407void giet_fb_sync_write( unsigned int offset, 
[258]408                        void *       buffer, 
409                        unsigned int length ) 
410{
[295]411    if ( sys_call( SYSCALL_FB_SYNC_WRITE, 
412                   offset, 
413                   (unsigned int)buffer, 
414                   length, 
415                   0 ) )  giet_exit("error in giet_fb_sync_write()");
[258]416}
[295]417
418///////////////////////////////////////////
419void giet_fb_sync_read( unsigned int offset, 
420                        void *       buffer, 
421                        unsigned int length ) 
[258]422{
[295]423    if ( sys_call( SYSCALL_FB_SYNC_READ, 
424                   offset, 
425                   (unsigned int)buffer, 
426                   length, 
427                   0 ) )   giet_exit("error in giet_fb_sync_read()");
[258]428}
[295]429
430/////////////////////////////////////////
431void giet_fb_cma_init( void *       buf0,
432                       void *       buf1,
433                       unsigned int length )
[258]434{
[295]435    if ( sys_call( SYSCALL_FB_CMA_INIT, 
436                   (unsigned int)buf0, 
437                   (unsigned int)buf1, 
438                   length, 
439                   0 ) )   giet_exit("error in giet_fb_cma_init()");
[258]440}
[295]441
442///////////////////////////////////////////////
443void giet_fb_cma_write( unsigned int buffer_id )
[258]444{
[295]445    if ( sys_call( SYSCALL_FB_CMA_WRITE, 
446                   buffer_id, 
447                   0, 0, 0 ) )   giet_exit("error in giet_fb_cma_write()");
[258]448}
[295]449
450////////////////////////
451void giet_fb_cma_stop()
[258]452{
[295]453    if ( sys_call( SYSCALL_FB_CMA_STOP, 
454                   0, 0, 0, 0 ) )    giet_exit("error in giet_fb_cma_stop()");
[258]455}
456
457
458//////////////////////////////////////////////////////////////////////////////////
459/////////////////////// NIC related system calls /////////////////////////////////
460//////////////////////////////////////////////////////////////////////////////////
461
[295]462/////////////////////////
463void giet_nic_cma_start()
[258]464{
[295]465    if ( sys_call( SYSCALL_NIC_CMA_START, 0, 0, 0, 0 ) ) 
466       giet_exit("error in giet_nic_cma_start()");
[258]467}
[295]468
469/////////////////////////
470void giet_nic_cma_stop()
[258]471{
[295]472    if ( sys_call( SYSCALL_NIC_CMA_STOP, 0, 0, 0, 0 ) ) 
473        giet_exit("error in giet_nic_cma_stop()");
[258]474}
475
[295]476///////////////////////////////////////////////////////////////////////////////////
477///////////////////// FAT related system calls ////////////////////////////////////
478///////////////////////////////////////////////////////////////////////////////////
[258]479
[295]480///////////////////////////////////////////
481int giet_fat_open( const char*   pathname, 
482                   unsigned int  flags )
483{
484    return sys_call( SYSCALL_FAT_OPEN, 
485                     (unsigned int)pathname, 
486                     flags,
487                     0, 0 );
488}
[258]489
[295]490////////////////////////////////////
491void giet_fat_read( unsigned int fd,     
492                    void*        buffer, 
493                    unsigned int count, 
494                    unsigned int offset ) 
495{
496    if ( sys_call( SYSCALL_FAT_READ,
497                   fd, 
498                   (unsigned int)buffer,
499                   count, 
500                   offset ) != count ) giet_exit("in giet_fat_read()");
501}
502
503/////////////////////////////////////
504void giet_fat_write( unsigned int fd,
505                     void*        buffer, 
506                     unsigned int count,
507                     unsigned int offset )
508{
509    if ( sys_call( SYSCALL_FAT_WRITE, 
510                   fd, 
511                   (unsigned int)buffer,
512                   count, 
513                   offset ) != count ) giet_exit("in giet_fat_write()");
514}
515
516/* variant implementing the UNIX spec
[258]517///////////////////////////////////////////////////////////////////////////////////
[295]518// This system call writes to a file identified by the "fd" file descriptor.
519// - "buffer" is the source buffer virtual address (must be word aligned).
520// - "count" is a number of bytes (must be multiple of 4).
521// It uses the implicit "lseek" pointer in file descriptor.
[258]522///////////////////////////////////////////////////////////////////////////////////
[295]523void giet_fat_write( unsigned int fd,
524                    void*        buffer,
525                    unsigned int count )  // number of bytes
[258]526{
[295]527    return sys_call( SYSCALL_FAT_WRITE,
528                     fd,
529                     (unsigned int)buffer,
530                     count, 0 );
[258]531}
[295]532*/
533
534/////////////////////////////////////
535void giet_fat_lseek( unsigned int fd, 
536                    unsigned int offset, 
537                    unsigned int whence )
[258]538{
[295]539    if ( sys_call( SYSCALL_FAT_LSEEK, 
540                   fd, 
541                   offset, 
542                   whence, 
543                   0 ) ) giet_exit("in giet_fat_lseek()");
[258]544}
[295]545
546//////////////////////////////////////
547void giet_fat_fstat( unsigned int fd )
[258]548{
[295]549    if ( sys_call( SYSCALL_FAT_FSTAT,
550                   fd,
551                   0, 0, 0 ) )  giet_exit("in giet_fat_lseek()");
[258]552}
[295]553
554/////////////////////////////////////
555void giet_fat_close( unsigned int fd )
[258]556{
[295]557    if ( sys_call( SYSCALL_FAT_CLOSE,
558                   fd,
559                   0, 0, 0 ) )  giet_exit("in giet_fat_close()");
[258]560}
[295]561
562
[258]563//////////////////////////////////////////////////////////////////////////////////
[295]564///////////////////// Miscellaneous system calls /////////////////////////////////
[258]565//////////////////////////////////////////////////////////////////////////////////
[295]566
567/////////////////
568int giet_procid() 
[258]569{
[295]570    return sys_call( SYSCALL_PROCID,
[258]571                     0, 0, 0, 0 );
572}
[295]573
574////////////////////
575int giet_proctime() 
576{
577    return sys_call( SYSCALL_PROCTIME, 
578                     0, 0, 0, 0 );
579}
580
581///////////////////////
[258]582int giet_proc_task_id() 
583{
584    return sys_call( SYSCALL_LOCAL_TASK_ID, 
585                     0, 0, 0, 0 );
586}
[295]587
588/////////////////////////
[258]589int giet_global_task_id() 
590{
591    return sys_call( SYSCALL_GLOBAL_TASK_ID, 
592                     0, 0, 0, 0 );
593}
594
[295]595////////////////////
[267]596int giet_thread_id() 
597{
598    return sys_call( SYSCALL_THREAD_ID, 
599                     0, 0, 0, 0 );
600}
601
[295]602///////////////
603int giet_rand() 
[258]604{
[295]605    unsigned int x = sys_call(SYSCALL_PROCTIME, 0, 0, 0, 0);
606    if ((x & 0xF) > 7) {
607        return (x*x & 0xFFFF);
608    }
609    else {
610        return (x*x*x & 0xFFFF);
611    }
[258]612}
[295]613
614//////////////////////////////
615void giet_exit( char* string ) 
[258]616{
[295]617    sys_call( SYSCALL_EXIT,
618              (unsigned int)string,
619              0, 0, 0 );
[258]620}
[295]621
622/////////////////////////////////////////
623void giet_assert( unsigned int condition,
624                  char*        string )
[258]625{
[295]626    if ( condition == 0 ) giet_exit( string );
[258]627}
[295]628
629////////////////////////////////////////////////////
630void giet_vobj_get_vbase( char*         vspace_name, 
631                          char*         vobj_name, 
632                          unsigned int* vobj_vaddr ) 
[258]633{
[295]634    if ( sys_call( SYSCALL_VOBJ_GET_VBASE, 
635                   (unsigned int) vspace_name,
636                   (unsigned int) vobj_name,
637                   (unsigned int) vobj_vaddr,
638                   0 ) )  giet_exit("in giet_vobj_get_vbase()");
[258]639}
[260]640
[295]641///////////////////////////////////////////////
642void giet_proc_number( unsigned int  cluster_id, 
[368]643                       unsigned int* buffer ) 
[260]644{
[295]645    if ( sys_call( SYSCALL_PROC_NUMBER, 
646                   cluster_id, 
647                   (unsigned int) buffer, 
648                   0, 0) )  giet_exit("in giet_proc_number()");
[260]649}
650
[295]651//////////////////////////
652void giet_context_switch() 
[258]653{
[295]654    sys_call( SYSCALL_CTX_SWITCH,
655              0, 0, 0, 0 );
[258]656}
657
[295]658/////////////////////////////////////////
659void giet_heap_info( unsigned int* vaddr, 
[368]660                     unsigned int* length,
661                     unsigned int  x,
662                     unsigned int  y ) 
[258]663{
[295]664    if ( sys_call( SYSCALL_HEAP_INFO, 
665                   (unsigned int)vaddr, 
666                   (unsigned int)length, 
[368]667                   x,
668                   y ) )  giet_exit("in giet_heap_info()");
[258]669}
670
671// Local Variables:
672// tab-width: 4
673// c-basic-offset: 4
674// c-file-offsets:((innamespace . 0)(inline-open . 0))
675// indent-tabs-mode: nil
676// End:
677// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
678
Note: See TracBrowser for help on using the repository browser.