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
Line 
1/*
2 * sys_write.c - Kernel function implementing the "write" system call.
3 *
4 * Author        Alain Greiner (2016,2017,2018)
5 *
6 * Copyright (c) UPMC Sorbonne Universites
7 *
8 * This file is part of ALMOS-MKH.
9 *
10 * ALMOS-MKH is free software; you can redistribute it and/or modify it
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 *
14 * ALMOS-MKH is distributed in the hope that it will be useful, but
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
20 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24#include <kernel_config.h>
25#include <hal_kernel_types.h>
26#include <hal_uspace.h>
27#include <hal_irqmask.h>
28#include <hal_special.h>
29#include <errno.h>
30#include <vfs.h>
31#include <vmm.h>
32#include <thread.h>
33#include <printk.h>
34#include <process.h>
35
36
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
52//////////////////////////////////
53int sys_write( uint32_t   file_id,
54               void     * vaddr,
55               uint32_t   count )
56{
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
68
69        thread_t    * this = CURRENT_THREAD;
70        process_t   * process = this->process;
71
72#if (DEBUG_SYS_WRITE || CONFIG_INSTRUMENTATION_SYSCALLS)
73uint64_t     tm_start = hal_get_cycles();
74#endif
75
76#if DEBUG_SYS_WRITE
77tm_start = hal_get_cycles();
78if( DEBUG_SYS_WRITE < tm_start )
79printk("\n[%s] thread[%x,%x] enter / vaddr %x / count %d / cycle %d\n",
80__FUNCTION__, process->pid, this->trdid, vaddr, count, (uint32_t)tm_start );
81#endif
82 
83#if (DEBUG_SYS_WRITE & 1)
84enter_sys_write = (uint32_t)tm_start;
85#endif
86
87    // check file_id argument
88        if( file_id >= CONFIG_PROCESS_FILE_MAX_NR )
89        {
90
91#if DEBUG_SYSCALLS_ERROR
92printk("\n[ERROR] in %s : thread[%x,%x] illegal file descriptor index %d\n",
93__FUNCTION__, process->pid, this->trdid, file_id );
94#endif
95        this->errno = EBADFD;
96                return -1;
97        }
98
99    // check user buffer in user space
100    error = vmm_get_vseg( process , (intptr_t)vaddr , &vseg );
101
102    if ( error )
103    {
104
105#if DEBUG_SYSCALLS_ERROR
106printk("\n[ERROR] in %s : thread[%x,%x] user buffer unmapped %x\n",
107__FUNCTION__ , process->pid, this->trdid, (intptr_t)vaddr );
108vmm_display( process , false );
109#endif
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    {
119
120#if DEBUG_SYSCALLS_ERROR
121printk("\n[ERROR] in %s : thread[%x,%x] undefined file descriptor = %d\n",
122__FUNCTION__, process->pid, this->trdid, file_id );
123#endif
124                this->errno = EBADFD;
125                return -1;
126    }
127
128    // get file descriptor cluster and local pointer
129    file_ptr = GET_PTR( file_xp );
130    file_cxy = GET_CXY( file_xp );
131
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 ) );
137
138    // enable IRQs
139    hal_enable_irq( &save_sr );
140
141   // action depend on file type
142    if( file_type == INODE_TYPE_FILE )  // write to file mapper
143    {
144        // check file writable
145        if( (file_attr & FD_ATTR_WRITE_ENABLE) == 0 )
146            {
147
148#if DEBUG_SYSCALLS_ERROR
149printk("\n[ERROR] in %s : thread[%x,%x] file %d not writable\n",
150__FUNCTION__ , process->pid, this->trdid, file_id );
151#endif
152            hal_restore_irq( save_sr );
153                    this->errno = EBADFD;
154                    return -1;
155            }
156
157        // move count bytes to mapper
158        nbytes = vfs_user_move( false,               // from buffer to mapper
159                                file_xp,
160                                vaddr, 
161                                count );
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
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
182    }
183    else if( file_type == INODE_TYPE_DEV )  // write to TXT device
184    {
185        // move count bytes to device
186        nbytes = devfs_user_move( false,             // from buffer to device
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        }
201    }
202    else  // not FILE and not DEV
203    {
204
205#if DEBUG_SYSCALLS_ERROR
206printk("\n[ERROR] in %s : thread[%x,%x] / illegal inode type %\n",
207__FUNCTION__, vfs_inode_type_str( file_type ) );
208#endif
209        hal_restore_irq( save_sr );
210                this->errno = EBADFD;
211                return -1;
212    }
213
214    // restore IRQs
215    hal_restore_irq( save_sr );
216
217    hal_fence();
218
219#if (DEBUG_SYS_WRITE || CONFIG_INSTRUMENTATION_SYSCALLS)
220uint64_t     tm_end = hal_get_cycles();
221#endif
222
223#if DEBUG_SYS_WRITE
224if( DEBUG_SYS_WRITE < tm_end )
225printk("\n[%s] thread[%x,%x] exit / cycle %d\n",
226__FUNCTION__, process->pid, this->trdid, (uint32_t)tm_end );
227#endif
228 
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
234#if (DEBUG_SYS_WRITE & 1)
235exit_sys_write = (uint32_t)tm_end;
236
237printk("\n***** timing to write a string *****\n"
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 
268        return nbytes;
269
270}  // end sys_write()
Note: See TracBrowser for help on using the repository browser.