wiki:library_stdio

GIET_VM / User-Level System Calls

The stdio.c and stdio.h files define all system calls provided to user applications by the GIET-VM. System calls are prefixed by giet_.

  1. GIET_VM / User-Level System Calls
    1. Processor related system calls
      1. 1) void giet_proc_xyp( unsigned int* cluster_x, unsigned int* …
      2. 2) unsigned int giet_proctime()
      3. 3) unsigned int giet_rand()
      4. 4) void giet_wait( unsigned int randomize , unsigned int value )
    2. Thread related system calls
      1. 1) int giet_pthread_create( pthread_t* trdid , pthread_attr_t* …
      2. 2) void giet_pthread_exit( void* string )
      3. 3) int giet_pthread_join( pthread_t trdid , void* ptr )
      4. 4) int giet_pthread_kill( pthread_t trdid , int signal )
      5. 5) void giet_pthread_yield()
      6. 6) void giet_pthread_assert( unsigned int condition, char* string )
      7. 7) void giet_pthread_control( unsigned int command , char* …
    3. Application related system calls
      1. 1) void giet_exec_application( char* vspace_name )
      2. 2) void giet_kill_application( char* vspace_name )
      3. 3) void get_applications_status( char* vspace_name )
    4. Coprocessors related system calls
      1. 1) void giet_coproc_alloc( unsigned int cluster_xy , unsigned …
      2. 2) void giet_coproc_release( unsigned int cluster_xy , unsigned …
      3. 3) void giet_coproc_channel_init( unsigned int cluster_xy , …
      4. 4) void giet_coproc_run( unsigned int cluster_xy , unsigned int …
      5. 5) void giet_coproc_completed( unsigned int cluster_xy , …
    5. TTY related system calls
      1. 1) void giet_tty_alloc( unsigned int shared )
      2. 2) void giet_tty_printf( char* format, ... )
      3. 3) void giet_tty_getc( char* byte )
      4. 4) void giet_tty_getw( unsigned int* val )
      5. 5) void giet_tty_gets( char* buf, unsigned int bufsize )
    6. Timer related system calls
      1. 1) void giet_timer_alloc()
      2. 2) void giet_timer_start( unsigned int period )
      3. 3) void giet_timer_stop( )
    7. File system related system calls
      1. 1) int giet_fat_open( char* pathname, unsigned int flags )
      2. 2) int giet_fat_close( unsigned int fd_id )
      3. 3) int get_fat_file_info( unsigned int fd_id , unsigned int* …
      4. 4) int giet_fat_read( unsigned int fd_id , void* buffer , …
      5. 5) int giet_fat_pread( unsigned int fd_id , void* buffer , …
      6. 6) int giet_fat_write( unsigned int fd_id , void* buffer, …
      7. 7) int giet_fat_lseek( unsigned int fd_id , unsigned int offset …
      8. 8) int giet_fat_remove( char* pathname , unsigned int should_be_dir )
      9. 9) int get_fat_rename( char* old_path , char* new_path )
      10. 10) int giet_fat_mkdir( char* pathname )
      11. 11) int giet_fat_opendir( char* pathname )
      12. 12) int giet_fat_closedir( unsigned int fd_id )
      13. 13) int giet_fat_readdir( unsigned int fd_id , fat_dirent_t* entry )
      14. 14) int giet_fat_fprintf( unsigned int fd_id , char* format , ... )
      15. 15) void* giet_fat_mmap( void* vaddr , unsigned int length , …
      16. 16) int giet_fat_munmap( void* vaddr , unsigned int length )
    8. Network related system call
      1. 1) int giet_nic_socket( int family , int type , int protocol )
      2. 2) int giet_nic_close( int socket )
      3. 3) int giet_nic_bind( int socket , sockaddr_t * addr , int addr_len )
      4. 4) int giet_nic_connect( int socket , sockaddr_t * addr , int …
      5. 5) int giet_nic_sendto( int socket , void * buffer , int length …
      6. 6) int giet_nic_recvfrom( int socket , void * buffer , int …
      7. 7) void giet_nic_print_stats( )
      8. 8) void giet_nic_clear_stats( )
    9. Frame Buffer related system calls
      1. 1) void giet_fbf_size( unsigned int* width , unsigned int* height)
      2. 2) void giet_fbf_alloc()
      3. 3) void giet_fbf_cma_alloc( unsigned int nbufs )
      4. 4) void giet_fbf_cma_init_buf( unsigned int index void* …
      5. 5) void giet_fbf_cma_start()
      6. 6) void giet_fbf_cma_check( unsigned int index )
      7. 7) void giet_fbf_cma_display( unsigned int index )
      8. 8) void giet_fbf_cma_stop( )
      9. 9) void giet_fbf_sync_read( unsigned int offset , void* buffer , …
      10. 10) void giet_fbf_sync_write( unsigned int offset , void* buffer …
    10. Miscelaneous system calls
      1. 1) void giet_procs_number( unsigned int* x_size , unsigned int* …
      2. 2) void giet_vseg_get_vbase( char* vspace_name, char* …
      3. 3) void giet_vseg_get_length( char* vspace_name, char* …
      4. 4) void giet_heap_info( unsigned int* vaddr, unsigned int* …
      5. 5) void giet_get_xy( void* ptr, unsigned int* px, unsigned int* py )

