Subversion Repositories HelenOS

Rev

Rev 2870 | Rev 2898 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2008 Jiri Svoboda
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup generic
  30.  * @{
  31.  */
  32.  
  33. /**
  34.  * @file
  35.  * @brief   Udebug.
  36.  */
  37.  
  38. #include <synch/waitq.h>
  39. #include <console/klog.h>
  40. #include <udebug/udebug.h>
  41. #include <errno.h>
  42. #include <arch.h>
  43.  
  44. void udebug_stoppable_begin(void)
  45. {
  46.     int nsc;
  47.     call_t *db_call;
  48.     ipl_t ipl;
  49.  
  50.     ipl = interrupts_disable();
  51.     spinlock_lock(&TASK->lock);
  52.  
  53.     nsc = --TASK->not_stoppable_count;
  54.     db_call = TASK->debug_begin_call;
  55.  
  56.     if (TASK->dt_state == UDEBUG_TS_BEGINNING) {
  57.         klog_printf("udebug_stoppable_begin");
  58.         klog_printf(" - nsc := %d", nsc);
  59.     }
  60.  
  61.     if (TASK->dt_state == UDEBUG_TS_BEGINNING && nsc == 0) {
  62.         TASK->dt_state = UDEBUG_TS_ACTIVE;
  63.         TASK->debug_begin_call = NULL;
  64.         spinlock_unlock(&TASK->lock);
  65.         interrupts_restore(ipl);
  66.  
  67.         IPC_SET_RETVAL(db_call->data, 0);
  68.         klog_printf("udebug_stoppable_begin/ipc_answer");
  69.         ipc_answer(&TASK->answerbox, db_call);     
  70.     } else {
  71.             spinlock_unlock(&TASK->lock);
  72.         interrupts_restore(ipl);
  73.     }
  74. }
  75.  
  76. void udebug_stoppable_end(void)
  77. {
  78.     ipl_t ipl;
  79.  
  80. restart:
  81.     ipl = interrupts_disable();
  82.     spinlock_lock(&TASK->lock);
  83.  
  84.     if ((TASK->dt_state == UDEBUG_TS_BEGINNING ||
  85.         TASK->dt_state == UDEBUG_TS_ACTIVE) &&
  86.         THREAD->debug_stop == true) {
  87.         TASK->debug_begin_call = NULL;
  88.         spinlock_unlock(&TASK->lock);
  89.         interrupts_restore(ipl);
  90.  
  91.         klog_printf("udebug_stoppable_end: waitq_sleep");
  92.         waitq_sleep(&THREAD->go_wq);
  93.         goto restart;
  94.         /* must try again - have to lose stoppability atomically */
  95.     } else {
  96.         ++TASK->not_stoppable_count;
  97.         spinlock_unlock(&TASK->lock);
  98.         interrupts_restore(ipl);
  99.     }
  100. }
  101.  
  102. void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3,
  103.     unative_t a4, unative_t a5, unative_t a6, unative_t id, unative_t rc)
  104. {
  105.     call_t *call;
  106.     ipl_t ipl;
  107.  
  108.     ipl = interrupts_disable();
  109.     spinlock_lock(&THREAD->debug_lock);
  110.  
  111.     /* Must only generate events when in debugging session and have go */
  112.     if (THREAD->debug_active != true ||
  113.         THREAD->debug_stop == true) {
  114.         spinlock_unlock(&THREAD->debug_lock);
  115.         interrupts_restore(ipl);
  116.         return;
  117.     }
  118.  
  119.     klog_printf("udebug_syscall_event");
  120.     call = THREAD->debug_go_call;
  121.     IPC_SET_RETVAL(call->data, 0);
  122.     IPC_SET_ARG1(call->data, UDEBUG_EVENT_SYSCALL);
  123.     IPC_SET_ARG2(call->data, id);
  124.     IPC_SET_ARG3(call->data, rc);
  125.     klog_printf("udebug_syscall_event/ipc_answer");
  126.  
  127.     THREAD->syscall_args[0] = a1;
  128.     THREAD->syscall_args[1] = a2;
  129.     THREAD->syscall_args[2] = a3;
  130.     THREAD->syscall_args[3] = a4;
  131.     THREAD->syscall_args[4] = a5;
  132.     THREAD->syscall_args[5] = a6;
  133.  
  134.     /*
  135.      * Make sure debug_stop is true when going to sleep
  136.      * in case we get woken up by DEBUG_END. (At which
  137.      * point it must be back to the initial true value).
  138.      */
  139.     THREAD->debug_stop = true;
  140.  
  141.     THREAD->cur_event = UDEBUG_EVENT_SYSCALL;
  142.     spinlock_unlock(&THREAD->debug_lock);
  143.  
  144.     spinlock_lock(&TASK->lock);
  145.     ipc_answer(&TASK->answerbox, THREAD->debug_go_call);
  146.     spinlock_unlock(&TASK->lock);
  147.  
  148.     interrupts_restore(ipl);
  149.  
  150.     waitq_sleep(&THREAD->go_wq);
  151. }
  152.  
  153. void udebug_new_thread_event(struct thread *t)
  154. {
  155.     call_t *call;
  156.     ipl_t ipl;
  157.  
  158.     ipl = interrupts_disable();
  159.     spinlock_lock(&THREAD->debug_lock);
  160.  
  161.     klog_printf("udebug_new_thread_event");
  162.     klog_printf("- check state");
  163.  
  164.     /* Must only generate events when in debugging session */
  165.     if (THREAD->debug_active != true) {
  166.         klog_printf("- debug_active: %s, debug_stop: %s",
  167.             THREAD->debug_active ? "yes(+)" : "no(-)",
  168.             THREAD->debug_stop ? "yes(-)" : "no(+)");
  169.         spinlock_unlock(&THREAD->debug_lock);
  170.         interrupts_restore(ipl);
  171.         return;
  172.     }
  173.  
  174.     klog_printf("- trigger event");
  175.  
  176.     call = THREAD->debug_go_call;
  177.     IPC_SET_RETVAL(call->data, 0);
  178.     IPC_SET_ARG1(call->data, UDEBUG_EVENT_NEW_THREAD);
  179.     IPC_SET_ARG2(call->data, (unative_t)t);
  180.  
  181.     /*
  182.      * Make sure debug_stop is true when going to sleep
  183.      * in case we get woken up by DEBUG_END. (At which
  184.      * point it must be back to the initial true value).
  185.      */
  186.     THREAD->debug_stop = true;
  187.  
  188.     THREAD->cur_event = UDEBUG_EVENT_NEW_THREAD;
  189.     spinlock_unlock(&THREAD->debug_lock);
  190.  
  191.     spinlock_lock(&TASK->lock);
  192.     ipc_answer(&TASK->answerbox, THREAD->debug_go_call);
  193.     spinlock_unlock(&TASK->lock);
  194.  
  195.     interrupts_restore(ipl);
  196.     klog_printf("- sleep");
  197.  
  198.     waitq_sleep(&THREAD->go_wq);
  199. }
  200.  
  201. /**
  202.  * Terminate task debugging session.
  203.  *
  204.  * \param ta Must be already locked and interrupts must be disabled.
  205.  * \return Zero on success or negative error code.
  206.  */
  207. int udebug_task_cleanup(struct task *ta)
  208. {
  209.     thread_t *t;
  210.     link_t *cur;
  211.     int flags;
  212.  
  213.     klog_printf("udebug_task_cleanup()");
  214.     klog_printf("task %llu", ta->taskid);
  215.  
  216.     if (ta->dt_state == UDEBUG_TS_BEGINNING &&
  217.         ta->dt_state != UDEBUG_TS_ACTIVE) {
  218.         klog_printf("udebug_task_cleanup(): task not being debugged");
  219.         return EINVAL;
  220.     }
  221.  
  222.     /* Finish debugging of all userspace threads */
  223.     for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
  224.         t = list_get_instance(cur, thread_t, th_link);
  225.  
  226.         spinlock_lock(&t->debug_lock);
  227.         spinlock_lock(&t->lock);
  228.  
  229.         flags = t->flags;
  230.  
  231.         spinlock_unlock(&t->lock);
  232.  
  233.         /* Only process userspace threads */
  234.         if ((flags & THREAD_FLAG_USPACE) != 0) {
  235.             /* Prevent any further debug activity in thread */
  236.             t->debug_active = false;
  237.             t->cur_event = 0;   /* none */
  238.  
  239.             /* Still has go? */
  240.             if (t->debug_stop == false) {
  241.                 /*
  242.                 * Yes, so clear go. As debug_active == false,
  243.                  * this doesn't affect anything.
  244.                  */
  245.                 t->debug_stop = true;  
  246.  
  247.                 /* Answer GO call */
  248.                 klog_printf("answer GO call with EVENT_FINISHED");
  249.                 IPC_SET_RETVAL(t->debug_go_call->data, 0);
  250.                 IPC_SET_ARG1(t->debug_go_call->data, UDEBUG_EVENT_FINISHED);
  251.                 ipc_answer(&ta->answerbox, t->debug_go_call);
  252.             } else {
  253.                 /*
  254.                  * Debug_stop is already at initial value.
  255.                  * Yet this means the thread needs waking up.
  256.                  */
  257.  
  258.                 /*
  259.                  * t's lock must not be held when calling
  260.                  * waitq_wakeup.
  261.                  */
  262.                 waitq_wakeup(&t->go_wq, WAKEUP_FIRST);
  263.             }
  264.         }
  265.         spinlock_unlock(&t->debug_lock);
  266.     }
  267.  
  268.     ta->dt_state = UDEBUG_TS_INACTIVE;
  269.     ta->debugger = NULL;
  270.  
  271.     return 0;
  272. }
  273.  
  274.  
  275. /** @}
  276.  */
  277.