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 <hwcore/mm_context.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
045 struct sos_mm_context *mm_context;
046
047
048
049 struct sos_thread *thread_list;
050 sos_count_t nb_threads;
051
052
053 sos_count_t ref_cnt;
054
055 struct sos_process *prev, *next;
056 };
057
058
059
060 static struct sos_process *process_list = NULL;
061
062
063
064 struct sos_kslab_cache *cache_struct_process;
065
066
067
068
069
070 void sos_process_dumplist()
071 {
072 struct sos_thread * cur_thr = sos_thread_get_current();
073 struct sos_process * proc;
074 int nb_procs;
075
076 sos_bochs_printf("<ps>\n");
077 list_foreach(process_list, proc, nb_procs)
078 {
079 struct sos_thread * thr;
080 int nb_thrs;
081
082 sos_bochs_printf(" proc@%p: '%s', %d threads, %d refs\n",
083 proc, proc->name?proc->name:"(none)",
084 proc->nb_threads, proc->ref_cnt);
085
086 list_foreach_forward_named(proc->thread_list, thr, nb_thrs,
087 prev_in_process, next_in_process)
088 {
089 if (thr == cur_thr)
090 sos_bochs_printf(" thr@%p: [CURRENT]\n", thr);
091 else
092 sos_bochs_printf(" thr@%p: %cstate=%d eip=%p\n",
093 thr,
094 sos_cpu_context_is_in_user_mode(thr->cpu_state)?'u':'k',
095 thr->state,
096 (void*)sos_cpu_context_get_PC(thr->cpu_state));
097 }
098 }
099 sos_bochs_printf(" ======= %d processes =======\n", nb_procs);
100 sos_bochs_printf("</ps>\n");
101 }
102
103
104 sos_ret_t sos_process_subsystem_setup()
105 {
106
107 cache_struct_process = sos_kmem_cache_create("struct_process",
108 sizeof(struct sos_process),
109 3,
110 0,
111 SOS_KSLAB_CREATE_MAP
112 | SOS_KSLAB_CREATE_ZERO);
113 if (! cache_struct_process)
114 return -SOS_ENOMEM;
115
116 return SOS_OK;
117 }
118
119
120 struct sos_process *sos_process_create_empty(const char *name)
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
133 proc->mm_context = sos_mm_context_create();
134 if (NULL == proc->mm_context)
135 {
136
137 sos_kmem_cache_free((sos_vaddr_t)proc);
138 return NULL;
139 }
140
141 if (!name)
142 {
143 name = "[UNNAMED]";
144 }
145
146 strzcpy(proc->name, name, SOS_PROCESS_MAX_NAMELEN);
147
148
149 sos_disable_IRQs(flags);
150 list_add_tail(process_list, proc);
151 sos_restore_IRQs(flags);
152
153
154 proc->ref_cnt = 1;
155 return proc;
156 }
157
158
159 inline
160 sos_ret_t sos_process_ref(struct sos_process *proc)
161 {
162 sos_ui32_t flags;
163 sos_disable_IRQs(flags);
164 proc->ref_cnt ++;
165 sos_restore_IRQs(flags);
166 return SOS_OK;
167 }
168
169
170 sos_count_t sos_process_get_nb_threads(const struct sos_process *proc)
171 {
172 sos_count_t retval;
173 sos_ui32_t flags;
174 sos_disable_IRQs(flags);
175 retval = proc->nb_threads;
176 sos_restore_IRQs(flags);
177 return retval;
178 }
179
180
181 struct sos_mm_context *
182 sos_process_get_mm_context(const struct sos_process *proc)
183 {
184 return proc->mm_context;
185 }
186
187
188
189
190
191
192
193 sos_ret_t sos_process_register_thread(struct sos_process *in_proc,
194 struct sos_thread *thr)
195 {
196 sos_ui32_t flags;
197
198
199 SOS_ASSERT_FATAL(in_proc->ref_cnt > 0);
200
201
202
203 SOS_ASSERT_FATAL(thr->state == SOS_THR_CREATED);
204
205
206 thr->process = in_proc;
207
208
209 sos_process_ref(in_proc);
210
211
212 sos_disable_IRQs(flags);
213 list_add_tail_named(in_proc->thread_list, thr,
214 prev_in_process, next_in_process);
215 in_proc->nb_threads ++;
216 sos_restore_IRQs(flags);
217
218 return SOS_OK;
219 }
220
221
222
223
224 sos_ret_t sos_process_unref(struct sos_process *proc)
225 {
226 sos_ui32_t flags;
227 sos_ret_t retval;
228
229 SOS_ASSERT_FATAL(proc->ref_cnt > 0);
230
231 sos_disable_IRQs(flags);
232 proc->ref_cnt --;
233 if (proc->ref_cnt > 0)
234 {
235 sos_restore_IRQs(flags);
236 return -SOS_EBUSY;
237 }
238 list_delete(process_list, proc);
239 sos_restore_IRQs(flags);
240
241
242 retval = sos_mm_context_unref(proc->mm_context);
243 SOS_ASSERT_FATAL(SOS_OK == retval);
244
245
246 sos_kmem_cache_free((sos_vaddr_t)proc);
247
248 return SOS_OK;
249 }
250
251
252 sos_ret_t sos_process_unregister_thread(struct sos_thread *thr)
253 {
254 sos_ui32_t flags;
255 struct sos_process * in_proc = thr->process;
256
257 SOS_ASSERT_FATAL(thr->state == SOS_THR_ZOMBIE);
258
259
260 thr->process = NULL;
261 sos_disable_IRQs(flags);
262 list_delete_named(in_proc->thread_list, thr,
263 prev_in_process, next_in_process);
264 SOS_ASSERT_FATAL(in_proc->nb_threads > 0);
265 in_proc->nb_threads --;
266 sos_restore_IRQs(flags);
267
268
269 sos_process_unref(in_proc);
270
271 return SOS_OK;
272 }
273
274
275 sos_ret_t sos_process_set_name(struct sos_process * proc,
276 const char * new_name)
277 {
278 strzcpy(proc->name, new_name, SOS_PROCESS_MAX_NAMELEN);
279 return SOS_OK;
280 }