From owner-p4-projects@FreeBSD.ORG Thu Apr 7 09:31:18 2005 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id ACA3A16A4D0; Thu, 7 Apr 2005 09:31:17 +0000 (GMT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 6469816A4CE for ; Thu, 7 Apr 2005 09:31:17 +0000 (GMT) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2738343D2F for ; Thu, 7 Apr 2005 09:31:17 +0000 (GMT) (envelope-from davidxu@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id j379VHD2033001 for ; Thu, 7 Apr 2005 09:31:17 GMT (envelope-from davidxu@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id j379VGg2032997 for perforce@freebsd.org; Thu, 7 Apr 2005 09:31:16 GMT (envelope-from davidxu@freebsd.org) Date: Thu, 7 Apr 2005 09:31:16 GMT Message-Id: <200504070931.j379VGg2032997@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to davidxu@freebsd.org using -f From: David Xu To: Perforce Change Reviews Subject: PERFORCE change 74657 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Apr 2005 09:31:18 -0000 http://perforce.freebsd.org/chv.cgi?CH=74657 Change 74657 by davidxu@davidxu_celeron on 2005/04/07 09:30:51 Add event reporting code. Affected files ... .. //depot/projects/davidxu_thread/src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c#5 edit Differences ... ==== //depot/projects/davidxu_thread/src/gnu/usr.bin/gdb/libgdb/fbsd-threads.c#5 (text+ko) ==== @@ -130,6 +130,11 @@ static td_err_e (*td_thr_dbsuspend_p) (const td_thrhandle_t *); static td_err_e (*td_thr_dbresume_p) (const td_thrhandle_t *); +static CORE_ADDR td_create_bp_addr; + +/* Location of the thread death event breakpoint. */ +static CORE_ADDR td_death_bp_addr; + /* Prototypes for local functions. */ static void fbsd_thread_find_new_threads (void); static int fbsd_thread_alive (ptid_t ptid); @@ -319,7 +324,99 @@ init_thread_list (); } +static td_err_e +enable_thread_event (td_thragent_t *thread_agent, int event, CORE_ADDR *bp) +{ + td_notify_t notify; + td_err_e err; + + /* Get the breakpoint address for thread EVENT. */ + err = td_ta_event_addr_p (thread_agent, event, ¬ify); + if (err != TD_OK) + return err; + + /* Set up the breakpoint. */ + (*bp) = gdbarch_convert_from_func_ptr_addr (current_gdbarch, + (CORE_ADDR) notify.u.bptaddr, + ¤t_target); + create_thread_event_breakpoint ((*bp)); + + return TD_OK; +} + +static void +enable_thread_event_reporting (void) +{ + td_thr_events_t events; + td_notify_t notify; + td_err_e err; + + /* We cannot use the thread event reporting facility if these + functions aren't available. */ + if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL + || td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL) + return; + + /* Set the process wide mask saying which events we're interested in. */ + td_event_emptyset (&events); + td_event_addset (&events, TD_CREATE); +#if 0 + /* FIXME: kettenis/2000-04-23: The event reporting facility is + broken for TD_DEATH events in glibc 2.1.3, so don't enable it for + now. */ + td_event_addset (&events, TD_DEATH); +#endif + + err = td_ta_set_event_p (thread_agent, &events); + if (err != TD_OK) + { + warning ("Unable to set global thread event mask: %s", + thread_db_err_str (err)); + return; + } + + /* Delete previous thread event breakpoints, if any. */ + remove_thread_event_breakpoints (); + td_create_bp_addr = 0; + td_death_bp_addr = 0; + + /* Set up the thread creation event. */ + err = enable_thread_event (thread_agent, TD_CREATE, &td_create_bp_addr); + if (err != TD_OK) + { + warning ("Unable to get location for thread creation breakpoint: %s", + thread_db_err_str (err)); + return; + } + + /* Set up the thread death event. */ + err = enable_thread_event (thread_agent, TD_DEATH, &td_death_bp_addr); + if (err != TD_OK) + { + warning ("Unable to get location for thread death breakpoint: %s", + thread_db_err_str (err)); + return; + } +} + static void +disable_thread_event_reporting (void) +{ + td_thr_events_t events; + + /* Set the process wide mask saying we aren't interested in any + events anymore. */ + td_event_emptyset (&events); + td_ta_set_event_p (thread_agent, &events); + + /* Delete thread event breakpoints, if any. */ + remove_thread_event_breakpoints (); + td_create_bp_addr = 0; + td_death_bp_addr = 0; +} + + +static void fbsd_thread_new_objfile (struct objfile *objfile) { td_err_e err; @@ -544,6 +641,85 @@ perror_with_name ("PT_CONTINUE"); } +static void +attach_thread (ptid_t ptid, const td_thrhandle_t *th_p, + const td_thrinfo_t *ti_p, int verbose) +{ + td_err_e err; + + /* Add the thread to GDB's thread list. */ + add_thread (ptid); + + if (verbose) + printf_unfiltered ("[New %s]\n", target_pid_to_str (ptid)); + + if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE) + return; /* A zombie thread -- do not attach. */ + + /* Enable thread event reporting for this thread. */ + err = td_thr_event_enable_p (th_p, 1); + if (err != TD_OK) + error ("Cannot enable thread event reporting for %s: %s", + target_pid_to_str (ptid), thread_db_err_str (err)); +} + +static void +detach_thread (ptid_t ptid, int verbose) +{ + if (verbose) + printf_unfiltered ("[%s exited]\n", target_pid_to_str (ptid)); +} + +static void +check_event (ptid_t ptid) +{ + td_event_msg_t msg; + td_thrinfo_t ti; + td_err_e err; + CORE_ADDR stop_pc; + int loop = 0; + + /* Bail out early if we're not at a thread event breakpoint. */ + stop_pc = read_pc_pid (ptid) - DECR_PC_AFTER_BREAK; + if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr) + return; + + loop = 1; + + do + { + err = td_ta_event_getmsg_p (thread_agent, &msg); + if (err != TD_OK) + { + if (err == TD_NOMSG) + return; + error ("Cannot get thread event message: %s", thread_db_err_str (err)); + } + err = td_thr_get_info_p (msg.th_p, &ti); + if (err != TD_OK) + error ("Cannot get thread info: %s", thread_db_err_str (err)); + ptid = BUILD_THREAD (ti.ti_tid, GET_PID (ptid)); + switch (msg.event) + { + case TD_CREATE: + /* We may already know about this thread, for instance when the + user has issued the `info threads' command before the SIGTRAP + for hitting the thread creation breakpoint was reported. */ + if (!in_thread_list (ptid)) + attach_thread (ptid, msg.th_p, &ti, 1); + break; + case TD_DEATH: + if (!in_thread_list (ptid)) + error ("Spurious thread death event."); + detach_thread (ptid, 1); + break; + default: + error ("Spurious thread event."); + } + } + while (loop); +} + static ptid_t fbsd_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus) { @@ -554,6 +730,8 @@ ret = child_ops.to_wait (ptid, ourstatus); if (GET_PID(ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED) { + if (ourstatus->value.sig == TARGET_SIGNAL_TRAP) + check_event(ptid); lwp = get_current_lwp (GET_PID(ret)); ret = thread_from_lwp (BUILD_LWP (lwp, GET_PID (ret))); if (!in_thread_list (ret)) @@ -567,7 +745,7 @@ { delete_thread (inferior_ptid); inferior_ptid = ret; - } + } } return (ret); @@ -1180,6 +1358,13 @@ return 0; } + /* These are not essential. */ + td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr"); + td_ta_set_event_p = dlsym (handle, "td_ta_set_event"); + td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg"); + td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable"); + td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr"); + return 1; }