[BACK]Return to task.c CVS log [TXT][DIR] Up to [local] / prex-old / sys / kern

Diff for /prex-old/sys/kern/task.c between version 1.1.1.1 and 1.1.1.1.2.1

version 1.1.1.1, 2008/06/03 10:38:46 version 1.1.1.1.2.1, 2008/08/13 17:12:32
Line 44 
Line 44 
  * Kernel task.   * Kernel task.
  * kern_task acts as a list head of all tasks in the system.   * kern_task acts as a list head of all tasks in the system.
  */   */
 struct task kern_task;  struct task     kern_task;
   
 /**  /**
  * task_create - create a new task.   * task_create - create a new task.
Line 57 
Line 57 
  *   Task name         No   *   Task name         No
  *   Object list       No   *   Object list       No
  *   Threads           No   *   Threads           No
  *   Memory map        New/Duplicate/Share   *   Memory map        New/Copy/Share
  *   Suspend count     No   *   Suspend count     No
  *   Exception handler Yes   *   Exception handler Yes
  *   Capability        Yes   *   Capability        Yes
  *   *
  * If vm_option is VM_COPY, the child task will have the same memory   * vm_option:
  * image with the parent task. Especially, text region and read-only   *   VM_NEW:   The child task will have clean memory image.
  * region are physically shared among them. VM_COPY is supported only   *   VM_SHARE: The child task will share whole memory image with parent.
  * with MMU system.   *   VM_COPY:  The parent's memory image is copied to the child's one.
  * The child task initially contains no threads.   *             However, the text region and read-only region will be
    *             physically shared among them. VM_COPY is supported only
    *             with MMU system.
    *
    * Note: The child task initially contains no threads.
  */   */
 int  int
 task_create(task_t parent, int vm_option, task_t *child)  task_create(task_t parent, int vm_option, task_t *child)
Line 91 
Line 95 
                 goto out;                  goto out;
         }          }
         if (cur_task() != &kern_task) {          if (cur_task() != &kern_task) {
                 if(!task_access(parent)) {                  if (!task_access(parent)) {
                         err = EPERM;                          err = EPERM;
                         goto out;                          goto out;
                 }                  }
                 /*                  /*
                  * Set zero as child task id before copying parent's                   * Set zero as child task id before copying
                  * memory space. So, the child task can identify                   * parent's memory space. So, the child task
                  * whether it is a child.                   * can identify whether it is a child.
                  */                   */
                 task = 0;                  task = 0;
                 if (umem_copyout(&task, child, sizeof(task_t))) {                  if (umem_copyout(&task, child, sizeof(task))) {
                         err = EFAULT;                          err = EFAULT;
                         goto out;                          goto out;
                 }                  }
Line 127 
Line 131 
         case VM_COPY:          case VM_COPY:
                 map = vm_fork(parent->map);                  map = vm_fork(parent->map);
                 break;                  break;
           default:
                   /* DO NOTHING */
                   break;
         }          }
         if (map == NULL) {          if (map == NULL) {
                 kmem_free(task);                  kmem_free(task);
                 err = ENOMEM;                  err = ENOMEM;
                 goto out;                  goto out;
         }          }
   
         /*          /*
          * Fill initial task data.           * Fill initial task data.
          */           */
         task->map = map;          task->map = map;
         task->exc_handler = parent->exc_handler;          task->handler = parent->handler;
         task->capability = parent->capability;          task->capability = parent->capability;
         task->parent = parent;          task->parent = parent;
         task->magic = TASK_MAGIC;          task->magic = TASK_MAGIC;
Line 148 
Line 156 
         if (cur_task() == &kern_task)          if (cur_task() == &kern_task)
                 *child = task;                  *child = task;
         else          else
                 err = umem_copyout(&task, child, sizeof(task_t));                  err = umem_copyout(&task, child, sizeof(task));
  out:   out:
         sched_unlock();          sched_unlock();
         return err;          return err;
