Subversion Repositories HelenOS

Rev

Rev 3428 | Rev 3606 | 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 hooks and data structure management.
  36.  *
  37.  * Udebug is an interface that makes userspace debuggers possible.
  38.  *
  39.  * Functions in this file are executed directly in each thread, which
  40.  * may or may not be the subject of debugging. The udebug_stoppable_begin/end()
  41.  * functions are also executed in the clock interrupt handler. To avoid
  42.  * deadlock, functions in this file are protected from the interrupt
  43.  * by locking the recursive lock THREAD->udebug.int_lock (just an atomic
  44.  * variable). This prevents udebug_stoppable_begin/end() from being
  45.  * executed in the interrupt handler (they are skipped).
  46.  *
  47.  * Functions in udebug_ops.c and udebug_ipc.c execute in different threads,
  48.  * so they needn't be protected from the (preemptible) interrupt-initiated
  49.  * code.
  50.  */
  51.  
  52. #include <synch/waitq.h>
  53. #include <debug.h>
  54. #include <udebug/udebug.h>
  55. #include <errno.h>
  56. #include <arch.h>
  57.  
  58. static inline void udebug_int_lock(void)
  59. {
  60.     atomic_inc(&THREAD->udebug.int_lock);
  61. }
  62.  
  63. static inline void udebug_int_unlock(void)
  64. {
  65.     atomic_dec(&THREAD->udebug.int_lock);
  66. }
  67.  
  68. /** Initialize udebug part of task structure.
  69.  *
  70.  * Called as part of task structure initialization.
  71.  * @param ut    Pointer to the structure to initialize.
  72.  */
  73. void udebug_task_init(udebug_task_t *ut)
  74. {
  75.     mutex_initialize(&ut->lock, MUTEX_PASSIVE);
  76.     ut->dt_state = UDEBUG_TS_INACTIVE;
  77.     ut->begin_call = NULL;
  78.     ut->not_stoppable_count = 0;
  79.     ut->evmask = 0;
  80. }
  81.  
  82. /** Initialize udebug part of thread structure.
  83.  *
  84.  * Called as part of thread structure initialization.
  85.  * @param ut    Pointer to the structure to initialize.
  86.  */
  87. void udebug_thread_initialize(udebug_thread_t *ut)
  88. {
  89.     mutex_initialize(&ut->lock, MUTEX_PASSIVE);
  90.     waitq_initialize(&ut->go_wq);
  91.  
  92.     /*
  93.      * At the beginning the thread is stoppable, so int_lock be set, too.
  94.      */
  95.     atomic_set(&ut->int_lock, 1);
  96.  
  97.     ut->go_call = NULL;
  98.     ut->uspace_state = NULL;
  99.     ut->stop = true;
  100.     ut->stoppable = true;
  101.     ut->debug_active = false;
  102.     ut->cur_event = 0; /* none */
  103. }
  104.  
  105. /** Wait for a GO message.
  106.  *
  107.  * When a debugging event occurs in a thread or the thread is stopped,
  108.  * this function is called to block the thread until a GO message
  109.  * is received.
  110.  *
  111.  * @param wq    The wait queue used by the thread to wait for GO messages.
  112.  */
  113. static void udebug_wait_for_go(waitq_t *wq)
  114. {
  115.     int rc;
  116.     ipl_t ipl;
  117.  
  118.     ipl = waitq_sleep_prepare(wq);
  119.  
  120.     wq->missed_wakeups = 0; /* Enforce blocking. */
  121.     rc = waitq_sleep_timeout_unsafe(wq, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE);
  122.  
  123.     waitq_sleep_finish(wq, rc, ipl);
  124. }
  125.  
  126. /** Do a preliminary check that a debugging session is in progress.
  127.  *
  128.  * This only requires the THREAD->udebug.lock mutex (and not TASK->udebug.lock
  129.  * mutex). For an undebugged task, this will never block (while there could be
  130.  * collisions by different threads on the TASK mutex), thus improving SMP
  131.  * perormance for undebugged tasks.
  132.  *
  133.  * @return  True if the thread was in a debugging session when the function
  134.  *      checked, false otherwise.
  135.  */
  136. static bool udebug_thread_precheck(void)
  137. {
  138.     bool res;
  139.  
  140.     mutex_lock(&THREAD->udebug.lock);
  141.     res = THREAD->udebug.debug_active;
  142.     mutex_unlock(&THREAD->udebug.lock);
  143.  
  144.     return res;
  145. }
  146.  
  147. /** Start of stoppable section.
  148.  *
  149.  * A stoppable section is a section of code where if the thread can be stoped. In other words,
  150.  * if a STOP operation is issued, the thread is guaranteed not to execute
  151.  * any userspace instructions until the thread is resumed.
  152.  *
  153.  * Having stoppable sections is better than having stopping points, since
  154.  * a thread can be stopped even when it is blocked indefinitely in a system
  155.  * call (whereas it would not reach any stopping point).
  156.  */
  157. void udebug_stoppable_begin(void)
  158. {
  159.     int nsc;
  160.     call_t *db_call, *go_call;
  161.  
  162.     ASSERT(THREAD);
  163.     ASSERT(TASK);
  164.  
  165.     udebug_int_lock();
  166.  
  167.     /* Early check for undebugged tasks */
  168.     if (!udebug_thread_precheck()) {
  169.         udebug_int_unlock();
  170.         return;
  171.     }
  172.  
  173.     mutex_lock(&TASK->udebug.lock);
  174.  
  175.     nsc = --TASK->udebug.not_stoppable_count;
  176.  
  177.     /* Lock order OK, THREAD->udebug.lock is after TASK->udebug.lock */
  178.     mutex_lock(&THREAD->udebug.lock);
  179.     ASSERT(THREAD->udebug.stoppable == false);
  180.     THREAD->udebug.stoppable = true;
  181.  
  182.     if (TASK->udebug.dt_state == UDEBUG_TS_BEGINNING && nsc == 0) {
  183.         /*
  184.          * This was the last non-stoppable thread. Reply to
  185.          * DEBUG_BEGIN call.
  186.          */
  187.  
  188.         db_call = TASK->udebug.begin_call;
  189.         ASSERT(db_call);
  190.  
  191.         TASK->udebug.dt_state = UDEBUG_TS_ACTIVE;
  192.         TASK->udebug.begin_call = NULL;
  193.  
  194.         IPC_SET_RETVAL(db_call->data, 0);
  195.         ipc_answer(&TASK->answerbox, db_call);     
  196.  
  197.     } else if (TASK->udebug.dt_state == UDEBUG_TS_ACTIVE) {
  198.         /*
  199.          * Active debugging session
  200.          */
  201.  
  202.         if (THREAD->udebug.debug_active && THREAD->udebug.stop) {
  203.             /*
  204.              * Thread was requested to stop - answer go call
  205.              */
  206.  
  207.             /* Make sure nobody takes this call away from us */
  208.             go_call = THREAD->udebug.go_call;
  209.             THREAD->udebug.go_call = NULL;
  210.             ASSERT(go_call);
  211.  
  212.             IPC_SET_RETVAL(go_call->data, 0);
  213.             IPC_SET_ARG1(go_call->data, UDEBUG_EVENT_STOP);
  214.  
  215.             THREAD->udebug.cur_event = UDEBUG_EVENT_STOP;
  216.  
  217.                 ipc_answer(&TASK->answerbox, go_call);
  218.         }
  219.     }
  220.  
  221.     mutex_unlock(&THREAD->udebug.lock);
  222.         mutex_unlock(&TASK->udebug.lock);
  223. }
  224.  
  225. /** End of a stoppable section.
  226.  *
  227.  * This is the point where the thread will block if it is stopped.
  228.  * (As, by definition, a stopped thread must not leave its stoppable section).
  229.  */
  230. void udebug_stoppable_end(void)
  231. {
  232.     /* Early check for undebugged tasks */
  233.     if (!udebug_thread_precheck()) {
  234.         udebug_int_unlock();
  235.         return;
  236.     }
  237.  
  238. restart:
  239.     mutex_lock(&TASK->udebug.lock);
  240.     mutex_lock(&THREAD->udebug.lock);
  241.  
  242.     if (THREAD->udebug.debug_active &&
  243.         THREAD->udebug.stop == true) {
  244.         TASK->udebug.begin_call = NULL;
  245.         mutex_unlock(&THREAD->udebug.lock);
  246.         mutex_unlock(&TASK->udebug.lock);
  247.  
  248.         udebug_wait_for_go(&THREAD->udebug.go_wq);
  249.  
  250.         goto restart;
  251.         /* must try again - have to lose stoppability atomically */
  252.     } else {
  253.         ++TASK->udebug.not_stoppable_count;
  254.         ASSERT(THREAD->udebug.stoppable == true);
  255.         THREAD->udebug.stoppable = false;
  256.  
  257.         mutex_unlock(&THREAD->udebug.lock);
  258.         mutex_unlock(&TASK->udebug.lock);
  259.     }
  260.  
  261.     udebug_int_unlock();
  262. }
  263.  
  264. /** Upon being scheduled to run, check if the current thread should stop.
  265.  *
  266.  * This function is called from clock(). Preemption is enabled.
  267.  * interrupts are disabled, but since this is called after
  268.  * being scheduled-in, we can enable them, if we're careful enough
  269.  * not to allow arbitrary recursion or deadlock with the thread context.
  270.  */
  271. void udebug_before_thread_runs(void)
  272. {
  273.     ipl_t ipl;
  274.  
  275.     return;
  276.     ASSERT(!PREEMPTION_DISABLED);
  277.  
  278.     /*
  279.      * Prevent agains re-entering, such as when preempted inside this
  280.      * function.
  281.      */
  282.     if (atomic_get(&THREAD->udebug.int_lock) != 0)
  283.         return;
  284.  
  285.     udebug_int_lock();
  286.  
  287.     ipl = interrupts_enable();
  288.  
  289.     /* Now we're free to do whatever we need (lock mutexes, sleep, etc.) */
  290.  
  291.     /* Check if we're supposed to stop */
  292.     udebug_stoppable_begin();
  293.     udebug_stoppable_end();
  294.  
  295.     interrupts_restore(ipl);
  296.  
  297.     udebug_int_unlock();
  298. }
  299.  
  300. /** Syscall event hook.
  301.  *
  302.  * Must be called before and after servicing a system call. This generates
  303.  * a SYSCALL_B or SYSCALL_E event, depending on the value of @a end_variant.
  304.  */
  305. void udebug_syscall_event(unative_t a1, unative_t a2, unative_t a3,
  306.     unative_t a4, unative_t a5, unative_t a6, unative_t id, unative_t rc,
  307.     bool end_variant)
  308. {
  309.     call_t *call;
  310.     udebug_event_t etype;
  311.  
  312.     etype = end_variant ? UDEBUG_EVENT_SYSCALL_E : UDEBUG_EVENT_SYSCALL_B;
  313.  
  314.     udebug_int_lock();
  315.  
  316.     /* Early check for undebugged tasks */
  317.     if (!udebug_thread_precheck()) {
  318.         udebug_int_unlock();
  319.         return;
  320.     }
  321.  
  322.     mutex_lock(&TASK->udebug.lock);
  323.     mutex_lock(&THREAD->udebug.lock);
  324.  
  325.     /* Must only generate events when in debugging session and have go */
  326.     if (THREAD->udebug.debug_active != true ||
  327.         THREAD->udebug.stop == true ||
  328.         (TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) {
  329.         mutex_unlock(&THREAD->udebug.lock);
  330.         mutex_unlock(&TASK->udebug.lock);
  331.         return;
  332.     }
  333.  
  334.     //printf("udebug_syscall_event\n");
  335.     call = THREAD->udebug.go_call;
  336.     THREAD->udebug.go_call = NULL;
  337.  
  338.     IPC_SET_RETVAL(call->data, 0);
  339.     IPC_SET_ARG1(call->data, etype);
  340.     IPC_SET_ARG2(call->data, id);
  341.     IPC_SET_ARG3(call->data, rc);
  342.     //printf("udebug_syscall_event/ipc_answer\n");
  343.  
  344.     THREAD->udebug.syscall_args[0] = a1;
  345.     THREAD->udebug.syscall_args[1] = a2;
  346.     THREAD->udebug.syscall_args[2] = a3;
  347.     THREAD->udebug.syscall_args[3] = a4;
  348.     THREAD->udebug.syscall_args[4] = a5;
  349.     THREAD->udebug.syscall_args[5] = a6;
  350.  
  351.     /*
  352.      * Make sure udebug.stop is true when going to sleep
  353.      * in case we get woken up by DEBUG_END. (At which
  354.      * point it must be back to the initial true value).
  355.      */
  356.     THREAD->udebug.stop = true;
  357.     THREAD->udebug.cur_event = etype;
  358.  
  359.     ipc_answer(&TASK->answerbox, call);
  360.  
  361.     mutex_unlock(&THREAD->udebug.lock);
  362.     mutex_unlock(&TASK->udebug.lock);
  363.  
  364.     udebug_wait_for_go(&THREAD->udebug.go_wq);
  365.  
  366.     udebug_int_unlock();
  367. }
  368.  
  369. /** Thread-creation event hook.
  370.  *
  371.  * Must be called when a new userspace thread is created in the debugged
  372.  * task. Generates a THREAD_B event.
  373.  *
  374.  * @param t Structure of the thread being created. Not locked, as the
  375.  *      thread is not executing yet.
  376.  */
  377. void udebug_thread_b_event(struct thread *t)
  378. {
  379.     call_t *call;
  380.  
  381.     udebug_int_lock();
  382.  
  383.     mutex_lock(&TASK->udebug.lock);
  384.     mutex_lock(&THREAD->udebug.lock);
  385.  
  386.     LOG("udebug_thread_b_event\n");
  387.     LOG("- check state\n");
  388.  
  389.     /* Must only generate events when in debugging session */
  390.     if (THREAD->udebug.debug_active != true) {
  391.         LOG("- debug_active: %s, udebug.stop: %s\n",
  392.             THREAD->udebug.debug_active ? "yes(+)" : "no(-)",
  393.             THREAD->udebug.stop ? "yes(-)" : "no(+)");
  394.         mutex_unlock(&THREAD->udebug.lock);
  395.         mutex_unlock(&TASK->udebug.lock);
  396.         return;
  397.     }
  398.  
  399.     LOG("- trigger event\n");
  400.  
  401.     call = THREAD->udebug.go_call;
  402.     THREAD->udebug.go_call = NULL;
  403.     IPC_SET_RETVAL(call->data, 0);
  404.     IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_B);
  405.     IPC_SET_ARG2(call->data, (unative_t)t);
  406.  
  407.     /*
  408.      * Make sure udebug.stop is true when going to sleep
  409.      * in case we get woken up by DEBUG_END. (At which
  410.      * point it must be back to the initial true value).
  411.      */
  412.     THREAD->udebug.stop = true;
  413.     THREAD->udebug.cur_event = UDEBUG_EVENT_THREAD_B;
  414.  
  415.     ipc_answer(&TASK->answerbox, call);
  416.  
  417.     mutex_unlock(&THREAD->udebug.lock);
  418.     mutex_unlock(&TASK->udebug.lock);
  419.  
  420.     LOG("- sleep\n");
  421.     udebug_wait_for_go(&THREAD->udebug.go_wq);
  422.  
  423.     udebug_int_unlock();
  424. }
  425.  
  426. /** Thread-termination event hook.
  427.  *
  428.  * Must be called when the current thread is terminating.
  429.  * Generates a THREAD_E event.
  430.  */
  431. void udebug_thread_e_event(void)
  432. {
  433.     call_t *call;
  434.  
  435.     udebug_int_lock();
  436.  
  437.     mutex_lock(&TASK->udebug.lock);
  438.     mutex_lock(&THREAD->udebug.lock);
  439.  
  440.     LOG("udebug_thread_e_event\n");
  441.     LOG("- check state\n");
  442.  
  443.     /* Must only generate events when in debugging session */
  444.     if (THREAD->udebug.debug_active != true) {
  445. /*      printf("- debug_active: %s, udebug.stop: %s\n",
  446.             THREAD->udebug.debug_active ? "yes(+)" : "no(-)",
  447.             THREAD->udebug.stop ? "yes(-)" : "no(+)");*/
  448.         mutex_unlock(&THREAD->udebug.lock);
  449.         mutex_unlock(&TASK->udebug.lock);
  450.         return;
  451.     }
  452.  
  453.     LOG("- trigger event\n");
  454.  
  455.     call = THREAD->udebug.go_call;
  456.     THREAD->udebug.go_call = NULL;
  457.     IPC_SET_RETVAL(call->data, 0);
  458.     IPC_SET_ARG1(call->data, UDEBUG_EVENT_THREAD_E);
  459.  
  460.     /* Prevent any further debug activity in thread */
  461.     THREAD->udebug.debug_active = false;
  462.     THREAD->udebug.cur_event = 0;       /* none */
  463.     THREAD->udebug.stop = true; /* set to initial value */
  464.  
  465.     ipc_answer(&TASK->answerbox, call);
  466.  
  467.     mutex_unlock(&THREAD->udebug.lock);
  468.     mutex_unlock(&TASK->udebug.lock);
  469.  
  470.     /* Leave int_lock enabled */
  471.     /* This event does not sleep - debugging has finished in this thread */
  472. }
  473.  
  474. static void breakpoint_trap_event(uintptr_t addr, udebug_event_t etype)
  475. {
  476.     call_t *call;
  477.  
  478.     udebug_int_lock();
  479.  
  480.     mutex_lock(&TASK->udebug.lock);
  481.     mutex_lock(&THREAD->udebug.lock);
  482.  
  483.     /* Must only generate events when in debugging session and have go */
  484.     if (THREAD->udebug.debug_active != true ||
  485.         THREAD->udebug.stop == true) {
  486.         mutex_unlock(&THREAD->udebug.lock);
  487.         mutex_unlock(&TASK->udebug.lock);
  488.         udebug_int_unlock();
  489.         return;
  490.     }
  491.  
  492.     /* Verify that the event is enabled */
  493.     if ((TASK->udebug.evmask & UDEBUG_EVMASK(etype)) == 0) {
  494.         mutex_unlock(&THREAD->udebug.lock);
  495.         mutex_unlock(&TASK->udebug.lock);
  496.         udebug_int_unlock();
  497.         return;
  498.     }
  499.  
  500.     printf("udebug_breakpoint/trap_event\n");
  501.     call = THREAD->udebug.go_call;
  502.     THREAD->udebug.go_call = NULL;
  503.  
  504.     IPC_SET_RETVAL(call->data, 0);
  505.     IPC_SET_ARG1(call->data, etype);
  506.     IPC_SET_ARG2(call->data, addr);
  507.  
  508.     /*
  509.      * Make sure udebug.stop is true when going to sleep
  510.      * in case we get woken up by DEBUG_END. (At which
  511.      * point it must be back to the initial true value).
  512.      */
  513.     THREAD->udebug.stop = true;
  514.     THREAD->udebug.cur_event = etype;
  515.  
  516.     printf("- send answer\n");
  517.     ipc_answer(&TASK->answerbox, call);
  518.  
  519.     mutex_unlock(&THREAD->udebug.lock);
  520.     mutex_unlock(&TASK->udebug.lock);
  521.  
  522.     udebug_wait_for_go(&THREAD->udebug.go_wq);
  523.  
  524.     udebug_int_unlock();
  525. }
  526.  
  527. void udebug_breakpoint_event(uintptr_t addr)
  528. {
  529.     breakpoint_trap_event(addr, UDEBUG_EVENT_BREAKPOINT);
  530. }
  531.  
  532. void udebug_trap_event(uintptr_t addr)
  533. {
  534.     breakpoint_trap_event(addr, UDEBUG_EVENT_TRAP);
  535. }
  536.  
  537. /**
  538.  * Terminate task debugging session.
  539.  *
  540.  * Gracefully terminates the debugging session for a task. If the debugger
  541.  * is still waiting for events on some threads, it will receive a
  542.  * FINISHED event for each of them.
  543.  *
  544.  * @param ta    Task structure. ta->udebug.lock must be already locked.
  545.  * @return  Zero on success or negative error code.
  546.  */
  547. int udebug_task_cleanup(struct task *ta)
  548. {
  549.     thread_t *t;
  550.     link_t *cur;
  551.     int flags;
  552.     ipl_t ipl;
  553.  
  554.     LOG("udebug_task_cleanup()\n");
  555.     LOG("task %" PRIu64 "\n", ta->taskid);
  556.  
  557.     udebug_int_lock();
  558.  
  559.     if (ta->udebug.dt_state != UDEBUG_TS_BEGINNING &&
  560.         ta->udebug.dt_state != UDEBUG_TS_ACTIVE) {
  561.         LOG("udebug_task_cleanup(): task not being debugged\n");
  562.         return EINVAL;
  563.     }
  564.  
  565.     /* Finish debugging of all userspace threads */
  566.     for (cur = ta->th_head.next; cur != &ta->th_head; cur = cur->next) {
  567.         t = list_get_instance(cur, thread_t, th_link);
  568.  
  569.         mutex_lock(&t->udebug.lock);
  570.  
  571.         ipl = interrupts_disable();
  572.         spinlock_lock(&t->lock);
  573.  
  574.         flags = t->flags;
  575.  
  576.         spinlock_unlock(&t->lock);
  577.         interrupts_restore(ipl);
  578.  
  579.         /* Only process userspace threads */
  580.         if ((flags & THREAD_FLAG_USPACE) != 0) {
  581.             /* Prevent any further debug activity in thread */
  582.             t->udebug.debug_active = false;
  583.             t->udebug.cur_event = 0;    /* none */
  584.  
  585.             /* Still has go? */
  586.             if (t->udebug.stop == false) {
  587.                 /*
  588.                 * Yes, so clear go. As debug_active == false,
  589.                  * this doesn't affect anything.
  590.                  */
  591.                 t->udebug.stop = true; 
  592.  
  593.                 /* Answer GO call */
  594.                 LOG("answer GO call with EVENT_FINISHED\n");
  595.                 IPC_SET_RETVAL(t->udebug.go_call->data, 0);
  596.                 IPC_SET_ARG1(t->udebug.go_call->data,
  597.                     UDEBUG_EVENT_FINISHED);
  598.  
  599.                 ipc_answer(&ta->answerbox, t->udebug.go_call);
  600.                 t->udebug.go_call = NULL;
  601.             } else {
  602.                 /*
  603.                  * Debug_stop is already at initial value.
  604.                  * Yet this means the thread needs waking up.
  605.                  */
  606.  
  607.                 /*
  608.                  * t's lock must not be held when calling
  609.                  * waitq_wakeup.
  610.                  */
  611.                 waitq_wakeup(&t->udebug.go_wq, WAKEUP_FIRST);
  612.             }
  613.         }
  614.         mutex_unlock(&t->udebug.lock);
  615.     }
  616.  
  617.     ta->udebug.dt_state = UDEBUG_TS_INACTIVE;
  618.     ta->udebug.debugger = NULL;
  619.  
  620.     udebug_int_unlock();
  621.  
  622.     return 0;
  623. }
  624.  
  625.  
  626. /** @}
  627.  */
  628.