Rev 2927 | Rev 3004 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2927 | Rev 3001 | ||
---|---|---|---|
Line 77... | Line 77... | ||
77 | */ |
77 | */ |
78 | avltree_t tasks_tree; |
78 | avltree_t tasks_tree; |
79 | 79 | ||
80 | static task_id_t task_counter = 0; |
80 | static task_id_t task_counter = 0; |
81 | 81 | ||
- | 82 | /** |
|
- | 83 | * Points to the binary image used as the program loader. All non-initial |
|
- | 84 | * tasks are created from this executable image. |
|
- | 85 | */ |
|
- | 86 | void *program_loader = NULL; |
|
- | 87 | ||
- | 88 | ||
82 | /** Initialize tasks |
89 | /** Initialize tasks |
83 | * |
90 | * |
84 | * Initialize kernel tasks support. |
91 | * Initialize kernel tasks support. |
85 | * |
92 | * |
86 | */ |
93 | */ |
Line 233... | Line 240... | ||
233 | TASK = NULL; |
240 | TASK = NULL; |
234 | } |
241 | } |
235 | 242 | ||
236 | /** Create new task with 1 thread and run it |
243 | /** Create new task with 1 thread and run it |
237 | * |
244 | * |
- | 245 | * @param as Address space containing a binary program image. |
|
238 | * @param program_addr Address of program executable image. |
246 | * @param entry_addr Program entry-point address in program address space. |
239 | * @param name Program name. |
247 | * @param name Program name. |
240 | * |
248 | * |
241 | * @return Task of the running program or NULL on error. |
249 | * @return Task of the running program or NULL on error. |
242 | */ |
250 | */ |
243 | task_t *task_run_program(void *program_addr, char *name) |
251 | task_t *task_create_from_as(as_t *as, uintptr_t entry_addr, char *name) |
244 | { |
252 | { |
245 | as_t *as; |
- | |
246 | as_area_t *a; |
253 | as_area_t *a; |
247 | unsigned int rc; |
- | |
248 | thread_t *t; |
254 | thread_t *t; |
249 | task_t *task; |
255 | task_t *task; |
250 | uspace_arg_t *kernel_uarg; |
256 | uspace_arg_t *kernel_uarg; |
251 | 257 | ||
252 | as = as_create(0); |
- | |
253 | ASSERT(as); |
- | |
254 | - | ||
255 | rc = elf_load((elf_header_t *) program_addr, as); |
- | |
256 | if (rc != EE_OK) { |
- | |
257 | as_destroy(as); |
- | |
258 | return NULL; |
- | |
259 | } |
- | |
260 | - | ||
261 | kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
258 | kernel_uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t), 0); |
262 | kernel_uarg->uspace_entry = |
259 | kernel_uarg->uspace_entry = (void *) entry_addr; |
263 | (void *) ((elf_header_t *) program_addr)->e_entry; |
- | |
264 | kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS; |
260 | kernel_uarg->uspace_stack = (void *) USTACK_ADDRESS; |
265 | kernel_uarg->uspace_thread_function = NULL; |
261 | kernel_uarg->uspace_thread_function = NULL; |
266 | kernel_uarg->uspace_thread_arg = NULL; |
262 | kernel_uarg->uspace_thread_arg = NULL; |
267 | kernel_uarg->uspace_uarg = NULL; |
263 | kernel_uarg->uspace_uarg = NULL; |
268 | 264 | ||
Line 281... | Line 277... | ||
281 | */ |
277 | */ |
282 | t = thread_create(uinit, kernel_uarg, task, THREAD_FLAG_USPACE, |
278 | t = thread_create(uinit, kernel_uarg, task, THREAD_FLAG_USPACE, |
283 | "uinit", false); |
279 | "uinit", false); |
284 | ASSERT(t); |
280 | ASSERT(t); |
285 | 281 | ||
286 | thread_ready(t); |
- | |
287 | - | ||
288 | return task; |
282 | return task; |
289 | } |
283 | } |
290 | 284 | ||
- | 285 | /** Parse an executable image in the physical memory. |
|
- | 286 | * |
|
- | 287 | * If the image belongs to a program loader, it is registered as such, |
|
- | 288 | * (and *task is set to NULL). Otherwise a task is created from the |
|
- | 289 | * executable image. The task is returned in *task. |
|
- | 290 | * |
|
- | 291 | * @param program_addr Address of program executable image. |
|
- | 292 | * @param name Program name. |
|
- | 293 | * @param task Where to store the pointer to the newly created task. |
|
- | 294 | * |
|
- | 295 | * @return EOK on success or negative error code. |
|
- | 296 | */ |
|
- | 297 | int task_parse_initial(void *program_addr, char *name, task_t **task) |
|
- | 298 | { |
|
- | 299 | as_t *as; |
|
- | 300 | unsigned int rc; |
|
- | 301 | ||
- | 302 | as = as_create(0); |
|
- | 303 | ASSERT(as); |
|
- | 304 | ||
- | 305 | rc = elf_load((elf_header_t *) program_addr, as, 0); |
|
- | 306 | if (rc != EE_OK) { |
|
- | 307 | as_destroy(as); |
|
- | 308 | *task = NULL; |
|
- | 309 | if (rc != EE_LOADER) |
|
- | 310 | return ENOTSUP; |
|
- | 311 | ||
- | 312 | /* Register image as the program loader */ |
|
- | 313 | ASSERT(program_loader == NULL); |
|
- | 314 | program_loader = program_addr; |
|
- | 315 | return EOK; |
|
- | 316 | } |
|
- | 317 | ||
- | 318 | *task = task_create_from_as(as, ((elf_header_t *) program_addr)->e_entry, |
|
- | 319 | name); |
|
- | 320 | ||
- | 321 | return EOK; |
|
- | 322 | } |
|
- | 323 | ||
- | 324 | /** Create a task from the program loader image. |
|
- | 325 | * |
|
- | 326 | * @param program_addr Address of program executable image. |
|
- | 327 | * @param name Program name. |
|
- | 328 | * |
|
- | 329 | * @return Task of the running program or NULL on error. |
|
- | 330 | */ |
|
- | 331 | task_t *task_create_from_loader(char *name) |
|
- | 332 | { |
|
- | 333 | as_t *as; |
|
- | 334 | unsigned int rc; |
|
- | 335 | ||
- | 336 | as = as_create(0); |
|
- | 337 | ASSERT(as); |
|
- | 338 | ||
- | 339 | rc = elf_load((elf_header_t *) program_loader, as, ELD_F_LOADER); |
|
- | 340 | if (rc != EE_OK) { |
|
- | 341 | as_destroy(as); |
|
- | 342 | return NULL; |
|
- | 343 | } |
|
- | 344 | ||
- | 345 | return task_create_from_as( |
|
- | 346 | as, ((elf_header_t *) program_loader)->e_entry, name); |
|
- | 347 | } |
|
- | 348 | ||
- | 349 | /** Make task ready. |
|
- | 350 | * |
|
- | 351 | * Switch task's thread to the ready state. |
|
- | 352 | * |
|
- | 353 | * @param ta Task to make ready. |
|
- | 354 | */ |
|
- | 355 | void task_ready(task_t *t) |
|
- | 356 | { |
|
- | 357 | thread_t *th; |
|
- | 358 | ||
- | 359 | th = list_get_instance(t->th_head.next, thread_t, th_link); |
|
- | 360 | thread_ready(th); |
|
- | 361 | } |
|
- | 362 | ||
291 | /** Syscall for reading task ID from userspace. |
363 | /** Syscall for reading task ID from userspace. |
292 | * |
364 | * |
293 | * @param uspace_task_id Userspace address of 8-byte buffer where to store |
365 | * @param uspace_task_id Userspace address of 8-byte buffer where to store |
294 | * current task ID. |
366 | * current task ID. |
295 | * |
367 | * |
Line 303... | Line 375... | ||
303 | */ |
375 | */ |
304 | return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid, |
376 | return (unative_t) copy_to_uspace(uspace_task_id, &TASK->taskid, |
305 | sizeof(TASK->taskid)); |
377 | sizeof(TASK->taskid)); |
306 | } |
378 | } |
307 | 379 | ||
- | 380 | /** Syscall for creating a new task from userspace. |
|
- | 381 | * |
|
- | 382 | * Creates a new task from the program loader image and stores its |
|
- | 383 | * task id into the provided buffer. |
|
- | 384 | * |
|
- | 385 | * @param uspace_task_id Userspace address of 8-byte buffer where to store |
|
- | 386 | * current task ID. |
|
- | 387 | * |
|
- | 388 | * @return 0 on success or an error code from @ref errno.h. |
|
- | 389 | */ |
|
- | 390 | unative_t sys_task_spawn(task_id_t *uspace_task_id) |
|
- | 391 | { |
|
- | 392 | task_t *t; |
|
- | 393 | task_id_t fake_id; |
|
- | 394 | int rc; |
|
- | 395 | ||
- | 396 | /* Before we even try creating the task, see if we can write the id */ |
|
- | 397 | rc = (unative_t) copy_to_uspace(uspace_task_id, &fake_id, |
|
- | 398 | sizeof(fake_id)); |
|
- | 399 | if (rc != 0) |
|
- | 400 | return rc; |
|
- | 401 | ||
- | 402 | t = task_create_from_loader("loader"); |
|
- | 403 | ||
- | 404 | /* No need to aquire lock before task_ready() */ |
|
- | 405 | rc = (unative_t) copy_to_uspace(uspace_task_id, &t->taskid, |
|
- | 406 | sizeof(t->taskid)); |
|
- | 407 | if (rc != 0) { |
|
- | 408 | /* Ooops */ |
|
- | 409 | task_kill(t->taskid); |
|
- | 410 | return rc; |
|
- | 411 | } |
|
- | 412 | ||
- | 413 | task_ready(t); |
|
- | 414 | ||
- | 415 | return EOK; |
|
- | 416 | } |
|
- | 417 | ||
308 | /** Find task structure corresponding to task ID. |
418 | /** Find task structure corresponding to task ID. |
309 | * |
419 | * |
310 | * The tasks_lock must be already held by the caller of this function |
420 | * The tasks_lock must be already held by the caller of this function |
311 | * and interrupts must be disabled. |
421 | * and interrupts must be disabled. |
312 | * |
422 | * |