All these functions use a syscall instruction to enter the system. For most system calls, in case of failure (illegal arguments), the calling thread is killed with a giet_pthread_exit().

Processor related system calls

These system calls access the MIPS32 protected registers CP0_PROCID and CP0_TIME.

1) void giet_proc_xyp( unsigned int* cluster_x, unsigned int* cluster_y unsigned int* p )

Each thread is statically allocated to one processor P[x,y,p] in the boot phase, and there is no thread migration. This function returns the processor identifiers (x,y,p) for the processor running the calling thread. It access the wired global processor index stored in the CP0_PROCID register.

The <x> and <y> arguments are the the cluster coordinates. The <p> argument is the processor local index.

The format is CP0_PROCID = ( ( cluster_x << Y_WIDTH + cluster_y ) << P_WIDTH ) + lpid

2) unsigned int giet_proctime()

This function returns the local processor time from the CP0_TIME register (number of cycles from reset), This register is a 32 bits wrapping register

3) unsigned int giet_rand()

This function returns a pseudo-random value derived from both the CP0_PROCID and CP0_TIME registers. The value is always between 0 & 65535.

4) void giet_wait( unsigned int randomize , unsigned int value )

This function implements a 5 cycles waiting loop. If the <randomize> argument is set, the number of iterations is a pseudo-random number whose number of bits is defined by the <value> argument. If the <randomize> argument is zero, the number of iterations is defined by the <value> argument.

Thread related system calls

The GIET-VM support a subset of the POSIX Threads API, defined below. . The pthread_t and pthread_attr_t types are defined in the stdio.h file.

1) int giet_pthread_create( pthread_t* trdid , pthread_attr_t* attr , void* function , void* arg )

This functions activates one thread that will execute the C function defined by the <function> argument. All thread activated by this system call must have been defined in the application mapping. The <attr> argument (pthread attributes) is not supported, and should be set to NULL : The stack size must be defined in the mapping, and the pthread is activated in attached mode. The <arg> argument is a pointer on an user-defined structure containing the arguments to be passed to the called function. It can be set to NULL if the function has no arguments. The thread identifier stored in the <trdid> argument by the kernel is unique in a given vspace: It is actually build from the 4 following informations : [x,y,p,ltid] where x,y,p are the processor coordinates, and ltid is the thread index in the scheduler.

Return 0 if success. Return -1 if no matching thread. Return -2 if attr not NULL.

2) void giet_pthread_exit( void* string )

This function send a KILL signal to the calling thread, that is immediately desactivated, and goes to the blocked state. All resources dynamically allocated to the thread, such as private peripheral channels are released. The user defined <string> message is displayed on the kernel terminal TTY0.

3) int giet_pthread_join( pthread_t trdid , void* ptr )

This blocking function can be used to detect completion of a thread previously activated by a giet_pthread_create(). It returns only when the thread identified by the <trdid> argument is desactivated. The <ptr> argument is not supported, and should be set to NULL.

Return 0 if success. Return -1 if no matching thread. Return -2 if ptr not NULL

4) int giet_pthread_kill( pthread_t trdid , int signal )

This function send a KILL signal to the thread identified by the <trdid> argument, in the same space as the calling thread. If the <signal> argument has a non zero value, the target thread will be deactivated at the next context switch. If the <signal> argument is zero, the thread existence is checked, but the KILL signal it is not sent.

Return 0 if success. Return -1 if no matching thread.

5) void giet_pthread_yield()

The thread calling this function is descheduled and the processor is allocated to another thread. The calling thread is not deactivated and stay in the runable state.

The following functions define various GIET_VM specific extensions to the POSIX threads API.

6) void giet_pthread_assert( unsigned int condition, char* string )

This function is an extension to the POSIX standard. It send a KILL signal and deactivates immediately the calling thread (as does the giet_pthread_exit() function), with a message on the kernel TTY0, if the <condition> argument has a zero value. The message is defined by the <string> argument.

7) void giet_pthread_control( unsigned int command , char* vspace , char* thread )

This function is an extension to the POSIX standard. It execute the command defined by the<command> argument for the thread identified by the <vspace> and <thread> arguments. The supported command types are:

  • THREAD_CMD_PAUSE : The target thread is deactivated. It goes immediately to the blocked state, and will not be scheduled until the thread is reactivated. The thread context (including the resources dynamically allocated to the thread) is not modified.
  • THREAD_CMD_RESUME : The target thread is reactivated. It goes immediately to the runable state, and can be rescheduled at the next context switch to resume execution.
  • THREAD_CMD_CONTEXT : Display the context of the target thread on the TTY allocated to the calling thread.

