1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
/* SPDX-License-Identifier: GPL-3.0-or-later */
/* Copyright 2021 - 2022, Kim Kuparinen < kimi.h.kuparinen@gmail.com > */
/**
* @file proc.c
* Process/thread handling syscall implementations.
*/
#include <apos/elf.h>
#include <apos/uapi.h>
#include <apos/proc.h>
#include <apos/bits.h>
#include <apos/mem_regions.h>
/**
* Create syscall handler.
*
* \todo Implement.
*
* @param func Function to jump to at thread creation.
* @param arg Argument to pass to the function.
*
* @return \ref OK and 0.
*/
SYSCALL_DEFINE2(create)(sys_arg_t func, sys_arg_t arg){
return (struct sys_ret){ OK, 0, 0, 0, 0, 0 };
}
/**
* Fork syscall handler.
*
* \todo Not entirely sure how I should handle forks/execs etc, mostly whether I
* should allow forks/execs to be called directly or only though the process
* manager. Probably though the process manager, although that will add in a
* slight bit of delay.
*
* I suppose I could add in a runtime parameter
* that would allow them to be called directly, and then the process manager
* would have to periodically ask the kernel about all threads it is aware of
* via sys_sync. Dunno.
*
* @return \ref OK and 0.
*/
SYSCALL_DEFINE0(fork)(){
return (struct sys_ret){ OK, 0, 0, 0, 0, 0 };
}
/**
* Exec syscall handler.
*
* @param bin Binary to execute.
* @param interp Optional interpreter binary.
* @return \see prepare_proc() and 0.
*/
SYSCALL_DEFINE2(exec)(sys_arg_t bin, sys_arg_t interp){
/** \todo execute new process, probably with more sensible argc passing */
struct tcb *r = cur_tcb();
/* mark binary to be kept */
struct mem_region *b = find_used_region(&r->sp_r, bin);
if (!b)
return (struct sys_ret){ERR_INVAL, 0, 0, 0, 0, 0};
set_bit(b->flags, MR_KEEP);
struct mem_region *i = 0;
if (interp) {
/* mark interpreter to be kept */
i = find_used_region(&r->sp_r, interp);
if (!i)
return (struct sys_ret){ERR_INVAL, 1, 0, 0, 0, 0};
set_bit(i->flags, MR_KEEP);
}
/* free everything except regions to be kept */
clear_uvmem(r);
/* restore to normal */
clear_bit(b->flags, MR_KEEP);
if (interp)
clear_bit(b->flags, MR_KEEP);
return (struct sys_ret){ prepare_proc(r, bin, interp), 0, 0, 0, 0, 0 };
}
/**
* Kill syscall handler.
*
* \todo Implement.
*
* @return No?
*/
SYSCALL_DEFINE0(kill)()
{
return (struct sys_ret){ OK, 0, 0, 0, 0, 0};
}
/**
* Signal syscall handler.
*
* \todo Implement.
*
* @param tid Thread ID to signal.
* @param signal Signal to send to \c tid.
* @param swap Whether to immediately swap to thread.
* @return \ref OK and 0.
*/
SYSCALL_DEFINE3(signal)(sys_arg_t tid, sys_arg_t signal, sys_arg_t swap){
return (struct sys_ret){ OK, 0, 0, 0, 0, 0 };
}
/**
* Swap syscall handler.
*
* \todo Implement.
* \todo Should swap return the registers of the new thread that would be used
* for message passing?
*
* @param tid Thread ID to swap to.
* @return \ref OK and 0.
*/
SYSCALL_DEFINE1(swap)(sys_arg_t tid){
/** \todo switch to process */
/** \todo should switch return the registers of the new thread that would
* be used for message passing? */
return (struct sys_ret){ OK, 0, 0, 0, 0, 0 };
}
|