source: trunk/kernel/syscalls/sys_read.c @ 624

Last change on this file since 624 was 624, checked in by alain, 5 years ago

Fix several bugs to use the instruction MMU in kernel mode
in replacement of the instruction address extension register,
and remove the "kentry" segment.

This version is running on the tsar_generic_iob" platform.

One interesting bug: the cp0_ebase defining the kernel entry point
(for interrupts, exceptions and syscalls) must be initialized
early in kernel_init(), because the VFS initialisation done by
kernel_ini() uses RPCs, and RPCs uses Inter-Processor-Interrup.

File size: 9.5 KB
RevLine 
[1]1/*
[23]2 * sys_read.c - read bytes from a file
[1]3 *
[440]4 * Author     Alain Greiner (2016,2017,2018)
[1]5 *
[23]6 * Copyright (c) UPMC Sorbonne Universites
[1]7 *
[23]8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
[1]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 *
[23]14 * ALMOS-MKH is distributed in the hope that it will be useful, but
[1]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
[23]20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
[1]21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
[23]24#include <kernel_config.h>
[457]25#include <hal_kernel_types.h>
[23]26#include <hal_uspace.h>
[409]27#include <hal_irqmask.h>
[23]28#include <hal_special.h>
[1]29#include <errno.h>
[23]30#include <vfs.h>
31#include <vmm.h>
[1]32#include <thread.h>
[23]33#include <printk.h>
34#include <process.h>
[1]35
[506]36
[407]37extern uint32_t enter_sys_read;
[436]38extern uint32_t enter_devfs_read;
[407]39extern uint32_t enter_txt_read;
[436]40extern uint32_t enter_chdev_cmd_read;
41extern uint32_t enter_chdev_server_read;
42extern uint32_t enter_tty_cmd_read;
43extern uint32_t enter_tty_isr_read;
44extern uint32_t exit_tty_isr_read;
45extern uint32_t exit_tty_cmd_read;
46extern uint32_t exit_chdev_server_read;
47extern uint32_t exit_chdev_cmd_read;
[407]48extern uint32_t exit_txt_read;
[436]49extern uint32_t exit_devfs_read;
[407]50extern uint32_t exit_sys_read;
51
52
[23]53/////////////////////////////////
54int sys_read( uint32_t   file_id,
[407]55              void     * vaddr,
[23]56              uint32_t   count )
[1]57{
[604]58    error_t       error;
59    vseg_t      * vseg;            // required for user space checking
60        xptr_t        file_xp;         // remote file extended pointer
61    vfs_file_t  * file_ptr;        // remote file local pointer
62    cxy_t         file_cxy;        // remote file cluster identifier
63    uint32_t      file_type;       // file type
64    uint32_t      file_offset;     // current file offset
65    uint32_t      file_attr;       // file_attribute
66    vfs_inode_t * inode_ptr;       // local pointer on associated inode
67    uint32_t      nbytes;          // number of bytes actually read
68    reg_t         save_sr;         // required to enable IRQs during syscall
[407]69
[604]70        thread_t    * this             = CURRENT_THREAD;
71        process_t   * process          = this->process;
72    xptr_t        process_owner_xp = process->owner_xp;
[23]73 
[566]74#if (DEBUG_SYS_READ || CONFIG_INSTRUMENTATION_SYSCALLS)
75uint64_t     tm_start = hal_get_cycles();
76#endif
77
[438]78#if DEBUG_SYS_READ
79if( DEBUG_SYS_READ < tm_start )
[610]80printk("\n[%s] thread[%x,%x] enter / vaddr %x / count %d / cycle %d\n",
[584]81__FUNCTION__, process->pid, this->trdid, vaddr, count, (uint32_t)tm_start );
[433]82#endif
83
[438]84#if (DEBUG_SYS_READ & 1)
[436]85enter_sys_read = (uint32_t)tm_start;
86#endif
87
[23]88    // check file_id argument
89        if( file_id >= CONFIG_PROCESS_FILE_MAX_NR )
[1]90        {
[435]91
[438]92#if DEBUG_SYSCALLS_ERROR
[604]93printk("\n[ERROR] in %s : thread[%x,%x] illegal file descriptor index %d\n",
[584]94__FUNCTION__ , process->pid, this->trdid, file_id );
[435]95#endif
[23]96                this->errno = EBADFD;
[1]97                return -1;
98        }
99
[23]100    // check user buffer in user space
[440]101    error = vmm_get_vseg( process , (intptr_t)vaddr , &vseg );
[23]102
103    if ( error )
104    {
[435]105
[438]106#if DEBUG_SYSCALLS_ERROR
[584]107printk("\n[ERROR] in %s : thread[%x,%x] user buffer unmapped %x\n",
108__FUNCTION__ , process->pid, this->trdid, (intptr_t)vaddr );
[624]109hal_vmm_display( process , false );
[435]110#endif
[23]111                this->errno = EINVAL;
112                return -1;
113    }
114
115    // get extended pointer on remote file descriptor
116    file_xp = process_fd_get_xptr( process , file_id );
117
118    if( file_xp == XPTR_NULL )
119    {
[435]120
[438]121#if DEBUG_SYSCALLS_ERROR
[584]122printk("\n[ERROR] in %s : thread[%x,%x] undefined fd_id %d\n",
123__FUNCTION__, process->pid, this->trdid, file_id );
[435]124#endif
[23]125        this->errno = EBADFD;
126        return -1;
127    }
128
129    // get file descriptor cluster and local pointer
[604]130    file_ptr = GET_PTR( file_xp );
131    file_cxy = GET_CXY( file_xp );
[23]132
[604]133    // get file type, offset, attributes and associated inode
134    file_type   = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) );
135    file_offset = hal_remote_l32( XPTR( file_cxy , &file_ptr->offset ) );
136    inode_ptr   = hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
137    file_attr   = hal_remote_l32( XPTR( file_cxy , &file_ptr->attr ) );
[313]138
[604]139    // enable IRQs
140    hal_enable_irq( &save_sr );
141
[407]142    // action depend on file type
[604]143    if( file_type == INODE_TYPE_FILE )      // read from file mapper
[23]144    {
[421]145        // check file readable
[604]146        if( (file_attr & FD_ATTR_READ_ENABLE) == 0 )
[421]147            {
[435]148
[438]149#if DEBUG_SYSCALLS_ERROR
[584]150printk("\n[ERROR] in %s : thread[%x,%x] file %d not readable\n",
151__FUNCTION__, process->pid, this->trdid, file_id );
[435]152#endif
[604]153            hal_restore_irq( save_sr );
[421]154                    this->errno = EBADFD;
155                    return -1;
156            }
157
158        // move count bytes from mapper
[407]159        nbytes = vfs_user_move( true,               // from mapper to buffer
160                                file_xp,
161                                vaddr, 
162                                count );
[604]163        if( nbytes != count )
164        {
165
166#if DEBUG_SYSCALLS_ERROR
167printk("\n[ERROR] in %s : thread[%x,‰x] cannot read %d bytes from file %d\n",
168__FUNCTION__, process->pid, this->trdid, count, file_id );
169#endif
170            this->errno = EIO;
171            hal_restore_irq( save_sr );
172            return -1;
173        }
[407]174    }
[604]175    else if( file_type == INODE_TYPE_DEV )  // read from TXT device
[407]176    {
[436]177        // get cluster and pointers on TXT_RX chdev
178        xptr_t    chdev_xp  = chdev_from_file( file_xp );
179        cxy_t     chdev_cxy = GET_CXY( chdev_xp );
180        chdev_t * chdev_ptr = GET_PTR( chdev_xp );
181
[446]182        volatile xptr_t    txt_owner_xp;   
183        uint32_t           iter = 0;
[436]184
185        while( 1 )
186        {
[446]187            // extended pointer on TXT owner process
[566]188            txt_owner_xp  = hal_remote_l64( XPTR( chdev_cxy , &chdev_ptr->ext.txt.owner_xp ) );
[436]189
190            // check TXT_RX ownership
[446]191            if ( process_owner_xp != txt_owner_xp )
[436]192            {
[446]193                if( (iter & 0xFFF) == 0 )
[584]194                printk("\n[WARNING] in %s : thread[%x,%x] wait TXT_RX / cycle %d\n",
195                __FUNCTION__, process->pid, this->trdid, (uint32_t)hal_get_cycles() );
[446]196
[436]197                // deschedule without blocking
[446]198                sched_yield( "wait TXT_RX ownership" );
199
200                iter++;
[436]201            }
202            else
203            {
204                break;
205            }
206        }
207
[421]208        // move count bytes from device
[407]209        nbytes = devfs_user_move( true,             // from device to buffer
210                                  file_xp,
211                                  vaddr,
212                                  count );
[604]213        if( nbytes != count )
214        {
[421]215
[604]216#if DEBUG_SYSCALLS_ERROR
217printk("\n[ERROR] in %s : thread[%x,‰x] cannot read data from file %d\n",
218__FUNCTION__, process->pid, this->trdid, file_id );
219#endif
220            this->errno = EIO;
221            hal_restore_irq( save_sr );
222            return -1;
223        }
[407]224    }
[594]225    else    // not FILE and not DEV
[407]226    {
[594]227
228#if DEBUG_SYSCALLS_ERROR
229printk("\n[ERROR] in %s : thread[%x,%x] / illegal inode type %\n",
[604]230__FUNCTION__, vfs_inode_type_str( file_type ) );
[594]231#endif
232                this->errno = EBADFD;
[604]233        hal_restore_irq( save_sr );
[594]234                return -1;
[407]235    }
236
[408]237    // restore IRQs
[421]238    hal_restore_irq( save_sr );
[408]239
[124]240    hal_fence();
[23]241
[566]242#if (DEBUG_SYS_READ || CONFIG_INSTRUMENTATION_SYSCALLS)
243uint64_t     tm_end = hal_get_cycles();
244#endif
245
[438]246#if DEBUG_SYS_READ
247if( DEBUG_SYS_READ < tm_end )
[610]248printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
[584]249__FUNCTION__ , process->pid, this->trdid, (uint32_t)tm_end );
[409]250#endif
[23]251
[566]252#if CONFIG_INSTRUMENTATION_SYSCALLS
253hal_atomic_add( &syscalls_cumul_cost[SYS_READ] , tm_end - tm_start );
254hal_atomic_add( &syscalls_occurences[SYS_READ] , 1 );
255#endif
256
[438]257#if (DEBUG_SYS_READ & 1)
[418]258exit_sys_read = (uint32_t)tm_end;
[407]259
[443]260printk("\n***** timing to read one character *****\n"
[435]261" - enter_sys_read          = %d / delta %d\n"
262" - enter_devfs_read        = %d / delta %d\n"
263" - enter_txt_read          = %d / delta %d\n"
264" - enter_chdev_cmd_read    = %d / delta %d\n"
265" - enter_chdev_server_read = %d / delta %d\n"
266" - enter_tty_cmd_read      = %d / delta %d\n"
267" - enter_tty_isr_read      = %d / delta %d\n"
268" - exit_tty_isr_read       = %d / delta %d\n"
269" - exit_tty_cmd_read       = %d / delta %d\n"
270" - exit_chdev_server_read  = %d / delta %d\n"
271" - exit_chdev_cmd_read     = %d / delta %d\n"
272" - exit_txt_read           = %d / delta %d\n"
273" - exit_devfs_read         = %d / delta %d\n"
274" - exit_sys_read           = %d / delta %d\n",
275enter_sys_read          , 0 ,
276enter_devfs_read        , enter_devfs_read        - enter_sys_read          ,
277enter_txt_read          , enter_txt_read          - enter_devfs_read        ,
278enter_chdev_cmd_read    , enter_chdev_cmd_read    - enter_txt_read          ,
279enter_chdev_server_read , enter_chdev_server_read - enter_chdev_cmd_read    ,
280enter_tty_cmd_read      , enter_tty_cmd_read      - enter_chdev_server_read ,
281enter_tty_isr_read      , enter_tty_isr_read      - enter_tty_cmd_read      ,
282exit_tty_isr_read       , exit_tty_isr_read       - enter_tty_isr_read      ,
283exit_tty_cmd_read       , exit_tty_cmd_read       - exit_tty_isr_read       ,
284exit_chdev_server_read  , exit_chdev_server_read  - exit_tty_cmd_read       ,
285exit_chdev_cmd_read     , exit_chdev_cmd_read     - exit_chdev_server_read  ,
286exit_txt_read           , exit_txt_read           - exit_chdev_cmd_read     ,
287exit_devfs_read         , exit_devfs_read         - exit_txt_read           ,
288exit_sys_read           , exit_sys_read           - exit_devfs_read         );
[407]289#endif
290 
291        return nbytes;
292
[23]293}  // end sys_read()
Note: See TracBrowser for help on using the repository browser.