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

Diff for /prex-old/sys/kern/exception.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:31
Line 83 
Line 83 
   
 /*  /*
  * Install an exception handler for the current task.   * Install an exception handler for the current task.
    *
  * NULL can be specified as handler to remove current handler.   * NULL can be specified as handler to remove current handler.
  * If handler is removed, all pending exceptions are discarded   * If handler is removed, all pending exceptions are discarded
  * immediately. In this case, all threads blocked in exception_wait()   * immediately. In this case, all threads blocked in
  * are unblocked.   * exception_wait() are unblocked.
  *   *
  * Only one exception handler can be set per task. If the previous   * Only one exception handler can be set per task. If the
  * handler exists in task, exception_setup() just override that   * previous handler exists in task, exception_setup() just
  * handler.   * override that handler.
  */   */
 int  int
 exception_setup(void (*handler)(int, u_long))  exception_setup(void (*handler)(int))
 {  {
         task_t self;          task_t self = cur_task();
         list_t head, n;          list_t head, n;
         thread_t th;          thread_t th;
   
Line 103 
Line 104 
                 return EFAULT;                  return EFAULT;
   
         sched_lock();          sched_lock();
         self = cur_task();          if (self->handler && handler == NULL) {
         if (self->exc_handler && handler == NULL) {  
                 /*                  /*
                  * Remove existing exception handler. Do clean up                   * Remove existing exception handler. Do clean up
                  * job for all threads in the target task.                   * job for all threads in the target task.
Line 116 
Line 116 
                          */                           */
                         th = list_entry(n, struct thread, task_link);                          th = list_entry(n, struct thread, task_link);
                         irq_lock();                          irq_lock();
                         th->exc_bitmap = 0;                          th->excbits = 0;
                         irq_unlock();                          irq_unlock();
   
                         /*                          /*
                          * If the thread is waiting for an exception,                           * If the thread is waiting for an exception,
                          * cancel it.                           * cancel it.
                          */                           */
                         if (th->sleep_event == &exception_event)                          if (th->slpevt == &exception_event)
                                 sched_unsleep(th, SLP_BREAK);                                  sched_unsleep(th, SLP_BREAK);
                 }                  }
         }          }
         self->exc_handler = handler;          self->handler = handler;
         sched_unlock();          sched_unlock();
         return 0;          return 0;
 }  }
   
 /*  /*
  * exception_raise - raise an exception for specified task.   * exception_raise - system call to raise an exception.
  * @task: task id  
  * @exc:  exception code  
  *   *
  * The exception pending flag is marked here, and it is processed   * The exception pending flag is marked here, and it is
  * by exception_deliver() later. If the task want to raise an   * processed by exception_deliver() later. If the task
  * exception to another task, the caller task must have CAP_KILL   * want to raise an exception to another task, the caller
  * capability. If the exception is sent to the kernel task, this   * task must have CAP_KILL capability. If the exception
  * routine just returns error.   * is sent to the kernel task, this routine just returns
    * error.
  */   */
 int  int
 exception_raise(task_t task, int exc)  exception_raise(task_t task, int exc)
Line 151 
Line 151 
   
         if (!task_valid(task)) {          if (!task_valid(task)) {
                 err = ESRCH;                  err = ESRCH;
         } else if (task != cur_task() && !task_capable(CAP_KILL)) {                  goto out;
           }
           if (task != cur_task() && !task_capable(CAP_KILL)) {
                 err = EPERM;                  err = EPERM;
         } else if (task == &kern_task || task->exc_handler == NULL ||                  goto out;
                  list_empty(&task->threads)) {          }
           if (task == &kern_task || task->handler == NULL ||
               list_empty(&task->threads)) {
                 err = EPERM;                  err = EPERM;
         } else {                  goto out;
                 err = exception_post(task, exc);  
         }          }
           err = exception_post(task, exc);
    out:
         sched_unlock();          sched_unlock();
         return err;          return err;
 }  }
   
 /*  /*
  * Post an exception to the specified task.   * exception_post-- the internal version of exception_raise().
  */   */
 int  int
 exception_post(task_t task, int exc)  exception_post(task_t task, int exc)
