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 | * |