Skip to content

Commit fcfd427

Browse files
committed
sched: exec() from ramdisk
1 parent c980ee2 commit fcfd427

File tree

1 file changed

+102
-1
lines changed

1 file changed

+102
-1
lines changed

src/sched/exec.c

+102-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include <kernel/sched.h>
1313
#include <kernel/logger.h>
1414
#include <kernel/elf.h>
15+
#include <kernel/modules.h>
16+
17+
int execmve(Thread *, void *, const char **, const char **);
1518

1619
/* execveMemory(): executes a program from memory
1720
* params: ptr - pointer to the program in memory
@@ -107,7 +110,7 @@ pid_t execveMemory(const void *ptr, const char **argv, const char **envp) {
107110
return pid;
108111
}
109112

110-
/* execve(): executes a program from a file
113+
/* execve(): replaces the current program, executes a program from a file
111114
* params: t - parent thread structure
112115
* params: name - file name of the program
113116
* params: argv - arguments to be passed to the program
@@ -118,3 +121,101 @@ pid_t execveMemory(const void *ptr, const char **argv, const char **envp) {
118121
int execve(Thread *t, const char *name, const char **argv, const char **envp) {
119122
return 0; /* todo */
120123
}
124+
125+
/* execrdv(): replaces the current program, executes a program from the ramdisk
126+
* this is only used before file system drivers are loaded
127+
* params: t - parent thread structure
128+
* params: name - file name of the program
129+
* params: argv - arguments to be passed to the program
130+
* returns: should not return on success
131+
*/
132+
133+
int execrdv(Thread *t, const char *name, const char **argv) {
134+
schedLock();
135+
setScheduling(false);
136+
137+
// load from ramdisk
138+
int64_t size = ramdiskFileSize(name);
139+
if(size <= sizeof(ELFFileHeader)) {
140+
setScheduling(true);
141+
schedRelease();
142+
return -1;
143+
}
144+
145+
void *image = malloc(size);
146+
if(!image) {
147+
setScheduling(true);
148+
schedRelease();
149+
return -1;
150+
}
151+
152+
if(ramdiskRead(image, name, size) != size) {
153+
setScheduling(true);
154+
schedRelease();
155+
return -1;
156+
}
157+
158+
return execmve(t, image, argv, NULL);
159+
}
160+
161+
/* execmve(): helper function that replaces the current running program from memory
162+
* params: t - parent thread structure
163+
* params: image - image of the program in memory
164+
* params: argv - arguments to be passed to the program
165+
* params: envp - environmental variables
166+
* returns: should not return on success
167+
*/
168+
169+
int execmve(Thread *t, void *image, const char **argv, const char **envp) {
170+
// create the new context before deleting the current one
171+
// this guarantees we can return on failure
172+
void *newctx = calloc(1, PLATFORM_CONTEXT_SIZE);
173+
if(!newctx) {
174+
free(image);
175+
setScheduling(true);
176+
schedRelease();
177+
return -1;
178+
}
179+
180+
if(!platformCreateContext(newctx, PLATFORM_CONTEXT_USER, 0, 0)) {
181+
free(newctx);
182+
free(image);
183+
setScheduling(true);
184+
schedRelease();
185+
return -1;
186+
}
187+
188+
void *oldctx = t->context;
189+
t->context = newctx;
190+
191+
threadUseContext(t->tid); // switch to our new context
192+
193+
// parse the binary
194+
uint64_t highest;
195+
uint64_t entry = loadELF(image, &highest);
196+
free(image);
197+
if(!entry || !highest) {
198+
t->context = oldctx;
199+
free(newctx);
200+
setScheduling(true);
201+
schedRelease();
202+
return -1;
203+
}
204+
205+
if(platformSetContext(t, entry, highest, argv, envp)) {
206+
t->context = oldctx;
207+
free(newctx);
208+
setScheduling(true);
209+
schedRelease();
210+
return -1;
211+
}
212+
213+
// TODO: here we've successfully loaded the new program, but we also need
214+
// to free up memory used by the original program
215+
free(oldctx);
216+
217+
schedAdjustTimeslice();
218+
setScheduling(true);
219+
schedRelease();
220+
return 0; // return to syscall dispatcher; the thread will not see this return
221+
}

0 commit comments

Comments
 (0)