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

Last change on this file since 628 was 625, checked in by alain, 6 years ago

Fix a bug in the vmm_remove_vseg() function: the physical pages
associated to an user DATA vseg were released to the kernel when
the target process descriptor was in the reference cluster.
This physical pages release should be done only when the page
forks counter value is zero.
All other modifications are cosmetic.

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