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

Last change on this file since 670 was 670, checked in by alain, 6 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.