Line 193 
Line 201 
         head = &task->objects;          head = &task->objects;
         for (n = list_first(head); n != head; n = list_next(n)) {          for (n = list_first(head); n != head; n = list_next(n)) {
                 /*                  /*
                  * A current task may not have the right to delete                   * A current task may not have the right to
                  * target objects. So, we set the owner of the object                   * delete target objects. So, we set the owner
                  * to the current task before deleting it.                   * of the object to the current task before
                    * deleting it.
                  */                   */
                 obj = list_entry(n, struct object, task_link);                  obj = list_entry(n, struct object, task_link);
                 obj->owner = cur_task();                  obj->owner = cur_task();
Line 204 
Line 213 
         /*          /*
          * Release all other task related resources.           * Release all other task related resources.
          */           */
           timer_stop(&task->alarm);
         vm_terminate(task->map);          vm_terminate(task->map);
         list_remove(&task->link);          list_remove(&task->link);
         kmem_free(task);          kmem_free(task);
Line 231 
Line 241 
 {  {
         list_t head, n;          list_t head, n;
         thread_t th;          thread_t th;
         int err = 0;  
   
         sched_lock();          sched_lock();
         if (!task_valid(task)) {          if (!task_valid(task)) {
                 err = ESRCH;                  sched_unlock();
         } else if (!task_access(task)) {                  return ESRCH;
                 err = EPERM;          }
         } else if (++task->suspend_count == 1) {          if (!task_access(task)) {
                   sched_unlock();
                   return EPERM;
           }
   
           if (++task->suscnt == 1) {
                 /*                  /*
                  * Suspend all threads within the task.                   * Suspend all threads within the task.
                  */                   */
Line 249 
Line 263 
                 }                  }
         }          }
         sched_unlock();          sched_unlock();
         return err;          return 0;
 }  }
   
 /*  /*
Line 270 
Line 284 
         sched_lock();          sched_lock();
         if (!task_valid(task)) {          if (!task_valid(task)) {
                 err = ESRCH;                  err = ESRCH;
         } else if (!task_access(task)) {                  goto out;
           }
           if (!task_access(task)) {
                 err = EPERM;                  err = EPERM;
         } else if (task->suspend_count == 0) {                  goto out;
           }
           if (task->suscnt == 0) {
                 err = EINVAL;                  err = EINVAL;
         } else if (--task->suspend_count == 0) {                  goto out;
           }
           if (--task->suscnt == 0) {
                 /*                  /*
                  * Resume all threads in the target task.                   * Resume all threads in the target task.
                  */                   */
Line 284 
Line 304 
                         thread_resume(th);                          thread_resume(th);
                 }                  }
         }          }
    out:
         sched_unlock();          sched_unlock();
         return err;          return err;
 }  }
Line 303 
Line 324 
         sched_lock();          sched_lock();
         if (!task_valid(task)) {          if (!task_valid(task)) {
                 err = ESRCH;                  err = ESRCH;
         } else if (!task_access(task)) {                  goto out;
           }
           if (!task_access(task)) {
                 err = EPERM;                  err = EPERM;
                   goto out;
           }
           if (cur_task() == &kern_task) {
                   strlcpy(task->name, name, MAXTASKNAME);
         } else {          } else {
                 if (cur_task() == &kern_task)                  if (umem_strnlen(name, MAXTASKNAME, &len))
                         strlcpy(task->name, name, MAXTASKNAME);                          err = EFAULT;
                 else {                  else if (len >= MAXTASKNAME)
                         if (umem_strnlen(name, MAXTASKNAME, &len))                          err = ENAMETOOLONG;
                                 err = EFAULT;                  else
                         else if (len >= MAXTASKNAME)                          err = umem_copyin(name, task->name, len + 1);
                                 err = ENAMETOOLONG;  
                         else  
                                 err = umem_copyin((void *)name, task->name,  
                                                   len + 1);  
                 }  
         }          }
    out:
         sched_unlock();          sched_unlock();
         return err;          return err;
 }  }
