source: trunk/kernel/syscalls/sys_write.c @ 625

Last change on this file since 625 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: 8.9 KB
RevLine 
[1]1/*
[566]2 * sys_write.c - Kernel function implementing the "write" 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>
[624]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>
31#include <vfs.h>
[566]32#include <vmm.h>
[1]33#include <thread.h>
[23]34#include <printk.h>
35#include <process.h>
[1]36
[23]37
[440]38extern uint32_t enter_sys_write;
39extern uint32_t enter_devfs_write;
40extern uint32_t enter_txt_write;
41extern uint32_t enter_chdev_cmd_write;
42extern uint32_t enter_chdev_server_write;
43extern uint32_t enter_tty_cmd_write;
44extern uint32_t enter_tty_isr_write;
45extern uint32_t exit_tty_isr_write;
46extern uint32_t exit_tty_cmd_write;
47extern uint32_t exit_chdev_server_write;
48extern uint32_t exit_chdev_cmd_write;
49extern uint32_t exit_txt_write;
50extern uint32_t exit_devfs_write;
51extern uint32_t exit_sys_write;
52
[23]53//////////////////////////////////
54int sys_write( 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 written
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;
[433]72
[566]73#if (DEBUG_SYS_WRITE || CONFIG_INSTRUMENTATION_SYSCALLS)
74uint64_t     tm_start = hal_get_cycles();
75#endif
76
[438]77#if DEBUG_SYS_WRITE
78if( DEBUG_SYS_WRITE < tm_start )
[625]79printk("\n[%s] thread[%x,%x] enter / vaddr %x / %d bytes / cycle %d\n",
[584]80__FUNCTION__, process->pid, this->trdid, vaddr, count, (uint32_t)tm_start );
[409]81#endif
[1]82 
[469]83#if (DEBUG_SYS_WRITE & 1)
84enter_sys_write = (uint32_t)tm_start;
85#endif
86
[23]87    // check file_id argument
88        if( file_id >= CONFIG_PROCESS_FILE_MAX_NR )
[1]89        {
[433]90
[438]91#if DEBUG_SYSCALLS_ERROR
[584]92printk("\n[ERROR] in %s : thread[%x,%x] illegal file descriptor index %d\n",
93__FUNCTION__, process->pid, this->trdid, file_id );
[433]94#endif
[23]95        this->errno = EBADFD;
[1]96                return -1;
97        }
98
[23]99    // check user buffer in user space
[440]100    error = vmm_get_vseg( process , (intptr_t)vaddr , &vseg );
[23]101
102    if ( error )
103    {
[433]104
[438]105#if DEBUG_SYSCALLS_ERROR
[584]106printk("\n[ERROR] in %s : thread[%x,%x] user buffer unmapped %x\n",
107__FUNCTION__ , process->pid, this->trdid, (intptr_t)vaddr );
[624]108hal_vmm_display( process , false );
[433]109#endif
[23]110                this->errno = EINVAL;
111                return -1;
112    }
113
114    // get extended pointer on remote file descriptor
115    file_xp = process_fd_get_xptr( process , file_id );
116
117    if( file_xp == XPTR_NULL )
118    {
[433]119
[438]120#if DEBUG_SYSCALLS_ERROR
[604]121printk("\n[ERROR] in %s : thread[%x,%x] undefined file descriptor = %d\n",
[584]122__FUNCTION__, process->pid, this->trdid, file_id );
[433]123#endif
[23]124                this->errno = EBADFD;
125                return -1;
126    }
127
128    // get file descriptor cluster and local pointer
[604]129    file_ptr = GET_PTR( file_xp );
130    file_cxy = GET_CXY( file_xp );
[23]131
[604]132    // get file type, offset, aatributes, and associated inode
133    file_type   = hal_remote_l32( XPTR( file_cxy , &file_ptr->type ) );
134    file_offset = hal_remote_l32( XPTR( file_cxy , &file_ptr->offset ) );
135    inode_ptr   = hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
136    file_attr   = hal_remote_l32( XPTR( file_cxy , &file_ptr->attr ) );
[313]137
[443]138    // enable IRQs
139    hal_enable_irq( &save_sr );
140
[625]141    // action depend on file type
142    if( file_type == INODE_TYPE_FILE )  // write to a file mapper
[23]143    {
[421]144        // check file writable
[604]145        if( (file_attr & FD_ATTR_WRITE_ENABLE) == 0 )
[421]146            {
[433]147
[438]148#if DEBUG_SYSCALLS_ERROR
[584]149printk("\n[ERROR] in %s : thread[%x,%x] file %d not writable\n",
150__FUNCTION__ , process->pid, this->trdid, file_id );
[433]151#endif
[604]152            hal_restore_irq( save_sr );
[421]153                    this->errno = EBADFD;
154                    return -1;
155            }
156
157        // move count bytes to mapper
[407]158        nbytes = vfs_user_move( false,               // from buffer to mapper
159                                file_xp,
160                                vaddr, 
161                                count );
[604]162        if ( nbytes != count )
163        {
164
165#if DEBUG_SYSCALLS_ERROR
166printk("\n[ERROR] in %s : thread[%x,%x] cannot write %d bytes into file %d\n",
167__FUNCTION__ , process->pid, this->trdid, count, file_id );
168#endif
169            hal_restore_irq( save_sr );
170            this->errno = EIO;
171            return -1;
172
173        }
174
[623]175        // update file size in inode descriptor
176        // only if (file_offset + count) > current_size
177        // note: the parent directory entry in mapper will
178        // be updated by the close syscall     
179        xptr_t inode_xp = XPTR( file_cxy , inode_ptr );
180        vfs_inode_update_size( inode_xp , file_offset + count );
[407]181    }
[604]182    else if( file_type == INODE_TYPE_DEV )  // write to TXT device
[407]183    {
[421]184        // move count bytes to device
[407]185        nbytes = devfs_user_move( false,             // from buffer to device
[604]186                                  file_xp,
187                                  vaddr,
188                                  count );
189        if( nbytes != count )
190        {
191
192#if DEBUG_SYSCALLS_ERROR
193printk("\n[ERROR] in %s : thread[%x,‰x] cannot write data to file %d\n",
194__FUNCTION__ , process->pid, this->trdid, file_id );
195#endif
196            hal_restore_irq( save_sr );
197            this->errno = EIO;
198            return -1;
199        }
[407]200    }
[443]201    else  // not FILE and not DEV
[407]202    {
[594]203
204#if DEBUG_SYSCALLS_ERROR
205printk("\n[ERROR] in %s : thread[%x,%x] / illegal inode type %\n",
[604]206__FUNCTION__, vfs_inode_type_str( file_type ) );
[594]207#endif
[604]208        hal_restore_irq( save_sr );
[594]209                this->errno = EBADFD;
210                return -1;
[407]211    }
212
[408]213    // restore IRQs
214    hal_restore_irq( save_sr );
215
[124]216    hal_fence();
[23]217
[566]218#if (DEBUG_SYS_WRITE || CONFIG_INSTRUMENTATION_SYSCALLS)
219uint64_t     tm_end = hal_get_cycles();
220#endif
221
[438]222#if DEBUG_SYS_WRITE
223if( DEBUG_SYS_WRITE < tm_end )
[610]224printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
[584]225__FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end );
[409]226#endif
[407]227 
[566]228#if CONFIG_INSTRUMENTATION_SYSCALLS
229hal_atomic_add( &syscalls_cumul_cost[SYS_WRITE] , tm_end - tm_start );
230hal_atomic_add( &syscalls_occurences[SYS_WRITE] , 1 );
231#endif
232
[438]233#if (DEBUG_SYS_WRITE & 1)
[435]234exit_sys_write = (uint32_t)tm_end;
235
[443]236printk("\n***** timing to write a string *****\n"
[435]237" - enter_sys_write          = %d / delta %d\n"
238" - enter_devfs_write        = %d / delta %d\n"
239" - enter_txt_write          = %d / delta %d\n"
240" - enter_chdev_cmd_write    = %d / delta %d\n"
241" - enter_chdev_server_write = %d / delta %d\n"
242" - enter_tty_cmd_write      = %d / delta %d\n"
243" - enter_tty_isr_write      = %d / delta %d\n"
244" - exit_tty_isr_write       = %d / delta %d\n"
245" - exit_tty_cmd_write       = %d / delta %d\n"
246" - exit_chdev_server_write  = %d / delta %d\n"
247" - exit_chdev_cmd_write     = %d / delta %d\n"
248" - exit_txt_write           = %d / delta %d\n"
249" - exit_devfs_write         = %d / delta %d\n"
250" - exit_sys_write           = %d / delta %d\n",
251enter_sys_write          , 0 ,
252enter_devfs_write        , enter_devfs_write        - enter_sys_write          ,
253enter_txt_write          , enter_txt_write          - enter_devfs_write        ,
254enter_chdev_cmd_write    , enter_chdev_cmd_write    - enter_txt_write          ,
255enter_chdev_server_write , enter_chdev_server_write - enter_chdev_cmd_write    ,
256enter_tty_cmd_write      , enter_tty_cmd_write      - enter_chdev_server_write ,
257enter_tty_isr_write      , enter_tty_isr_write      - enter_tty_cmd_write      ,
258exit_tty_isr_write       , exit_tty_isr_write       - enter_tty_isr_write      ,
259exit_tty_cmd_write       , exit_tty_cmd_write       - exit_tty_isr_write       ,
260exit_chdev_server_write  , exit_chdev_server_write  - exit_tty_cmd_write       ,
261exit_chdev_cmd_write     , exit_chdev_cmd_write     - exit_chdev_server_write  ,
262exit_txt_write           , exit_txt_write           - exit_chdev_cmd_write     ,
263exit_devfs_write         , exit_devfs_write         - exit_txt_write           ,
264exit_sys_write           , exit_sys_write           - exit_devfs_write         );
265#endif
266 
[407]267        return nbytes;
268
[23]269}  // end sys_write()
Note: See TracBrowser for help on using the repository browser.