Application related system calls

1) void giet_exec_application( char* vspace_name )

This function starts execution for the the application identified by the <vspace_name> argument. The application data segments are (re)loaded into memory from the .elf file. Only thread that has the is_main flag set in the mapping is activated.

2) void giet_kill_application( char* vspace_name )

This function kill the application identified by the <vspace_name> argument: All application threads defined in the mapping receive a KILL signal and will be deactivated at the next context switch. The private peripherals or coprocessors are released. The physical memory allocated to the killed application segments is not released.

3) void get_applications_status( char* vspace_name )

This function displays, for application identified by the <vspace_name> argument, the status of each thread defined in the vspace. If the <vspace_name> argument is NULL, it displays the status of all mapped applications.

Coprocessors related system calls

The GIET_VM allows an user applications to use hardware accelerators (called coprocessors). These coprocessors can be distributed in the architecture, but there is at most one coprocessor per cluster. To be supported by the GIET_VM, a coprocessor must use the vci_mwmr_dma component, that is a generic multi-channels DMA controller.

The vci_mwmr_dma component provides to a coprocessor a variable number of TO_COPROC or FROM_COPROC ports, that implement FIFO interfaces. Coprocessor can request to transfer one or several bursts of 32 bits words, without address. The burst size (generally a cache line), the number of TO_COPROC and FROM_COPROC ports, and the number of bursts for a given port are hardware parameters, depending on the coprocessor type. Each port define a private communication channel between the coprocessor and a user memory buffer. The total number of channels cannot be larger than 16. A channel is identified by an index, and the TO_COPROC channels have the smallest indexes.

The user application must use the giet_coproc_alloc() system call to get a private hardware coprocessor. Then it must use the giet_coproc_channel_init() system call to configure the TO_COPROC/FROM_COPROC channels. Finally, the coprocessor and the communication channels are activated by the giet_coproc_run() system call.

The vci_mwmr_dma component implements two transfer modes:

  • In MODE_MWMR, each channel FSM implements the 7 steps MWMR protocol, and transfer an "infinite" data stream, between one coprocessor port and a MWMR software FIFO in memory. The giet_coproc_run() system call is non blocking, as the synchronisation is done through the MWMR FIFOs (no transfer completion event). The MWR IRQ is only asserted if a VCI error is reported in a memory access.
  • In MODE_DMA_IRQ or MODE_DMA_NO_IRQ, each channel FSM transfers a single buffer between one coprocessor port and the memory, and keep blocked when the transfer is completed.
    • In MODE_DMA_IRQ, the calling thread is descheduled, after coprocessor activation, in the giet_coproc_run() system call. It is rescheduled by the MWR IRQ signaling the global completion. The _mwr_isr() scan all channels status registers to report possible addressing errors, and reset the communication channels.
    • In MODE_DMA_NO_IRQ, the giet_coproc_run() system call returns after coprocessor activation, and the user application must use the blocking giet_coproc_completed() system call that directly scan the channels registers to detect completion, report errors, and reset the channels.

The VCI transactions corresponding to different TO_COPROC / FROM_COPROC channels are interleaved and parallelized on the VCI network.

Besides the TO_COPROC/FROM_COPROC communication channels, the vci_mwmr_dma component support up to 16 coprocessor-specific configuration or status registers.

  • The configuration registers are Read and Write.
  • The status registers are Read only.

WARNING: The GIET-VM supports at most one hardware coprocessor per cluster.

WARNING: For a given coprocessor, all channels must be running in the same mode.

WARNING : For all channels, the memory buffer base address and size must be multiple of the hardware burst size.

WARNING: All coprocessors must have at least one configuration register : writing a non zero value in register[0] activates the coprocessor; writing a zero value deactivates the coprocessor.

The list of currently supported coprocessors and their characteristics are defined below :

coproc_ type Function nb_status nb_config nb_from_coproc nb_to_coproc
MWR_SUBTYPE_GCD Greater Common Divider 0 1 1 2
MWR_SUBTYPE_DCT Discrete Cosinus Transform 0 1 1 1
MWMR_SUTYPE_CPY Memory Copy 0 1 1 1

1) void giet_coproc_alloc( unsigned int cluster_xy , unsigned int coproc_type , unsigned int* return_info )

This function allocates a private coprocessor of type <coproc_type>, located in cluster identified by the <cluster_xy> arguments. It takes the lock granting exclusive ownership to the calling application. In the current implementation, the calling thread exit if there is no coprocessor of requested type in cluster[x,y]. The supported values for the <coproc_type> argument are specified above (and actually defined in the mapping_info.h file). In case of success, it returns the coprocessor characteristics in the <return_info> variable. The <return_info> is structured in 4 fields : nb_to_coprocs = info[7:0] / nb_from_coproc = info[15:8] / nb_config = info[23:16] / nb_status = info[31:24]