Line 172 
Line 177 
         list_t head, n;          list_t head, n;
         thread_t th;          thread_t th;
   
         if (exc < 0 || exc >= NR_EXCS)          if (exc < 0 || exc >= NEXC)
                 return EINVAL;                  return EINVAL;
   
         /*          /*
          * Determine which thread should we send an exception.           * Determine which thread should we send an exception.
          * First, search the thread that is waiting an exception by           * First, search the thread that is waiting an exception
          * calling exception_wait(). Then, if no thread is waiting           * by calling exception_wait(). Then, if no thread is
          * exceptions, it is sent to the master thread in task.           * waiting exceptions, it is sent to the master thread in
            * task.
          */           */
         head = &task->threads;          head = &task->threads;
         for (n = list_first(head); n != head; n = list_next(n)) {          for (n = list_first(head); n != head; n = list_next(n)) {
                 th = list_entry(n, struct thread, task_link);                  th = list_entry(n, struct thread, task_link);
                 if (th->sleep_event == &exception_event)                  if (th->slpevt == &exception_event)
                         break;                          break;
         }          }
         if (n == head) {          if (n == head) {
Line 195 
Line 201 
          * Mark pending bit for this exception.           * Mark pending bit for this exception.
          */           */
         irq_lock();          irq_lock();
         th->exc_bitmap |= (1 << exc);          th->excbits |= (1 << exc);
         irq_unlock();          irq_unlock();
   
         /*          /*
          * Wakeup the target thread regardless of its waiting           * Wakeup the target thread regardless of its
          * event.           * waiting event.
          */           */
         sched_unsleep(th, SLP_INTR);          sched_unsleep(th, SLP_INTR);
   
Line 208 
Line 214 
 }  }
   
 /*  /*
  * exception_wait - block a current thread until some exceptions are   * exception_wait - block a current thread until some exceptions
  * raised to the current thread.   * are raised to the current thread.
  * @exc: exception code returned.  
  *   *
  * The routine returns EINTR on success.   * The routine returns EINTR on success.
  */   */
 int  int
 exception_wait(int *exc)  exception_wait(int *exc)
 {  {
           task_t self = cur_task();
         int i, rc;          int i, rc;
   
         if (cur_task()->exc_handler == NULL)          self = cur_task();
           if (self->handler == NULL)
                 return EINVAL;                  return EINVAL;
         if (!user_area(exc))          if (!user_area(exc))
                 return EFAULT;                  return EFAULT;
Line 235 
Line 242 
                 return EINVAL;                  return EINVAL;
         }          }
         irq_lock();          irq_lock();
         for (i = 0; i < NR_EXCS; i++) {          for (i = 0; i < NEXC; i++) {
                 if (cur_thread->exc_bitmap & (1 << i))                  if (cur_thread->excbits & (1 << i))
                         break;                          break;
         }          }
         irq_unlock();          irq_unlock();
         ASSERT(i != NR_EXCS);          ASSERT(i != NEXC);
         sched_unlock();          sched_unlock();
   
         if (umem_copyout(&i, exc, sizeof(int)))          if (umem_copyout(&i, exc, sizeof(i)))
                 return EFAULT;                  return EFAULT;
         return EINTR;          return EINTR;
 }  }