Line 328 
Line 351 
 int  int
 task_getcap(task_t task, cap_t *cap)  task_getcap(task_t task, cap_t *cap)
 {  {
         cap_t cur_cap;          cap_t curcap;
   
         sched_lock();          sched_lock();
         if (!task_valid(task)) {          if (!task_valid(task)) {
                 sched_unlock();                  sched_unlock();
                 return ESRCH;                  return ESRCH;
         }          }
         cur_cap = task->capability;          curcap = task->capability;
         sched_unlock();          sched_unlock();
   
         return umem_copyout(&cur_cap, cap, sizeof(cap_t));          return umem_copyout(&curcap, cap, sizeof(cap_t));
 }  }
   
 /*  /*
Line 347 
Line 370 
 int  int
 task_setcap(task_t task, cap_t *cap)  task_setcap(task_t task, cap_t *cap)
 {  {
         cap_t new_cap;          cap_t newcap;
         int err = 0;  
   
         if (!task_capable(CAP_SETPCAP))          if (!task_capable(CAP_SETPCAP))
                 return EPERM;                  return EPERM;
   
         sched_lock();          sched_lock();
         if (!task_valid(task)) {          if (!task_valid(task)) {
                 err = ESRCH;                  sched_unlock();
         } else if (umem_copyin(cap, &new_cap, sizeof(cap_t))) {                  return ESRCH;
                 err = EFAULT;  
         } else {  
                 task->capability = new_cap;  
         }          }
           if (umem_copyin(cap, &newcap, sizeof(cap_t))) {
                   sched_unlock();
                   return EFAULT;
           }
           task->capability = newcap;
         sched_unlock();          sched_unlock();
         return err;          return 0;
 }  }
   
 /*  /*
  * Check if the current task can access the specified task.   * Check if the current task can access the specified task.
    * Return true on success, or false on error.
  */   */
 int  int
 task_access(task_t task)  task_access(task_t task)
 {  {
   
         return (task != &kern_task &&          if (task == &kern_task)
                 (task == cur_task() || task->parent == cur_task() ||                  return 0;
                  task_capable(CAP_TASK)));          else {
                   if (task == cur_task() ||
                       task->parent == cur_task() ||
                       task_capable(CAP_TASK))
                           return 1;
           }
           return 0;
 }  }
   
 /*  /*
Line 383 
Line 414 
 void  void
 task_bootstrap(void)  task_bootstrap(void)
 {  {
         struct module *m;          struct module *mod;
         task_t task;          task_t task;
         thread_t th;          thread_t th;
         void *stack;          void *stack;
           vaddr_t sp;
         int i;          int i;
   
         m = &boot_info->tasks[0];          mod = &boot_info->tasks[0];
         for (i = 0; i < boot_info->nr_tasks; i++, m++) {          for (i = 0; i < boot_info->nr_tasks; i++) {
                 /*                  /*
                  * Create a new task.                   * Create a new task.
                  */                   */
                 if (task_create(&kern_task, VM_NEW, &task))                  if (task_create(&kern_task, VM_NEW, &task))
                         break;                          break;
                 task_name(task, m->name);                  task_name(task, mod->name);
                 if (vm_load(task->map, m, &stack))                  if (vm_load(task->map, mod, &stack))
                         break;                          break;
   
                 /*                  /*
Line 405 
Line 437 
                  */                   */
                 if (thread_create(task, &th))                  if (thread_create(task, &th))
                         break;                          break;
                 stack = (void *)((u_long)stack + USTACK_SIZE - sizeof(int));                  sp = (vaddr_t)stack + USTACK_SIZE - (sizeof(int) * 3);
                 if (thread_load(th, (void (*)(void))m->entry, stack))                  if (thread_load(th, (void (*)(void))mod->entry, (void *)sp))
                         break;                          break;
                 thread_resume(th);                  thread_resume(th);
   
                   mod++;
         }          }
         if (i != boot_info->nr_tasks)          if (i != boot_info->nr_tasks)
                 panic("task_boot");                  panic("task_bootstrap: unable to load boot task");
 }  }
   
 #if defined(DEBUG) && defined(CONFIG_KDUMP)  #ifdef DEBUG
 void  void
 task_dump(void)  task_dump(void)
 {  {
         list_t i, j;          list_t i, j;
         task_t task;          task_t task;
         int nobjs, nthreads;          int nthreads;
   
         printk("Task dump:\n");          printf("\nTask dump:\n");
         printk(" mod task      nobjs  nthrds vm map   susp exc hdlr "          printf(" mod task      nthrds susp exc hdlr cap      name\n");
                "cap      name\n");          printf(" --- --------- ------ ---- -------- -------- ------------\n");
         printk(" --- --------- ------ ------ -------- ---- -------- "  
                "-------- ------------\n");  
   
         i = &kern_task.link;          i = &kern_task.link;
         do {          do {
                 task = list_entry(i, struct task, link);                  task = list_entry(i, struct task, link);
   
                 nthreads = 0;                  nthreads = 0;
                 j = &task->threads;                  j = list_first(&task->threads);
                 j = list_next(j);  
                 do {                  do {
                         nthreads++;                          nthreads++;
                         j = list_next(j);                          j = list_next(j);
                 } while (j != &task->threads);                  } while (j != &task->threads);
   
                 nobjs = 0;                  printf(" %s %08x%c    %3d %4d %08x %08x %s\n",
                 j = &task->objects;                         (task == &kern_task) ? "Knl" : "Usr", task,
                 j = list_next(j);                         (task == cur_task()) ? '*' : ' ', nthreads,
                 do {                         task->suscnt, task->handler, task->capability,
                         nobjs++;                         task->name != NULL ? task->name : "no name");
                         j = list_next(j);  
                 } while (j != &task->objects);  
   
                 printk(" %s %08x%c    %3d    %3d %08x %4d %08x %08x %s\n",  
                        (task == &kern_task) ? "Knl" : "Usr",  
                        task, (task == cur_task()) ? '*' : ' ', nobjs,  
                        nthreads, task->map, task->suspend_count,  
                        task->exc_handler, task->capability,  
                        task->name ? task->name : "no name");  
   
                 i = list_next(i);                  i = list_next(i);
         } while (i != &kern_task.link);          } while (i != &kern_task.link);
 }  }
   
 void  
 boot_dump(void)  
 {  
         struct module *m;  
         int i;  
   
         printk(" text base data base text size data size bss size   "  
                "task name\n");  
         printk(" --------- --------- --------- --------- ---------- "  
                "----------\n");  
   
         m = &boot_info->tasks[0];  
         for (i = 0; i < boot_info->nr_tasks; i++, m++) {  
                 printk("  %8x  %8x  %8d  %8d  %8d  %s\n",  
                        m->text, m->data, m->textsz,  
                        m->datasz, m->bsssz, m->name);  
         }  
 }  
 #endif  #endif
   
   /*
    * We assume the VM mapping of a kernel task has already
    * been initialized in vm_init().
    */
 void  void
 task_init(void)  task_init(void)
 {  {
         /*          /*
          * Create a kernel task as a first task in the system.           * Create a kernel task as the first task.
          *  
          * Note: We assume the VM mapping for a kernel task has  
          * already been initialized in vm_init().  
          */           */
         strlcpy(kern_task.name, "kernel", MAXTASKNAME);          strlcpy(kern_task.name, "kernel", MAXTASKNAME);
         list_init(&kern_task.link);          list_init(&kern_task.link);

Legend:
Removed from v.1.1.1.1  
changed lines
  Added in v.1.1.1.1.2.1

CVSweb