2) void giet_coproc_release( unsigned int cluster_xy , unsigned int coproc_type )

This function releases the lock granting exclusive access to the coprocessor identified by the <cluster_xy> and <coproc_type> arguments, after coprocessor and channels deactivation.

3) void giet_coproc_channel_init( unsigned int cluster_xy , unsigned int coproc_type , unsigned int channel , giet_coproc_channel_t* desc )

This function initializes a TO_COPROC/FROM_COPROC communication channel for the coprocessor identified by the <cluster_xy> and <coproc_type> arguments. The <channel> argument define the channel index (TO_COPROC channels use the smallest indexes). The <desc> argument is a pointer on the structure containing the channel parameters ( actually defined in the stdio.h file).

typedef struct giet_coproc_channel
{
    unsigned int  channel_mode;    // MWMR / DMA_IRQ / DMA_NO_IRQ
    unsigned int  buffer_size;     // memory buffer size
    unsigned int  buffer_vaddr;    // memory buffer virtual address
    unsigned int  status_vaddr;    // MWMR status virtual address (for MWMR mode only)
    unsigned int  lock_vaddr;      // MWMR lock virtual address (for MWMR mode only)
} giet_coproc_channel_t;

NOTE : The <status_vaddr> field define the virtual address of the MWMR channel status, that is an array of 3 uint32_t words (STS / PTR / PTW) as in the mwmr_channel_t structure defined in the mwmr_channel.h file. The <lock_vaddr> define the virtual address of the queuing user_lock_t structure defined in the user_lock.h file.

4) void giet_coproc_run( unsigned int cluster_xy , unsigned int coproc_type )

This function activates all communication channels and the allocated coprocessor itself in the cluster identified by the <x,y> arguments. The calling thread exit if the coprocessor does not exist.

5) void giet_coproc_completed( unsigned int cluster_xy , unsigned int coproc_type )

This blocking function can be used to synchronize a software thread with an hardware coprocessor identified by the <cluster_xy> and <coproc_type> arguments, and running in DMA_NO_IRQ mode. It polls the status register of all communication channels, and returns only when all transfers are completed. The calling thread exit when at least one channel status register indicates a bus error (illegal memory access).

TTY related system calls

The GIET_VM allows an user thread to use a private TTY terminal, or to display log message on the kernel TTY0 terminal.

1) void giet_tty_alloc( unsigned int shared )

If the shared argument has a zero value, this function allocates a private terminal : the TTY terminal index is registered only in the calling thread context. If the shared argument has a non-zero value, it allocate a shared terminal : the same TTY terminal index is registered in the thread context of all threads that are in the same vspace as the calling thread. The calling thread exit if no TTY terminal available.

WARNING: A shared TTY should be protected by an user-level lock.

2) void giet_tty_printf( char* format, ... )

This function print formated text on a private terminal that must have been allocated to the calling thread by the get_tty_alloc() function. Therefore, it does not take any lock, but checks terminal allocation. Only a limited number of formats are supported:

  • %d : signed decimal
  • %u : unsigned decimal
  • %x : 32 bits hexadecimal
  • %l : 64 bits hexadecimal
  • %c : char
  • %s : string

thread exit if private terminal index not defined, or in case of illegal format.

3) void giet_tty_getc( char* byte )

This blocking function fetches a single character from the private terminal that must have been previously allocated to the calling thread. It uses the TTY_RX_IRQ interrupt, and the associated kernel buffer. The thread exit if a threadprivate TTY index not defined.

4) void giet_tty_getw( unsigned int* val )

This blocking function fetches a string of decimal characters (most significant digit first) to build a 32-bits unsigned integer from the private TTY terminal that must have been allocated to the calling thread. It uses the TTY_RX_IRQ interrupt, and the associated kernel buffer. The non-blocking system function _tty_read is called several times, and the decimal characters are written in a 32 characters buffer until a <LF> character is read. It ignores non-decimal characters, and displays an echo for each decimal character. The <DEL> character is interpreted, and previous characters can be cancelled. When the <LF> character is received, the string is converted to an unsigned int value. If the number of decimal digit is too large for the 32 bits range, the zero value is returned. The thread threadexit if private TTY index not defined.

5) void giet_tty_gets( char* buf, unsigned int bufsize )

This blocking function fetches a string from the private terminal that must have been allocated to the calling thread. It writes the string to a fixed length buffer. It uses the TTY_RX_IRQ interrupt, and the associated kernel buffer. Up to (bufsize - 1) characters (including the non printable characters) are copied into buffer, and the string is completed by a NUL character. The <LF> character is interpreted, and the function close the string with a NUL character if <LF> is read. The <DEL> character is interpreted, and the corresponding character(s) are removed from the target buffer. It does not provide an echo. The thread exit if a private TTY index is threadnot defined.

