Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
script3r
GitHub Repository: script3r/os161
Path: blob/master/kern/proc/proc.c
2092 views
1
#include <types.h>
2
#include <lib.h>
3
#include <kern/errno.h>
4
#include <proc.h>
5
6
struct proc *allproc[MAX_PROCESSES];
7
struct lock *lk_allproc;
8
struct lock *lk_exec;
9
int next_pid;
10
11
/**
12
* add the given function to the allproc array.
13
*/
14
static
15
void
16
proc_add_to_allproc( struct proc *p, int spot ) {
17
lock_acquire( lk_allproc );
18
19
KASSERT( allproc[spot] == (void *)PROC_RESERVED_SPOT );
20
allproc[spot] = p;
21
lock_release( lk_allproc );
22
}
23
24
/**
25
* quick function that simply a spot as reserved,
26
* stores the index of the spot inside the pid
27
* and unlocks allproc.
28
*/
29
static
30
void
31
proc_found_spot( pid_t *pid, int spot ) {
32
//if we are being called, allproc[spot] must be null.
33
KASSERT( allproc[spot] == NULL );
34
35
//mark it as reserved.
36
allproc[spot] = (void *)PROC_RESERVED_SPOT;
37
*pid = spot;
38
39
//adjust next_pid to be the one just given.
40
next_pid = spot + 1;
41
42
//release the lock
43
lock_release( lk_allproc );
44
}
45
46
/**
47
* attempts to allocate a new pid by looping
48
* through allproc, starting from next_pid, until finding an empty spot.
49
* once a spot is given, it is marked as reserved.
50
*/
51
static
52
int
53
proc_alloc_pid( pid_t *pid ) {
54
int i = 0;
55
56
//lock allproc, to guarantee atomicity
57
lock_acquire( lk_allproc );
58
59
//if the next_pid is greater than the maximum number of processes
60
//we need to start failing pid allocations.
61
if( next_pid >= MAX_PROCESSES )
62
next_pid = 0;
63
64
65
//first we loop until the end, starting from lastpid.
66
for( i = next_pid; i < MAX_PROCESSES; ++i ) {
67
if( allproc[i] == NULL ) {
68
proc_found_spot( pid, i );
69
return 0;
70
}
71
}
72
73
//now we loop from the beginning until next_pid
74
for( i = 0; i < next_pid; ++i ) {
75
if( allproc[i] == NULL ) {
76
proc_found_spot( pid, i );
77
return 0;
78
}
79
}
80
81
//we couldn't find a spot, so we have to fail.
82
lock_release( lk_allproc );
83
return ENPROC;
84
}
85
86
/**
87
* de-allocates the given pid.
88
*/
89
static
90
void
91
proc_dealloc_pid( pid_t pid ) {
92
//lock for atomicity.
93
lock_acquire( lk_allproc );
94
95
//it cannot be null, it must be either reserved or fulfilled.
96
KASSERT( allproc[pid] != NULL );
97
allproc[pid] = NULL;
98
99
//unlock and be done.
100
lock_release( lk_allproc );
101
}
102
103
int
104
proc_create( struct proc **res ) {
105
struct proc *p = NULL;
106
int err = 0;
107
pid_t pid;
108
109
//first, attempt to allocate a pid.
110
err = proc_alloc_pid( &pid );
111
if( err )
112
return err;
113
114
//alloc memory for the structure
115
p = kmalloc( sizeof( struct proc ) );
116
if( p == NULL ) {
117
proc_dealloc_pid( pid );
118
return ENOMEM;
119
}
120
121
//associcate it with the pid.
122
p->p_pid = pid;
123
124
//create the filedescriptor table
125
err = fd_create( &p->p_fd );
126
if( err ) {
127
kfree( p );
128
proc_dealloc_pid( pid );
129
return err;
130
}
131
132
//create the lock
133
p->p_lk = lock_create( "p_lk" );
134
if( p->p_lk == NULL ) {
135
fd_destroy( p->p_fd );
136
kfree( p );
137
proc_dealloc_pid( pid );
138
return ENOMEM;
139
}
140
141
//create the semaphore
142
p->p_sem = sem_create( "p_sem", 0 );
143
if( p->p_sem == NULL ) {
144
lock_destroy( p->p_lk );
145
fd_destroy( p->p_fd );
146
kfree( p );
147
proc_dealloc_pid( pid );
148
return ENOMEM;
149
}
150
151
//adjust static information
152
p->p_retval = 0;
153
p->p_is_dead = false;
154
p->p_nsyscalls = 0;
155
p->p_nice = 0;
156
p->p_proc = NULL;
157
158
//add to the list of allproc
159
proc_add_to_allproc( p, pid );
160
161
*res = p;
162
return 0;
163
}
164
165
/**
166
* clone a process into a new process.
167
*/
168
int
169
proc_clone( struct proc *source, struct proc **target ) {
170
struct proc *p = NULL;
171
int err;
172
173
//try to create the process.
174
err = proc_create( &p );
175
if( err )
176
return err;
177
178
//clone all the files from the source file-descriptor table
179
//into the childs file-descriptor table.
180
fd_clone( source->p_fd, p->p_fd );
181
182
//we are done, simply copy the new proc
183
//into the given pointer.
184
*target = p;
185
186
return 0;
187
}
188
/**
189
* destroy a given process.
190
*/
191
void
192
proc_destroy( struct proc *p ) {
193
pid_t pid;
194
195
//copy the pid for later used.
196
pid = p->p_pid;
197
198
//destroy the cv
199
sem_destroy( p->p_sem );
200
201
//destroy the lock associated with it.
202
lock_destroy( p->p_lk );
203
204
//destroy the filedescriptor table
205
fd_destroy( p->p_fd );
206
207
//free the memory.
208
kfree( p );
209
210
//deallocate the pid.
211
proc_dealloc_pid( pid );
212
}
213
214
/**
215
* initialize the proc-system
216
*/
217
void
218
proc_system_init( void ) {
219
int i = 0;
220
221
//initialize the array
222
for( i = 0; i < MAX_PROCESSES; ++i ) {
223
allproc[i] = NULL;
224
}
225
226
//create the lock
227
lk_allproc = lock_create( "lk_allproc" );
228
if( lk_allproc == NULL )
229
panic( "could not initialize proc system." );
230
231
//create the lock protecting exec args
232
lk_exec = lock_create( "lk_exec" );
233
if( lk_exec == NULL ) {
234
lock_destroy( lk_allproc );
235
panic( "could not create lk_exec." );
236
}
237
//set last pid to be 0.
238
next_pid = 0;
239
}
240
241
/**
242
* find a process inside allproc.
243
* if it exists, return it locked.
244
*/
245
int
246
proc_get( pid_t pid, struct proc **res ) {
247
//invalid pid.
248
if( pid >= MAX_PROCESSES || pid <= 0 )
249
return EINVAL;
250
251
//lock allproc.
252
lock_acquire( lk_allproc );
253
254
//if the requested pid is associated with a valid process
255
if( allproc[pid] != NULL && allproc[pid] != (void *)PROC_RESERVED_SPOT ) {
256
PROC_LOCK( allproc[pid] );
257
*res = allproc[pid];
258
lock_release( lk_allproc );
259
return 0;
260
}
261
262
//the requested pid is actually invalid.
263
lock_release( lk_allproc );
264
return ESRCH;
265
266
}
267
/**
268
* stress tests.
269
*/
270
void
271
proc_test_pid_allocation() {
272
pid_t pid;
273
int err;
274
int i;
275
276
for( i = 0; i < 100; ++i ) {
277
err = proc_alloc_pid( &pid );
278
if( err )
279
panic( "failed to allocate a pid. pid allocation is broken.\n" );
280
281
kprintf( "awarded PID = %d\n", pid );
282
proc_dealloc_pid( pid );
283
}
284
}
285
286
287