2 /* Low level interface for debugging FreeBSD user threads for GDB, the GNU debugger.
3 Copyright 1996, 1999 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 /* This module implements a sort of half target that sits between the
22 machine-independent parts of GDB and the ptrace interface (infptrace.c) to
23 provide access to the FreeBSD user-mode thread implementation.
25 FreeBSD threads are true user-mode threads, which are invoked via
26 the pthread_* interfaces. These are mostly implemented in
27 user-space, with all thread context kept in various structures that
28 live in the user's heap. For the most part, the kernel has no
29 knowlege of these threads.
31 Based largely on hpux-thread.c
37 #include <sys/queue.h>
40 #include "gdbthread.h"
48 extern int child_suppress_run;
49 extern struct target_ops child_ops; /* target vector for inftarg.c */
51 extern void _initialize_freebsd_uthread PARAMS ((void));
53 static int main_pid = -1; /* Real process ID */
55 /* Set to true while we are part-way through attaching */
56 static int freebsd_uthread_attaching;
58 static int freebsd_uthread_active = 0;
59 static CORE_ADDR P_thread_list;
60 static CORE_ADDR P_thread_run;
62 static struct cleanup * save_inferior_pid PARAMS ((void));
64 static void restore_inferior_pid PARAMS ((int pid));
66 static void freebsd_uthread_resume PARAMS ((int pid, int step,
67 enum target_signal signo));
69 static void init_freebsd_uthread_ops PARAMS ((void));
71 static struct target_ops freebsd_uthread_ops;
72 static struct target_thread_vector freebsd_uthread_vec;
78 save_inferior_pid - Save inferior_pid on the cleanup list
79 restore_inferior_pid - Restore inferior_pid from the cleanup list
83 struct cleanup *save_inferior_pid ()
84 void restore_inferior_pid (int pid)
88 These two functions act in unison to restore inferior_pid in
93 inferior_pid is a global variable that needs to be changed by many of
94 these routines before calling functions in procfs.c. In order to
95 guarantee that inferior_pid gets restored (in case of errors), you
96 need to call save_inferior_pid before changing it. At the end of the
97 function, you should invoke do_cleanups to restore it.
101 static struct cleanup *
104 return make_cleanup ((make_cleanup_func) restore_inferior_pid,
105 (void *)(intptr_t) inferior_pid);
109 restore_inferior_pid (pid)
115 static int find_active_thread PARAMS ((void));
117 struct cached_pthread {
122 ucontext_t saved_sigcontext;
123 jmp_buf saved_jmp_buf;
126 static int cached_thread;
127 static struct cached_pthread cached_pthread;
128 static CORE_ADDR cached_pthread_addr;
130 #define THREADID_TID(id) ((id) >> 17)
131 #define THREADID_PID(id) ((id) & ((1 << 17) - 1))
133 LIST_HEAD(idmaplist, struct idmap);
136 LIST_ENTRY(struct idmap) link;
141 #define MAPHASH_SIZE 257
143 #define TID_MAX 16383
145 static int tid_to_hash[TID_MAX + 1]; /* set to map_hash index */
146 static struct idmaplist map_hash[MAPHASH_SIZE];
147 static int next_free_tid = TID_MIN; /* first available tid */
148 static int last_free_tid = TID_MIN; /* first unavailable */
150 static CORE_ADDR P_thread_next_offset;
151 static CORE_ADDR P_thread_uniqueid_offset;
152 static CORE_ADDR P_thread_state_offset;
153 static CORE_ADDR P_thread_name_offset;
154 static CORE_ADDR P_thread_sig_saved_offset;
155 static CORE_ADDR P_thread_saved_sigcontext_offset;
156 static CORE_ADDR P_thread_saved_jmp_buf_offset;
157 static CORE_ADDR P_thread_PS_RUNNING_value;
158 static CORE_ADDR P_thread_PS_DEAD_value;
160 static int next_offset;
161 static int uniqueid_offset;
162 static int state_offset;
163 static int name_offset;
164 static int sig_saved_offset;
165 static int saved_sigcontext_offset;
166 static int saved_jmp_buf_offset;
167 static int PS_RUNNING_value;
168 static int PS_DEAD_value;
170 #define UNIQUEID_HASH(id) (id % MAPHASH_SIZE)
171 #define TID_ADD1(tid) (((tid) + 1) == TID_MAX + 1 \
172 ? TID_MIN : (tid) + 1)
173 #define IS_TID_FREE(tid) (tid_to_hash[tid] == -1)
179 int tid = next_free_tid;
181 tid_to_hash[tid] = h;
182 next_free_tid = TID_ADD1(next_free_tid);
183 if (next_free_tid == last_free_tid)
187 for (i = last_free_tid; TID_ADD1(i) != last_free_tid; i = TID_ADD1(i))
190 if (TID_ADD1(i) == last_free_tid)
192 error("too many threads");
196 for (i = TID_ADD1(i); IS_TID_FREE(i); i = TID_ADD1(i))
208 int h = UNIQUEID_HASH(uniqueid);
211 LIST_FOREACH(im, &map_hash[h], link)
212 if (im->uniqueid == uniqueid)
213 return (im->tid << 17) + main_pid;
215 im = xmalloc(sizeof(struct idmap));
216 im->uniqueid = uniqueid;
217 im->tid = get_new_tid(h);
218 LIST_INSERT_HEAD(&map_hash[h], im, link);
220 return (im->tid << 17) + main_pid;
227 int tid = THREADID_TID(pid);
228 int h = tid_to_hash[tid];
233 LIST_FOREACH(im, &map_hash[h], link)
239 LIST_REMOVE(im, link);
240 tid_to_hash[tid] = -1;
244 #define READ_OFFSET(field) read_memory(P_thread_##field##_offset, \
245 (char *) &field##_offset, \
246 sizeof(field##_offset))
248 #define READ_VALUE(name) read_memory(P_thread_##name##_value, \
249 (char *) &name##_value, \
250 sizeof(name##_value))
253 read_thread_offsets ()
256 READ_OFFSET(uniqueid);
259 READ_OFFSET(sig_saved);
260 READ_OFFSET(saved_sigcontext);
261 READ_OFFSET(saved_jmp_buf);
263 READ_VALUE(PS_RUNNING);
267 #define READ_FIELD(ptr, T, field, result) \
268 read_memory ((ptr) + field##_offset, (char *) &(result), sizeof result)
271 read_pthread_uniqueid (ptr)
275 READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
280 read_pthread_next (ptr)
284 READ_FIELD(ptr, CORE_ADDR, next, next);
289 read_cached_pthread (ptr, cache)
291 struct cached_pthread *cache;
293 READ_FIELD(ptr, u_int64_t, uniqueid, cache->uniqueid);
294 READ_FIELD(ptr, int, state, cache->state);
295 READ_FIELD(ptr, CORE_ADDR, name, cache->name);
296 READ_FIELD(ptr, int, sig_saved, cache->sig_saved);
297 READ_FIELD(ptr, ucontext_t, saved_sigcontext,cache->saved_sigcontext);
298 READ_FIELD(ptr, jmp_buf, saved_jmp_buf, cache->saved_jmp_buf);
302 find_active_thread ()
309 read_memory ((CORE_ADDR)P_thread_run,
313 return find_pid(read_pthread_uniqueid(ptr));
316 static CORE_ADDR find_pthread_addr PARAMS ((int thread));
317 static struct cached_pthread * find_pthread PARAMS ((int thread));
320 find_pthread_addr (thread)
325 if (thread == cached_thread)
326 return cached_pthread_addr;
328 read_memory ((CORE_ADDR)P_thread_list,
334 if (find_pid(read_pthread_uniqueid(ptr)) == thread)
336 cached_thread = thread;
337 cached_pthread_addr = ptr;
338 read_cached_pthread(ptr, &cached_pthread);
341 ptr = read_pthread_next(ptr);
347 static struct cached_pthread *
348 find_pthread (thread)
353 if (thread == cached_thread)
354 return &cached_pthread;
356 read_memory ((CORE_ADDR)P_thread_list,
362 if (find_pid(read_pthread_uniqueid(ptr)) == thread)
364 cached_thread = thread;
365 cached_pthread_addr = ptr;
366 read_cached_pthread(ptr, &cached_pthread);
367 return &cached_pthread;
369 ptr = read_pthread_next(ptr);
373 error ("Can't find pthread %d,%d",
374 THREADID_TID(thread), THREADID_PID(thread));
380 /* Most target vector functions from here on actually just pass through to
381 inftarg.c, as they don't need to do anything specific for threads. */
385 freebsd_uthread_open (arg, from_tty)
389 child_ops.to_open (arg, from_tty);
392 /* Attach to process PID, then initialize for debugging it
393 and wait for the trace-trap that results from attaching. */
396 freebsd_uthread_attach (args, from_tty)
400 child_ops.to_attach (args, from_tty);
401 push_target (&freebsd_uthread_ops);
402 freebsd_uthread_attaching = 1;
405 /* After an attach, see if the target is threaded */
408 freebsd_uthread_post_attach (pid)
411 if (freebsd_uthread_active)
413 read_thread_offsets ();
417 bind_target_thread_vector (&freebsd_uthread_vec);
419 inferior_pid = find_active_thread ();
421 add_thread (inferior_pid);
425 unpush_target (&freebsd_uthread_ops);
426 push_target (&child_ops);
429 freebsd_uthread_attaching = 0;
432 /* Take a program previously attached to and detaches it.
433 The program resumes execution and will no longer stop
434 on signals, etc. We'd better not have left any breakpoints
435 in the program or it'll die when it hits one. For this
436 to work, it may be necessary for the process to have been
437 previously attached. It *might* work if the program was
438 started via the normal ptrace (PTRACE_TRACEME). */
441 freebsd_uthread_detach (args, from_tty)
445 child_ops.to_detach (args, from_tty);
448 /* Resume execution of process PID. If STEP is nozero, then
449 just single step it. If SIGNAL is nonzero, restart it with that
450 signal activated. We may have to convert pid from a thread-id to an LWP id
454 freebsd_uthread_resume (pid, step, signo)
457 enum target_signal signo;
459 struct cleanup *old_chain;
461 if (freebsd_uthread_attaching)
463 child_ops.to_resume (pid, step, signo);
467 old_chain = save_inferior_pid ();
469 pid = inferior_pid = main_pid;
471 child_ops.to_resume (pid, step, signo);
475 do_cleanups (old_chain);
478 /* Wait for any threads to stop. We may have to convert PID from a thread id
479 to a LWP id, and vice versa on the way out. */
482 freebsd_uthread_wait (pid, ourstatus)
484 struct target_waitstatus *ourstatus;
487 struct cleanup *old_chain;
489 if (freebsd_uthread_attaching)
491 return child_ops.to_wait (pid, ourstatus);
494 old_chain = save_inferior_pid ();
496 inferior_pid = main_pid;
501 rtnval = child_ops.to_wait (pid, ourstatus);
505 rtnval = find_active_thread ();
506 if (!in_thread_list (rtnval))
510 do_cleanups (old_chain);
517 static char sigmap[NUM_REGS] = /* map reg to sigcontext */
537 static char jmpmap[NUM_REGS] = /* map reg to jmp_buf */
561 static char sigmap[NUM_REGS] = /* map reg to sigcontext */
563 1, 2, 3, 4, 5, 6, 7, 8, /* v0 - t6 */
564 9, 10, 11, 12, 13, 14, 15, 16, /* t7 - fp */
565 17, 18, 19, 20, 21, 22, 23, 24, /* a0 - t9 */
566 25, 26, 27, 28, 29, 30, 31, 32, /* t10 - zero */
567 38, 39, 40, 41, 42, 43, 44, 45, /* f0 - f7 */
568 46, 47, 48, 49, 50, 51, 52, 53, /* f8 - f15 */
569 54, 55, 56, 57, 58, 59, 60, 61, /* f16 - f23 */
570 62, 63, 64, 65, 66, 67, 68, 69, /* f24 - f31 */
573 static char jmpmap[NUM_REGS] = {
574 4, 5, 6, 7, 8, 9, 10, 11, /* v0 - t6 */
575 12, 13, 14, 15, 16, 17, 18, 19, /* t7 - fp */
576 20, 21, 22, 23, 24, 25, 26, 27, /* a0 - t9 */
577 28, 29, 30, 31, 32, 33, 34, 35, /* t10 - zero */
578 37, 38, 39, 40, 41, 42, 43, 44, /* f0 - f7 */
579 45, 46, 47, 48, 49, 50, 51, 52, /* f8 - f15 */
580 53, 54, 55, 56, 57, 58, 59, 60, /* f16 - f23 */
581 61, 62, 63, 64, 65, 66, 67, 68, /* f24 - f31 */
588 freebsd_uthread_fetch_registers (regno)
591 struct cached_pthread *thread;
592 struct cleanup *old_chain;
595 int first_regno, last_regno;
599 if (freebsd_uthread_attaching)
601 child_ops.to_fetch_registers (regno);
605 thread = find_pthread (inferior_pid);
607 old_chain = save_inferior_pid ();
609 active = (inferior_pid == find_active_thread());
611 inferior_pid = main_pid;
615 child_ops.to_fetch_registers (regno);
617 do_cleanups (old_chain);
625 last_regno = NUM_REGS - 1;
633 if (thread->sig_saved)
635 regbase = (register_t*) &thread->saved_sigcontext.uc_mcontext;
640 regbase = (register_t*) &thread->saved_jmp_buf[0];
644 for (regno = first_regno; regno <= last_regno; regno++)
646 if (regmap[regno] == -1)
647 child_ops.to_fetch_registers (regno);
649 supply_register (regno, (char*) ®base[regmap[regno]]);
652 do_cleanups (old_chain);
656 freebsd_uthread_store_registers (regno)
659 struct cached_pthread *thread;
661 struct cleanup *old_chain;
663 int first_regno, last_regno;
667 if (freebsd_uthread_attaching)
669 child_ops.to_store_registers (regno);
673 thread = find_pthread (inferior_pid);
675 old_chain = save_inferior_pid ();
677 inferior_pid = main_pid;
679 if (thread->state == PS_RUNNING_value)
681 child_ops.to_store_registers (regno);
683 do_cleanups (old_chain);
691 last_regno = NUM_REGS - 1;
699 if (thread->sig_saved)
701 regbase = (u_int32_t*) &thread->saved_sigcontext;
706 regbase = (u_int32_t*) &thread->saved_jmp_buf[0];
710 ptr = find_pthread_addr (inferior_pid);
711 for (regno = first_regno; regno <= last_regno; regno++)
713 if (regmap[regno] == -1)
714 child_ops.to_store_registers (regno);
717 u_int32_t *reg = ®base[regmap[regno]];
720 /* Hang onto cached value */
721 memcpy(reg, registers + REGISTER_BYTE (regno),
722 REGISTER_RAW_SIZE (regno));
724 /* And push out to inferior */
725 off = (char *) reg - (char *) thread;
726 write_memory (ptr + off,
727 registers + REGISTER_BYTE (regno),
728 REGISTER_RAW_SIZE (regno));
732 do_cleanups (old_chain);
735 /* Get ready to modify the registers array. On machines which store
736 individual registers, this doesn't need to do anything. On machines
737 which store all the registers in one fell swoop, this makes sure
738 that registers contains all the registers from the program being
742 freebsd_uthread_prepare_to_store ()
744 struct cleanup *old_chain;
746 if (freebsd_uthread_attaching)
748 child_ops.to_prepare_to_store ();
752 old_chain = save_inferior_pid ();
753 inferior_pid = main_pid;
755 child_ops.to_prepare_to_store ();
757 do_cleanups (old_chain);
761 freebsd_uthread_xfer_memory (memaddr, myaddr, len, dowrite, target)
766 struct target_ops *target; /* ignored */
769 struct cleanup *old_chain;
771 if (freebsd_uthread_attaching)
773 return child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
776 old_chain = save_inferior_pid ();
778 inferior_pid = main_pid;
780 retval = child_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
782 do_cleanups (old_chain);
787 /* Print status information about what we're accessing. */
790 freebsd_uthread_files_info (ignore)
791 struct target_ops *ignore;
793 child_ops.to_files_info (ignore);
797 freebsd_uthread_kill_inferior ()
799 inferior_pid = main_pid;
800 child_ops.to_kill ();
804 freebsd_uthread_notice_signals (pid)
807 struct cleanup *old_chain;
808 old_chain = save_inferior_pid ();
809 inferior_pid = main_pid;
811 child_ops.to_notice_signals (pid);
813 do_cleanups (old_chain);
816 /* Fork an inferior process, and start debugging it with /proc. */
819 freebsd_uthread_create_inferior (exec_file, allargs, env)
824 child_ops.to_create_inferior (exec_file, allargs, env);
826 if (inferior_pid && freebsd_uthread_active)
828 read_thread_offsets ();
830 main_pid = inferior_pid;
832 push_target (&freebsd_uthread_ops);
833 bind_target_thread_vector (&freebsd_uthread_vec);
835 inferior_pid = find_active_thread ();
837 add_thread (inferior_pid);
841 /* This routine is called to find out if the inferior is using threads.
842 We check for the _thread_run and _thread_list globals. */
845 freebsd_uthread_new_objfile (objfile)
846 struct objfile *objfile;
848 struct minimal_symbol *ms;
852 freebsd_uthread_active = 0;
856 ms = lookup_minimal_symbol ("_thread_run", NULL, objfile);
861 P_thread_run = SYMBOL_VALUE_ADDRESS (ms);
863 ms = lookup_minimal_symbol ("_thread_list", NULL, objfile);
868 P_thread_list = SYMBOL_VALUE_ADDRESS (ms);
870 #define OFFSET_SYM(field) "_thread_" #field "_offset"
871 #define LOOKUP_OFFSET(field) \
873 ms = lookup_minimal_symbol (OFFSET_SYM(field), NULL, objfile); \
876 P_thread_##field##_offset = SYMBOL_VALUE_ADDRESS (ms); \
879 #define VALUE_SYM(name) "_thread_" #name "_value"
880 #define LOOKUP_VALUE(name) \
882 ms = lookup_minimal_symbol (VALUE_SYM(name), NULL, objfile); \
885 P_thread_##name##_value = SYMBOL_VALUE_ADDRESS (ms); \
889 LOOKUP_OFFSET(uniqueid);
890 LOOKUP_OFFSET(state);
892 LOOKUP_OFFSET(sig_saved);
893 LOOKUP_OFFSET(saved_sigcontext);
894 LOOKUP_OFFSET(saved_jmp_buf);
896 LOOKUP_VALUE(PS_RUNNING);
897 LOOKUP_VALUE(PS_DEAD);
899 freebsd_uthread_active = 1;
903 freebsd_uthread_has_exited (pid, wait_status, exit_status)
908 int t = child_ops.to_has_exited (pid, wait_status, exit_status);
914 /* Clean up after the inferior dies. */
917 freebsd_uthread_mourn_inferior ()
919 inferior_pid = main_pid; /* don't bother to restore inferior_pid */
920 child_ops.to_mourn_inferior ();
921 unpush_target (&freebsd_uthread_ops);
924 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
927 freebsd_uthread_can_run ()
929 return child_suppress_run;
933 freebsd_uthread_thread_alive (pid)
936 struct cleanup *old_chain;
937 struct cached_pthread *thread;
940 if (freebsd_uthread_attaching)
944 * We can get called from child_ops.to_wait() which passes the underlying
945 * pid (without a thread number).
947 if (THREADID_TID(pid) == 0)
950 old_chain = save_inferior_pid ();
951 inferior_pid = main_pid;
953 if (find_pthread_addr (pid) != 0)
955 thread = find_pthread (pid);
956 ret = (thread->state != PS_DEAD_value);
959 do_cleanups (old_chain);
968 freebsd_uthread_stop ()
970 struct cleanup *old_chain;
971 old_chain = save_inferior_pid ();
972 inferior_pid = main_pid;
974 child_ops.to_stop ();
976 do_cleanups (old_chain);
980 freebsd_uthread_find_new_threads ()
985 struct cleanup *old_chain;
987 old_chain = save_inferior_pid ();
988 inferior_pid = main_pid;
990 read_memory ((CORE_ADDR)P_thread_list,
996 READ_FIELD(ptr, int, state, state);
997 READ_FIELD(ptr, u_int64_t, uniqueid, uniqueid);
998 if (state != PS_DEAD_value &&
999 !in_thread_list (find_pid(uniqueid)))
1000 add_thread (find_pid(uniqueid));
1001 ptr = read_pthread_next(ptr);
1004 do_cleanups (old_chain);
1009 /* MUST MATCH enum pthread_state */
1010 static const char *statenames[] = {
1033 freebsd_uthread_get_thread_info (ref, selection, info)
1036 struct gdb_ext_thread_info *info;
1039 struct cached_pthread *thread = find_pthread (pid);
1040 struct cleanup *old_chain;
1042 old_chain = save_inferior_pid ();
1043 inferior_pid = main_pid;
1045 memset(&info->threadid, 0, OPAQUETHREADBYTES);
1047 memcpy(&info->threadid, ref, sizeof *ref);
1048 info->active = thread->state == PS_RUNNING_value;
1049 strcpy(info->display, statenames[thread->state]);
1051 read_memory ((CORE_ADDR) thread->name, info->shortname, 32);
1053 strcpy(info->shortname, "");
1055 do_cleanups (old_chain);
1059 freebsd_uthread_pid_to_str (pid)
1062 static char buf[30];
1064 if (STREQ (current_target.to_shortname, "freebsd-uthreads"))
1065 sprintf (buf, "process %d, thread %d\0",
1066 THREADID_PID(pid), THREADID_TID(pid));
1068 sprintf (buf, "process %d\0", pid);
1075 init_freebsd_uthread_ops ()
1077 freebsd_uthread_ops.to_shortname = "freebsd-uthreads";
1078 freebsd_uthread_ops.to_longname = "FreeBSD uthreads";
1079 freebsd_uthread_ops.to_doc = "FreeBSD user threads support.";
1080 freebsd_uthread_ops.to_open = freebsd_uthread_open;
1081 freebsd_uthread_ops.to_attach = freebsd_uthread_attach;
1082 freebsd_uthread_ops.to_post_attach = freebsd_uthread_post_attach;
1083 freebsd_uthread_ops.to_detach = freebsd_uthread_detach;
1084 freebsd_uthread_ops.to_resume = freebsd_uthread_resume;
1085 freebsd_uthread_ops.to_wait = freebsd_uthread_wait;
1086 freebsd_uthread_ops.to_fetch_registers = freebsd_uthread_fetch_registers;
1087 freebsd_uthread_ops.to_store_registers = freebsd_uthread_store_registers;
1088 freebsd_uthread_ops.to_prepare_to_store = freebsd_uthread_prepare_to_store;
1089 freebsd_uthread_ops.to_xfer_memory = freebsd_uthread_xfer_memory;
1090 freebsd_uthread_ops.to_files_info = freebsd_uthread_files_info;
1091 freebsd_uthread_ops.to_insert_breakpoint = memory_insert_breakpoint;
1092 freebsd_uthread_ops.to_remove_breakpoint = memory_remove_breakpoint;
1093 freebsd_uthread_ops.to_terminal_init = terminal_init_inferior;
1094 freebsd_uthread_ops.to_terminal_inferior = terminal_inferior;
1095 freebsd_uthread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
1096 freebsd_uthread_ops.to_terminal_ours = terminal_ours;
1097 freebsd_uthread_ops.to_terminal_info = child_terminal_info;
1098 freebsd_uthread_ops.to_kill = freebsd_uthread_kill_inferior;
1099 freebsd_uthread_ops.to_create_inferior = freebsd_uthread_create_inferior;
1100 freebsd_uthread_ops.to_has_exited = freebsd_uthread_has_exited;
1101 freebsd_uthread_ops.to_mourn_inferior = freebsd_uthread_mourn_inferior;
1102 freebsd_uthread_ops.to_can_run = freebsd_uthread_can_run;
1103 freebsd_uthread_ops.to_notice_signals = freebsd_uthread_notice_signals;
1104 freebsd_uthread_ops.to_thread_alive = freebsd_uthread_thread_alive;
1105 freebsd_uthread_ops.to_stop = freebsd_uthread_stop;
1106 freebsd_uthread_ops.to_stratum = process_stratum;
1107 freebsd_uthread_ops.to_has_all_memory = 1;
1108 freebsd_uthread_ops.to_has_memory = 1;
1109 freebsd_uthread_ops.to_has_stack = 1;
1110 freebsd_uthread_ops.to_has_registers = 1;
1111 freebsd_uthread_ops.to_has_execution = 1;
1112 freebsd_uthread_ops.to_has_thread_control = 0;
1113 freebsd_uthread_ops.to_magic = OPS_MAGIC;
1115 freebsd_uthread_vec.find_new_threads = freebsd_uthread_find_new_threads;
1116 freebsd_uthread_vec.get_thread_info = freebsd_uthread_get_thread_info;
1120 _initialize_freebsd_uthread ()
1122 init_freebsd_uthread_ops ();
1123 add_target (&freebsd_uthread_ops);
1125 child_suppress_run = 1;