Timer related system calls

The GIET_VM allows an user thread to activate a private timer channel, generating periodical IRQs. This timer is allocated in the external multi-timers peripheral.

1) void giet_timer_alloc()

This function allocates a private user timer to the calling thread, and registers the channel index in the thread context. The thread exit if no timer channel is available

2) void giet_timer_start( unsigned int period )

This function starts the private timer allocated to the calling thread. The thread exit if no channel is allocated to the calling thread.

3) void giet_timer_stop( )

This function stops the private timer allocated to the calling thread. The thread exit if no channel is allocated to the calling thread.

File system related system calls

The Giet-VM supports a FAT32 file system, and uses distributed data structures to access the file system:

  • The Inode-Tree (distributed on all clusters) is the internal representation of the File System tree.
  • The Fat-Cache (distributed on all clusters) is used to cache the FAT region of the block device.
  • The File-Cache (distributed on all clusters / one cache per open file) is used to cache the DATA region of the block device.
  • The File-Descriptor-Array (in cluster[0,0]) contains the open files descriptors.
  • The Fat-Descriptor (in cluster[0,0] contains the FAT32 general information.

The error code map (negative values) is defined in the fat32_shared.h file.

1) int giet_fat_open( char* pathname, unsigned int flags )

This function allocates a file descriptor to the calling thread, for the file identified by its absolute <pathname>. If several threads try to open the same file, each thread obtains a private file descriptor. The semantic is similar to the UNIX open() function, but the UNIX access rights are not supported. The following flags are supported, and can be ored to define the <flags> argument:

  • O_RDONLY : The file can only be accessed for read.
  • O_WRONLY : The file can only be accessed for write.
  • O_RDWR : The file can be accessed for read or write. This the default value.
  • O_CREATE : The file is created if it does not exist on disk. Default is no creation.
  • O_TRUNC : All clusters allocated to the file are released, and the file size is reset to 0.
  • O_APPEND : The offset in the file descriptor is initialized to the file size. Default offset value is 0.

If one of the directories specified in the paththnamr does not exist, an error is returned.

WARNING : A single node name (file or directory) cannot be larger than 33 characters.

Returns file descriptor index if success. Returns a negative value if error.

2) int giet_fat_close( unsigned int fd_id )

Close a file identified by the fd_id file descriptor. It decrements the reference count in the inode associated to the file, and release the fd_id entry in the file descriptors array. If the reference count is zero, it writes all dirty clusters on block device, and releases the memory allocated to the file_cache.

Returns 0 if success. Returns a negative value if error.

3) int get_fat_file_info( unsigned int fd_id , unsigned int* size , unsigned int* offset )

This function returns the "size" and the current "offset" value for a file identified by the "fd_id" argument.

Returns 0 if success. Returns a negative value if error.

4) int giet_fat_read( unsigned int fd_id , void* buffer , unsigned int count )

This function has the same semantic as the UNIX read() function. It transfers up to <count> bytes from the kernel File_Cache associated to the file identified by <fd_id>, to the user <buffer>, starting from the current file offset. The number of bytes actually transferred can be smaller than the <count> argument if an EOF is encountered. The offset value is incremented by the number to bytes actually transferred. In case of miss in the File_Cache, it loads all involved clusters into cache.

Returns number of bytes actually transferred if success. Returns 0 if (offset + count) is larger than the file size. Returns a negative value if error.

5) int giet_fat_pread( unsigned int fd_id , void* buffer , unsigned int count , unsigned int offset )

This function has the same semantic as the UNIX pread() function. It transfers <count> bytes from the kernel File_Cache associated to the file identified by <fd_id>, to the user <buffer>, starting from the <offset> argument. The offset field in the file descriptor is not modified. In case of miss in the File_Cache, it loads all involved clusters into cache.

Returns number of bytes actually transferred if success. Returns 0 if (offset + count) is larger than the file size. Returns a negative value if error.

6) int giet_fat_write( unsigned int fd_id , void* buffer, unsigned int count )

This function has the same semantic as the UNIX <write()> function. It transfers <count> bytes from the user <buffer> to the kernel File_Cache associated to the file identified by <fd_id>, starting from the current file offset. The offset value is incremented by count. It increases the file size and allocate new clusters if (count + offset) is larger than the current file size. Then it loads and updates all involved clusters in the cache. The FAT region on block device is updated if new clusters are allocated, but the block device DATA region is NOT updated.

Returns number of bytes actually transferred if success. Returns a negative value if error.

7) int giet_fat_lseek( unsigned int fd_id , unsigned int offset , unsigned int whence )

