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

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

Introduce three new types of vsegs (KCODE,KDATA,KDEV)
to map the kernel vsegs in the process VSL and GPT.
This now used by both the TSAR and the I86 architectures.

File size: 8.9 KB
RevLine 
[1]1/*
[566]2 * sys_write.c - Kernel function implementing the "write" system call.
[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>
30#include <vfs.h>
[566]31#include <vmm.h>
[1]32#include <thread.h>
[23]33#include <printk.h>
34#include <process.h>
[1]35
[23]36
[440]37extern uint32_t enter_sys_write;
38extern uint32_t enter_devfs_write;
39extern uint32_t enter_txt_write;
40extern uint32_t enter_chdev_cmd_write;
41extern uint32_t enter_chdev_server_write;
42extern uint32_t enter_tty_cmd_write;
43extern uint32_t enter_tty_isr_write;
44extern uint32_t exit_tty_isr_write;
45extern uint32_t exit_tty_cmd_write;
46extern uint32_t exit_chdev_server_write;
47extern uint32_t exit_chdev_cmd_write;
48extern uint32_t exit_txt_write;
49extern uint32_t exit_devfs_write;
50extern uint32_t exit_sys_write;
51
[23]52//////////////////////////////////
53int sys_write( uint32_t   file_id,
[407]54               void     * vaddr,
[23]55               uint32_t   count )
[1]56{
[604]57    error_t       error;
58    vseg_t      * vseg;            // required for user space checking
59        xptr_t        file_xp;         // remote file extended pointer
60    vfs_file_t  * file_ptr;        // remote file local pointer
61    cxy_t         file_cxy;        // remote file cluster identifier
62    uint32_t      file_type;       // file type
63    uint32_t      file_offset;     // current file offset
64    uint32_t      file_attr;       // file_attribute
65    vfs_inode_t * inode_ptr;       // local pointer on associated inode
66    uint32_t      nbytes;          // number of bytes actually written
67    reg_t         save_sr;         // required to enable IRQs during syscall
[407]68
[604]69        thread_t    * this = CURRENT_THREAD;
70        process_t   * process = this->process;
[433]71
[566]72#if (DEBUG_SYS_WRITE || CONFIG_INSTRUMENTATION_SYSCALLS)
73uint64_t     tm_start = hal_get_cycles();
74#endif
75
[438]76#if DEBUG_SYS_WRITE
[409]77tm_start = hal_get_cycles();
[438]78if( DEBUG_SYS_WRITE < tm_start )
[610]79printk("\n[%s] thread[%x,%x] enter / vaddr %x / count %d / 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 );
[440]108vmm_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
141   // action depend on file type
[604]142    if( file_type == INODE_TYPE_FILE )  // write to 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 );
181
[407]182    }
[604]183    else if( file_type == INODE_TYPE_DEV )  // write to TXT device
[407]184    {
[421]185        // move count bytes to device
[407]186        nbytes = devfs_user_move( false,             // from buffer to device
[604]187                                  file_xp,
188                                  vaddr,
189                                  count );
190        if( nbytes != count )
191        {
192
193#if DEBUG_SYSCALLS_ERROR
194printk("\n[ERROR] in %s : thread[%x,‰x] cannot write data to file %d\n",
195__FUNCTION__ , process->pid, this->trdid, file_id );
196#endif
197            hal_restore_irq( save_sr );
198            this->errno = EIO;
199            return -1;
200        }
[407]201    }
[443]202    else  // not FILE and not DEV
[407]203    {
[594]204
205#if DEBUG_SYSCALLS_ERROR
206printk("\n[ERROR] in %s : thread[%x,%x] / illegal inode type %\n",
[604]207__FUNCTION__, vfs_inode_type_str( file_type ) );
[594]208#endif
[604]209        hal_restore_irq( save_sr );
[594]210                this->errno = EBADFD;
211                return -1;
[407]212    }
213
[408]214    // restore IRQs
215    hal_restore_irq( save_sr );
216
[124]217    hal_fence();
[23]218
[566]219#if (DEBUG_SYS_WRITE || CONFIG_INSTRUMENTATION_SYSCALLS)
220uint64_t     tm_end = hal_get_cycles();
221#endif
222
[438]223#if DEBUG_SYS_WRITE
224if( DEBUG_SYS_WRITE < tm_end )
[610]225printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
[584]226__FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end );
[409]227#endif
[407]228 
[566]229#if CONFIG_INSTRUMENTATION_SYSCALLS
230hal_atomic_add( &syscalls_cumul_cost[SYS_WRITE] , tm_end - tm_start );
231hal_atomic_add( &syscalls_occurences[SYS_WRITE] , 1 );
232#endif
233
[438]234#if (DEBUG_SYS_WRITE & 1)
[435]235exit_sys_write = (uint32_t)tm_end;
236
[443]237printk("\n***** timing to write a string *****\n"
[435]238" - enter_sys_write          = %d / delta %d\n"
239" - enter_devfs_write        = %d / delta %d\n"
240" - enter_txt_write          = %d / delta %d\n"
241" - enter_chdev_cmd_write    = %d / delta %d\n"
242" - enter_chdev_server_write = %d / delta %d\n"
243" - enter_tty_cmd_write      = %d / delta %d\n"
244" - enter_tty_isr_write      = %d / delta %d\n"
245" - exit_tty_isr_write       = %d / delta %d\n"
246" - exit_tty_cmd_write       = %d / delta %d\n"
247" - exit_chdev_server_write  = %d / delta %d\n"
248" - exit_chdev_cmd_write     = %d / delta %d\n"
249" - exit_txt_write           = %d / delta %d\n"
250" - exit_devfs_write         = %d / delta %d\n"
251" - exit_sys_write           = %d / delta %d\n",
252enter_sys_write          , 0 ,
253enter_devfs_write        , enter_devfs_write        - enter_sys_write          ,
254enter_txt_write          , enter_txt_write          - enter_devfs_write        ,
255enter_chdev_cmd_write    , enter_chdev_cmd_write    - enter_txt_write          ,
256enter_chdev_server_write , enter_chdev_server_write - enter_chdev_cmd_write    ,
257enter_tty_cmd_write      , enter_tty_cmd_write      - enter_chdev_server_write ,
258enter_tty_isr_write      , enter_tty_isr_write      - enter_tty_cmd_write      ,
259exit_tty_isr_write       , exit_tty_isr_write       - enter_tty_isr_write      ,
260exit_tty_cmd_write       , exit_tty_cmd_write       - exit_tty_isr_write       ,
261exit_chdev_server_write  , exit_chdev_server_write  - exit_tty_cmd_write       ,
262exit_chdev_cmd_write     , exit_chdev_cmd_write     - exit_chdev_server_write  ,
263exit_txt_write           , exit_txt_write           - exit_chdev_cmd_write     ,
264exit_devfs_write         , exit_devfs_write         - exit_txt_write           ,
265exit_sys_write           , exit_sys_write           - exit_devfs_write         );
266#endif
267 
[407]268        return nbytes;
269
[23]270}  // end sys_write()
Note: See TracBrowser for help on using the repository browser.