source: trunk/kernel/syscalls/sys_exec.c @ 670

Last change on this file since 670 was 670, checked in by alain, 3 years ago

1) Introduce up to 4 command lines arguments in the KSH "load" command.
These arguments are transfered to the user process through the
argc/argv mechanism, using the user space "args" vseg.

2) Introduce the named and anonymous "pipes", for inter-process communication
through the pipe() and mkfifo() syscalls.

3) Introduce the "chat" application to validate the two above mechanisms.

4) Improve printk() and assert() fonctions in printk.c.

File size: 5.6 KB
RevLine 
[1]1/*
[23]2 * sys_exec.c - Kernel function implementing the "exec" system call.
[302]3 *
[670]4 * Authors   Alain Greiner (2016,2017,2017,2019,2020)
[1]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
[14]24#include <kernel_config.h>
[457]25#include <hal_kernel_types.h>
[23]26#include <hal_uspace.h>
[1]27#include <errno.h>
28#include <printk.h>
29#include <core.h>
30#include <vfs.h>
31#include <cluster.h>
32#include <process.h>
33#include <thread.h>
34#include <vmm.h>
35#include <ppm.h>
36#include <rpc.h>
37
[506]38#include <syscalls.h>
[1]39
[670]40///////////////////////////////
41int sys_exec( char  * pathname,       // .elf file pathname in user space
42              char ** user_args,      // pointer on process arguments in user space
43              char ** user_envs )     // pointer on env variables in user space
[1]44{
[407]45    error_t       error;
[670]46    vseg_t      * vseg;
[1]47
[433]48    // get calling thread, process, & pid
[421]49    thread_t    * this    = CURRENT_THREAD;
50    process_t   * process = this->process;
51    pid_t         pid     = process->pid;
[670]52    trdid_t       trdid   = this->trdid;
[23]53
[670]54assert( __FUNCTION__, (CXY_FROM_PID( pid ) == local_cxy) ,
55"must be called in the owner cluster\n");
56
57assert( __FUNCTION__, (LTID_FROM_TRDID( trdid ) == 0) ,
58"must be called by the main thread\n");
59
60assert( __FUNCTION__, (user_envs == NULL) ,
61"environment variables not supported yet\n" );
62
63#if DEBUG_SYS_EXEC || DEBUG_SYSCALLS_ERROR
[566]64uint64_t     tm_start = hal_get_cycles();
65#endif
66
[670]67    // check "pathname" mapped in user space
68    if( vmm_get_vseg( process , (intptr_t)pathname , &vseg ) )
69        {
[23]70
[670]71#if DEBUG_SYSCALLS_ERROR
72if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
73printk("\n[ERROR] in %s : thread[%x,%] / pathname pointer %x unmapped\n",
74__FUNCTION__, pid, trdid, pathname );
75#endif
76        this->errno = EINVAL;
77                return -1;
78        }
[433]79
[670]80    // check "pathname" length
[407]81    if( hal_strlen_from_uspace( pathname ) >= CONFIG_VFS_MAX_PATH_LENGTH )
[23]82    {
[433]83
[438]84#if DEBUG_SYSCALLS_ERROR
[670]85if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
86printk("\n[ERROR] in %s : thread[%x,%x] / pathname too long\n",
87__FUNCTION__, pid, trdid );
[433]88#endif
[407]89        this->errno = ENFILE;
[23]90        return -1;
91    }
92
[670]93    // check "args" mapped in user space if non NULL
94    if( (user_args != NULL) && (vmm_get_vseg( process , (intptr_t)user_args , &vseg )) )
95        {
[408]96
[670]97#if DEBUG_SYSCALLS_ERROR
98printk("\n[ERROR] in %s for thread[%x,%] : user_args pointer %x unmapped\n",
99__FUNCTION__, pid, trdid, user_args );
100#endif
101        this->errno = EINVAL;
102                return -1;
103        }
104
105    // check "envs" mapped in user space if not NULL
106    if( (user_envs != NULL) && (vmm_get_vseg( process , (intptr_t)user_envs , &vseg )) )
107        {
108
109#if DEBUG_SYSCALLS_ERROR
110if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
111printk("\n[ERROR] in %s : thread[%x,%] / user_envs pointer %x unmapped\n",
112__FUNCTION__, pid, trdid, user_envs );
113#endif
114        this->errno = EINVAL;
115                return -1;
116        }
117
[438]118#if DEBUG_SYS_EXEC
[670]119if( DEBUG_SYS_EXEC < (uint32_t)tm_start )
120printk("\n[%s] thread[%x,%x] enter / path <%s> / args %x / envs %x / cycle %d\n",
121__FUNCTION__, pid, trdid, &process->exec_info.path[0], user_args, user_envs, cycle );
[433]122#endif
[23]123
[670]124    // 1. copy "pathname" in kernel exec_info structure
125    hal_strcpy_from_uspace( XPTR( local_cxy , &process->exec_info.path[0] ),
126                            pathname,
127                            CONFIG_VFS_MAX_PATH_LENGTH );
128
129    // 2. copy "arguments" pointers & strings in process exec_info if required
130    if( user_args != NULL )
[1]131    {
[670]132        if( process_exec_get_strings( true , user_args , &process->exec_info ) )
[407]133        {
[433]134
[438]135#if DEBUG_SYSCALLS_ERROR
[670]136if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
137printk("\n[ERROR] in %s : thread[%x,%] get arguments for <%s>\n",
138__FUNCTION__, pid, trdid, pathname );
[433]139#endif
[435]140            this->errno = EINVAL;
[407]141            return -1;
142        }
[670]143
144#if DEBUG_SYS_EXEC
145if( DEBUG_SYS_EXEC < (uint32_t)tm_start )
146printk("\n[%s] thread[%x,%x] got arguments / arg[0] = <%s>\n",
147__FUNCTION__, pid, trdid, process->exec_info.args_pointers[0] );
148#endif
149
[23]150    }
[1]151
[670]152    // 3. copy "environment" pointers & strings in process exec_info if required
153    if( user_envs != NULL )
[23]154    {
[670]155        if( process_exec_get_strings( false , user_envs , &process->exec_info ) )
[407]156        {
[433]157
[509]158#if DEBUG_SYSCALLS_ERROR
[670]159if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
160printk("\n[ERROR] in %s : thread[%x,%] get env variables for <%s>\n",
161__FUNCTION__, pid, trdid, pathname );
[433]162#endif
[435]163            this->errno = EINVAL;
[407]164            return -1;
165        }
[670]166
167#if DEBUG_SYS_EXEC
168if( DEBUG_SYS_EXEC < (uint32_t)tm_start )
169printk("\n[%s] thread[%x,%x] got envs / env[0] = <%s>\n",
170__FUNCTION__, pid, trdid, process->exec_info.envs_pointers[0] );
171#endif
172
[1]173    }
[23]174
[670]175    // call relevant kernel function (no return if success)
176    error = process_make_exec();
[408]177
[433]178    if( error )
[1]179    {
[302]180
[438]181#if DEBUG_SYSCALLS_ERROR
[670]182if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
183printk("\n[ERROR] in %s : thread[%x,%x] cannot create process <%s>\n",
184__FUNCTION__, pid, trdid, process->exec_info.path );
[433]185#endif
[23]186        this->errno = error;
187        return -1;
[1]188    }
189
[433]190    return 0; 
191
[1]192} // end sys_exec()
193
Note: See TracBrowser for help on using the repository browser.