001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019 #include <sos/assert.h>
020 #include <sos/list.h>
021 #include <sos/kmem_slab.h>
022 #include <hwcore/irq.h>
023 #include <drivers/bochs.h>
024
025 #include <sos/umem_vmm.h>
026
027 #include "process.h"
028
029
030 #define SOS_PROCESS_MAX_NAMELEN 32
031
032
033
034
035
036
037
038
039 struct sos_process
040 {
041 char name[SOS_PROCESS_MAX_NAMELEN];
042
043
044 struct sos_umem_vmm_as *address_space;
045
046
047
048 struct sos_thread *thread_list;
049 sos_count_t nb_threads;
050
051
052 sos_count_t ref_cnt;
053
054 struct sos_process *prev, *next;
055 };
056
057
058
059 static struct sos_process *process_list = NULL;
060
061
062
063 struct sos_kslab_cache *cache_struct_process;
064
065
066
067
068
069 void sos_process_dumplist()
070 {
071 struct sos_thread * cur_thr = sos_thread_get_current();
072 struct sos_process * proc;
073 int nb_procs;
074
075 sos_bochs_printf("<ps>\n");
076 list_foreach(process_list, proc, nb_procs)
077 {
078 struct sos_thread * thr;
079 int nb_thrs;
080
081 sos_bochs_printf(" proc@%p: '%s', %d threads, %d refs\n",
082 proc, proc->name?proc->name:"(none)",
083 proc->nb_threads, proc->ref_cnt);
084
085 list_foreach_forward_named(proc->thread_list, thr, nb_thrs,
086 prev_in_process, next_in_process)
087 {
088 if (thr == cur_thr)
089 sos_bochs_printf(" thr@%p: [CURRENT]\n", thr);
090 else
091 sos_bochs_printf(" thr@%p: %cstate=%d eip=%p\n",
092 thr,
093 sos_cpu_context_is_in_user_mode(thr->cpu_state)?'u':'k',
094 thr->state,
095 (void*)sos_cpu_context_get_PC(thr->cpu_state));
096 }
097 }
098 sos_bochs_printf(" ======= %d processes =======\n", nb_procs);
099 sos_bochs_printf("</ps>\n");
100 }
101
102
103 sos_ret_t sos_process_subsystem_setup()
104 {
105
106 cache_struct_process = sos_kmem_cache_create("struct_process",
107 sizeof(struct sos_process),
108 3,
109 0,
110 SOS_KSLAB_CREATE_MAP
111 | SOS_KSLAB_CREATE_ZERO);
112 if (! cache_struct_process)
113 return -SOS_ENOMEM;
114
115 return SOS_OK;
116 }
117
118
119 struct sos_process *sos_process_create(const char *name,
120 sos_bool_t do_copy_current_process)
121 {
122 sos_ui32_t flags;
123 struct sos_process *proc;
124
125 proc = (struct sos_process*) sos_kmem_cache_alloc(cache_struct_process, 0);
126 if (! proc)
127 return NULL;
128
129
130
131
132 if (do_copy_current_process)
133 proc->address_space = sos_umem_vmm_duplicate_current_thread_as(proc);
134 else
135 proc->address_space = sos_umem_vmm_create_empty_as(proc);
136
137 if (NULL == proc->address_space)
138 {
139
140 sos_kmem_cache_free((sos_vaddr_t)proc);
141 return NULL;
142 }
143
144 if (!name)
145 {
146 struct sos_thread * cur_thr = sos_thread_get_current();
147 if (do_copy_current_process)
148 name = cur_thr->process->name;
149 else
150 name = "[UNNAMED]";
151 }
152
153 strzcpy(proc->name, name, SOS_PROCESS_MAX_NAMELEN);
154
155
156 sos_disable_IRQs(flags);
157 list_add_tail(process_list, proc);
158 sos_restore_IRQs(flags);
159
160
161 proc->ref_cnt = 1;
162 return proc;
163 }
164
165
166 inline
167 sos_ret_t sos_process_ref(struct sos_process *proc)
168 {
169 sos_ui32_t flags;
170 sos_disable_IRQs(flags);
171 proc->ref_cnt ++;
172 sos_restore_IRQs(flags);
173 return SOS_OK;
174 }
175
176
177 sos_count_t sos_process_get_nb_threads(const struct sos_process *proc)
178 {
179 sos_count_t retval;
180 sos_ui32_t flags;
181 sos_disable_IRQs(flags);
182 retval = proc->nb_threads;
183 sos_restore_IRQs(flags);
184 return retval;
185 }
186
187
188 struct sos_mm_context *
189 sos_process_get_mm_context(const struct sos_process *proc)
190 {
191 return sos_umem_vmm_get_mm_context(proc->address_space);
192 }
193
194
195 struct sos_umem_vmm_as *
196 sos_process_get_address_space(const struct sos_process *proc)
197 {
198 return proc->address_space;
199 }
200
201
202 sos_ret_t sos_process_set_address_space(struct sos_process *proc,
203 struct sos_umem_vmm_as *new_as)
204 {
205 if (proc->address_space)
206 {
207 sos_ret_t retval = sos_umem_vmm_delete_as(proc->address_space);
208 if (SOS_OK != retval)
209 return retval;
210 }
211
212 proc->address_space = new_as;
213 return SOS_OK;
214 }
215
216
217
218
219
220
221
222 sos_ret_t sos_process_register_thread(struct sos_process *in_proc,
223 struct sos_thread *thr)
224 {
225 sos_ui32_t flags;
226
227
228 SOS_ASSERT_FATAL(in_proc->ref_cnt > 0);
229
230
231
232 SOS_ASSERT_FATAL(thr->state == SOS_THR_CREATED);
233
234
235 thr->process = in_proc;
236
237
238 sos_process_ref(in_proc);
239
240
241 sos_disable_IRQs(flags);
242 list_add_tail_named(in_proc->thread_list, thr,
243 prev_in_process, next_in_process);
244 in_proc->nb_threads ++;
245 sos_restore_IRQs(flags);
246
247 return SOS_OK;
248 }
249
250
251
252
253 sos_ret_t sos_process_unref(struct sos_process *proc)
254 {
255 sos_ui32_t flags;
256 sos_ret_t retval;
257
258 SOS_ASSERT_FATAL(proc->ref_cnt > 0);
259
260 sos_disable_IRQs(flags);
261 proc->ref_cnt --;
262 if (proc->ref_cnt > 0)
263 {
264 sos_restore_IRQs(flags);
265 return -SOS_EBUSY;
266 }
267 list_delete(process_list, proc);
268 sos_restore_IRQs(flags);
269
270
271 retval = sos_umem_vmm_delete_as(proc->address_space);
272 SOS_ASSERT_FATAL(SOS_OK == retval);
273
274
275 sos_kmem_cache_free((sos_vaddr_t)proc);
276
277 return SOS_OK;
278 }
279
280
281 sos_ret_t sos_process_unregister_thread(struct sos_thread *thr)
282 {
283 sos_ui32_t flags;
284 struct sos_process * in_proc = thr->process;
285
286 SOS_ASSERT_FATAL(thr->state == SOS_THR_ZOMBIE);
287
288
289 thr->process = NULL;
290 sos_disable_IRQs(flags);
291 list_delete_named(in_proc->thread_list, thr,
292 prev_in_process, next_in_process);
293 SOS_ASSERT_FATAL(in_proc->nb_threads > 0);
294 in_proc->nb_threads --;
295 sos_restore_IRQs(flags);
296
297
298 sos_process_unref(in_proc);
299
300 return SOS_OK;
301 }
302
303
304 sos_ret_t sos_process_set_name(struct sos_process * proc,
305 const char * new_name)
306 {
307 strzcpy(proc->name, new_name, SOS_PROCESS_MAX_NAMELEN);
308 return SOS_OK;
309 }