This function has the same semantic as the UNIX lseek() function. It repositions the offset in the file descriptor <fd_id>, according to the <offset> and <whence> arguments. The two accepted values for the whence argument are

  • SEEK_SET : new_offset <= offset
  • SEEK_CUR : new_offset <= current_offset + offset
  • SEEK_END : new_offset <= file_size + offset

Returns new offset value (bytes) if success. Returns a negative value if error.

8) int giet_fat_remove( char* pathname , unsigned int should_be_dir )

This function has the same semantic as the UNIX unlink() function. It deletes a file identified by the absolute "pathname" argument from the sile system. An error is reported if the references count (number of open file descriptor) is not zero. All clusters allocated to this file in the block device DATA region are released. The Inode-Tree is updated. the Fat-Cache is updated, and the FAT region is updated on the block device. The memory allocated for the associated File_Cache is released.

Returns 0 if success. Returns a negative value if error.

9) int get_fat_rename( char* old_path , char* new_path )

This function has the same semantic as the UNIX rename() function. It causes the node identified by <old_path> to be renamed as <new_path>. If <new_path> exists, it is first removed. Both <old_path> and <new_path> must be of the same type (either directories or non directories).

Returns 0 if success. Returns a negative value if error.

10) int giet_fat_mkdir( char* pathname )

This function has the same semantic as the UNIX mkdir() function. It creates in the file system the directory specified by the absolute "pathname" argument. The Inode-Tree is updated. One cluster is allocated to the new directory, containing the "." and ".." entries. The associated File-Cache is created. The Fat-Cache is updated, and the FAT region on block device is updated. The DATA region on block device is updated.

Returns 0 if success. Returns a negative value if error.

11) int giet_fat_opendir( char* pathname )

This function allocates a file descriptor to the calling thread, for the directory identified by its absolute <pathname>.

Returns the file descriptor associated to the diredtory if success. Returns a negative value if error.

12) int giet_fat_closedir( unsigned int fd_id )

Close a directory identified by the <fd_id> file descriptor. It decrements the reference count in the inode associated to the directory, and release the fd_id entry in the file descriptors array.

Returns 0 if success. Returns a negative value if error.

13) int giet_fat_readdir( unsigned int fd_id , fat_dirent_t* entry )

This function access one directory entry identified by the <fd_id> argument (obtained by the giet_fat_opendir() function), and writes the relevant informations to the <entry> argument. This includes the cluster, size, is_dir, and name.

Returns 0 if success. Returns a negative value if error.

14) int giet_fat_fprintf( unsigned int fd_id , char* format , ... )

This function has the same semantic as the UNIX <fprintf()> function. It transfers all bytes contained in the string defined by the <format> argument to the kernel File_Cache associated to the file identified by <fd_id>, starting from the current file offset. The offset value is incremented by the string length. It increases the file size and allocate new clusters if (count + offset) is larger than the current file size. Then it loads and updates all involved clusters in the cache. The FAT region on block device is updated if new clusters are allocated, but the block device DATA region is NOT updated.

Returns number of bytes actually transferred if success. Returns a negative value if error.

15) void* giet_fat_mmap( void* vaddr , unsigned int length , unsigned int prot , unsigned int flags , unsigned int fd_id , unsigned int offset )

This function has the same semantic as the UNIX <mmap()> function. It allocates as many small pages (4 Kbytes) as required by the number of bytes defined by the <length> argument, from the MMAP vseg of the calling vspace. It maps all these pages directly to the file_cache as defined by the <fd_id> and <offset> arguments. The supported values for the <prot> argument are : MAP_PROT_READ / MAP_PROT_WRITE / MAP_PROT_EXEC (can be ored). It has the following limitations:

  • it does not support the MAP_PRIVATE flag : write are seen by any thread in any application.
  • it does not support the MAP_FIXED flag : the <vaddr> argument is not used.
  • it does not support the MAP_ANONYMOUS flog : only file mapping.
  • The only supported value for the <flags> argument is MAP_SHARED.
  • The <length> and <offset> arguments must be multiple of 4 Kbytes.

Returns a pointer on the allocated buffer in user space (from the MMAP space). Returns NULL in case of error (illegal arguments).

16) int giet_fat_munmap( void* vaddr , unsigned int length )

This function has the same semantic as the UNIX <munmap()> function. It desallocates as many small pages (4 Kbytes) as defined by the <vaddr> and <length> arguments from the MMAP vseg of the calling space. The dirty pages will be written on disk when the mapped file is closed. It has the following limitations:

  • The <vaddr> argument must be in the MMAP vseg.
  • The <length> argument must be multiple of 4 Kbytes.

Returns 0 in case of success. Returns -1 in case of error (illegal arguments).

Network related system call

The GIET_VM allows a user application to dynamically create and access sockets in non-connected mode. Only the AF_INET family, SOCK_DGRAM type, and UDP protocol are supported. To define a socket address the giet_VM uses the following structure, defined in the stdio.h file.