Line 251 
Line 258 
 /*  /*
  * Mark an exception flag for the current thread.   * Mark an exception flag for the current thread.
  *   *
  * This is called from architecture dependent code when H/W trap is   * This is called from architecture dependent code when H/W
  * occurred. If current task does not have exception handler, then   * trap is occurred. If current task does not have exception
  * current task will be terminated.   * handler, then current task will be terminated. This routine
  * This routine may be called at interrupt level.   * may be called at interrupt level.
  */   */
 void  void
 exception_mark(int exc)  exception_mark(int exc)
 {  {
         ASSERT(exc > 0 && exc < NR_EXCS);          ASSERT(exc > 0 && exc < NEXC);
   
         /* Mark pending bit */          /* Mark pending bit */
         irq_lock();          irq_lock();
         cur_thread->exc_bitmap |= (1 << exc);          cur_thread->excbits |= (1 << exc);
         irq_unlock();          irq_unlock();
 }  }
   
 /*  /*
  * Check if pending exception exists for current task, and deliver   * exception_deliver - deliver pending exception to the task.
  * it to the exception handler if needed.   *
  * All exception is delivered at the time when the control goes back   * Check if pending exception exists for current task, and
  * to the user mode.   * deliver it to the exception handler if needed. All
  * This routine is called from architecture dependent code.   * exception is delivered at the time when the control goes
  * Some application may use longjmp() during its signal handler.   * back to the user mode. This routine is called from
  * So, current context must be saved to user mode stack.   * architecture dependent code. Some application may use
    * longjmp() during its signal handler. So, current context
    * must be saved to user mode stack.
  */   */
 void  void
 exception_deliver(void)  exception_deliver(void)
 {  {
         thread_t th = cur_thread;          thread_t th = cur_thread;
         task_t self = cur_task();          task_t self = cur_task();
         void (*handler)(int, u_long);          void (*handler)(int);
         uint32_t bitmap;          uint32_t bitmap;
         int exc;          int exc;
   
         sched_lock();          sched_lock();
         irq_lock();          irq_lock();
         bitmap = th->exc_bitmap;          bitmap = th->excbits;
         irq_unlock();          irq_unlock();
   
         if (bitmap != 0) {          if (bitmap != 0) {
                 /*                  /*
                  * Find a pending exception.                   * Find a pending exception.
                  */                   */
                 for (exc = 0; exc < NR_EXCS; exc++) {                  for (exc = 0; exc < NEXC; exc++) {
                         if (bitmap & (1 << exc))                          if (bitmap & (1 << exc))
                                 break;                                  break;
                 }                  }
                 handler = self->exc_handler;                  handler = self->handler;
                 if (handler == NULL) {                  if (handler == NULL) {
                         printk("Exception #%d is not handled by task.\n", exc);                          DPRINTF(("Exception #%d is not handled by task.\n",
                         printk("Terminate task:%s (id:%x)\n",                                  exc));
                                self->name ? self->name : "no name", self);                          DPRINTF(("Terminate task:%s (id:%x)\n",
                                    self->name != NULL ? self->name : "no name",
                                    self));
   
                         task_terminate(self);                          task_terminate(self);
                         goto out;                          goto out;
                 }                  }
                 /*                  /*
                  * Transfer control to an exception handler.                   * Transfer control to an exception handler.
                  */                   */
                 context_save(&th->context, exc);                  context_save(&th->ctx);
                 context_set(&th->context, CTX_UENTRY, (u_long)handler);                  context_set(&th->ctx, CTX_UENTRY, (vaddr_t)handler);
                   context_set(&th->ctx, CTX_UARG, (vaddr_t)exc);
   
                 irq_lock();                  irq_lock();
                 th->exc_bitmap &= ~(1 << exc);                  th->excbits &= ~(1 << exc);
                 irq_unlock();                  irq_unlock();
         }          }
  out:   out:
Line 321 
Line 334 
 }  }
   
 /*  /*
  * exception_return() is called from exception handler to restore   * exception_return() is called from exception handler to
  * the original context.   * restore the original context.
  * @regs: context pointer which is passed to exception handler.  
  *  
  * TODO: should validate passed data area.  
  */   */
 int  int
 exception_return(void *regs)  exception_return(void)
 {  {
   
         if ((regs == NULL) || !user_area(regs))          context_restore(&cur_thread->ctx);
                 return EFAULT;  
   
         context_restore(&cur_thread->context, regs);  
         return 0;          return 0;
 }  }
   

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

CVSweb