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

Last change on this file since 674 was 670, checked in by alain, 4 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
Line 
1/*
2 * sys_exec.c - Kernel function implementing the "exec" system call.
3 *
4 * Authors   Alain Greiner (2016,2017,2017,2019,2020)
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 <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
38#include <syscalls.h>
39
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
44{
45    error_t       error;
46    vseg_t      * vseg;
47
48    // get calling thread, process, & pid
49    thread_t    * this    = CURRENT_THREAD;
50    process_t   * process = this->process;
51    pid_t         pid     = process->pid;
52    trdid_t       trdid   = this->trdid;
53
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
64uint64_t     tm_start = hal_get_cycles();
65#endif
66
67    // check "pathname" mapped in user space
68    if( vmm_get_vseg( process , (intptr_t)pathname , &vseg ) )
69        {
70
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        }
79
80    // check "pathname" length
81    if( hal_strlen_from_uspace( pathname ) >= CONFIG_VFS_MAX_PATH_LENGTH )
82    {
83
84#if DEBUG_SYSCALLS_ERROR
85if( DEBUG_SYSCALLS_ERROR < (uint32_t)tm_start )
86printk("\n[ERROR] in %s : thread[%x,%x] / pathname too long\n",
87__FUNCTION__, pid, trdid );
88#endif
89        this->errno = ENFILE;
90        return -1;
91    }
92
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        {
96
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
118#if DEBUG_SYS_EXEC
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 );
122#endif
123
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 )
131    {
132        if( process_exec_get_strings( true , user_args , &process->exec_info ) )
133        {
134
135#if DEBUG_SYSCALLS_ERROR
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 );
139#endif
140            this->errno = EINVAL;
141            return -1;
142        }
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
150    }
151
152    // 3. copy "environment" pointers & strings in process exec_info if required
153    if( user_envs != NULL )
154    {
155        if( process_exec_get_strings( false , user_envs , &process->exec_info ) )
156        {
157
158#if DEBUG_SYSCALLS_ERROR
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 );
162#endif
163            this->errno = EINVAL;
164            return -1;
165        }
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
173    }
174
175    // call relevant kernel function (no return if success)
176    error = process_make_exec();
177
178    if( error )
179    {
180
181#if DEBUG_SYSCALLS_ERROR
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 );
185#endif
186        this->errno = error;
187        return -1;
188    }
189
190    return 0; 
191
192} // end sys_exec()
193
Note: See TracBrowser for help on using the repository browser.