typedef struct sockaddr_s
{
    unsigned int    sin_addr;     // IPV4 address
    unsigned short  sin_port;     // port number
    short           sin_family;   // should be AF_INET

} 
sockaddr_t;

1) int giet_nic_socket( int family , int type , int protocol )

This function must creates a socket. It returns a socket identifier that can be used by the calling thread to send or receive packets form the internet network. It cannot be accessed by another thread. This function creates also the RX packets & Tx packets queues associated to the socket, as well as the kernel threads that are in charge of moving packets between these queues and the hardware NIC controller. As only non connected sockets communicating with remote hosts are supported, the three arguments have imposed values:

  • family : should be AF_INET.
  • type : must be SOCK_DGRAM.
  • protocol : must be 0 (actually UDP).
  • return socket identifier if success / returns -1 if error.

2) int giet_nic_close( int socket )

This function releases all memory allocated for a socket: the socket descriptor itself, and the RX/TX queues associated to the socket. The kernel threads associated to these queues are desactivated.

  • socket : socket identifier.
  • return 0 if success / returns -1 if error.

3) int giet_nic_bind( int socket , sockaddr_t * addr , int addr_len )

This function makes the binding between a socket identified by the <socket> argument, and a local socket addres, that is a couple (IPV4 address / port number). The default value INADDR_ANY value can be used fot thr IPV4 address, toask the kernel to define the value.

  • socket : socket identifier.
  • addr : pointer on the local socket address.
  • addr_len : socket address length (in bytes).
  • return 0 if success / returns -1 if error.

4) int giet_nic_connect( int socket , sockaddr_t * addr , int addr_len )

This function is generally used by a client to connect a local client socket to a remote server socket. It forces the local socket in connected mode, and register the remote socket address in the local socket descriptor. It allows the client to use the read() / write() sytem call without specifying the explicitely the remote server address.

  • socket : socket identifier.
  • addr : pointer on the remote socket address.
  • addr_len : address structure length (in bytes).
  • return 0 if success / returns -1 if error.

5) int giet_nic_sendto( int socket , void * buffer , int length , int flags , sockaddr_t * dest_addr , int addr_len )

This blocking function moves one raw packet from an user buffer defined by the <buffer> argument to a kernel buffer. The packet length (in bytes) is defned by the <length> arguments. The destination socket is defined by the <remote_addr> argument. It uses the <socket> and <remote_addr> arguments to build the ETH/IP/UDP header. It returns only when the user buffer can be re-used, and uses a descheduling policy for blocking.

  • socket : socket identifier.
  • buffer : pointer on user buffer.
  • length : raw packet length (bytes).
  • flags : unsupported / must be 0.
  • remote_addr : pointer on remote socket address.
  • addr_len : unused.
  • return 0 if success / returns -1 if error.

6) int giet_nic_recvfrom( int socket , void * buffer , int length , int flags , sockaddr_t * dest_addr , int * pkt_len )

This blocking function moves one raw packet from a kernel buffer to an user buffer defined by the <buffer> argument. The <size> argument define the user buffer size and must be larger than 2 Kbytes. Only packets matching the local IP address and local port number, defined by the <socket> argument will be delivered (2 matching conditions). If the socket is in connected mode, the matching must also be on remote IP address an remote port number (4 matching conditions). The remote socket address is returned in the <src_addr> argument. The actual received packet length is returned in the <length> argument. It returns only when the user buffer has been written, and uses a descheduling policy for blocking.

  • socket : socket identifier.
  • buffer : pointer on user buffer.
  • size : buffer size (bytes).
  • flags : unsupported / must be 0.
  • src_addr : pointer on remote socket address.
  • length : pointer on received packet length (bytes).
  • return 0 if success / returns -1 if error.

7) void giet_nic_print_stats( )

This function print on the calling thread terminal the current values of the hardware NIC instrumentation counters.

8) void giet_nic_clear_stats( )

This function reset all Hardware NIC instrumentation counters.

Frame Buffer related system calls

To display images, an user application must get the frame buffer ownership, and check the frame buffer size (width and height). Then, it can access the frame buffer through a (software) memcpy() or through the (hardware) Chained Buffer DMA controller (called CMA).

1) void giet_fbf_size( unsigned int* width , unsigned int* height)

This function returns in the <width> and <height> arguments the number of pixels per line, and the number of lines of the frame buffer

2) void giet_fbf_alloc()

This blocking function allows an application to get exclusive ownership of the shared FBF peripheral. It returns only when the lock has been taken. All threads in the same space as the calling thread can access concurrently the frame buffer, under the user responsibility. This lock is released only when when all threads in the application complete execution, after a giet_pthread_exit(), or a giet_pthread_kill().

