Subversion Repositories HelenOS

Rev

Rev 4153 | 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 hooks and data structure management.
  36.  *
  37.  * Udebug is an interface that makes userspace debuggers possible.
  38.  */
  39.  
  40. #include <synch/waitq.h>
  41. #include <debug.h>
  42. #include <udebug/udebug.h>
  43. #include <errno.h>
  44. #include <print.h>
  45. #include <arch.h>
  46.  
  47.  
  48. /** Initialize udebug part of task structure.
  49.  *
  50.  * Called as part of task structure initialization.
  51.  * @param ut    Pointer to the structure to initialize.
  52.  */
  53. void udebug_task_init(udebug_task_t *ut)
  54. {
  55.     mutex_initialize(&ut->lock, MUTEX_PASSIVE);
  56.     ut->dt_state = UDEBUG_TS_INACTIVE;
  57.     ut->begin_call = NULL;
  58.     ut->not_stoppable_count = 0;
  59.     ut->evmask = 0;
  60. }
  61.  
  62. /** Initialize udebug part of thread structure.
  63.  *
  64.  * Called as part of thread structure initialization.
  65.  * @param ut    Pointer to the structure to initialize.
  66.  */
  67. void udebug_thread_initialize(udebug_thread_t *ut)
  68. {
  69.     mutex_initialize(&ut->lock, MUTEX_PASSIVE);
  70.     waitq_initialize(&ut->go_wq);
  71.  
  72.     ut->go_call = NULL;
  73.     ut->uspace_state = NULL;
  74.     ut->go = false;
  75.     ut->stoppable = true;
  76.     ut->active = false;
  77.     ut->cur_event = 0; /* none */
  78. }
  79.  
  80. /** Wait for a GO message.
  81.  *
  82.  * When a debugging event occurs in a thread or the thread is stopped,
  83.  * this function is called to block the thread until a GO message
  84.  * is received.
  85.  *
  86.  * @param wq    The wait queue used by the thread to wait for GO messages.
  87.  */
  88. static void udebug_wait_for_go(waitq_t *wq)
  89. {
  90.     int rc;
  91.     ipl_t ipl;
  92.  
  93.     ipl = waitq_sleep_prepare(wq);
  94.  
  95.     wq->missed_wakeups = 0; /* Enforce blocking. */
  96.     rc = waitq_sleep_timeout_unsafe(wq, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
  97.  
  98.     waitq_sleep_finish(wq, rc, ipl);
  99. }
  100.  
  101. /** Start of stoppable section.
  102.  *
  103.  * A stoppable section is a section of code where if the thread can be stoped. In other words,
  104.  * if a STOP operation is issued, the thread is guaranteed not to execute
  105.  * any userspace instructions until the thread is resumed.
  106.  *
  107.  * Having stoppable sections is better than having stopping points, since
  108.  * a thread can be stopped even when it is blocked indefinitely in a system
  109.  * call (whereas it would not reach any stopping point).
  110.  */
  111. void udebug_stoppable_begin(void)
  112. {
  113.     int nsc;
  114.     call_t *db_call, *go_call;
  115.  
  116.     ASSERT(THREAD);
  117.     ASSERT(TASK);
  118.  
  119.     mutex_lock(&TASK->udebug.lock);
  120.  
  121.     nsc = --TASK->udebug.not_stoppable_count;
  122.  
  123.     /* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */
  124.     mutex_lock(&THREAD->udebug.lock);
  125.     ASSERT(THREAD->udebug.stoppable == false);
  126.     THREAD->udebug.stoppable = true;
  127.  
  128.     if (TASK->udebug.dt_state == UDEBUG_TS_BEGINNING && nsc == 0) {
  129.         /*
  130.          * This was the last non-stoppable thread. Reply to
  131.          * DEBUG_BEGIN call.
  132.          */
  133.  
  134.         db_call = TASK->udebug.begin_call;
  135.         ASSERT(db_call);
  136.  
  137.         TASK->udebug.dt_state = UDEBUG_TS_ACTIVE;
  138.         TASK->udebug.begin_call = NULL;
  139.  
  140.         IPC_SET_RETVAL(db_call->data, 0);
  141.         ipc_answer(&TASK->answerbox, db_call);     
  142.  
  143.     } else if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) {
  144.         /*
  145.          * Active debugging session
  146.          */
  147.  
  148.         if (THREAD->udebug.active == true &&
  149.             THREAD->udebug.go == false) {
  150.             /*
  151.              * Thread was requested to stop - answer go call
  152.              */
  153.  
  154.             /* Make sure nobody takes this call away from us */
  155.             go_call = THREAD->udebug.go_call;
  156.             THREAD->udebug.go_call = NULL;
  157.             ASSERT(go_call);
  158.  
  159.             IPC_SET_RETVAL(go_call->data, 0);
  160.             IPC_SET_ARG1(go_call->data, UDEBUG_EVENT_STOP);
  161.  
  162.             THREAD->udebug.cur_event = UDEBUG_EVENT_STOP;
  163.  
  164.                 ipc_answer(&TASK->answerbox, go_call);
  165.         }
  166.     }
  167.  
  168.     mutex_unlock(&THREAD->udebug.lock);
  169.         mutex_unlock(&TASK->udebug.lock);
  170. }
  171.  
  172. /** End of a stoppable section.
  173.  *
  174.  * This is the point where the thread will block if it is stopped.
  175.  * (As, by definition, a stopped thread must not leave its stoppable section).
  176.  */
  177. void udebug_stoppable_end(void)
  178. {
  179. restart:
  180.     mutex_lock(&TASK->udebug.lock);
  181.     mutex_lock(&THREAD->udebug.lock);
  182.  
  183.     if (THREAD->udebug.active && THREAD->udebug.go == false) {
  184.         TASK->udebug.begin_call = NULL;
  185.         mutex_unlock(&THREAD->udebug.lock);
  186.         mutex_unlock(&TASK->udebug.lock);
  187.  
  188.         udebug_wait_for_go(&THREAD->udebug.go_wq);
  189.  
  190.         goto restart;
  191.         /* Must try again - have to lose stoppability atomically. */
  192.     } else {
  193.         ++TASK->udebug.not_stoppable_count;
  194.         ASSERT(THREAD->udebug.stoppable == true);
  195.         THREAD->udebug.stoppable = false;
  196.  
  197.         mutex_unlock(&THREAD->udebug.lock);
  198.         mutex_unlock(&TASK->udebug.lock);
  199.     }
  200. }
  201.  
  202. /** Upon being scheduled to run, check if the current thread should stop.
  203.  *
  204.  * This function is called from clock().
  205.  */
  206. void udebug_before_thread_runs(void)
  207. {
  208.     /* Check if we're supposed to stop */
  209.     udebug_stoppable_begin();
  210.     udebug_stoppable_end();
  211. }
  212.  
  213. /** Syscall event hook.
  214.  *
  215.  * Must be called before and after servicing a system call. This generates
  216.  * a SYSCALL_B or SYSCALL_E event, depending on the value of @a end_variant.
  217.  */
  218. void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3,
  219.     unative_t a4, unative_t a5, unative_t a6, unative_t id, unative_t rc,
  220.     bool end_variant)
  221. {
  222.     call_t *call;
  223.     udebug_event_t etype;
  224.  
  225.     etype = end_variant ? UDEBUG_EVENT_SYSCALL_E : UDEBUG_EVENT_SYSCALL_B;
  226.  
  227.     mutex_lock(&TASK->udebug.lock);
  228.     mutex_lock(&THREAD->udebug.lock);
  229.  
  230.     /* Must only generate events when in debugging session and is go. */
  231.     if (THREAD->udebug.active != true || THREAD->udebug.go == false ||
  232.         (TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) {
  233.         mutex_unlock(&THREAD->udebug.lock);
  234.         mutex_unlock(&TASK->udebug.lock);
  235.         return;
  236.     }
  237.  
  238.     /* Fill in the GO response. */
  239.     call = THREAD->udebug.go_call;
  240.     THREAD->udebug.go_call = NULL;
  241.  
  242.     IPC_SET_RETVAL(call->data, 0);
  243.     IPC_SET_ARG1(call->data, etype);
  244.     IPC_SET_ARG2(call->data, id);
  245.     IPC_SET_ARG3(call->data, rc);
  246.  
  247.     THREAD->udebug.syscall_args[0] = a1;
  248.     THREAD->udebug.syscall_args[1] = a2;
  249.     THREAD->udebug.syscall_args[2] = a3;
  250.     THREAD->udebug.syscall_args[3] = a4;
  251.     THREAD->udebug.syscall_args[4] = a5;
  252.     THREAD->udebug.syscall_args[5] = a6;
  253.  
  254.     /*
  255.      * Make sure udebug.go is false when going to sleep
  256.      * in case we get woken up by DEBUG_END. (At which
  257.      * point it must be back to the initial true value).
  258.      */
  259.     THREAD->udebug.go = false;
  260.     THREAD->udebug.cur_event = etype;
  261.  
  262.     ipc_answer(&TASK->answerbox, call);
  263.  
  264.     mutex_unlock(&THREAD->udebug.lock);
  265.     mutex_unlock(&TASK->udebug.lock);
  266.  
  267.     udebug_wait_for_go(&THREAD->udebug.go_wq);
  268. }
  269.  
  270. /** Thread-creation event hook combined with attaching the thread.
  271.  *
  272.  * Must be called when a new userspace thread is created in the debugged
  273.  * task. Generates a THREAD_B event. Also attaches the thread @a t
  274.  * to the task @a ta.
  275.  *
  276.  * This is necessary to avoid a race condition where the BEGIN and THREAD_READ
  277.  * requests would be handled inbetween attaching the thread and checking it
  278.  * for being in a debugging session to send the THREAD_B event. We could then
  279.  * either miss threads or get some threads both in the thread list
  280.  * and get a THREAD_B event for them.
  281.  *
  282.  * @param t Structure of the thread being created. Not locked, as the
  283.  *      thread is not executing yet.
  284.  * @param ta    Task to which the thread should be attached.
  285.  */
  286. void udebug_thread_b_event_attach(struct thread *t, struct task *ta)
  287. {
  288.     call_t *call;
  289.  
  290.     mutex_lock(&TASK->udebug.lock);
  291.     mutex_lock(&THREAD->udebug.lock);
  292.  
  293.     thread_attach(t, ta);
  294.  
  295.     LOG("Check state");
  296.  
  297.     /* Must only generate events when in debugging session */
  298.     if (THREAD->udebug.active != true) {
  299.         LOG("udebug.active: %s, udebug.go: %s",
  300.             THREAD->udebug.active ? "Yes(+)" : "No",
  301.             THREAD->udebug.go ? "Yes(-)" : "No");
  302.         mutex_unlock(&THREAD->udebug.lock);
  303.         mutex_unlock(&TASK->udebug.lock);
  304.         return;
  305.     }
  306.  
  307.     LOG("Trigger event");
  308.     call = THREAD->udebug.go_call;
  309.     THREAD->udebug.go_call = NULL;
  310.     IPC_SET_RETVAL(call->data, 0);
  311.     IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_B);
  312.     IPC_SET_ARG2(call->data, (unative_t)t);
  313.  
  314.     /*
  315.      * Make sure udebug.go is false when going to sleep
  316.      * in case we get woken up by DEBUG_END. (At which
  317.      * point it must be back to the initial true value).
  318.      */
  319.     THREAD->udebug.go = false;
  320.     THREAD->udebug.cur_event = UDEBUG_EVENT_THREAD_B;
  321.  
  322.     ipc_answer(&TASK->answerbox, call);
  323.  
  324.     mutex_unlock(&THREAD->udebug.lock);
  325.     mutex_unlock(&TASK->udebug.lock);
  326.  
  327.     LOG("Wait for Go");
  328.     udebug_wait_for_go(&THREAD->udebug.go_wq);
  329. }
  330.  
  331. /** Thread-termination event hook.
  332.  *
  333.  * Must be called when the current thread is terminating.
  334.  * Generates a THREAD_E event.
  335.  */
  336. void udebug_thread_e_event(void)
  337. {
  338.     call_t *call;
  339.  
  340.     mutex_lock(&TASK->udebug.lock);
  341.     mutex_lock(&THREAD->udebug.lock);
  342.  
  343.     LOG("Check state");
  344.  
  345.     /* Must only generate events when in debugging session. */
  346.     if (THREAD->udebug.active != true) {
  347.         LOG("udebug.active: %s, udebug.go: %s",
  348.             THREAD->udebug.active ? "Yes" : "No",
  349.             THREAD->udebug.go ? "Yes" : "No");
  350.         mutex_unlock(&THREAD->udebug.lock);
  351.         mutex_unlock(&TASK->udebug.lock);
  352.         return;
  353.     }
  354.  
  355.     LOG("Trigger event");
  356.     call = THREAD->udebug.go_call;
  357.     THREAD->udebug.go_call = NULL;
  358.     IPC_SET_RETVAL(call->data, 0);
  359.     IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E);
  360.  
  361.     /* Prevent any further debug activity in thread. */
  362.     THREAD->udebug.active = false;
  363.     THREAD->udebug.cur_event = 0;       /* none */
  364.     THREAD->udebug.go = false;  /* set to initial value */
  365.  
  366.     ipc_answer(&TASK->answerbox, call);
  367.  
  368.     mutex_unlock(&THREAD->udebug.lock);
  369.     mutex_unlock(&TASK->udebug.lock);
  370.  
  371.     /*
  372.      * This event does not sleep - debugging has finished
  373.      * in this thread.
  374.      */
  375. }
  376.  
  377. /**
  378.  * Terminate task debugging session.
  379.  *
  380.  * Gracefully terminates the debugging session for a task. If the debugger
  381.  * is still waiting for events on some threads, it will receive a
  382.  * FINISHED event for each of them.
  383.  *
  384.  * @param ta    Task structure. ta->udebug.lock must be already locked.
  385.  * @return  Zero on success or negative error code.
  386.  */
  387. int udebug_task_cleanup(struct task *ta)
  388. {
  389.     thread_t *t;
  390.     link_t *cur;
  391.     int flags;
  392.     ipl_t ipl;
  393.  
  394.     if (ta->udebug.dt_state != UDEBUG_TS_BEGINNING &&
  395.         ta->udebug.dt_state != UDEBUG_TS_ACTIVE) {
  396.         return EINVAL;
  397.     }
  398.  
  399.     LOG("Task %" PRIu64, ta->taskid);
  400.  
  401.     /* Finish debugging of all userspace threads */
  402.     for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
  403.         t = list_get_instance(cur, thread_t, th_link);
  404.  
  405.         mutex_lock(&t->udebug.lock);
  406.  
  407.         ipl = interrupts_disable();
  408.         spinlock_lock(&t->lock);
  409.  
  410.         flags = t->flags;
  411.  
  412.         spinlock_unlock(&t->lock);
  413.         interrupts_restore(ipl);
  414.  
  415.         /* Only process userspace threads. */
  416.         if ((flags & THREAD_FLAG_USPACE) != 0) {
  417.             /* Prevent any further debug activity in thread. */
  418.             t->udebug.active = false;
  419.             t->udebug.cur_event = 0;    /* none */
  420.  
  421.             /* Is the thread still go? */
  422.             if (t->udebug.go == true) {
  423.                 /*
  424.                 * Yes, so clear go. As active == false,
  425.                  * this doesn't affect anything.
  426.                  */
  427.                 t->udebug.go = false;  
  428.  
  429.                 /* Answer GO call */
  430.                 LOG("Answer GO call with EVENT_FINISHED.");
  431.                 IPC_SET_RETVAL(t->udebug.go_call->data, 0);
  432.                 IPC_SET_ARG1(t->udebug.go_call->data,
  433.                     UDEBUG_EVENT_FINISHED);
  434.  
  435.                 ipc_answer(&ta->answerbox, t->udebug.go_call);
  436.                 t->udebug.go_call = NULL;
  437.             } else {
  438.                 /*
  439.                  * Debug_stop is already at initial value.
  440.                  * Yet this means the thread needs waking up.
  441.                  */
  442.  
  443.                 /*
  444.                  * t's lock must not be held when calling
  445.                  * waitq_wakeup.
  446.                  */
  447.                 waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST);
  448.             }
  449.         }
  450.         mutex_unlock(&t->udebug.lock);
  451.     }
  452.  
  453.     ta->udebug.dt_state = UDEBUG_TS_INACTIVE;
  454.     ta->udebug.debugger = NULL;
  455.  
  456.     return 0;
  457. }
  458.  
  459.  
  460. /** @}
  461.  */
  462.