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
Line 
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>
14#include <giet_config.h>
15
16////////////////////////////////////////////////////////////////////////////////////
17/////////////////////  TTY device related system calls /////////////////////////////
18////////////////////////////////////////////////////////////////////////////////////
19
20///////////////////////////////////////////////////////////////////////
21static int __printf( char* format, unsigned int channel, va_list* args) 
22{
23    int ret;                    // return value from the syscalls
24
25printf_text:
26
27    while (*format) 
28    {
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,
37                           0);
38
39            if (ret != i) goto return_error;
40
41            format += i;
42        }
43        if (*format == '%') 
44        {
45            format++;
46            goto printf_arguments;
47        }
48    }
49
50    return 0;
51
52printf_arguments:
53
54    {
55        char buf[20];
56        char * pbuf;
57        unsigned int len = 0;
58        static const char HexaTab[] = "0123456789ABCDEF";
59        unsigned int i;
60
61        switch (*format++) 
62        {
63            case ('c'):             /* char conversion */
64            {
65                int val = va_arg( *args, int );
66                len = 1;
67                buf[0] = val;
68                pbuf = &buf[0];
69                break;
70            }
71            case ('d'):             /* 32 bits decimal signed integer */
72            {
73                int val = va_arg( *args, int );
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;
92            }
93            case ('u'):             /* 32 bits decimal unsigned integer */
94            {
95                unsigned int val = va_arg( *args, unsigned int );
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            {
107                unsigned int val = va_arg( *args, unsigned int );
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            {
125                unsigned long long val = va_arg( *args, unsigned long long );
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            {
143                char* str = va_arg( *args, char* );
144                while (str[len]) 
145                {
146                    len++;
147                }
148                pbuf = str;
149                break;
150            }
151            default:
152                goto return_error;
153        }
154
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;
163    }
164
165return_error:
166    return 1;
167} // end __printf()
168
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);
177    va_end( args );
178
179    if (ret)
180    {
181        giet_exit("ERROR in giet_tty_printf()");
182    }
183} // end giet_tty_printf()
184
185////////////////////////////////////////
186void giet_shr_printf( char* format, ...) 
187{
188    va_list args;
189    const int channel = 0;
190    volatile unsigned int sr_save;
191
192    sys_call( SYSCALL_TTY_GET_LOCK,
193              channel,
194              (unsigned int)&sr_save,
195              0, 0 );
196
197    va_start( args, format );
198    int ret = __printf(format, channel, &args);
199    va_end( args );
200
201    sys_call( SYSCALL_TTY_RELEASE_LOCK,
202              channel,
203              (unsigned int)&sr_save,
204              0, 0 );
205
206    if (ret)
207    {
208        giet_exit("error in giet_shr_printf()");
209    }
210} // end giet_shr_printf()
211
212/////////////////////////////////
213void giet_tty_getc( char * byte ) 
214{
215    int ret;
216
217    do
218    {
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()");
225    }
226    while (ret != 1); 
227}
228
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;
265}
266
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);
296
297        // analyse character
298        if ((string_byte > 0x2F) && (string_byte < 0x3A))  /* decimal character */
299        {
300            buf[length] = (unsigned char)string_byte;
301            length++;
302
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 );
327                if ( ret < 0 ) giet_exit("error in giet_tty_getw()");
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 );
366            if ( ret < 0 ) giet_exit("error in giet_tty_getw()");
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 );
375        if ( ret < 0 ) giet_exit("error in giet_tty_getw()");
376
377        // return 0 value
378        *val = 0;
379    }
380}
381
382
383//////////////////////////////////////////////////////////////////////////////////
384/////////////////////  TIMER related system calls ////////////////////////////////
385//////////////////////////////////////////////////////////////////////////////////
386
387///////////////////////
388void giet_timer_start() 
389{
390    if ( sys_call( SYSCALL_TIMER_START, 0, 0, 0, 0 ) ) 
391       giet_exit("error in giet_timer_start()");
392}
393
394//////////////////////
395void giet_timer_stop() 
396{
397    if ( sys_call( SYSCALL_TIMER_STOP, 0, 0, 0, 0 ) ) 
398        giet_exit("error in giet_timer_stop()");
399}
400
401
402//////////////////////////////////////////////////////////////////////////////////
403///////////////  Frame buffer device related system calls  ///////////////////////
404//////////////////////////////////////////////////////////////////////////////////
405
406////////////////////////////////////////////
407void giet_fb_sync_write( unsigned int offset, 
408                        void *       buffer, 
409                        unsigned int length ) 
410{
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()");
416}
417
418///////////////////////////////////////////
419void giet_fb_sync_read( unsigned int offset, 
420                        void *       buffer, 
421                        unsigned int length ) 
422{
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()");
428}
429
430/////////////////////////////////////////
431void giet_fb_cma_init( void *       buf0,
432                       void *       buf1,
433                       unsigned int length )
434{
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()");
440}
441
442///////////////////////////////////////////////
443void giet_fb_cma_write( unsigned int buffer_id )
444{
445    if ( sys_call( SYSCALL_FB_CMA_WRITE, 
446                   buffer_id, 
447                   0, 0, 0 ) )   giet_exit("error in giet_fb_cma_write()");
448}
449
450////////////////////////
451void giet_fb_cma_stop()
452{
453    if ( sys_call( SYSCALL_FB_CMA_STOP, 
454                   0, 0, 0, 0 ) )    giet_exit("error in giet_fb_cma_stop()");
455}
456
457
458//////////////////////////////////////////////////////////////////////////////////
459/////////////////////// NIC related system calls /////////////////////////////////
460//////////////////////////////////////////////////////////////////////////////////
461
462/////////////////////////
463void giet_nic_cma_start()
464{
465    if ( sys_call( SYSCALL_NIC_CMA_START, 0, 0, 0, 0 ) ) 
466       giet_exit("error in giet_nic_cma_start()");
467}
468
469/////////////////////////
470void giet_nic_cma_stop()
471{
472    if ( sys_call( SYSCALL_NIC_CMA_STOP, 0, 0, 0, 0 ) ) 
473        giet_exit("error in giet_nic_cma_stop()");
474}
475
476///////////////////////////////////////////////////////////////////////////////////
477///////////////////// FAT related system calls ////////////////////////////////////
478///////////////////////////////////////////////////////////////////////////////////
479
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}
489
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
517///////////////////////////////////////////////////////////////////////////////////
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.
522///////////////////////////////////////////////////////////////////////////////////
523void giet_fat_write( unsigned int fd,
524                    void*        buffer,
525                    unsigned int count )  // number of bytes
526{
527    return sys_call( SYSCALL_FAT_WRITE,
528                     fd,
529                     (unsigned int)buffer,
530                     count, 0 );
531}
532*/
533
534/////////////////////////////////////
535void giet_fat_lseek( unsigned int fd, 
536                    unsigned int offset, 
537                    unsigned int whence )
538{
539    if ( sys_call( SYSCALL_FAT_LSEEK, 
540                   fd, 
541                   offset, 
542                   whence, 
543                   0 ) ) giet_exit("in giet_fat_lseek()");
544}
545
546//////////////////////////////////////
547void giet_fat_fstat( unsigned int fd )
548{
549    if ( sys_call( SYSCALL_FAT_FSTAT,
550                   fd,
551                   0, 0, 0 ) )  giet_exit("in giet_fat_lseek()");
552}
553
554/////////////////////////////////////
555void giet_fat_close( unsigned int fd )
556{
557    if ( sys_call( SYSCALL_FAT_CLOSE,
558                   fd,
559                   0, 0, 0 ) )  giet_exit("in giet_fat_close()");
560}
561
562
563//////////////////////////////////////////////////////////////////////////////////
564///////////////////// Miscellaneous system calls /////////////////////////////////
565//////////////////////////////////////////////////////////////////////////////////
566
567/////////////////
568int giet_procid() 
569{
570    return sys_call( SYSCALL_PROCID,
571                     0, 0, 0, 0 );
572}
573
574////////////////////
575int giet_proctime() 
576{
577    return sys_call( SYSCALL_PROCTIME, 
578                     0, 0, 0, 0 );
579}
580
581///////////////////////
582int giet_proc_task_id() 
583{
584    return sys_call( SYSCALL_LOCAL_TASK_ID, 
585                     0, 0, 0, 0 );
586}
587
588/////////////////////////
589int giet_global_task_id() 
590{
591    return sys_call( SYSCALL_GLOBAL_TASK_ID, 
592                     0, 0, 0, 0 );
593}
594
595////////////////////
596int giet_thread_id() 
597{
598    return sys_call( SYSCALL_THREAD_ID, 
599                     0, 0, 0, 0 );
600}
601
602///////////////
603int giet_rand() 
604{
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    }
612}
613
614//////////////////////////////
615void giet_exit( char* string ) 
616{
617    sys_call( SYSCALL_EXIT,
618              (unsigned int)string,
619              0, 0, 0 );
620}
621
622/////////////////////////////////////////
623void giet_assert( unsigned int condition,
624                  char*        string )
625{
626    if ( condition == 0 ) giet_exit( string );
627}
628
629////////////////////////////////////////////////////
630void giet_vobj_get_vbase( char*         vspace_name, 
631                          char*         vobj_name, 
632                          unsigned int* vobj_vaddr ) 
633{
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()");
639}
640
641///////////////////////////////////////////////
642void giet_proc_number( unsigned int  cluster_id, 
643                       unsigned int* buffer ) 
644{
645    if ( sys_call( SYSCALL_PROC_NUMBER, 
646                   cluster_id, 
647                   (unsigned int) buffer, 
648                   0, 0) )  giet_exit("in giet_proc_number()");
649}
650
651//////////////////////////
652void giet_context_switch() 
653{
654    sys_call( SYSCALL_CTX_SWITCH,
655              0, 0, 0, 0 );
656}
657
658/////////////////////////////////////////
659void giet_heap_info( unsigned int* vaddr, 
660                     unsigned int* length,
661                     unsigned int  x,
662                     unsigned int  y ) 
663{
664    if ( sys_call( SYSCALL_HEAP_INFO, 
665                   (unsigned int)vaddr, 
666                   (unsigned int)length, 
667                   x,
668                   y ) )  giet_exit("in giet_heap_info()");
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.