3) void giet_fbf_cma_alloc( unsigned int nbufs )

This function allocates a CMA channel to an application, and registers the channel index in the contexts of all threads that are in the same space as the calling thread. The <nbufs> argument define the total number of chained user buffers. As each user buffer contains one image, the buffer size must be FBUF_X_SIZE * FBUF_Y_SIZE. The user buffers can be distributed (one buffer per cluster) or not (all buffers in same cluster). This function initializes the chained buffer descriptor for the frame buffer (one single buffer). The thread exit if no CMA channel available.

4) void giet_fbf_cma_init_buf( unsigned int index void* buf_vaddr , void* sts_vaddr )

This function initializes the chained buffer descriptor for one user buffer identified by the <index> argument. The <buf_vaddr> and <sts_vaddr> arguments are pointers on the buffer and on the buffer status. This <index> argument must be smaller than the <nbufs> argument in giet_fbf_cma_alloc() above. The set of user buffers will be transferred by the CMA peripheral in the order of increasing indexes. This function must be called <nbufs> times, to initialize the <nbufs> chained buffers descriptors. Each user buffer must be large enough to store a complete image, and must be aligned on a 64 bytes boundary. The buffer status contain just a Boolean, but it must occupy 64 bytes, and must be aligned on a 64 bytes boundary. For a given user buffer, the buffer and the associated status must be in the same cluster. The thread exit if buffers are not aligned, index too large, or buffer and status in different clusters.

5) void giet_fbf_cma_start()

This function activates the transfer of a stream of images from a set of chained user buffers to the frame buffer. It must be used in conjunction with the giet_fbf_cma_display() function. The chained buffer descriptors should have been initialized by the giet_fbf_cma_init_buf() function.

6) void giet_fbf_cma_check( unsigned int index )

For each user buffer, the status is acting as a SET/RESET synchronisation flip-flop, that is set by the application when the buffer is full, and is reset by the CMA peripheral when the transfer is completed. This blocking function checks the status of the buffer identified by the <index> argument, and returns only when the buffer is empty.

7) void giet_fbf_cma_display( unsigned int index )

For each user buffer, the status is acting as a SET/RESET synchronisation flip-flop, that is set by the application when the buffer is full, and is reset by the CMA peripheral when the transfer is completed. This function set the status to enable the transfer of the buffer identified by the <index> argument.

8) void giet_fbf_cma_stop( )

This function desactivates the CMA channel allocated to the calling thread.

9) void giet_fbf_sync_read( unsigned int offset , void* buffer , unsigned int length )

This blocking function use a memcopy strategy to transfer data from the frame buffer to an user buffer.

  • offset defines the offset (in bytes) in the frame buffer,
  • buffer is the user buffer base address,
  • length is the number of bytes to be transfered.

10) void giet_fbf_sync_write( unsigned int offset , void* buffer , unsigned int length )

This blocking function use a memcopy strategy to transfer data from an user buffer to the frame buffer.

  • offset defines the offset (in bytes) in the frame buffer,
  • buffer is the user buffer base address,
  • length is the number of bytes to be transfered.

Miscelaneous system calls

1) void giet_procs_number( unsigned int* x_size , unsigned int* y_size , unsigned int* nprocs )

This function returns the actual number of processors in a clusterized 2D mesh architecture. The <x_size> argument is the number of clusters containing processors in a row. The <y_size> argument is the number of clusters containing processors in a column. The <nprocs> argument is the number of processors per cluster.

2) void giet_vseg_get_vbase( char* vspace_name, char* vseg_name, unsigned int* vbase)

This function returns in the <vbase> argument the virtual base address of a vseg defined in the mapping_info data structure. The vseg is identified by the <vspace_name> and <vseg_name> arguments. In case of error (such as undefined vspace or undefined vseg), the calling thread exit.

3) void giet_vseg_get_length( char* vspace_name, char* vseg_name, unsigned int* length)

This function returns in the <length> argument the length (bytes) of a vseg defined in the mapping_info data structure. The vseg is identified by the <vspace_name> and <vseg_name>. In case of error (such as undefined vspace or undefined vseg), the calling thread exit.

4) void giet_heap_info( unsigned int* vaddr, unsigned int* length, unsigned int x, unsigned int y );

This function returns in the <vaddr> and <length> arguments the characteristics of the user heap located in cluster[x,y] and defined in the vspace containing the calling thread. In case of error (such as undefined heap segment in the selected cluster, or illegal cluster coordinates) it returns <vaddr> = <length> = 0.

5) void giet_get_xy( void* ptr, unsigned int* px, unsigned int* py )

This function returns through the <px> and <py> arguments the coordinates of the cluster containing the physical address associated to the <ptr> argument containing a virtual address. In case of error (unmapped virtual address), the calling thread exit.

Last modified 7 years ago Last modified on Jan 6, 2017, 9:21:11 PM