Subversion Repositories HelenOS

Rev

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
 *