This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[multiprocess] gdbserver multiprocess + non-stop installed


Hi!

I've installed the attached patches in the multiprocess branch.

These implement multi-process and non-stop mode support in
linux gdbserver, and tweak a few things here and there in GDB to
make that work.

(Non-stop relies on the displaced stepping support implemented
on the GDB side, so that means it will work best against
ia32 or ppc.)

You can now play with multiple inferiors by connecting to this
gdbserver with "target extended-remote", and issuing multiple
"run"s and/or "attach"es.

This also includes a couple of experimental remote protocol extensions.

 - follow fork support, to be used with the
   usual "set follow-fork-mode ...", "set detach-on-fork ..." commands.

 - a way to query the executable program of the remote inferior (qExecFile),
   used in the new implementation of target_pid_to_exec_file for
   target remote.

The branch is pretty much functional, but still has many issues to resolve
before it's ready for prime time, particularly, hacks to remove, and
regressions to fix: everyone's invited to contribute!

I'll post a more detailed description of the pending issues separately,
and wikify it.

-- 
Pedro Alves
2008-11-25  Pedro Alves  <pedro@codesourcery.com>

	2008-10-13  Pedro Alves  <pedro@codesourcery.com>

	* server.c (discard_pending_stop_replies): Initialize prev.

	2008-10-12  Pedro Alves  <pedro@codesourcery.com>

	* linux-low.c (linux_wait_1): Cancel breakpoint hits in threads
	we're not reporting.
	(cancel_breakpoints_callback): New.

	2008-10-12  Pedro Alves  <pedro@codesourcery.com>
	
	* server.c (queue_stop_reply_callback, handle_status): Pass
	TARGET_SIGNAL_TRAP, not TARGET_SIGNAL_0.

	* linux-low.c (ptid_is_pid): Delete.
	(linux_wait_for_event): In non-stop, don't set the current
	inferior arbitrarily.
	(linux_wait): Flush the event pipe before polling for an event.
	(wait_for_sigstop): In non-stop, don't set the current
	inferior arbitrarily.
	(linux_resume_one_lwp): Small cleanup.
	(cancel_breakpoint): New.
	(linux_resume_one_thread): Use it.  Still report SIGTRAPs.
	(regsets_store_inferior_registers): Plug leak.
	(sigchld_handler): Don't use fprintf here.

	* mem-break.c (breakpoint_at): New.
	* inferiors.c (ptid_is_pid): New.
	* mem-break.h (breakpoint_at): Declare.
	* server.c (discard_queued_stop_replies): Add `pid' argument.
	Handle it.
	(send_next_stop_reply): Cleanup.
	(attach_inferior): Don't wait here in non-stop mode.
	(handle_v_attach): Don't queue stop replies here.
	(handle_v_kill): Discard queued stop replies of the inferior we
	just killed.
	(queue_stop_reply_callback): Add `arg' argument.  Handle it.
	(handle_status): Adjust.
	(kill_inferior_callback): Discard queued stop replies of the
	inferior we just killed.
	(detach_or_kill_inferior_callback): Discard queued stop replies of
	the inferior we just killed or detached from.
	(process_serial_event): Cleanup.  Discard queued stop replies of
	the inferior we just detached.  Don't write 0 bytes to the inferior.
	(handle_serial_event): Debug output.
	* server.h (ptid_is_pid): Declare.

	* remote-utils.c (prepare_resume_reply): Avoid reading registers
	and memory from a thread that is gone.

	2008-09-26  Pedro Alves  <pedro@codesourcery.com>

	* server.h (struct sym_cache, struct process_info_private):
	Forward declare.
	(struct process_info): Add symbol_cache, all_symbols_looked_up and
	private fields.
	(current_process): Declare.
	* remote-utils.c (struct sym_cache) <name>: Remove constness.
	(symbol_cache): Delete.
	(free_sym_cache, clear_symbol_cache): New.
	(look_up_one_symbol): Adjust, to per-process symbol cache.
	* inferiors.c (current_process): New.

	* linux-low.h: Include "gdb_proc_service.h".
	(struct process_info_private): Define.
	* linux-low.c (thread_db_active): Delete.
	(linux_add_process): New.
	(handle_extended_wait, linux_create_inferior, linux_attach): Use
	it.
	(linux_wait_for_event, linux_look_up_symbols): Adjust.
	(initialize_low): Don't clear the global thread_db_active.
	* thread-db.c (proc_handle, thread_agent): Delete.
	(fixup_proc_handle): New.
	(thread_db_err_str, thread_db_enable_reporting): Use it.  Adjust.
	(thread_db_find_new_threads): Look for the current inferior
	thread, not the first thread in the list.  Use fixup_proc_handle.
	Adjust.
	(thread_db_get_tls_address): Use fixup_proc_handle.
	(thread_db_init): Likewise.  Adjust.

	2008-09-26  Pedro Alves  <pedro@codesourcery.com>

	* mem-break.c (get_breakpoint_list): Add `create' argument.  Only
	create the list if create is set.
	(remove_breakpoint_list): New.
	(set_breakpoint_at, find_breakpoint_at, check_mem_read)
	(check_mem_write, delete_all_breakpoints): Adjust.

	2008-09-26  Pedro Alves  <pedro@codesourcery.com>

	* server.c (gdbserver_usage): Describe --remote-debug option.
	(main): Handle --remote-debug switch.

	2008-09-19  Pedro Alves  <pedro@codesourcery.com>

	Non-stop mode support.

	* linux-low.c (linux_event_pipe): New int array for pipe.
	(target_is_async_p): New.
	(handle_extended_wait): Use my_waitpid.
	(linux_kill_one_lwp): Stop the LWP if it is not stopped already.
	Use my_waitpid, not linux_wait_for_event.  Remove the lwp and the
	corresponding thread from the lists.
	(linux_kill_one_process, linux_kill): Delete.
	(linux_kill_1): Rename back to ...
	(linux_kill) ... this.  Stop the LWP if it is not stopped already.
	Use my_waitpid, not linux_wait_for_event.  Remove the lwp and the
	corresponding thread from the lists.
	(linux_detach_one_lwp): Make sure the LWP is stopped.  Adjust to
	new linux_wait_for_event interface.
	(linux_detach_one_process, linux_detach): Delete.
	(linux_detach_1): Rename back to ...
	(linux_detach): This.
	(linux_join): Add PID argument.  Use my_waitpid instead of
	waitpid.
	(status_pending_p): Ignore suspended threads.
	(my_waitpid): Emulate __WALL.
	(linux_wait_for_lwp): Add 'options' argument.  Handle it.  Use
	my_wait.  If requesting an event from a specific process, leave
	events in other processes pending.
	(resume_stopped_lwps): New.
	(linux_wait_for_event): Delete.
	(linux_wait_for_event_1): Rename back to ...
	(linux_wait_for_event): ... this.  Change interface: add wstat and
	options arguments, return -1 on error, 0 otherwise.  Adjust.  In
	all-stop, resume stopped lwps if there was no pending status.
	Don't return immediatelly if a pending status was found ---
	continue handling it instead.  Don't loop, only handle one event.
	(linux_wait): Rename to ...
	(linux_wait_1): ... this.  Add target_options argument.  Handle
	it.  Don't loop --- only handle one event.  Ignore the continue
	thread in non_stop mode.  Adjust to new resume_kind interface.
	Only stop all threads in all-stop mode.
	(async_file_flush, async_file_mark): New.
	(linux_wait): New.
	(wait_for_sigstop): Set stopping_threads here.  Use
	linux_wait_for_lwp instead of linux_wait_for_event.  Adjust.
	(stop_all_lwps): Don't set stopping_threads here.
	(resume_ptr): Delete.
	(struct resume_info): New.
	(linux_set_resume_request): Add arg argument.  Adjust to take a
	struct remove_info instead of the global resume_ptr.  Accept
	pid,-1 to apply to all threads.
	(linux_continue_one_thread, linux_queue_one_thread): Merge both
	and create ...
	(linux_resume_one_thread): ... this.  New.  Handle rk_stop.
	(resume_status_pending_p): Assume no resume info to mean do
	nothing.  Ignore suspended LWPs.
	(linux_resume): Add n argument.  Adjust.  In non-stop mode, don't
	look for a pending status over all threads.
	(linux_read_offsets): Minor cleanup.
	(sigchld_handler, linux_async, linux_start_non_stop): New.
	(linux_target_ops): Register linux_async and linux_start_non_stop.
	(initialize_low): Register sigchld_handler as SIGCHLD handler.

	* utils.c (internal_verror, internal_error_file_line): New.

	* Makefile.in (SFILES): Add event-loop.c.
	(OBS): Add event-loop.o.
	(event-loop.o): New rule.

	* linux-low.h (struct lwp_info) <suspended>: New flag.

	* thread-db.c (thread_db_create_event): Make sure thread_db reads
	from the current inferior.
	(thread_db_get_tls_address): Comment.

	* server.c (thread_from_wait, old_thread_from_wait, attached):
	Delete.
	(non_stop): New global.
	(own_buf, mem_buf): New globals.
	(struct vstop_notif): New.
	(notif_queue): New.
	(queue_stop_reply, push_event, discard_queued_stop_replies)
	(send_next_stop_reply): New.
	(start_inferior): Adjust to new thread_resume interface.  Adjust
	to new mywait interface.
	(attach_inferior): Adjust.
	(handle_general_set): Handle QNonStop.
	(handle_query): Pass 'QNonStop+'.
	(handle_v_cont): Handle vCont;t.  Don't enable/disable async io in
	non-stop mode.  In non-stop return OK, and don't wait for the
	target.
	(handle_v_attach): In non-stop, return OK, and queue events for
	all threads.
	(handle_v_run): In non-stop, set the general thread here.
	(handle_v_stopped): New.
	(handle_v_requests): Report support for 't'.  Handle 'vStopped'.
	(proceed): Add comment.  Adjust.  In non-stop, don't
	enable/disable async io; write 'OK', and don't wait for the
	target.
	(queue_stop_reply_callback, handle_status): New.
	(kill_inferior_callback, detach_or_kill_inferior_callback)
	(join_inferiors_callback): New.
	(main): In --debug mode, also enable remote debug.  Don't pass -1
	to kill_inferior or detach_inferior; instead, iterate over all
	processes killing or detaching them.  Adjust to use the even-loop.
	(process_serial_event): New, factored out of main.  If the
	connection closed, remove all sources from the event loop.
	Iterate over all inferiors joining them.  Use handle_status.
	Don't print inferior exit notices here.  In non-stop, defer
	exiting until GDB read all queued events.
	(handle_serial_event, handle_target_event): New.

	* server.h (FOR_EACH_INFERIOR): New.
	(thread_from_wait, old_thread_from_wait): Remove.
	(non_stop): Declare.
	(gdb_client_data, handler_func): New typedefs.
	(delete_file_handler, add_file_handler, start_event_loop)
	(handle_serial_event, handle_target_event, push_event)
	(putpkt_notif, internal_error_file_line): Declare.
	(internal_error): Define.

	* target.c (mywait): Add `options' argument.  Print inferior exit
	notices here.
	(start_non_stop): New.

	* event-loop.c: New.

	* remote-utils.c (remote_open): Register remote_desc in the event
	loop, with handle_serial_event as callback.
	(remote_close): Remove remote_desc from the event loop.
	(hex_or_minus_one): New.
	(read_ptid, read_ptid): Use it.
	(putpkt_binary): Rename to ...
	(putpkt_binary_1): ... this.  Add `notif' argument.  Handle
	pushing a remote protocol notification.
	(putpkt_binary): New as wrapper around putpkt_binary_1.
	(putpkt_notif): New.
	(getpkt): Debug output.
	(prepare_resume_reply): Remove dead code.  In non-stop, don't set
	the general thread here.

	* target.h (enum resume_kind): New.
	(struct thread_resume) <leave_stopped, step>: Delete.
	(struct thread_resume) <kind>: New field.
	(TARGET_WNOHANG): Define.
	(struct target_ops) <kill, detach>: Adjust comments.
	(struct target_ops) <join>: Add `pid' argument.
	(struct target_ops) <resume>: Add `n' argument.
	(struct target_ops) <wait>: Add `options' argument.
	(struct target_ops) <async, start_non_stop>: New fields.
	(join_inferior): Add `pid' argument.
	(target_async): New.
	(start_non_stop): Declare.
	(mywait): Add options argument.

	2008-09-15  Pedro Alves  <pedro@codesourcery.com>

	* linux-low.c (new_inferior): Mention in the comment that all
	inferiors should have the same architecture for now.
	(linux_create_inferior, linux_attach): Only set new_inferior if
	this is the first process.
	
	2008-08-29  Pedro Alves  <pedro@codesourcery.com>

	* linux-low.c (ptid_is_pid): Move higher.
	(linux_wait_for_lwp): Remove dead code.
	(linux_wait_for_event): Rename to ...
	(linux_wait_for_event_1): ... this.
	(linux_wait_for_event): New.
	(ptid_same_pid): Delete.
	(linux_set_resume_request): Clearify.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* linux-low.c (handle_extended_wait, linux_attach_lwp)
	(linux_attach): Minor cleanups.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* linux-low.c (linux_thread_alive): Return false for a listed
	thread known to be dead.
	(linux_wait_for_event): Don't set the dead flag here.
	(wait_for_sigstop): Store ptid before waiting for the event.
	Minor cleanup.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* inferiors.c (find_inferior): Allow deleting the current iterated
	inferior.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* linux-low.c (linux_pid_to_exec_file): Move higher.
	(linux_enable_event_reporting): Enable PTRACE_O_TRACEEXEC.
	(handle_extended_wait): Handle PTRACE_EVENT_EXEC.

	* remote-utils.c (prepare_resume_reply): Set the general thread to
	the last thread that had an event in TARGET_WAITKIND_FORKED and
	TARGET_WAITKIND_VFORKED.  Handle TARGET_WAITKIND_EXECD.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* server.c (handle_query): Pass "QExecFile:PID;" back in the reply.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* linux-low.c (linux_supports_tracefork_flag): Move higher.
	(linux_enable_event_reporting): New.
	(handle_extended_wait): Change return type to int.  Handle
	PTRACE_EVENT_FORK and PTRACE_EVENT_VFORK.
	(add_lwp): Set waitstatus.kind to TARGET_WAITKIND_IGNORE.
	(linux_attach_lwp): Use linux_enable_event_reporting.
	(linux_wait_for_event): Don't keep waiting if the extended wait
	status should be reported to gdb.
	(linux_wait): Use linux_enable_event_reporting.  If waitstatus
	holds a processed event, return it instead.
	* remote-utils.c (prepare_resume_reply): Handle
	TARGET_WAITKIND_FORKED and TARGET_WAITKIND_VFORKED.
	* linux-low.h (struct lwp_info) <waitstatus>: New member.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* target.h (struct target_ops) <pid_to_exec_file>: New member.
	* server.c (handle_query): Handle qExecFile.
	* linux-low.c (linux_pid_to_exec_file): New.
	(linux_target_ops): Register it.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* linux-low.c (is_lwpid): New.
	(linux_kill_one_lwp, linux_kill_1, linux_detach_one_lwp): Adjust.
	(status_pending_p): Check if we're interested in this lwp.
	(linux_wait_for_lwp): Change signature: return an lwp_info*, and
	take a ptid instead of an lwp_info**.
	(linux_wait_for_event): Take a ptid instead of a thread_info
	pointer.  Adjust.
	(wait_for_sigstop): Adjust.  If a whole process died, keep the
	exit status pending.
	(ptid_is_pid, ptid_same_pid): New.
	(linux_set_resume_request): Allow resuming all threads of a process.
	(resume_status_pending_p): Check for dead lwps.

	* linux-low.h (struct lwp_info) <dead>: New field.

	* server.c (start_inferior): Only resume and wait for events from
	the inferior we're creating.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	Decouple target code from remote protocol.

	* linux-low.c (linux_wait): Change prototype.  Adjust.
	* server.c (last_status, last_ptid): New.
	(start_inferior): Remove "statusptr" argument.  Adjust.
	(attach_inferior, handle_v_cont, handle_v_attach, handle_v_run)
	(handle_v_kill, handle_v_requests): Remove "status" and "signal"
	parameters.  Adjust.
	(myresume): Rename to ...
	(proceed): ... this.  Remove "statusp" parameter.  Adjust.
	(main): Remove "status" local.  Adjust.
	* target.c (mywait): Change prototype.  Adjust.
	* target.h (enum target_waitkind): New.
	(struct target_waitstatus): New.
	(struct target_ops) <wait>: Change prototype.
	(mywait): Adjust.
	* remote-utils.c: Include "target.h".
	(prepare_resume_reply): Change prototype to take a ptid and a
	target_waitstatus.  Adjust.
	* server.h (prepare_resume_reply): Adjust prototype.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* inferiors.c (all_processes): New.
	(add_process): New.
	
	* linux-low.c (linux_create_inferior): Add process.
	(linux_attach_lwp): Add "initial" parameter, and use it instead of
	relying on having only one thread in the global list.
	(linux_attach): Add process.
	(struct counter): New.
	(check_if_last_thread_of_pid, is_last_thread_of_process): New.
	(linux_kill_one_lwp): Add ARGS parameter.  Change return type to
	int.  Check if we're interested in this lwp.  Use
	is_last_thread_of_process.
	(linux_kill): Rename to ...
	(linux_kill_1): ... this.  Kill lwps of the requested only.
	(linux_kill_one_process): New.
	(linux_kill): New.
	(linux_detach_one_lwp): Add ARGS parameter.  Change return type to
	int.  Check if we're interested in this lwp.  Remove the lwp from
	both the lwp list and the thread list.
	(any_thread_of, linux_detach_1, linux_detach_one_process): New.
	(linux_detach): Reimplement.
	(linux_wait_for_event): Use is_last_thread_of_process.
	(linux_wait): Likewise.  On process exit, don't clear all inferiors.
	Implement multi-process extensions.

	* mem-break.c (breakpoints): Delete.
	(struct breakpoint_list): New.
	(all_breakpoints): New.
	(get_breakpoint_list): New.
	(set_breakpoint_at, delete_breakpoint, find_breakpoint_at)
	(check_mem_read, check_mem_write, delete_all_breakpoints): Use it.

	* server.h (struct process_info): New.
	(all_processes): Declare.
	(add_process): Declare.

	* linux-low.h (linux_attach_lwp): Add "initial" parameter.

	* thread-db.c (maybe_attach_thread): Adjust.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* linux-low.c, linux-low.h, proc-service.c, thread-db.c: Rename
	`struct process_info' to `struct lwp_info', and adjust throughout.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	Implement remote protocol multi-process extensions.

	* inferiors.c (null_ptid, minus_one_ptid): New.
	(ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp)
	(ptid_get_tid, ptid_equal): New functions.
	(add_thread): Drop gdb_id argument.  Retype thread_id argument to
	ptid_t.  Adjust.
	(thread_id_to_gdb_id): Adjust.
	(thread_to_gdb_id): Change return type to ptid_t.  Adjust.
	(gdb_id_to_thread): Rename to ...
	(find_thread_pid): ... this.  Adjust.
	(gdb_id_to_thread_id): Change return type to ptid_t.  Adjust.
	(find_inferior_id): Change id argument type to ptid_t.  Adjust.
	(loaded_dll, add_pid_to_list, pull_pid_from_list): Adjust.
	(initialize_inferiors): New.

	* remote-utils.c (hexchars): New.
	(ishex, unpack_varlen_hex, write_ptid, read_ptid): New.
	(prepare_resume_reply): Adjust.

	* server.c (cont_thread, general_thread, step_thread)
	(thread_from_wait, old_thread_from_wait): Change type to ptid_t.
	(multi_process): New.
	(start_inferior): Adjust.
	(handle_query): Adjust.  Report multiprocess extensions support.
	(handle_v_cont): Adjust.
	(handle_v_kill): New.
	(handle_v_requests): Handle vKill.
	(myresume): Adjust.
	(first_thread_of): New.
	(main): Call initialize_inferiors.  If bailing out, kill all
	inferiors.  Handle multi-process detach.  Handle multi-process H
	and T.

	* server.h (ULONGEST): New typedef.
	(struct ptid): New struct.
	(ptid_t): New typedef.
	(minus_one_ptid, null_ptid): New.
	(ptid_t ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp)
	(ptid_get_tid, ptid_equal): New.
	(struct inferior_list_entry) <id>: Change type to ptid_t.
	(add_thread, thread_id_to_gdb_id, thread_to_gdb_id)
	(gdb_id_to_thread_id): Adjust prototypes.
	(find_thread_pid): Declare.
	(find_inferior_id): Adjust prototype.
	(cont_thread, general_thread, step_thread, thread_from_wait)
	(old_thread_from_wait): Adjust type to ptid_t.
	(multi_process): Declare.
	(read_ptid, write_ptid): Declare.

	* linux-low.c (pid_of): Adjust.
	(lwpid_of): New.
	(inferior_lwpid): New.
	(handle_extended_wait): Adjust.
	(add_process): Change pid argument to a ptid.  Adjust.
	(linux_create_inferior): Adjust.
	(linux_attach_lwp): Adjust.  Clear new_inferior on error.  If
	creating a new inferior, don't rely on inferior_pid, instead use
	the lwpid as pid.
	(linux_attach): Set new_inferior earlier.  Adjust.
	(linux_kill): Change return type to int.  Adjust.
	(linux_detach): Add pid parameter.
	(linux_thread_alive): Change lwpid paremeter type to ptid.
	Adjust.
	(same_lwp, find_lwp_pid): New.
	(linux_wait_for_process): Adjust.
	(linux_wait_for_process, linux_wait_for_event, send_sigstop)
	(wait_for_sigstop, linux_resume_one_process,
	(linux_resume_one_process, linux_set_resume_request)
	(linux_continue_one_thread, linux_queue_one_thread)
	(fetch_register, usr_store_inferior_registers)
	(regsets_fetch_inferior_registers)
	(regsets_store_inferior_registers, linux_read_memory)
	(linux_write_memory, linux_request_interrupt, linux_read_auxv):
	Adjust.

	* linux-low.h (get_process_thread): Adjust.
	(struct process_info) <lwpid>: Remove.
	(find_lwp_pid): Declare.

	* target.c (set_desired_inferior): Adjust.
	(target_pid_to_str): New.

	* target.h (struct thread_resume) <thread>: Change type to ptid_t.
	(struct target_ops) <kill>: Change return type to int, and take an
	int as parameter.
	(struct target_ops) <detach>: Take an int as parameter.
	(struct target_ops) <thread_alive>: Change pid argument type to
	ptid_t.
	(kill_inferior, detach_inferior): Add PID argument.

	* thread-db.c (thread_db_create_event): Adjust.
	(find_one_thread): Change argument to a ptid.  Adjust.
	(maybe_attach_thread, thread_db_get_tls_address, thread_db_init):
	Adjust.

	* proc-service.c (ps_lgetregs): Adjust.

---
 gdb/gdbserver/Makefile.in    |    3 
 gdb/gdbserver/event-loop.c   |  660 +++++++++++++
 gdb/gdbserver/inferiors.c    |  163 ++-
 gdb/gdbserver/linux-low.c    | 2070 +++++++++++++++++++++++++++++++------------
 gdb/gdbserver/linux-low.h    |   55 -
 gdb/gdbserver/mem-break.c    |  117 ++
 gdb/gdbserver/mem-break.h    |    4 
 gdb/gdbserver/proc-service.c |    9 
 gdb/gdbserver/regcache.c     |   10 
 gdb/gdbserver/remote-utils.c |  402 ++++++--
 gdb/gdbserver/server.c       |  959 +++++++++++++++----
 gdb/gdbserver/server.h       |  159 +++
 gdb/gdbserver/target.c       |   76 +
 gdb/gdbserver/target.h       |  169 ++-
 gdb/gdbserver/thread-db.c    |  148 +--
 gdb/gdbserver/utils.c        |   22 
 16 files changed, 4005 insertions(+), 1021 deletions(-)

Index: src/gdb/gdbserver/event-loop.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/gdbserver/event-loop.c	2008-11-25 17:28:12.000000000 +0000
@@ -0,0 +1,660 @@
+/* Event loop machinery for the remote server for GDB.
+   Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
+
+/* Based on src/gdb/event-loop.c.  */
+
+#include "server.h"
+
+#ifdef HAVE_POLL
+#if defined (HAVE_POLL_H)
+#include <poll.h>
+#elif defined (HAVE_SYS_POLL_H)
+#include <sys/poll.h>
+#endif
+#endif
+
+#include <sys/types.h>
+#include <string.h>
+#include <sys/time.h>
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+typedef struct gdb_event gdb_event;
+typedef void (event_handler_func) (int);
+
+/* Tell create_file_handler what events we are interested in.
+   This is used by the select version of the event loop. */
+
+#define GDB_READABLE	(1<<1)
+#define GDB_WRITABLE	(1<<2)
+#define GDB_EXCEPTION	(1<<3)
+
+/* Event for the GDB event system.  Events are queued by calling
+   async_queue_event and serviced later on by gdb_do_one_event. An
+   event can be, for instance, a file descriptor becoming ready to be
+   read. Servicing an event simply means that the procedure PROC will
+   be called.  We have 2 queues, one for file handlers that we listen
+   to in the event loop, and one for the file handlers+events that are
+   ready. The procedure PROC associated with each event is always the
+   same (handle_file_event).  Its duty is to invoke the handler
+   associated with the file descriptor whose state change generated
+   the event, plus doing other cleanups and such. */
+
+struct gdb_event
+  {
+    event_handler_func *proc;	/* Procedure to call to service this event. */
+    int fd;			/* File descriptor that is ready. */
+    struct gdb_event *next_event;	/* Next in list of events or NULL. */
+  };
+
+/* Information about each file descriptor we register with the event
+   loop. */
+
+typedef struct file_handler
+  {
+    int fd;			/* File descriptor. */
+    int mask;			/* Events we want to monitor: POLLIN, etc. */
+    int ready_mask;		/* Events that have been seen since
+				   the last time. */
+    handler_func *proc;		/* Procedure to call when fd is ready. */
+    gdb_client_data client_data;	/* Argument to pass to proc. */
+    int error;			/* Was an error detected on this fd? */
+    struct file_handler *next_file;	/* Next registered file descriptor. */
+  }
+file_handler;
+
+/* Event queue:
+   - the first event in the queue is the head of the queue.
+   It will be the next to be serviced.
+   - the last event in the queue
+
+   Events can be inserted at the front of the queue or at the end of
+   the queue.  Events will be extracted from the queue for processing
+   starting from the head.  Therefore, events inserted at the head of
+   the queue will be processed in a last in first out fashion, while
+   those inserted at the tail of the queue will be processed in a first
+   in first out manner.  All the fields are NULL if the queue is
+   empty. */
+
+static struct
+  {
+    gdb_event *first_event;	/* First pending event */
+    gdb_event *last_event;	/* Last pending event */
+  }
+event_queue;
+
+/* Gdb_notifier is just a list of file descriptors gdb is interested
+   in.  These are the input file descriptor, and the target file
+   descriptor. We have two flavors of the notifier, one for platforms
+   that have the POLL function, the other for those that don't, and
+   only support SELECT. Each of the elements in the gdb_notifier list
+   is basically a description of what kind of events gdb is interested
+   in, for each fd.  */
+
+#ifdef USE_WIN32API
+#include <windows.h>
+#include <io.h>
+#endif
+
+static struct
+  {
+    /* Ptr to head of file handler list. */
+    file_handler *first_file_handler;
+
+#ifdef HAVE_POLL
+    /* Ptr to array of pollfd structures. */
+    struct pollfd *poll_fds;
+#endif
+
+    /* Masks to be used in the next call to select.
+       Bits are set in response to calls to create_file_handler. */
+    fd_set check_masks[3];
+
+    /* What file descriptors were found ready by select. */
+    fd_set ready_masks[3];
+
+    /* Number of file descriptors to monitor. (for poll) */
+    /* Number of valid bits (highest fd value + 1). (for select) */
+    int num_fds;
+  }
+gdb_notifier;
+
+static void create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data client_data);
+static void handle_file_event (int event_file_desc);
+static int gdb_wait_for_event (void);
+static void async_queue_event (gdb_event * event_ptr);
+static gdb_event *create_file_event (int fd);
+static int process_event (void);
+
+
+/* Insert an event object into the gdb event queue
+
+   EVENT_PTR points to the event to be inserted into the queue.  The
+   caller must allocate memory for the event. It is freed after the
+   event has ben handled.  Events in the queue will be processed head
+   to tail, therefore, events will be processed first in first out. */
+static void
+async_queue_event (gdb_event *event_ptr)
+{
+  /* The event will become the new last_event. */
+
+  event_ptr->next_event = NULL;
+  if (event_queue.first_event == NULL)
+    event_queue.first_event = event_ptr;
+  else
+    event_queue.last_event->next_event = event_ptr;
+  event_queue.last_event = event_ptr;
+}
+
+/* Create a file event, to be enqueued in the event queue for
+   processing. The procedure associated to this event is always
+   handle_file_event, which will in turn invoke the one that was
+   associated to FD when it was registered with the event loop. */
+static gdb_event *
+create_file_event (int fd)
+{
+  gdb_event *file_event_ptr;
+
+  file_event_ptr = malloc (sizeof (gdb_event));
+  file_event_ptr->proc = handle_file_event;
+  file_event_ptr->fd = fd;
+  return (file_event_ptr);
+}
+
+/* Process one event.  If an event was processed, 1 is returned
+   otherwise 0 is returned.  Scan the queue from head to tail,
+   processing therefore the high priority events first, by invoking
+   the associated event handler procedure.  */
+static int
+process_event (void)
+{
+  gdb_event *event_ptr, *prev_ptr;
+  event_handler_func *proc;
+  int fd;
+
+  /* Look in the event queue to find an event that is ready
+     to be processed. */
+
+  for (event_ptr = event_queue.first_event; event_ptr != NULL;
+       event_ptr = event_ptr->next_event)
+    {
+      /* Call the handler for the event. */
+
+      proc = event_ptr->proc;
+      fd = event_ptr->fd;
+
+      /* Let's get rid of the event from the event queue.  We need to
+         do this now because while processing the event, the proc
+         function could end up calling 'error' and therefore jump out
+         to the caller of this function, gdb_do_one_event. In that
+         case, we would have on the event queue an event wich has been
+         processed, but not deleted. */
+
+      if (event_queue.first_event == event_ptr)
+	{
+	  event_queue.first_event = event_ptr->next_event;
+	  if (event_ptr->next_event == NULL)
+	    event_queue.last_event = NULL;
+	}
+      else
+	{
+	  prev_ptr = event_queue.first_event;
+	  while (prev_ptr->next_event != event_ptr)
+	    prev_ptr = prev_ptr->next_event;
+
+	  prev_ptr->next_event = event_ptr->next_event;
+	  if (event_ptr->next_event == NULL)
+	    event_queue.last_event = prev_ptr;
+	}
+      free (event_ptr);
+
+      /* Now call the procedure associated with the event. */
+      (*proc) (fd);
+      return 1;
+    }
+
+  /* this is the case if there are no event on the event queue. */
+  return 0;
+}
+
+/* Process one high level event.  If nothing is ready at this time,
+   wait for something to happen (via gdb_wait_for_event), then process
+   it.  Returns >0 if something was done otherwise returns <0 (this
+   can happen if there are no event sources to wait for).  */
+
+int
+gdb_do_one_event (void)
+{
+  /* Any events already waiting in the queue?  */
+  if (process_event ())
+    return 1;
+
+  /* Wait for a new event.  If gdb_wait_for_event returns -1, we
+     should get out because this means that there are no event sources
+     left. This will make the event loop stop, and the application
+     exit.  */
+
+  if (gdb_wait_for_event () < 0)
+    return -1;
+
+  /* Handle any new events occurred while waiting.  */
+  if (process_event ())
+    return 1;
+
+  /* If gdb_wait_for_event has returned 1, it means that one
+     event has been handled. We break out of the loop. */
+  return 1;
+}
+
+/* Start up the event loop. This is the entry point to the event loop
+   from the command loop. */
+
+void
+start_event_loop (void)
+{
+  /* Loop until there is nothing to do. This is the entry point to the
+     event loop engine. gdb_do_one_event, called via catch_errors()
+     will process one event for each invocation.  It blocks waiting
+     for an event and then processes it.  >0 when an event is
+     processed, 0 when catch_errors() caught an error and <0 when
+     there are no longer any event sources registered.  */
+
+  while (1)
+    {
+      int gdb_result;
+
+      gdb_result = gdb_do_one_event ();
+      if (gdb_result < 0)
+	break;
+    }
+
+  /* We are done with the event loop. There are no more event sources
+     to listen to.  So we exit gdbserver.  */
+  return;
+}
+
+
+/* Wrapper function for create_file_handler, so that the caller
+   doesn't have to know implementation details about the use of poll
+   vs. select.  */
+void
+add_file_handler (int fd, handler_func * proc, gdb_client_data client_data)
+{
+#ifdef HAVE_POLL
+  create_file_handler (fd, POLLIN, proc, client_data);
+#else
+  create_file_handler (fd, GDB_READABLE | GDB_EXCEPTION, proc, client_data);
+#endif
+}
+
+/* Add a file handler/descriptor to the list of descriptors we are
+   interested in.
+   FD is the file descriptor for the file/stream to be listened to.
+   For the poll case, MASK is a combination (OR) of
+   POLLIN, POLLRDNORM, POLLRDBAND, POLLPRI, POLLOUT, POLLWRNORM,
+   POLLWRBAND: these are the events we are interested in. If any of them
+   occurs, proc should be called.
+   For the select case, MASK is a combination of READABLE, WRITABLE, EXCEPTION.
+   PROC is the procedure that will be called when an event occurs for
+   FD.  CLIENT_DATA is the argument to pass to PROC. */
+static void
+create_file_handler (int fd, int mask, handler_func * proc, gdb_client_data client_data)
+{
+  file_handler *file_ptr;
+
+  /* Do we already have a file handler for this file? (We may be
+     changing its associated procedure). */
+  for (file_ptr = gdb_notifier.first_file_handler;
+       file_ptr != NULL;
+       file_ptr = file_ptr->next_file)
+    if (file_ptr->fd == fd)
+      break;
+
+  /* It is a new file descriptor.  Add it to the list.  Otherwise,
+     just change the data associated with it. */
+  if (file_ptr == NULL)
+    {
+      file_ptr = malloc (sizeof (*file_ptr));
+      file_ptr->fd = fd;
+      file_ptr->ready_mask = 0;
+      file_ptr->next_file = gdb_notifier.first_file_handler;
+      gdb_notifier.first_file_handler = file_ptr;
+
+#ifdef HAVE_POLL
+      gdb_notifier.num_fds++;
+      if (gdb_notifier.poll_fds)
+	gdb_notifier.poll_fds =
+	  realloc (gdb_notifier.poll_fds,
+		   (gdb_notifier.num_fds
+		    * sizeof (struct pollfd)));
+      else
+	gdb_notifier.poll_fds =
+	  malloc (sizeof (struct pollfd));
+      (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->fd = fd;
+      (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->events = mask;
+      (gdb_notifier.poll_fds + gdb_notifier.num_fds - 1)->revents = 0;
+#else
+      if (mask & GDB_READABLE)
+	FD_SET (fd, &gdb_notifier.check_masks[0]);
+      else
+	FD_CLR (fd, &gdb_notifier.check_masks[0]);
+
+      if (mask & GDB_WRITABLE)
+	FD_SET (fd, &gdb_notifier.check_masks[1]);
+      else
+	FD_CLR (fd, &gdb_notifier.check_masks[1]);
+
+      if (mask & GDB_EXCEPTION)
+	FD_SET (fd, &gdb_notifier.check_masks[2]);
+      else
+	FD_CLR (fd, &gdb_notifier.check_masks[2]);
+
+      if (gdb_notifier.num_fds <= fd)
+	gdb_notifier.num_fds = fd + 1;
+#endif
+    }
+
+  file_ptr->proc = proc;
+  file_ptr->client_data = client_data;
+  file_ptr->mask = mask;
+}
+
+/* Remove the file descriptor FD from the list of monitored fd's:
+   i.e. we don't care anymore about events on the FD. */
+void
+delete_file_handler (int fd)
+{
+  file_handler *file_ptr, *prev_ptr = NULL;
+  int i;
+#ifdef HAVE_POLL
+  int j;
+  struct pollfd *new_poll_fds;
+#endif
+
+  /* Find the entry for the given file. */
+
+  for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
+       file_ptr = file_ptr->next_file)
+    {
+      if (file_ptr->fd == fd)
+	break;
+    }
+
+  if (file_ptr == NULL)
+    return;
+
+#ifdef HAVE_POLL
+  /* Create a new poll_fds array by copying every fd's information but the
+     one we want to get rid of. */
+
+  new_poll_fds = malloc ((gdb_notifier.num_fds - 1) * sizeof (struct pollfd));
+
+  for (i = 0, j = 0; i < gdb_notifier.num_fds; i++)
+    {
+      if ((gdb_notifier.poll_fds + i)->fd != fd)
+	{
+	  (new_poll_fds + j)->fd = (gdb_notifier.poll_fds + i)->fd;
+	  (new_poll_fds + j)->events = (gdb_notifier.poll_fds + i)->events;
+	  (new_poll_fds + j)->revents = (gdb_notifier.poll_fds + i)->revents;
+	  j++;
+	}
+    }
+  free (gdb_notifier.poll_fds);
+  gdb_notifier.poll_fds = new_poll_fds;
+  gdb_notifier.num_fds--;
+#else
+  if (file_ptr->mask & GDB_READABLE)
+    FD_CLR (fd, &gdb_notifier.check_masks[0]);
+  if (file_ptr->mask & GDB_WRITABLE)
+    FD_CLR (fd, &gdb_notifier.check_masks[1]);
+  if (file_ptr->mask & GDB_EXCEPTION)
+    FD_CLR (fd, &gdb_notifier.check_masks[2]);
+
+  /* Find current max fd. */
+
+  if ((fd + 1) == gdb_notifier.num_fds)
+    {
+      gdb_notifier.num_fds--;
+      for (i = gdb_notifier.num_fds; i; i--)
+	{
+	  if (FD_ISSET (i - 1, &gdb_notifier.check_masks[0])
+	      || FD_ISSET (i - 1, &gdb_notifier.check_masks[1])
+	      || FD_ISSET (i - 1, &gdb_notifier.check_masks[2]))
+	    break;
+	}
+      gdb_notifier.num_fds = i;
+    }
+#endif /* HAVE_POLL */
+
+  /* Deactivate the file descriptor, by clearing its mask,
+     so that it will not fire again. */
+
+  file_ptr->mask = 0;
+
+  /* Get rid of the file handler in the file handler list. */
+  if (file_ptr == gdb_notifier.first_file_handler)
+    gdb_notifier.first_file_handler = file_ptr->next_file;
+  else
+    {
+      for (prev_ptr = gdb_notifier.first_file_handler;
+	   prev_ptr->next_file != file_ptr;
+	   prev_ptr = prev_ptr->next_file)
+	;
+      prev_ptr->next_file = file_ptr->next_file;
+    }
+  free (file_ptr);
+}
+
+/* Handle the given event by calling the procedure associated to the
+   corresponding file handler.  Called by process_event indirectly,
+   through event_ptr->proc.  EVENT_FILE_DESC is file descriptor of the
+   event in the front of the event queue. */
+static void
+handle_file_event (int event_file_desc)
+{
+  file_handler *file_ptr;
+  int mask;
+#ifdef HAVE_POLL
+  int error_mask;
+  int error_mask_returned;
+#endif
+
+  /* Search the file handler list to find one that matches the fd in
+     the event. */
+  for (file_ptr = gdb_notifier.first_file_handler; file_ptr != NULL;
+       file_ptr = file_ptr->next_file)
+    {
+      if (file_ptr->fd == event_file_desc)
+	{
+	  /* With poll, the ready_mask could have any of three events
+	     set to 1: POLLHUP, POLLERR, POLLNVAL. These events cannot
+	     be used in the requested event mask (events), but they
+	     can be returned in the return mask (revents). We need to
+	     check for those event too, and add them to the mask which
+	     will be passed to the handler. */
+
+	  /* See if the desired events (mask) match the received
+	     events (ready_mask). */
+
+#ifdef HAVE_POLL
+	  error_mask = POLLHUP | POLLERR | POLLNVAL;
+	  mask = (file_ptr->ready_mask & file_ptr->mask) |
+	    (file_ptr->ready_mask & error_mask);
+	  error_mask_returned = mask & error_mask;
+
+	  if (error_mask_returned != 0)
+	    {
+	      /* Work in progress.  We may need to tell somebody what
+		 kind of error we had. */
+	      if (error_mask_returned & POLLHUP)
+		printf ("Hangup detected on fd %d\n", file_ptr->fd);
+	      if (error_mask_returned & POLLERR)
+		printf ("Error detected on fd %d\n", file_ptr->fd);
+	      if (error_mask_returned & POLLNVAL)
+		printf ("Invalid or non-`poll'able fd %d\n", file_ptr->fd);
+	      file_ptr->error = 1;
+	    }
+	  else
+	    file_ptr->error = 0;
+#else
+	  if (file_ptr->ready_mask & GDB_EXCEPTION)
+	    {
+	      fprintf (stderr, "Exception condition detected on fd %d\n",
+		       file_ptr->fd);
+	      file_ptr->error = 1;
+	    }
+	  else
+	    file_ptr->error = 0;
+	  mask = file_ptr->ready_mask & file_ptr->mask;
+#endif /* HAVE_POLL */
+
+	  /* Clear the received events for next time around. */
+	  file_ptr->ready_mask = 0;
+
+	  /* If there was a match, then call the handler. */
+	  if (mask != 0)
+	    (*file_ptr->proc) (file_ptr->error, file_ptr->client_data);
+	  break;
+	}
+    }
+}
+
+/* Called by gdb_do_one_event to wait for new events on the
+   monitored file descriptors. Queue file events as they are
+   detected by the poll.
+   If there are no events, this function will block in the
+   call to poll.
+   Return -1 if there are no files descriptors to monitor,
+   otherwise return 0. */
+static int
+gdb_wait_for_event (void)
+{
+  file_handler *file_ptr;
+  gdb_event *file_event_ptr;
+  int num_found = 0;
+
+  /* Make sure all output is done before getting another event. */
+  fflush (stdout);
+  fflush (stderr);
+
+  if (gdb_notifier.num_fds == 0)
+    return -1;
+
+#ifdef HAVE_POLL
+  num_found =
+    poll (gdb_notifier.poll_fds,
+	  (unsigned long) gdb_notifier.num_fds, -1);
+
+  /* Don't print anything if we get out of poll because of a
+     signal. */
+  if (num_found == -1 && errno != EINTR)
+    perror_with_name (("poll"));
+#else
+  gdb_notifier.ready_masks[0] = gdb_notifier.check_masks[0];
+  gdb_notifier.ready_masks[1] = gdb_notifier.check_masks[1];
+  gdb_notifier.ready_masks[2] = gdb_notifier.check_masks[2];
+  num_found = select (gdb_notifier.num_fds,
+		      &gdb_notifier.ready_masks[0],
+		      &gdb_notifier.ready_masks[1],
+		      &gdb_notifier.ready_masks[2],
+		      NULL);
+
+  /* Clear the masks after an error from select. */
+  if (num_found == -1)
+    {
+      FD_ZERO (&gdb_notifier.ready_masks[0]);
+      FD_ZERO (&gdb_notifier.ready_masks[1]);
+      FD_ZERO (&gdb_notifier.ready_masks[2]);
+#ifdef EINTR
+      /* Dont print anything is we got a signal, let gdb handle it. */
+      if (errno != EINTR)
+	perror_with_name (("select"));
+#endif
+    }
+#endif /* HAVE_POLL */
+
+  /* Enqueue all detected file events. */
+
+#ifdef HAVE_POLL
+    {
+      int i;
+      for (i = 0; (i < gdb_notifier.num_fds) && (num_found > 0); i++)
+	{
+	  if ((gdb_notifier.poll_fds + i)->revents)
+	    num_found--;
+	  else
+	    continue;
+
+	  for (file_ptr = gdb_notifier.first_file_handler;
+	       file_ptr != NULL;
+	       file_ptr = file_ptr->next_file)
+	    {
+	      if (file_ptr->fd == (gdb_notifier.poll_fds + i)->fd)
+		break;
+	    }
+
+	  if (file_ptr)
+	    {
+	      /* Enqueue an event only if this is still a new event for
+	         this fd. */
+	      if (file_ptr->ready_mask == 0)
+		{
+		  file_event_ptr = create_file_event (file_ptr->fd);
+		  async_queue_event (file_event_ptr);
+		}
+	      file_ptr->ready_mask = (gdb_notifier.poll_fds + i)->revents;
+	    }
+	}
+    }
+#else
+    {
+      for (file_ptr = gdb_notifier.first_file_handler;
+	   (file_ptr != NULL) && (num_found > 0);
+	   file_ptr = file_ptr->next_file)
+	{
+	  int mask = 0;
+
+	  if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[0]))
+	    mask |= GDB_READABLE;
+	  if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[1]))
+	    mask |= GDB_WRITABLE;
+	  if (FD_ISSET (file_ptr->fd, &gdb_notifier.ready_masks[2]))
+	    mask |= GDB_EXCEPTION;
+
+	  if (!mask)
+	    continue;
+	  else
+	    num_found--;
+
+	  /* Enqueue an event only if this is still a new event for
+	     this fd. */
+
+	  if (file_ptr->ready_mask == 0)
+	    {
+	      file_event_ptr = create_file_event (file_ptr->fd);
+	      async_queue_event (file_event_ptr);
+	    }
+	  file_ptr->ready_mask = mask;
+	}
+    }
+#endif /* HAVE_POLL */
+  return 0;
+}
Index: src/gdb/gdbserver/inferiors.c
===================================================================
--- src.orig/gdb/gdbserver/inferiors.c	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/inferiors.c	2008-11-25 19:15:53.000000000 +0000
@@ -30,12 +30,88 @@ struct thread_info
   unsigned int gdb_id;
 };
 
+struct inferior_list all_processes;
 struct inferior_list all_threads;
 struct inferior_list all_dlls;
 int dlls_changed;
 
 struct thread_info *current_inferior;
 
+
+/* Oft used ptids */
+ptid_t null_ptid;
+ptid_t minus_one_ptid;
+
+/* Create a ptid given the necessary PID, LWP, and TID components.  */
+
+ptid_t
+ptid_build (int pid, long lwp, long tid)
+{
+  ptid_t ptid;
+
+  ptid.pid = pid;
+  ptid.lwp = lwp;
+  ptid.tid = tid;
+  return ptid;
+}
+
+/* Create a ptid from just a pid.  */
+
+ptid_t
+pid_to_ptid (int pid)
+{
+  return ptid_build (pid, 0, 0);
+}
+
+/* Fetch the pid (process id) component from a ptid.  */
+
+int
+ptid_get_pid (ptid_t ptid)
+{
+  return ptid.pid;
+}
+
+/* Fetch the lwp (lightweight process) component from a ptid.  */
+
+long
+ptid_get_lwp (ptid_t ptid)
+{
+  return ptid.lwp;
+}
+
+/* Fetch the tid (thread id) component from a ptid.  */
+
+long
+ptid_get_tid (ptid_t ptid)
+{
+  return ptid.tid;
+}
+
+/* ptid_equal() is used to test equality of two ptids.  */
+
+int
+ptid_equal (ptid_t ptid1, ptid_t ptid2)
+{
+  return (ptid1.pid == ptid2.pid
+	  && ptid1.lwp == ptid2.lwp
+	  && ptid1.tid == ptid2.tid);
+}
+
+/* Return true if this ptid represents a process.  */
+
+int
+ptid_is_pid (ptid_t ptid)
+{
+  if (ptid_equal (minus_one_ptid, ptid))
+    return 0;
+  if (ptid_equal (null_ptid, ptid))
+    return 0;
+
+  return (ptid_get_pid (ptid) != 0
+	  && ptid_get_lwp (ptid) == 0
+	  && ptid_get_tid (ptid) == 0);
+}
+
 #define get_thread(inf) ((struct thread_info *)(inf))
 #define get_dll(inf) ((struct dll_info *)(inf))
 
@@ -93,7 +169,7 @@ remove_inferior (struct inferior_list *l
 }
 
 void
-add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
+add_thread (ptid_t thread_id, void *target_data)
 {
   struct thread_info *new_thread = malloc (sizeof (*new_thread));
 
@@ -101,47 +177,45 @@ add_thread (unsigned long thread_id, voi
 
   new_thread->entry.id = thread_id;
 
-  add_inferior_to_list (&all_threads, & new_thread->entry);
+  add_inferior_to_list (&all_threads, &new_thread->entry);
 
   if (current_inferior == NULL)
     current_inferior = new_thread;
 
   new_thread->target_data = target_data;
   set_inferior_regcache_data (new_thread, new_register_cache ());
-  new_thread->gdb_id = gdb_id;
 }
 
-unsigned int
-thread_id_to_gdb_id (unsigned long thread_id)
+ptid_t
+thread_id_to_gdb_id (ptid_t thread_id)
 {
   struct inferior_list_entry *inf = all_threads.head;
 
   while (inf != NULL)
     {
-      struct thread_info *thread = get_thread (inf);
-      if (inf->id == thread_id)
-	return thread->gdb_id;
+      if (ptid_equal (inf->id, thread_id))
+	return thread_id;
       inf = inf->next;
     }
 
-  return 0;
+  return null_ptid;
 }
 
-unsigned int
+ptid_t
 thread_to_gdb_id (struct thread_info *thread)
 {
-  return thread->gdb_id;
+  return thread->entry.id;
 }
 
 struct thread_info *
-gdb_id_to_thread (unsigned int gdb_id)
+find_thread_pid (ptid_t ptid)
 {
   struct inferior_list_entry *inf = all_threads.head;
 
   while (inf != NULL)
     {
       struct thread_info *thread = get_thread (inf);
-      if (thread->gdb_id == gdb_id)
+      if (ptid_equal (thread->entry.id, ptid))
 	return thread;
       inf = inf->next;
     }
@@ -149,12 +223,12 @@ gdb_id_to_thread (unsigned int gdb_id)
   return NULL;
 }
 
-unsigned long
-gdb_id_to_thread_id (unsigned int gdb_id)
+ptid_t
+gdb_id_to_thread_id (ptid_t gdb_id)
 {
-  struct thread_info *thread = gdb_id_to_thread (gdb_id);
+  struct thread_info *thread = find_thread_pid (gdb_id);
 
-  return thread ? thread->entry.id : 0;
+  return thread ? thread->entry.id : null_ptid;
 }
 
 static void
@@ -180,22 +254,25 @@ find_inferior (struct inferior_list *lis
 
   while (inf != NULL)
     {
+      struct inferior_list_entry *next;
+
+      next = inf->next;
       if ((*func) (inf, arg))
 	return inf;
-      inf = inf->next;
+      inf = next;
     }
 
   return NULL;
 }
 
 struct inferior_list_entry *
-find_inferior_id (struct inferior_list *list, unsigned long id)
+find_inferior_id (struct inferior_list *list, ptid_t id)
 {
   struct inferior_list_entry *inf = list->head;
 
   while (inf != NULL)
     {
-      if (inf->id == id)
+      if (ptid_equal (inf->id, id))
 	return inf;
       inf = inf->next;
     }
@@ -264,7 +341,7 @@ loaded_dll (const char *name, CORE_ADDR 
   struct dll_info *new_dll = malloc (sizeof (*new_dll));
   memset (new_dll, 0, sizeof (*new_dll));
 
-  new_dll->entry.id = -1;
+  new_dll->entry.id = minus_one_ptid;
 
   new_dll->name = strdup (name);
   new_dll->base_addr = base_addr;
@@ -315,7 +392,7 @@ add_pid_to_list (struct inferior_list *l
   struct inferior_list_entry *new_entry;
 
   new_entry = malloc (sizeof (struct inferior_list_entry));
-  new_entry->id = pid;
+  new_entry->id = pid_to_ptid (pid);
   add_inferior_to_list (list, new_entry);
 }
 
@@ -324,7 +401,7 @@ pull_pid_from_list (struct inferior_list
 {
   struct inferior_list_entry *new_entry;
 
-  new_entry = find_inferior_id (list, pid);
+  new_entry = find_inferior_id (list, pid_to_ptid (pid));
   if (new_entry == NULL)
     return 0;
   else
@@ -334,3 +411,43 @@ pull_pid_from_list (struct inferior_list
       return 1;
     }
 }
+
+struct process_info *
+add_process (int pid, int attached)
+{
+  struct process_info *process;
+
+  process = (struct process_info *) malloc (sizeof (*process));
+  memset (process, 0, sizeof (*process));
+
+  process->head.id = pid_to_ptid (pid);
+  process->attached = attached;
+
+  add_inferior_to_list (&all_processes, &process->head);
+
+  return process;
+}
+
+struct process_info *
+current_process (void)
+{
+  struct process_info *process;
+  int pid;
+
+  if (current_inferior == NULL)
+    internal_error ("No current_inferior\n");
+
+  pid = ptid_get_pid (current_inferior->entry.id);
+  process = (struct process_info *) find_inferior_id (&all_processes,
+						      pid_to_ptid (pid));
+
+  return process;
+}
+
+
+void
+initialize_inferiors (void)
+{
+  null_ptid = ptid_build (0, 0, 0);
+  minus_one_ptid = ptid_build (-1, 0, 0);
+}
Index: src/gdb/gdbserver/linux-low.c
===================================================================
--- src.orig/gdb/gdbserver/linux-low.c	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/linux-low.c	2008-11-25 19:15:35.000000000 +0000
@@ -82,16 +82,19 @@
 #endif
 #endif
 
-/* ``all_threads'' is keyed by the LWP ID, which we use as the GDB protocol
-   representation of the thread ID.
+/* ``all_processes'' is keyed by the "overall process ID", which
+   GNU/Linux calls tgid, "thread group ID".
 
-   ``all_processes'' is keyed by the process ID - which on Linux is (presently)
-   the same as the LWP ID.  */
+   ``all_threads'' is keyed by the LWP ID, which we use as the GDB
+   protocol representation of the thread ID.
 
-struct inferior_list all_processes;
+   ``all_lwps'' is keyed by the LWP ID - on Linux the LWP IDs are
+   global (presently).  */
 
-/* A list of all unknown processes which receive stop signals.  Some other
-   process will presumably claim each of these as forked children
+struct inferior_list all_lwps;
+
+/* A list of all unknown lwps which receive stop signals.  Some other
+   lwp will presumably claim each of these as forked children
    momentarily.  */
 
 struct inferior_list stopped_pids;
@@ -101,22 +104,25 @@ int stopping_threads;
 
 /* FIXME make into a target method?  */
 int using_threads = 1;
-static int thread_db_active;
 
 static int must_set_ptrace_flags;
 
-/* This flag is true iff we've just created or attached to a new inferior
-   but it has not stopped yet.  As soon as it does, we need to call the
-   low target's arch_setup callback.  */
+/* This flag is true iff we've just created or attached to our first
+   inferior but it has not stopped yet.  As soon as it does, we need
+   to call the low target's arch_setup callback.  Doing this only on
+   the first inferior avoids reinializing the architecture on every
+   inferior, and avoids messing with the register caches of the
+   already running inferiors.  NOTE: this assumes all inferiors under
+   control of gdbserver have the same architecture.  */
 static int new_inferior;
 
-static void linux_resume_one_process (struct inferior_list_entry *entry,
-				      int step, int signal, siginfo_t *info);
-static void linux_resume (struct thread_resume *resume_info);
-static void stop_all_processes (void);
-static int linux_wait_for_event (struct thread_info *child);
-static int check_removed_breakpoint (struct process_info *event_child);
-static void *add_process (unsigned long pid);
+static void linux_resume_one_lwp (struct inferior_list_entry *entry,
+				  int step, int signal, siginfo_t *info);
+static void linux_resume (struct thread_resume *resume_info, size_t n);
+static void stop_all_lwps (void);
+static int linux_wait_for_event (ptid_t ptid, int *wstat, int options);
+static int check_removed_breakpoint (struct lwp_info *event_child);
+static void *add_lwp (ptid_t ptid);
 
 struct pending_signals
 {
@@ -133,23 +139,124 @@ static char *disabled_regsets;
 static int num_regsets;
 #endif
 
-#define pid_of(proc) ((proc)->head.id)
+#define pid_of(proc) ptid_get_pid ((proc)->head.id)
+#define lwpid_of(proc) ptid_get_lwp ((proc)->head.id)
+
+#define is_lwpid(ptid) (ptid_get_lwp (ptid) != 0)
 
 /* FIXME: Delete eventually.  */
-#define inferior_pid (pid_of (get_thread_process (current_inferior)))
+#define inferior_pid (pid_of (get_thread_lwp (current_inferior)))
+#define inferior_lwpid (lwpid_of (get_thread_lwp (current_inferior)))
+
+/* The read/write ends of the pipe registered as waitable file in the
+   event loop.  */
+static int linux_event_pipe[2] = { -1, -1 };
+
+/* True if we're currently in async mode.  */
+#define target_is_async_p() (linux_event_pipe[0] != -1)
+
+static int my_waitpid (int pid, int *status, int flags);
+static void send_sigstop (struct inferior_list_entry *entry);
+static void wait_for_sigstop (struct inferior_list_entry *entry);
+static int cancel_breakpoints_callback (struct inferior_list_entry *entry,
+					void *data);
+
+/* Add a process to the common process list, and set its private
+   data.  */
+
+static struct process_info *
+linux_add_process (int pid, int attached)
+{
+  struct process_info *proc;
+
+  proc = add_process (pid, attached);
+  proc->private = calloc (1, sizeof (*proc->private));
+
+  return proc;
+}
+
+/* Read the tgid of an lwp from `/proc/PID/status'.  */
+
+static int
+tgid_of_pid (int pid)
+{
+  FILE *status_file;
+  char buf[100];
+  int tgid = 0;
+
+  snprintf (buf, sizeof (buf), "/proc/%d/status", pid);
+  status_file = fopen (buf, "r");
+  if (status_file != NULL)
+    {
+      while (fgets (buf, sizeof (buf), status_file))
+	{
+	  if (strncmp (buf, "Tgid:", 5) == 0)
+	    {
+	      tgid = strtol (buf + 5, NULL, 0);
+	      break;
+	    }
+	}
+      fclose (status_file);
+    }
+
+  return tgid;
+}
+
+static char *
+linux_pid_to_exec_file (int pid)
+{
+  static char path[MAXPATHLEN];
+  char procexe[MAXPATHLEN];
+
+  sprintf (procexe, "/proc/%d/exe", pid);
+  if (readlink (procexe, path, MAXPATHLEN) > 0)
+    return path;
+  else
+    return NULL;
+}
+
+static int linux_supports_tracefork_flag;
 
 static void
-handle_extended_wait (struct process_info *event_child, int wstat)
+linux_enable_event_reporting (int pid)
+{
+  int options;
+
+  options = PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK
+    | PTRACE_O_TRACEEXEC | PTRACE_O_TRACECLONE;
+
+#if 0
+  /* TODO: We need to model this in the remote protocol.  */
+  if (linux_supports_tracevforkdone (pid))
+    options |= PTRACE_O_TRACEVFORKDONE;
+#endif
+
+  /* Do not enable PTRACE_O_TRACEEXIT until GDB is more prepared to support
+     read-only process state.  */
+  ptrace (PTRACE_SETOPTIONS, pid, 0, options);
+}
+
+/* Handle a GNU/Linux extended wait response.  If we see a clone
+   event, we need to add the new LWP to our list (and not report the
+   trap to higher layers).  This function returns non-zero if the
+   event should be ignored and we should wait again.  */
+
+static int
+handle_extended_wait (struct lwp_info *event_child, int wstat)
 {
   int event = wstat >> 16;
-  struct process_info *new_process;
+  struct lwp_info *new_lwp;
+  struct target_waitstatus *ourstatus = &event_child->waitstatus;
 
-  if (event == PTRACE_EVENT_CLONE)
+  if (event == PTRACE_EVENT_FORK
+      || event == PTRACE_EVENT_VFORK
+      || event == PTRACE_EVENT_CLONE)
     {
+      ptid_t ptid;
       unsigned long new_pid;
       int ret, status = W_STOPCODE (SIGSTOP);
 
-      ptrace (PTRACE_GETEVENTMSG, inferior_pid, 0, &new_pid);
+      ptrace (PTRACE_GETEVENTMSG, lwpid_of (event_child), 0, &new_pid);
 
       /* If we haven't already seen the new PID stop, wait for it now.  */
       if (! pull_pid_from_list (&stopped_pids, new_pid))
@@ -157,9 +264,7 @@ handle_extended_wait (struct process_inf
 	  /* The new child has a pending SIGSTOP.  We can't affect it until it
 	     hits the SIGSTOP, but we're already attached.  */
 
-	  do {
-	    ret = waitpid (new_pid, &status, __WALL);
-	  } while (ret == -1 && errno == EINTR);
+	  ret = my_waitpid (new_pid, &status, __WALL);
 
 	  if (ret == -1)
 	    perror_with_name ("waiting for new child");
@@ -169,54 +274,103 @@ handle_extended_wait (struct process_inf
 	    warning ("wait returned unexpected status 0x%x", status);
 	}
 
-      ptrace (PTRACE_SETOPTIONS, new_pid, 0, PTRACE_O_TRACECLONE);
+      ourstatus->value.related_pid = ptid_build (new_pid, new_pid, 0);
+
+      linux_enable_event_reporting (new_pid);
 
-      new_process = (struct process_info *) add_process (new_pid);
-      add_thread (new_pid, new_process, new_pid);
-      new_thread_notify (thread_id_to_gdb_id (new_process->lwpid));
-
-      /* Normally we will get the pending SIGSTOP.  But in some cases
-	 we might get another signal delivered to the group first.
-         If we do, be sure not to lose it.  */
-      if (WSTOPSIG (status) == SIGSTOP)
+      if (event == PTRACE_EVENT_FORK
+	  || event == PTRACE_EVENT_VFORK)
 	{
-	  if (stopping_threads)
-	    new_process->stopped = 1;
+	  int is_fork = (event == PTRACE_EVENT_FORK);
+
+	  if (is_fork)
+	    ourstatus->kind = TARGET_WAITKIND_FORKED;
 	  else
-	    ptrace (PTRACE_CONT, new_pid, 0, 0);
+	    ourstatus->kind = TARGET_WAITKIND_VFORKED;
+
+	  if (debug_threads)
+	    {
+	      if (is_fork)
+		fprintf (stderr, "PTRACE_EVENT_FORK pid=(%ld), newpid=(%ld)",
+			 lwpid_of (event_child), new_pid);
+	      else
+		fprintf (stderr, "PTRACE_EVENT_VFORK pid=(%ld), newpid=(%ld)",
+			 lwpid_of (event_child), new_pid);
+	    }
+
+	  linux_add_process (new_pid, 1);
+	  ptid = ptid_build (new_pid, new_pid, 0);
+	  new_lwp = (struct lwp_info *) add_lwp (ptid);
+	  new_lwp->stopped = 1;
+	  add_thread (ptid, new_lwp);
+
+	  event_child->stopped = 1;
+	  return 0;
 	}
       else
 	{
-	  new_process->stop_expected = 1;
-	  if (stopping_threads)
+	  ptid = ptid_build (pid_of (event_child), new_pid, 0);
+	  new_lwp = (struct lwp_info *) add_lwp (ptid);
+	  add_thread (ptid, new_lwp);
+#if 0
+	  new_thread_notify (thread_id_to_gdb_id (new_lwp->lwpid));
+#endif
+
+	  /* Normally we will get the pending SIGSTOP.  But in some
+	     cases we might get another signal delivered to the group
+	     first.  If we do, be sure not to lose it.  */
+	  if (WSTOPSIG (status) == SIGSTOP)
 	    {
-	      new_process->stopped = 1;
-	      new_process->status_pending_p = 1;
-	      new_process->status_pending = status;
+	      if (stopping_threads)
+		new_lwp->stopped = 1;
+	      else
+		ptrace (PTRACE_CONT, new_pid, 0, 0);
 	    }
 	  else
-	    /* Pass the signal on.  This is what GDB does - except
-	       shouldn't we really report it instead?  */
-	    ptrace (PTRACE_CONT, new_pid, 0, WSTOPSIG (status));
-	}
+	    {
+	      new_lwp->stop_expected = 1;
+	      if (stopping_threads)
+		{
+		  new_lwp->stopped = 1;
+		  new_lwp->status_pending_p = 1;
+		  new_lwp->status_pending = status;
+		}
+	      else
+		/* Pass the signal on.  This is what GDB does - except
+		   shouldn't we really report it instead?  */
+		ptrace (PTRACE_CONT, new_pid, 0, WSTOPSIG (status));
+	    }
 
-      /* Always resume the current thread.  If we are stopping
-	 threads, it will have a pending SIGSTOP; we may as well
-	 collect it now.  */
-      linux_resume_one_process (&event_child->head,
+	  /* Always resume the current thread.  If we are stopping
+	     threads, it will have a pending SIGSTOP; we may as well
+	     collect it now.  */
+	  linux_resume_one_lwp (&event_child->head,
 				event_child->stepping, 0, NULL);
+	  return 1;
+	}
+    }
+  else if (event == PTRACE_EVENT_EXEC)
+    {
+      fprintf (stderr, "got PTRACE_EVENT_EXEC\n");
+
+      ourstatus->kind = TARGET_WAITKIND_EXECD;
+      ourstatus->value.execd_pathname
+	= strdup (linux_pid_to_exec_file (lwpid_of (event_child)));
+      return 0;
     }
+
+  error ("unknown ptrace event %d", event);
 }
 
-/* This function should only be called if the process got a SIGTRAP.
+/* This function should only be called if the lwp got a SIGTRAP.
    The SIGTRAP could mean several things.
 
    On i386, where decr_pc_after_break is non-zero:
-   If we were single-stepping this process using PTRACE_SINGLESTEP,
+   If we were single-stepping this lwp using PTRACE_SINGLESTEP,
    we will get only the one SIGTRAP (even if the instruction we
    stepped over was a breakpoint).  The value of $eip will be the
    next instruction.
-   If we continue the process using PTRACE_CONT, we will get a
+   If we continue the lwp using PTRACE_CONT, we will get a
    SIGTRAP when we hit a breakpoint.  The value of $eip will be
    the instruction after the breakpoint (i.e. needs to be
    decremented).  If we report the SIGTRAP to GDB, we must also
@@ -235,26 +389,27 @@ get_stop_pc (void)
 {
   CORE_ADDR stop_pc = (*the_low_target.get_pc) ();
 
-  if (get_thread_process (current_inferior)->stepping)
+  if (get_thread_lwp (current_inferior)->stepping)
     return stop_pc;
   else
     return stop_pc - the_low_target.decr_pc_after_break;
 }
 
 static void *
-add_process (unsigned long pid)
+add_lwp (ptid_t ptid)
 {
-  struct process_info *process;
+  struct lwp_info *lwp;
+
+  lwp = (struct lwp_info *) malloc (sizeof (*lwp));
+  memset (lwp, 0, sizeof (*lwp));
 
-  process = (struct process_info *) malloc (sizeof (*process));
-  memset (process, 0, sizeof (*process));
+  lwp->head.id = ptid;
 
-  process->head.id = pid;
-  process->lwpid = pid;
+  lwp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
 
-  add_inferior_to_list (&all_processes, &process->head);
+  add_inferior_to_list (&all_lwps, &lwp->head);
 
-  return process;
+  return lwp;
 }
 
 /* Start an inferior process and returns its pid.
@@ -263,8 +418,9 @@ add_process (unsigned long pid)
 static int
 linux_create_inferior (char *program, char **allargs)
 {
-  void *new_process;
+  void *new_lwp;
   int pid;
+  ptid_t ptid;
 
 #if defined(__UCLIBC__) && defined(HAS_NOMMU)
   pid = vfork ();
@@ -292,10 +448,16 @@ linux_create_inferior (char *program, ch
       _exit (0177);
     }
 
-  new_process = add_process (pid);
-  add_thread (pid, new_process, pid);
+  /* If this the first process?  If so, then set the arch.  */
+  if (all_processes.head == NULL)
+    new_inferior = 1;
+
+  linux_add_process (pid, 0);
+
+  ptid = ptid_build (pid, pid, 0);
+  new_lwp = add_lwp (ptid);
+  add_thread (ptid, new_lwp);
   must_set_ptrace_flags = 1;
-  new_inferior = 1;
 
   return pid;
 }
@@ -303,165 +465,314 @@ linux_create_inferior (char *program, ch
 /* Attach to an inferior process.  */
 
 void
-linux_attach_lwp (unsigned long pid)
+linux_attach_lwp (unsigned long pid, int initial)
 {
-  struct process_info *new_process;
+  ptid_t ptid;
+  struct lwp_info *new_lwp;
 
   if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
     {
-      if (all_threads.head != NULL)
+      if (!initial)
 	{
 	  /* If we fail to attach to an LWP, just warn.  */
-	  fprintf (stderr, "Cannot attach to process %ld: %s (%d)\n", pid,
+	  fprintf (stderr, "Cannot attach to lwp %ld: %s (%d)\n", pid,
 		   strerror (errno), errno);
 	  fflush (stderr);
 	  return;
 	}
       else
-	/* If we fail to attach to a process, report an error.  */
-	error ("Cannot attach to process %ld: %s (%d)\n", pid,
-	       strerror (errno), errno);
+	{
+	  new_inferior = 0;
+
+	  /* If we fail to attach to a process, report an error.  */
+	  error ("Cannot attach to lwp %ld: %s (%d)\n", pid,
+		 strerror (errno), errno);
+	}
     }
 
-  ptrace (PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACECLONE);
+  linux_enable_event_reporting (pid);
 
-  new_process = (struct process_info *) add_process (pid);
-  add_thread (pid, new_process, pid);
-  new_thread_notify (thread_id_to_gdb_id (new_process->lwpid));
+  if (initial)
+    /* NOTE/FIXME: This lwp might have not been the tgid.  */
+    ptid = ptid_build (pid, pid, 0);
+  else
+    ptid = ptid_build (inferior_pid, pid, 0);
+
+  new_lwp = (struct lwp_info *) add_lwp (ptid);
+  add_thread (ptid, new_lwp);
+
+#if 0
+  new_thread_notify (thread_id_to_gdb_id (new_lwp->lwpid));
+#endif
 
   /* The next time we wait for this LWP we'll see a SIGSTOP as PTRACE_ATTACH
-     brings it to a halt.  We should ignore that SIGSTOP and resume the process
+     brings it to a halt.  We should ignore that SIGSTOP and resume the lwp
      (unless this is the first process, in which case the flag will be cleared
      in linux_attach).
 
      On the other hand, if we are currently trying to stop all threads, we
      should treat the new thread as if we had sent it a SIGSTOP.  This works
-     because we are guaranteed that add_process added us to the end of the
+     because we are guaranteed that add_lwp added us to the end of the
      list, and so the new thread has not yet reached wait_for_sigstop (but
      will).  */
   if (! stopping_threads)
-    new_process->stop_expected = 1;
+    new_lwp->stop_expected = 1;
 }
 
 int
 linux_attach (unsigned long pid)
 {
-  struct process_info *process;
+  struct lwp_info *lwp;
+  int tgid = tgid_of_pid (pid);
+
+  /* Maybe we could be smarter about this.  */
+  if (tgid != 0 && tgid != pid)
+    warning ("%s is a cloned process",
+	     target_pid_to_str (pid_to_ptid (pid)));
 
-  linux_attach_lwp (pid);
+  linux_attach_lwp (pid, 1);
+
+  /* If this the first process?  If so, then set the arch.  */
+  if (all_processes.head == NULL)
+    new_inferior = 1;
+
+  linux_add_process (pid, 1);
 
   /* Don't ignore the initial SIGSTOP if we just attached to this process.
      It will be collected by wait shortly.  */
-  process = (struct process_info *) find_inferior_id (&all_processes, pid);
-  process->stop_expected = 0;
+  lwp = (struct lwp_info *) find_inferior_id (&all_lwps,
+					      ptid_build (pid, pid, 0));
+  lwp->stop_expected = 0;
+
+  return 0;
+}
 
-  new_inferior = 1;
+struct counter
+{
+  int pid;
+  int count;
+};
+
+static int
+check_if_last_thread_of_pid (struct inferior_list_entry *entry, void *args)
+{
+  struct counter *counter = args;
+
+  if (ptid_get_pid (entry->id) == counter->pid)
+    {
+      counter->count++;
+
+      if (counter->count > 1)
+	/* OK, we know it's not the last, we can stop counting.  */
+	return 1;
+    }
 
   return 0;
 }
 
-/* Kill the inferior process.  Make us have no inferior.  */
+static int
+is_last_thread_of_process (struct thread_info *thread)
+{
+  ptid_t ptid = ((struct inferior_list_entry *)thread)->id;
+  int pid = ptid_get_pid (ptid);
+  struct counter counter = { pid , 0 };
 
-static void
-linux_kill_one_process (struct inferior_list_entry *entry)
+  return (find_inferior (&all_threads,
+			 check_if_last_thread_of_pid, &counter) == NULL);
+}
+
+/* Kill the inferior lwp.  */
+
+static int
+linux_kill_one_lwp (struct inferior_list_entry *entry, void *args)
 {
   struct thread_info *thread = (struct thread_info *) entry;
-  struct process_info *process = get_thread_process (thread);
+  struct lwp_info *lwp = get_thread_lwp (thread);
   int wstat;
+  int pid = * (int *) args;
+
+  if (ptid_get_pid (entry->id) != pid)
+    return 0;
 
   /* We avoid killing the first thread here, because of a Linux kernel (at
      least 2.6.0-test7 through 2.6.8-rc4) bug; if we kill the parent before
      the children get a chance to be reaped, it will remain a zombie
      forever.  */
-  if (entry == all_threads.head)
-    return;
+
+  if (pid_of (lwp) == lwpid_of (lwp))
+    {
+      if (debug_threads)
+	fprintf (stderr, "lkop: is last of process %s\n",
+		 target_pid_to_str (entry->id));
+      return 0;
+    }
+
+  /* If we're killing a running inferior, make sure it is stopped
+     first, as PTRACE_KILL will not work otherwise.  */
+  if (!lwp->stopped)
+    send_sigstop (&lwp->head);
 
   do
     {
-      ptrace (PTRACE_KILL, pid_of (process), 0, 0);
+      ptrace (PTRACE_KILL, lwpid_of (lwp), 0, 0);
 
       /* Make sure it died.  The loop is most likely unnecessary.  */
-      wstat = linux_wait_for_event (thread);
-    } while (WIFSTOPPED (wstat));
+      pid = my_waitpid (lwpid_of (lwp), &wstat, __WALL);
+    } while (pid == lwpid_of (lwp));
+
+  remove_inferior (&all_lwps, &lwp->head);
+  remove_thread (thread);
+
+  return 0;
 }
 
-static void
-linux_kill (void)
+static int
+linux_kill (int pid)
 {
-  struct thread_info *thread = (struct thread_info *) all_threads.head;
   struct process_info *process;
+  struct lwp_info *lwp;
+  struct thread_info *thread;
   int wstat;
+  int lwpid;
 
-  if (thread == NULL)
-    return;
+  process =
+    (struct process_info *) find_inferior_id (&all_processes, pid_to_ptid (pid));
 
-  for_each_inferior (&all_threads, linux_kill_one_process);
+  if (process == NULL)
+    return -1;
+
+  find_inferior (&all_threads, linux_kill_one_lwp, &pid);
 
-  /* See the comment in linux_kill_one_process.  We did not kill the first
+  /* See the comment in linux_kill_one_lwp.  We did not kill the first
      thread in the list, so do so now.  */
-  process = get_thread_process (thread);
+  lwp = find_lwp_pid (pid_to_ptid (pid));
+  thread = get_lwp_thread (lwp);
+
+  if (debug_threads)
+    fprintf (stderr, "lk_1: killing lwp %s, for pid: %d\n",
+	     target_pid_to_str (lwp->head.id), pid);
+
+  /* If we're killing a running inferior, make sure it is stopped
+     first, as PTRACE_KILL will not work otherwise.  */
+  if (!lwp->stopped)
+    send_sigstop (&lwp->head);
+
   do
     {
-      ptrace (PTRACE_KILL, pid_of (process), 0, 0);
+      ptrace (PTRACE_KILL, lwpid_of (lwp), 0, 0);
 
       /* Make sure it died.  The loop is most likely unnecessary.  */
-      wstat = linux_wait_for_event (thread);
-    } while (WIFSTOPPED (wstat));
+      lwpid = my_waitpid (lwpid_of (lwp), &wstat, __WALL);
+    } while (lwpid == lwpid_of (lwp));
 
-  clear_inferiors ();
-  free (all_processes.head);
-  all_processes.head = all_processes.tail = NULL;
+  remove_inferior (&all_lwps, &lwp->head);
+  remove_thread (thread);
+  remove_inferior (&all_processes, &process->head);
+
+  return 0;
 }
 
-static void
-linux_detach_one_process (struct inferior_list_entry *entry)
+static int
+linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
 {
   struct thread_info *thread = (struct thread_info *) entry;
-  struct process_info *process = get_thread_process (thread);
+  struct lwp_info *lp = get_thread_lwp (thread);
+  int pid = * (int *) args;
+
+  if (ptid_get_pid (entry->id) != pid)
+    return 0;
+
+  /* If we're detaching from a running inferior, make sure it is
+     stopped first, as PTRACE_DETACH will not work otherwise.  */
+  if (!lp->stopped)
+    {
+      send_sigstop (&lp->head);
+      wait_for_sigstop (&lp->head);
+    }
 
-  /* Make sure the process isn't stopped at a breakpoint that's
+  /* Make sure the LWP isn't stopped at a breakpoint that's
      no longer there.  */
-  check_removed_breakpoint (process);
+  check_removed_breakpoint (lp);
 
-  /* If this process is stopped but is expecting a SIGSTOP, then make
+  /* If this lwp is stopped but is expecting a SIGSTOP, then make
      sure we take care of that now.  This isn't absolutely guaranteed
      to collect the SIGSTOP, but is fairly likely to.  */
-  if (process->stop_expected)
+  if (lp->stop_expected)
     {
+      int wstat;
       /* Clear stop_expected, so that the SIGSTOP will be reported.  */
-      process->stop_expected = 0;
-      if (process->stopped)
-	linux_resume_one_process (&process->head, 0, 0, NULL);
-      linux_wait_for_event (thread);
+      lp->stop_expected = 0;
+      if (lp->stopped)
+	linux_resume_one_lwp (&lp->head, 0, 0, NULL);
+      linux_wait_for_event (lp->head.id, &wstat, __WALL);
     }
 
-  /* Flush any pending changes to the process's registers.  */
+  /* Flush any pending changes to the lwp's registers.  */
   regcache_invalidate_one ((struct inferior_list_entry *)
-			   get_process_thread (process));
+			   get_lwp_thread (lp));
 
   /* Finally, let it resume.  */
-  ptrace (PTRACE_DETACH, pid_of (process), 0, 0);
+  ptrace (PTRACE_DETACH, lwpid_of (lp), 0, 0);
+
+  /* Get rid of it.  */
+  remove_inferior (&all_lwps, &lp->head);
+  remove_thread (thread);
+
+  return 0;
 }
 
 static int
-linux_detach (void)
+any_thread_of (struct inferior_list_entry *entry, void *args)
 {
+  int *pid_p = args;
+
+  if (ptid_get_pid (entry->id) == *pid_p)
+    return 1;
+
+  return 0;
+}
+
+static int
+linux_detach (int pid)
+{
+  struct process_info *process;
+
+  process =
+    (struct process_info *) find_inferior_id (&all_processes,
+					      pid_to_ptid (pid));
+
+  if (process == NULL)
+    return -1;
+
+  current_inferior =
+    (struct thread_info *) find_inferior (&all_threads, any_thread_of, &pid);
+
   delete_all_breakpoints ();
-  for_each_inferior (&all_threads, linux_detach_one_process);
-  clear_inferiors ();
-  free (all_processes.head);
-  all_processes.head = all_processes.tail = NULL;
+  find_inferior (&all_threads, linux_detach_one_lwp, &pid);
+
+  remove_inferior (&all_processes, &process->head);
   return 0;
 }
 
 static void
-linux_join (void)
+linux_join (int pid)
 {
-  extern unsigned long signal_pid;
   int status, ret;
 
+  struct process_info *process;
+  process = (struct process_info *) find_inferior_id (&all_processes,
+						      pid_to_ptid (pid));
+
+  if (!process)
+    return; /* weird */
+
+  /* If we are attached, then we can exit.  Otherwise, we need to hang
+     around doing nothing, until the child is gone.  */
+  if (process->attached)
+    return;
+
   do {
-    ret = waitpid (signal_pid, &status, 0);
+    ret = my_waitpid (pid, &status, 0);
     if (WIFEXITED (status) || WIFSIGNALED (status))
       break;
   } while (ret != -1 || errno != ECHILD);
@@ -469,19 +780,24 @@ linux_join (void)
 
 /* Return nonzero if the given thread is still alive.  */
 static int
-linux_thread_alive (unsigned long lwpid)
+linux_thread_alive (ptid_t ptid)
 {
-  if (find_inferior_id (&all_threads, lwpid) != NULL)
-    return 1;
+  struct lwp_info *lwp = find_lwp_pid (ptid);
+
+  /* We assume we always know if a thread exits.  If a whole process
+     exited but we still haven't been able to report it to GDB, we'll
+     hold on to the last lwp of the dead process.  */
+  if (lwp != NULL)
+    return !lwp->dead;
   else
     return 0;
 }
 
-/* Return nonzero if this process stopped at a breakpoint which
+/* Return nonzero if this lwp stopped at a breakpoint which
    no longer appears to be inserted.  Also adjust the PC
    appropriately to resume where the breakpoint used to be.  */
 static int
-check_removed_breakpoint (struct process_info *event_child)
+check_removed_breakpoint (struct lwp_info *event_child)
 {
   CORE_ADDR stop_pc;
   struct thread_info *saved_inferior;
@@ -490,11 +806,11 @@ check_removed_breakpoint (struct process
     return 0;
 
   if (debug_threads)
-    fprintf (stderr, "Checking for breakpoint in process %ld.\n",
-	     event_child->lwpid);
+    fprintf (stderr, "Checking for breakpoint in lwp %ld.\n",
+	     lwpid_of (event_child));
 
   saved_inferior = current_inferior;
-  current_inferior = get_process_thread (event_child);
+  current_inferior = get_lwp_thread (event_child);
 
   stop_pc = get_stop_pc ();
 
@@ -539,63 +855,182 @@ check_removed_breakpoint (struct process
   return 1;
 }
 
-/* Return 1 if this process has an interesting status pending.  This function
-   may silently resume an inferior process.  */
+/* Return 1 if this lwp has an interesting status pending.  This function
+   may silently resume an inferior lwp.  */
 static int
-status_pending_p (struct inferior_list_entry *entry, void *dummy)
+status_pending_p (struct inferior_list_entry *entry, void *arg)
 {
-  struct process_info *process = (struct process_info *) entry;
+  struct lwp_info *lwp = (struct lwp_info *) entry;
+  ptid_t ptid = * (ptid_t *) arg;
 
-  if (process->status_pending_p)
-    if (check_removed_breakpoint (process))
+  /* Check if we're only interested in events from a specific process
+     or its lwps.  */
+  if (!ptid_equal (minus_one_ptid, ptid)
+      && ptid_get_pid (ptid) != ptid_get_pid (lwp->head.id))
+    return 0;
+
+  if (lwp->status_pending_p && !lwp->suspended)
+    if (check_removed_breakpoint (lwp))
       {
 	/* This thread was stopped at a breakpoint, and the breakpoint
 	   is now gone.  We were told to continue (or step...) all threads,
 	   so GDB isn't trying to single-step past this breakpoint.
 	   So instead of reporting the old SIGTRAP, pretend we got to
 	   the breakpoint just after it was removed instead of just
-	   before; resume the process.  */
-	linux_resume_one_process (&process->head, 0, 0, NULL);
+	   before; resume the lwp.  */
+	linux_resume_one_lwp (&lwp->head, 0, 0, NULL);
 	return 0;
       }
 
-  return process->status_pending_p;
+  return (lwp->status_pending_p && !lwp->suspended);
 }
 
-static void
-linux_wait_for_process (struct process_info **childp, int *wstatp)
+static int
+same_lwp (struct inferior_list_entry *entry, void *data)
 {
-  int ret;
-  int to_wait_for = -1;
+  ptid_t ptid = *(ptid_t *) data;
+  int lwp;
 
-  if (*childp != NULL)
-    to_wait_for = (*childp)->lwpid;
+  if (ptid_get_lwp (ptid) != 0)
+    lwp = ptid_get_lwp (ptid);
+  else
+    lwp = ptid_get_pid (ptid);
 
-retry:
-  while (1)
+  if (ptid_get_lwp (entry->id) == lwp)
+    return 1;
+
+  return 0;
+}
+
+struct lwp_info *
+find_lwp_pid (ptid_t ptid)
+{
+  return (struct lwp_info*) find_inferior (&all_lwps, same_lwp, &ptid);
+}
+
+/* Wrapper function for waitpid which handles EINTR, and emulates
+   __WALL for systems where that is not available.  */
+
+static int
+my_waitpid (int pid, int *status, int flags)
+{
+  int ret, out_errno;
+
+  if (debug_threads)
+    fprintf (stderr, "my_waitpid (%d, 0x%x)\n", pid, flags);
+
+  if (flags & __WALL)
     {
-      ret = waitpid (to_wait_for, wstatp, WNOHANG);
+      sigset_t mask;
+      sigset_t org_mask;
+      sigset_t suspend_mask;
 
-      if (ret == -1)
-	{
-	  if (errno != ECHILD)
-	    perror_with_name ("waitpid");
-	}
-      else if (ret > 0)
-	break;
+      int org_flags = flags;
+      int wnohang = (flags & WNOHANG) != 0;
+      flags &= ~__WALL;
+      flags |= WNOHANG;
+      flags &= ~__WCLONE;
+
+      sigemptyset (&mask);
+      sigaddset (&mask, SIGCHLD);
+
+      sigprocmask (SIG_BLOCK, &mask, &org_mask);
 
-      ret = waitpid (to_wait_for, wstatp, WNOHANG | __WCLONE);
+      /* Any signal unblocks the sigsuspend below.  */
+      sigemptyset (&suspend_mask);
 
-      if (ret == -1)
+      while (1)
 	{
-	  if (errno != ECHILD)
-	    perror_with_name ("waitpid (WCLONE)");
+	  do
+	    {
+	      errno = 0;
+	      ret = waitpid (pid, status, flags);
+	    }
+	  while (ret == -1 && errno == EINTR);
+	  out_errno = errno;
+
+	  if (ret == -1)
+	    {
+	      if (out_errno != ECHILD)
+		break;
+
+	      /* We know there's no child of this flavour, recurse
+		 with the right type.  */
+	      org_flags &= ~__WALL;
+	      org_flags |= (flags & __WCLONE) ? 0 : __WCLONE;
+	      ret = my_waitpid (pid, status, org_flags);
+	      out_errno = errno;
+	      break;
+	    }
+	  else if (ret > 0)
+	    break;
+
+	  if (flags & __WCLONE)
+	    {
+	      if (wnohang)
+		break;
+	      else
+		{
+		  if (debug_threads)
+		    fprintf (stderr, "blocking\n");
+
+		  /* Block waiting for any signal.  Ideally, we'd wait for
+		     SIGCHLD and LinuxThreads' signals, but this avoids
+		     knowing which signals those are.  */
+		  sigsuspend (&suspend_mask);
+		}
+	    }
+
+	  flags ^= __WCLONE;
 	}
-      else if (ret > 0)
-	break;
 
-      usleep (1000);
+      sigprocmask (SIG_SETMASK, &org_mask, NULL);
     }
+  else
+    {
+      do
+	ret = waitpid (pid, status, flags);
+      while (ret == -1 && errno == EINTR);
+      out_errno = errno;
+    }
+
+  if (debug_threads)
+    fprintf (stderr, "my_waitpid (%d, 0x%x): status(%x), %d\n",
+	     pid, flags, status ? *status : -1, ret);
+
+  errno = out_errno;
+  return ret;
+}
+
+static struct lwp_info *
+linux_wait_for_lwp (ptid_t ptid, int *wstatp, int options)
+{
+  int ret;
+  int to_wait_for = -1;
+  struct lwp_info *child = NULL;
+
+  if (debug_threads)
+    fprintf (stderr, "linux_wait_for_lwp: %s\n", target_pid_to_str (ptid));
+
+  if (ptid_equal (ptid, minus_one_ptid))
+    to_wait_for = -1;			/* any child */
+  else if (is_lwpid (ptid))
+    to_wait_for = ptid_get_lwp (ptid);	/* this lwp only */
+  else
+    to_wait_for = -1;			/* a specific tgid, but this
+					   is not possible.  We wait
+					   for everything, and cache
+					   what we don't need now.  */
+
+  options |= __WALL;
+
+retry:
+
+  ret = my_waitpid (to_wait_for, wstatp, options);
+  if (ret == 0 || (ret == -1 && errno == ECHILD && (options & WNOHANG)))
+    return NULL;
+  else if (ret == -1)
+    perror_with_name ("waitpid");
 
   if (debug_threads
       && (!WIFSTOPPED (*wstatp)
@@ -603,25 +1038,30 @@ retry:
 	      && WSTOPSIG (*wstatp) != 33)))
     fprintf (stderr, "Got an event from %d (%x)\n", ret, *wstatp);
 
-  if (to_wait_for == -1)
-    *childp = (struct process_info *) find_inferior_id (&all_processes, ret);
+  child = find_lwp_pid (pid_to_ptid (ret));
 
-  /* If we didn't find a process, one of two things presumably happened:
-     - A process we started and then detached from has exited.  Ignore it.
-     - A process we are controlling has forked and the new child's stop
+  /* If we didn't find a lwp, one of two things presumably happened:
+     - A lwp we started and then detached from has exited.  Ignore it.
+     - A lwp we are controlling has forked and the new child's stop
      was reported to us by the kernel.  Save its PID.  */
-  if (*childp == NULL && WIFSTOPPED (*wstatp))
+  if (child == NULL && WIFSTOPPED (*wstatp))
     {
       add_pid_to_list (&stopped_pids, ret);
+      if (options & WNOHANG)
+	return NULL;
+      goto retry;
+    }
+  else if (child == NULL)
+    {
+      if (options & WNOHANG)
+	return NULL;
       goto retry;
     }
-  else if (*childp == NULL)
-    goto retry;
 
-  (*childp)->stopped = 1;
-  (*childp)->pending_is_breakpoint = 0;
+  child->stopped = 1;
+  child->pending_is_breakpoint = 0;
 
-  (*childp)->last_status = *wstatp;
+  child->last_status = *wstatp;
 
   /* Architecture-specific setup after inferior is running.
      This needs to happen after we have attached to the inferior
@@ -640,117 +1080,184 @@ retry:
       && WIFSTOPPED (*wstatp))
     {
       current_inferior = (struct thread_info *)
-	find_inferior_id (&all_threads, (*childp)->lwpid);
+	find_inferior_id (&all_threads, child->head.id);
       /* For testing only; i386_stop_pc prints out a diagnostic.  */
       if (the_low_target.get_pc != NULL)
 	get_stop_pc ();
     }
+
+  if (ptid_is_pid (ptid))
+    {
+      if (pid_of (child) != ptid_get_pid (ptid))
+	{
+	  if (debug_threads)
+	    fprintf (stderr, "LWP %ld got an event %06x, leaving pending.\n",
+		     lwpid_of (child), *wstatp);
+	  child->status_pending_p = 1;
+	  child->status_pending = *wstatp;
+	  if ((options & WNOHANG) == 0)
+	    goto retry;
+
+	  child = NULL;
+	}
+    }
+
+  return child;
+}
+
+static int
+resume_stopped_lwps (struct inferior_list_entry *entry, void *arg)
+{
+  ptid_t ptid = * (ptid_t *) arg;
+  struct lwp_info *lwp = (struct lwp_info *) entry;
+
+  if ((ptid_equal (ptid, minus_one_ptid)
+       || (ptid_is_pid (ptid)
+	   && ptid_get_pid (ptid) == pid_of (lwp)))
+      && lwp->stopped
+      && !lwp->suspended)
+    {
+      if (debug_threads)
+	fprintf (stderr, "resuming stopped LWP %ld\n", lwpid_of (lwp));
+      linux_resume_one_lwp (&lwp->head, 0, 0, NULL);
+    }
+
+  return 0;
 }
 
+
 static int
-linux_wait_for_event (struct thread_info *child)
+linux_wait_for_event (ptid_t ptid, int *wstat, int options)
 {
   CORE_ADDR stop_pc;
-  struct process_info *event_child;
-  int wstat;
+  struct lwp_info *event_child = NULL;
   int bp_status;
+  struct lwp_info *requested_child = NULL;
 
-  /* Check for a process with a pending status.  */
+  /* Check for a lwp with a pending status.  */
   /* It is possible that the user changed the pending task's registers since
      it stopped.  We correctly handle the change of PC if we hit a breakpoint
      (in check_removed_breakpoint); signals should be reported anyway.  */
-  if (child == NULL)
+
+  if (ptid_equal (ptid, minus_one_ptid)
+      || ptid_equal (pid_to_ptid (ptid_get_pid (ptid)), ptid))
     {
-      event_child = (struct process_info *)
-	find_inferior (&all_processes, status_pending_p, NULL);
+      event_child = (struct lwp_info *)
+	find_inferior (&all_lwps, status_pending_p, &ptid);
       if (debug_threads && event_child)
-	fprintf (stderr, "Got a pending child %ld\n", event_child->lwpid);
+	fprintf (stderr, "Got a pending child %ld\n", lwpid_of (event_child));
+
+      /* If we just handled a pending status, and the event was not
+	 interesting to report to GDB, we will reach here again.  This
+	 time, we may find that there are no more interesting pending
+	 statuses to handle, but, the previous iteration left all
+	 threads stopped.  Resume them now.
+
+	 Don't do this in non-stop mode, as that would resume threads
+	 silently behind GDB's back --- e.g., just after starting a
+	 new inferior, we could get here due to a spurious
+	 target_wait(..., TARGET_WNOHANG) call.  In that case, we
+	 don't want to resume all stopped threads.  In all-stop, there
+	 should be no wnohang calls, so we always want to resume
+	 threads.  */
+      if (!non_stop && !event_child)
+	find_inferior (&all_lwps, resume_stopped_lwps, &ptid);
     }
   else
     {
-      event_child = get_thread_process (child);
-      if (event_child->status_pending_p
-	  && check_removed_breakpoint (event_child))
-	event_child = NULL;
+      requested_child = find_lwp_pid (ptid);
+      if (requested_child->status_pending_p
+	  && !check_removed_breakpoint (requested_child))
+	event_child = requested_child;
     }
 
   if (event_child != NULL)
     {
-      if (event_child->status_pending_p)
-	{
-	  if (debug_threads)
-	    fprintf (stderr, "Got an event from pending child %ld (%04x)\n",
-		     event_child->lwpid, event_child->status_pending);
-	  wstat = event_child->status_pending;
-	  event_child->status_pending_p = 0;
-	  event_child->status_pending = 0;
-	  current_inferior = get_process_thread (event_child);
-	  return wstat;
-	}
+      if (debug_threads)
+	fprintf (stderr, "Got an event from pending child %ld (%04x)\n",
+		 ptid_get_lwp (event_child->head.id), event_child->status_pending);
+      *wstat = event_child->status_pending;
+      event_child->status_pending_p = 0;
+      event_child->status_pending = 0;
     }
 
-  /* We only enter this loop if no process has a pending wait status.  Thus
-     any action taken in response to a wait status inside this loop is
-     responding as soon as we detect the status, not after any pending
-     events.  */
-  while (1)
-    {
-      if (child == NULL)
-	event_child = NULL;
-      else
-	event_child = get_thread_process (child);
+  /* If no lwp of interested had a pending wait status, wait for
+     one.  */
+  if (!event_child)
+    event_child = linux_wait_for_lwp (ptid, wstat, options);
 
-      linux_wait_for_process (&event_child, &wstat);
+    {
+      if ((options & WNOHANG) && event_child == NULL)
+	return -1;
 
       if (event_child == NULL)
 	error ("event from unknown child");
 
-      current_inferior = (struct thread_info *)
-	find_inferior_id (&all_threads, event_child->lwpid);
+      current_inferior = get_lwp_thread (event_child);
 
       /* Check for thread exit.  */
-      if (! WIFSTOPPED (wstat))
+      if (! WIFSTOPPED (*wstat))
 	{
 	  if (debug_threads)
-	    fprintf (stderr, "LWP %ld exiting\n", event_child->head.id);
+	    fprintf (stderr, "LWP %ld exiting\n",
+		     ptid_get_lwp (event_child->head.id));
 
 	  /* If the last thread is exiting, just return.  */
-	  if (all_threads.head == all_threads.tail)
-	    return wstat;
-
+	  if (is_last_thread_of_process (current_inferior))
+	    {
+	      if (debug_threads)
+		fprintf (stderr, "LWP %ld is last lwp of process\n",
+			 ptid_get_lwp (event_child->head.id));
+	      return 0;
+	    }
+#if 0
 	  dead_thread_notify (thread_id_to_gdb_id (event_child->lwpid));
+#endif
 
-	  remove_inferior (&all_processes, &event_child->head);
+	  remove_inferior (&all_lwps, &event_child->head);
 	  free (event_child);
 	  remove_thread (current_inferior);
-	  current_inferior = (struct thread_info *) all_threads.head;
+
+	  if (!non_stop)
+	    {
+	      current_inferior = (struct thread_info *) all_threads.head;
+	      if (debug_threads)
+		fprintf (stderr, "Current inferior is now %ld\n",
+			 lwpid_of (get_thread_lwp (current_inferior)));
+	    }
+	  else
+	    {
+	      current_inferior = NULL;
+	      if (debug_threads)
+		fprintf (stderr, "Current inferior is now <NULL>\n");
+	    }
 
 	  /* If we were waiting for this particular child to do something...
 	     well, it did something.  */
-	  if (child != NULL)
-	    return wstat;
+	  if (requested_child != NULL)
+	    return 0;
 
 	  /* Wait for a more interesting event.  */
-	  continue;
+	  return -1;
 	}
 
-      if (WIFSTOPPED (wstat)
-	  && WSTOPSIG (wstat) == SIGSTOP
+      if (WIFSTOPPED (*wstat)
+	  && WSTOPSIG (*wstat) == SIGSTOP
 	  && event_child->stop_expected)
 	{
 	  if (debug_threads)
 	    fprintf (stderr, "Expected stop.\n");
 	  event_child->stop_expected = 0;
-	  linux_resume_one_process (&event_child->head,
-				    event_child->stepping, 0, NULL);
-	  continue;
+	  linux_resume_one_lwp (&event_child->head,
+				event_child->stepping, 0, NULL);
+	  return -1;
 	}
 
-      if (WIFSTOPPED (wstat) && WSTOPSIG (wstat) == SIGTRAP
-	  && wstat >> 16 != 0)
+      if (WIFSTOPPED (*wstat) && WSTOPSIG (*wstat) == SIGTRAP
+	  && *wstat >> 16 != 0)
 	{
-	  handle_extended_wait (event_child, wstat);
-	  continue;
+	  if (handle_extended_wait (event_child, *wstat))
+	    return -1;
 	}
 
       /* If GDB is not interested in this signal, don't stop other
@@ -762,47 +1269,49 @@ linux_wait_for_event (struct thread_info
 	 special handling to skip the signal handler.  */
       /* FIXME drow/2002-06-09: Get signal numbers from the inferior's
 	 thread library?  */
-      if (WIFSTOPPED (wstat)
+      if (WIFSTOPPED (*wstat)
 	  && !event_child->stepping
 	  && (
 #ifdef USE_THREAD_DB
-	      (thread_db_active && (WSTOPSIG (wstat) == __SIGRTMIN
-				    || WSTOPSIG (wstat) == __SIGRTMIN + 1))
+	      (current_process ()->private->thread_db_active
+	       && (WSTOPSIG (*wstat) == __SIGRTMIN
+		   || WSTOPSIG (*wstat) == __SIGRTMIN + 1))
 	      ||
 #endif
-	      (pass_signals[target_signal_from_host (WSTOPSIG (wstat))]
-	       && (WSTOPSIG (wstat) != SIGSTOP || !stopping_threads))))
+	      (pass_signals[target_signal_from_host (WSTOPSIG (*wstat))]
+	       && (WSTOPSIG (*wstat) != SIGSTOP || !stopping_threads))))
 	{
 	  siginfo_t info, *info_p;
 
 	  if (debug_threads)
 	    fprintf (stderr, "Ignored signal %d for LWP %ld.\n",
-		     WSTOPSIG (wstat), event_child->head.id);
+		     WSTOPSIG (*wstat), ptid_get_lwp (event_child->head.id));
 
-	  if (ptrace (PTRACE_GETSIGINFO, event_child->lwpid, 0, &info) == 0)
+	  if (ptrace (PTRACE_GETSIGINFO, ptid_get_lwp (event_child->head.id), 0, &info) == 0)
 	    info_p = &info;
 	  else
 	    info_p = NULL;
-	  linux_resume_one_process (&event_child->head,
-				    event_child->stepping,
-				    WSTOPSIG (wstat), info_p);
-	  continue;
+
+	  linux_resume_one_lwp (&event_child->head,
+				event_child->stepping,
+				WSTOPSIG (*wstat), info_p);
+	  return -1;
 	}
 
       /* If this event was not handled above, and is not a SIGTRAP, report
 	 it.  */
-      if (!WIFSTOPPED (wstat) || WSTOPSIG (wstat) != SIGTRAP)
-	return wstat;
+      if (!WIFSTOPPED (*wstat) || WSTOPSIG (*wstat) != SIGTRAP)
+	return 0;
 
       /* If this target does not support breakpoints, we simply report the
 	 SIGTRAP; it's of no concern to us.  */
       if (the_low_target.get_pc == NULL)
-	return wstat;
+	return 0;
 
       stop_pc = get_stop_pc ();
 
       /* bp_reinsert will only be set if we were single-stepping.
-	 Notice that we will resume the process after hitting
+	 Notice that we will resume the lwp after hitting
 	 a gdbserver breakpoint; single-stepping to/over one
 	 is not supported (yet).  */
       if (event_child->bp_reinsert != 0)
@@ -813,8 +1322,8 @@ linux_wait_for_event (struct thread_info
 	  event_child->bp_reinsert = 0;
 
 	  /* Clear the single-stepping flag and SIGTRAP as we resume.  */
-	  linux_resume_one_process (&event_child->head, 0, 0, NULL);
-	  continue;
+	  linux_resume_one_lwp (&event_child->head, 0, 0, NULL);
+	  return -1;
 	}
 
       bp_status = check_breakpoints (stop_pc);
@@ -847,24 +1356,29 @@ linux_wait_for_event (struct thread_info
 
 	     Otherwise, call the target function to figure out where we need
 	     our temporary breakpoint, create it, and continue executing this
-	     process.  */
+	     lwp.  */
+
+	  /* NOTE: we're lifting breakpoints in non-stop mode.  This
+	     is currently only used for thread event breakpoints, so
+	     it isn't that bad as long as we have PTRACE_EVENT_CLONE
+	     events.  */
 	  if (bp_status == 2)
 	    /* No need to reinsert.  */
-	    linux_resume_one_process (&event_child->head, 0, 0, NULL);
+	    linux_resume_one_lwp (&event_child->head, 0, 0, NULL);
 	  else if (the_low_target.breakpoint_reinsert_addr == NULL)
 	    {
 	      event_child->bp_reinsert = stop_pc;
 	      uninsert_breakpoint (stop_pc);
-	      linux_resume_one_process (&event_child->head, 1, 0, NULL);
+	      linux_resume_one_lwp (&event_child->head, 1, 0, NULL);
 	    }
 	  else
 	    {
 	      reinsert_breakpoint_by_bp
 		(stop_pc, (*the_low_target.breakpoint_reinsert_addr) ());
-	      linux_resume_one_process (&event_child->head, 0, 0, NULL);
+	      linux_resume_one_lwp (&event_child->head, 0, 0, NULL);
 	    }
 
-	  continue;
+	  return -1;
 	}
 
       if (debug_threads)
@@ -882,11 +1396,11 @@ linux_wait_for_event (struct thread_info
       if (event_child->stepping)
 	{
 	  event_child->stepping = 0;
-	  return wstat;
+	  return 0;
 	}
 
       /* A SIGTRAP that we can't explain.  It may have been a breakpoint.
-	 Check if it is a breakpoint, and if so mark the process information
+	 Check if it is a breakpoint, and if so mark the lwp information
 	 accordingly.  This will handle both the necessary fiddling with the
 	 PC on decr_pc_after_break targets and suppressing extra threads
 	 hitting a breakpoint if two hit it at once and then GDB removes it
@@ -899,7 +1413,7 @@ linux_wait_for_event (struct thread_info
 	  event_child->pending_stop_pc = stop_pc;
 	}
 
-      return wstat;
+      return 0;
     }
 
   /* NOTREACHED */
@@ -908,84 +1422,205 @@ linux_wait_for_event (struct thread_info
 
 /* Wait for process, returns status.  */
 
-static unsigned char
-linux_wait (char *status)
+static ptid_t
+linux_wait_1 (ptid_t ptid, struct target_waitstatus *ourstatus, int target_options)
+{
+  int w;
+  struct thread_info *thread = NULL;
+  struct lwp_info *lwp = NULL;
+  int options;
+
+  /* Translate generic target options into linux options.  */
+  options = __WALL;
+  if (target_options & TARGET_WNOHANG)
+    options |= WNOHANG;
+
+  ourstatus->kind = TARGET_WAITKIND_IGNORE;
+
+  /* If we were only supposed to resume one thread, only wait for
+     that thread - if it's still alive.  If it died, however - which
+     can happen if we're coming from the thread death case below -
+     then we need to make sure we restart the other threads.  We could
+     pick a thread at random or restart all; restarting all is less
+     arbitrary.  */
+  /* TODO: Check if the incoming PTID is requesting an event for an
+     lwp of another process?  */
+  /* Don't do this in non-stop.  */
+  if (!non_stop
+      && !ptid_equal (cont_thread, null_ptid)
+      && !ptid_equal (cont_thread, minus_one_ptid))
+    {
+      thread = (struct thread_info *) find_inferior_id (&all_threads,
+							cont_thread);
+
+      /* No stepping, no signal - unless one is pending already, of course.  */
+      if (thread == NULL)
+	{
+	  struct thread_resume resume_info;
+	  resume_info.thread = minus_one_ptid;
+	  resume_info.kind = rk_continue;
+	  resume_info.sig = 0;
+	  linux_resume (&resume_info, 1);
+	}
+      else
+	ptid = cont_thread;
+    }
+
+  if (linux_wait_for_event (ptid, &w, options) != 0)
+    return minus_one_ptid;
+
+  if (!non_stop)
+    stop_all_lwps ();
+
+  if (must_set_ptrace_flags)
+    {
+      linux_enable_event_reporting (inferior_lwpid);
+      must_set_ptrace_flags = 0;
+    }
+
+  /* If we are waiting for a particular child, and it exited,
+     linux_wait_for_event will return its exit status.  Similarly if
+     the last child exited.  If this is not the last child, however,
+     do not report it as exited until there is a 'thread exited' response
+     available in the remote protocol.  Instead, just wait for another event.
+     This should be safe, because if the thread crashed we will already
+     have reported the termination signal to GDB; that should stop any
+     in-progress stepping operations, etc.
+
+     Report the exit status of the last thread to exit.  This matches
+     LinuxThreads' behavior.  */
+
+  lwp = get_thread_lwp (current_inferior);
+
+  /* Now that we've selected our final event LWP, cancel any
+     breakpoints in other LWPs that have hit a GDB breakpoint.  See
+     the comment in cancel_breakpoints_callback to find out why.  */
+  if (!non_stop)
+    find_inferior (&all_lwps, cancel_breakpoints_callback, lwp);
+
+  if (is_last_thread_of_process (current_inferior))
+    {
+      if (WIFEXITED (w) || WIFSIGNALED (w))
+	{
+	  struct process_info *process;
+	  int pid;
+
+	  pid = pid_of (lwp);
+
+	  process = (struct process_info *)
+	    find_inferior_id (&all_processes, pid_to_ptid (pid));
+
+	  remove_inferior (&all_lwps, &lwp->head);
+	  remove_thread (current_inferior);
+	  remove_inferior (&all_processes, &process->head);
+
+	  current_inferior = NULL;
+
+	  if (WIFEXITED (w))
+	    {
+	      ourstatus->kind = TARGET_WAITKIND_EXITED;
+	      ourstatus->value.integer = WEXITSTATUS (w);
+
+	      if (debug_threads)
+		fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
+
+	      return pid_to_ptid (pid);
+	    }
+	  else
+	    {
+	      ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+	      ourstatus->value.sig = target_signal_from_host (WTERMSIG (w));
+
+	      if (debug_threads)
+		fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
+
+	      return pid_to_ptid (pid);
+	    }
+	}
+    }
+  else
+    {
+      if (!WIFSTOPPED (w))
+	return lwp->head.id;
+    }
+
+  if (lwp->waitstatus.kind != TARGET_WAITKIND_IGNORE)
+    {
+      *ourstatus = lwp->waitstatus;
+      lwp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
+    }
+  else
+    {
+      ourstatus->kind = TARGET_WAITKIND_STOPPED;
+      ourstatus->value.sig = target_signal_from_host (WSTOPSIG (w));
+    }
+
+  if (debug_threads)
+    fprintf (stderr, "linux_wait ret = %s, %d, %d\n",
+	     target_pid_to_str (lwp->head.id),
+	     ourstatus->kind,
+	     ourstatus->value.sig);
+
+  return lwp->head.id;
+}
+
+/* Get rid of any pending event in the pipe.  */
+static void
+async_file_flush (void)
+{
+  int ret;
+  char buf;
+
+  do
+    ret = read (linux_event_pipe[0], &buf, 1);
+  while (ret == 0 || (ret == -1 && errno == EINTR));
+}
+
+/* Put something in the pipe, so the event loop wakes up.  */
+static void
+async_file_mark (void)
 {
-  int w;
-  struct thread_info *child = NULL;
-
-retry:
-  /* If we were only supposed to resume one thread, only wait for
-     that thread - if it's still alive.  If it died, however - which
-     can happen if we're coming from the thread death case below -
-     then we need to make sure we restart the other threads.  We could
-     pick a thread at random or restart all; restarting all is less
-     arbitrary.  */
-  if (cont_thread != 0 && cont_thread != -1)
-    {
-      child = (struct thread_info *) find_inferior_id (&all_threads,
-						       cont_thread);
+  int ret;
 
-      /* No stepping, no signal - unless one is pending already, of course.  */
-      if (child == NULL)
-	{
-	  struct thread_resume resume_info;
-	  resume_info.thread = -1;
-	  resume_info.step = resume_info.sig = resume_info.leave_stopped = 0;
-	  linux_resume (&resume_info);
-	}
-    }
+  async_file_flush ();
 
-  w = linux_wait_for_event (child);
-  stop_all_processes ();
+  do
+    ret = write (linux_event_pipe[1], "+", 1);
+  while (ret == 0 || (ret == -1 && errno == EINTR));
+}
 
-  if (must_set_ptrace_flags)
-    {
-      ptrace (PTRACE_SETOPTIONS, inferior_pid, 0, PTRACE_O_TRACECLONE);
-      must_set_ptrace_flags = 0;
-    }
+/* */
+static ptid_t
+linux_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int target_options)
+{
+  ptid_t event_ptid;
 
-  /* If we are waiting for a particular child, and it exited,
-     linux_wait_for_event will return its exit status.  Similarly if
-     the last child exited.  If this is not the last child, however,
-     do not report it as exited until there is a 'thread exited' response
-     available in the remote protocol.  Instead, just wait for another event.
-     This should be safe, because if the thread crashed we will already
-     have reported the termination signal to GDB; that should stop any
-     in-progress stepping operations, etc.
+  if (debug_threads)
+    fprintf (stderr, "linux_wait: [%s]\n", target_pid_to_str (ptid));
 
-     Report the exit status of the last thread to exit.  This matches
-     LinuxThreads' behavior.  */
+  /* Flush the async file first.  We can't do it below, because that
+     would be racy.  A SIGCHLD may arrive any time after we get out of
+     my_waitpid, which marks the async file.  */
+  if (target_is_async_p ())
+    async_file_flush ();
 
-  if (all_threads.head == all_threads.tail)
+  do
     {
-      if (WIFEXITED (w))
-	{
-	  fprintf (stderr, "\nChild exited with retcode = %x \n", WEXITSTATUS (w));
-	  *status = 'W';
-	  clear_inferiors ();
-	  free (all_processes.head);
-	  all_processes.head = all_processes.tail = NULL;
-	  return WEXITSTATUS (w);
-	}
-      else if (!WIFSTOPPED (w))
-	{
-	  fprintf (stderr, "\nChild terminated with signal = %x \n", WTERMSIG (w));
-	  *status = 'X';
-	  clear_inferiors ();
-	  free (all_processes.head);
-	  all_processes.head = all_processes.tail = NULL;
-	  return target_signal_from_host (WTERMSIG (w));
-	}
-    }
-  else
+      event_ptid = linux_wait_1 (ptid, ourstatus, target_options);
+    } while ((target_options & TARGET_WNOHANG) == 0
+	     && ourstatus->kind == TARGET_WAITKIND_IGNORE);
+
+  /* If we requested any event, and something came out, assume there
+     may be more.  If we requested a specific lwp or process, also
+     assume there may be more.  */
+  if (target_is_async_p ())
     {
-      if (!WIFSTOPPED (w))
-	goto retry;
+      if (!ptid_equal (ptid, minus_one_ptid)
+	  || ourstatus->kind != TARGET_WAITKIND_IGNORE)
+	async_file_mark ();
     }
 
-  *status = 'T';
-  return target_signal_from_host (WSTOPSIG (w));
+  return event_ptid;
 }
 
 /* Send a signal to an LWP.  For LinuxThreads, kill is enough; however, if
@@ -1015,126 +1650,159 @@ kill_lwp (unsigned long lwpid, int signo
 static void
 send_sigstop (struct inferior_list_entry *entry)
 {
-  struct process_info *process = (struct process_info *) entry;
+  int lwpid;
+  struct lwp_info *lwp;
 
-  if (process->stopped)
+  lwp = (struct lwp_info *) entry;
+
+  if (lwp->stopped)
     return;
 
-  /* If we already have a pending stop signal for this process, don't
+  lwpid = lwpid_of (lwp);
+
+  /* If we already have a pending stop signal for this lwp, don't
      send another.  */
-  if (process->stop_expected)
+  if (lwp->stop_expected)
     {
       if (debug_threads)
-	fprintf (stderr, "Have pending sigstop for process %ld\n",
-		 process->lwpid);
+	fprintf (stderr, "Have pending sigstop for lwp %d\n",
+		 lwpid);
 
       /* We clear the stop_expected flag so that wait_for_sigstop
 	 will receive the SIGSTOP event (instead of silently resuming and
 	 waiting again).  It'll be reset below.  */
-      process->stop_expected = 0;
+      lwp->stop_expected = 0;
       return;
     }
 
   if (debug_threads)
-    fprintf (stderr, "Sending sigstop to process %ld\n", process->head.id);
+    fprintf (stderr, "Sending sigstop to lwp %d\n", lwpid);
 
-  kill_lwp (process->head.id, SIGSTOP);
+  kill_lwp (lwpid, SIGSTOP);
 }
 
 static void
 wait_for_sigstop (struct inferior_list_entry *entry)
 {
-  struct process_info *process = (struct process_info *) entry;
-  struct thread_info *saved_inferior, *thread;
+  struct lwp_info *lwp = (struct lwp_info *) entry;
+  struct thread_info *saved_inferior;
   int wstat;
-  unsigned long saved_tid;
+  ptid_t saved_tid;
+  ptid_t ptid;
 
-  if (process->stopped)
+  if (lwp->stopped)
     return;
 
   saved_inferior = current_inferior;
   saved_tid = ((struct inferior_list_entry *) saved_inferior)->id;
-  thread = (struct thread_info *) find_inferior_id (&all_threads,
-						    process->lwpid);
-  wstat = linux_wait_for_event (thread);
+
+  ptid = lwp->head.id;
+
+  stopping_threads = 1;
+  linux_wait_for_lwp (ptid, &wstat, __WALL);
+  stopping_threads = 0;
 
   /* If we stopped with a non-SIGSTOP signal, save it for later
-     and record the pending SIGSTOP.  If the process exited, just
+     and record the pending SIGSTOP.  If the lwp exited, just
      return.  */
   if (WIFSTOPPED (wstat)
       && WSTOPSIG (wstat) != SIGSTOP)
     {
       if (debug_threads)
 	fprintf (stderr, "LWP %ld stopped with non-sigstop status %06x\n",
-		 process->lwpid, wstat);
-      process->status_pending_p = 1;
-      process->status_pending = wstat;
-      process->stop_expected = 1;
+		 lwpid_of (lwp), wstat);
+      lwp->status_pending_p = 1;
+      lwp->status_pending = wstat;
+      lwp->stop_expected = 1;
     }
+  else if (!WIFSTOPPED (wstat))
+    {
+      if (debug_threads)
+	fprintf (stderr, "Process %ld exited while stopping LWPs\n",
+		 ptid_get_lwp (lwp->head.id));
 
-  if (linux_thread_alive (saved_tid))
+      /* Leave this status pending for the next time we're able to
+	 report it.  In the mean time, we'll report this lwp as
+	 dead to GDB, so GDB doesn't try to read registers and
+	 memory from it.  */
+      lwp->dead = 1;
+      lwp->status_pending_p = 1;
+      lwp->status_pending = wstat;
+      lwp->stopped = 1; /* prevent trying to stop it again.  */
+      lwp->stop_expected = 0; /* No stop is expected, the lwp is
+				 dead.  */
+    }
+
+  if (non_stop)
+    /* We can't change the current inferior behind GDB's back,
+       otherwise, a subsequent command may apply to the wrong process.
+       Actually, we have to take care of this in all-stop +
+       multi-process too.  FIXME.  */
     current_inferior = saved_inferior;
   else
     {
-      if (debug_threads)
-	fprintf (stderr, "Previously current thread died.\n");
+      if (linux_thread_alive (saved_tid))
+	current_inferior = saved_inferior;
+      else
+	{
+	  if (debug_threads)
+	    fprintf (stderr, "Previously current thread died.\n");
 
-      /* Set a valid thread as current.  */
-      set_desired_inferior (0);
+	  /* Set a valid thread as current.  */
+	  set_desired_inferior (0);
+	}
     }
 }
 
 static void
-stop_all_processes (void)
+stop_all_lwps (void)
 {
-  stopping_threads = 1;
-  for_each_inferior (&all_processes, send_sigstop);
-  for_each_inferior (&all_processes, wait_for_sigstop);
-  stopping_threads = 0;
+  for_each_inferior (&all_lwps, send_sigstop);
+  for_each_inferior (&all_lwps, wait_for_sigstop);
 }
 
-/* Resume execution of the inferior process.
+/* Resume execution of the inferior lwp.
    If STEP is nonzero, single-step it.
    If SIGNAL is nonzero, give it that signal.  */
 
 static void
-linux_resume_one_process (struct inferior_list_entry *entry,
-			  int step, int signal, siginfo_t *info)
+linux_resume_one_lwp (struct inferior_list_entry *entry,
+		      int step, int signal, siginfo_t *info)
 {
-  struct process_info *process = (struct process_info *) entry;
+  struct lwp_info *lwp = (struct lwp_info *) entry;
   struct thread_info *saved_inferior;
 
-  if (process->stopped == 0)
+  if (lwp->stopped == 0)
     return;
 
   /* If we have pending signals or status, and a new signal, enqueue the
      signal.  Also enqueue the signal if we are waiting to reinsert a
      breakpoint; it will be picked up again below.  */
   if (signal != 0
-      && (process->status_pending_p || process->pending_signals != NULL
-	  || process->bp_reinsert != 0))
+      && (lwp->status_pending_p || lwp->pending_signals != NULL
+	  || lwp->bp_reinsert != 0))
     {
       struct pending_signals *p_sig;
       p_sig = malloc (sizeof (*p_sig));
-      p_sig->prev = process->pending_signals;
+      p_sig->prev = lwp->pending_signals;
       p_sig->signal = signal;
       if (info == NULL)
 	memset (&p_sig->info, 0, sizeof (siginfo_t));
       else
 	memcpy (&p_sig->info, info, sizeof (siginfo_t));
-      process->pending_signals = p_sig;
+      lwp->pending_signals = p_sig;
     }
 
-  if (process->status_pending_p && !check_removed_breakpoint (process))
+  if (lwp->status_pending_p && !check_removed_breakpoint (lwp))
     return;
 
   saved_inferior = current_inferior;
-  current_inferior = get_process_thread (process);
+  current_inferior = get_lwp_thread (lwp);
 
   if (debug_threads)
-    fprintf (stderr, "Resuming process %ld (%s, signal %d, stop %s)\n", inferior_pid,
+    fprintf (stderr, "Resuming lwp %ld (%s, signal %d, stop %s)\n", inferior_lwpid,
 	     step ? "step" : "continue", signal,
-	     process->stop_expected ? "expected" : "not expected");
+	     lwp->stop_expected ? "expected" : "not expected");
 
   /* This bit needs some thinking about.  If we get a signal that
      we must report while a single-step reinsert is still pending,
@@ -1143,13 +1811,13 @@ linux_resume_one_process (struct inferio
      the reinsert happened right away and not lose any signals.
 
      Making this stack would also shrink the window in which breakpoints are
-     uninserted (see comment in linux_wait_for_process) but not enough for
+     uninserted (see comment in linux_wait_for_lwp) but not enough for
      complete correctness, so it won't solve that problem.  It may be
      worthwhile just to solve this one, however.  */
-  if (process->bp_reinsert != 0)
+  if (lwp->bp_reinsert != 0)
     {
       if (debug_threads)
-	fprintf (stderr, "  pending reinsert at %08lx", (long)process->bp_reinsert);
+	fprintf (stderr, "  pending reinsert at %08lx", (long)lwp->bp_reinsert);
       if (step == 0)
 	fprintf (stderr, "BAD - reinserting but not stepping.\n");
       step = 1;
@@ -1158,7 +1826,7 @@ linux_resume_one_process (struct inferio
       signal = 0;
     }
 
-  check_removed_breakpoint (process);
+  check_removed_breakpoint (lwp);
 
   if (debug_threads && the_low_target.get_pc != NULL)
     {
@@ -1168,28 +1836,28 @@ linux_resume_one_process (struct inferio
 
   /* If we have pending signals, consume one unless we are trying to reinsert
      a breakpoint.  */
-  if (process->pending_signals != NULL && process->bp_reinsert == 0)
+  if (lwp->pending_signals != NULL && lwp->bp_reinsert == 0)
     {
       struct pending_signals **p_sig;
 
-      p_sig = &process->pending_signals;
+      p_sig = &lwp->pending_signals;
       while ((*p_sig)->prev != NULL)
 	p_sig = &(*p_sig)->prev;
 
       signal = (*p_sig)->signal;
       if ((*p_sig)->info.si_signo != 0)
-	ptrace (PTRACE_SETSIGINFO, process->lwpid, 0, &(*p_sig)->info);
+	ptrace (PTRACE_SETSIGINFO, ptid_get_lwp (lwp->head.id), 0, &(*p_sig)->info);
 
       free (*p_sig);
       *p_sig = NULL;
     }
 
   regcache_invalidate_one ((struct inferior_list_entry *)
-			   get_process_thread (process));
+			   get_lwp_thread (lwp));
   errno = 0;
-  process->stopped = 0;
-  process->stepping = step;
-  ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, process->lwpid, 0, signal);
+  lwp->stopped = 0;
+  lwp->stepping = step;
+  ptrace (step ? PTRACE_SINGLESTEP : PTRACE_CONT, lwpid_of (lwp), 0, signal);
 
   current_inferior = saved_inferior;
   if (errno)
@@ -1208,147 +1876,412 @@ linux_resume_one_process (struct inferio
     }
 }
 
-static struct thread_resume *resume_ptr;
+struct resume_info
+{
+  struct thread_resume *request;
+  size_t n;
+};
 
-/* This function is called once per thread.  We look up the thread
-   in RESUME_PTR, and mark the thread with a pointer to the appropriate
+/* This function is called once per thread.  We look up the thread in
+   RESUME_INFO, and mark the thread with a pointer to the appropriate
    resume request.
 
    This algorithm is O(threads * resume elements), but resume elements
    is small (and will remain small at least until GDB supports thread
    suspension).  */
-static void
-linux_set_resume_request (struct inferior_list_entry *entry)
+static int
+linux_set_resume_request (struct inferior_list_entry *entry, void *arg)
 {
-  struct process_info *process;
+  struct lwp_info *lwp;
   struct thread_info *thread;
   int ndx;
+  struct resume_info *resume_info;
 
   thread = (struct thread_info *) entry;
-  process = get_thread_process (thread);
+  lwp = get_thread_lwp (thread);
+  resume_info = arg;
+
+  for (ndx = 0; ndx < resume_info->n; ndx++)
+    {
+      ptid_t ptid = resume_info->request[ndx].thread;
+      if (ptid_equal (ptid, minus_one_ptid)
+	  || ptid_equal (ptid, entry->id)
+	  || (ptid_is_pid (ptid)
+	      && (ptid_get_pid (ptid) == pid_of (lwp)))
+	  || (ptid_get_lwp (ptid) == -1
+	      && (ptid_get_pid (ptid) == pid_of (lwp))))
+	{
+	  lwp->resume = &resume_info->request[ndx];
+	  return 0;
+	}
+    }
 
-  ndx = 0;
-  while (resume_ptr[ndx].thread != -1 && resume_ptr[ndx].thread != entry->id)
-    ndx++;
+  /* Don't touch.  */
+  lwp->resume = NULL;
 
-  process->resume = &resume_ptr[ndx];
+  return 0;
 }
 
-/* This function is called once per thread.  We check the thread's resume
-   request, which will tell us whether to resume, step, or leave the thread
-   stopped; and what signal, if any, it should be sent.  For threads which
-   we aren't explicitly told otherwise, we preserve the stepping flag; this
-   is used for stepping over gdbserver-placed breakpoints.  */
+/* Set *FLAG_P if this lwp has an interesting status pending.  */
+static int
+resume_status_pending_p (struct inferior_list_entry *entry, void *flag_p)
+{
+  struct lwp_info *lwp = (struct lwp_info *) entry;
 
-static void
-linux_continue_one_thread (struct inferior_list_entry *entry)
+  /* LWPs which will not be resumed are not interesting, because
+     we might not wait for them next time through linux_wait.  */
+  if (lwp->resume == NULL)
+    return 0;
+
+  if (lwp->dead)
+    {
+      /* If this thread is known to be dead, then the whole process it
+	 belonged to has exited.  Report it.  */
+
+      /* TODO: See if the dead flag is really needed, or the
+	 pending_status is enough.  */
+      if (!lwp->status_pending_p)
+	warning ("dead thread without a pending status?");
+
+      * (int *) flag_p = 1;
+      return 0;
+    }
+
+  /* If this thread has a removed breakpoint, we won't have any
+     events to report later, so check now.  check_removed_breakpoint
+     may clear status_pending_p.  We avoid calling check_removed_breakpoint
+     for any thread that we are not otherwise going to resume - this
+     lets us preserve stopped status when two threads hit a breakpoint.
+     GDB removes the breakpoint to single-step a particular thread
+     past it, then re-inserts it and resumes all threads.  We want
+     to report the second thread without resuming it in the interim.  */
+  if (lwp->status_pending_p && !lwp->suspended)
+    check_removed_breakpoint (lwp);
+
+  if (lwp->status_pending_p)
+    * (int *) flag_p = 1;
+
+  return 0;
+}
+
+static int
+cancel_breakpoint (struct lwp_info *lwp)
 {
-  struct process_info *process;
-  struct thread_info *thread;
-  int step;
+  /* Arrange for a breakpoint to be hit again later.  We don't keep
+     the SIGTRAP status and don't forward the SIGTRAP signal to the
+     thread.  Eventually we will resume this thread, and this
+     breakpoint will trap again.
+
+     If we do not do this, then we run the risk that the user will
+     delete or disable the breakpoint, but the thread will have
+     already tripped on it.  */
+
+  if (lwp->stopped
+      && !lwp->dead
+      && !lwp->stepping
+      && ((lwp->status_pending_p
+	   && WIFSTOPPED (lwp->status_pending)
+	   && WSTOPSIG (lwp->status_pending) == SIGTRAP)
+	  || (!lwp->status_pending_p
+	      && WIFSTOPPED (lwp->last_status)
+	      && WSTOPSIG (lwp->last_status) == SIGTRAP)))
+    {
+      CORE_ADDR stop_pc;
+      struct thread_info *saved_inferior;
 
-  thread = (struct thread_info *) entry;
-  process = get_thread_process (thread);
+      /* If there's a breakpoint here, adjust the PC, so the
+	 breakpoint is hit again when the thread is resumed.  */
 
-  if (process->resume->leave_stopped)
-    return;
+      if (debug_threads)
+	fprintf (stderr, "Checking for breakpoint in lwp %ld.\n",
+		 lwpid_of (lwp));
 
-  if (process->resume->thread == -1)
-    step = process->stepping || process->resume->step;
-  else
-    step = process->resume->step;
+      saved_inferior = current_inferior;
+      current_inferior = get_lwp_thread (lwp);
+
+      stop_pc = (*the_low_target.get_pc) ();
+      stop_pc -= the_low_target.decr_pc_after_break;
+
+      /* If there's a breakpoint there, back off the PC.  */
+      if (breakpoint_at (stop_pc)
+	  || (*the_low_target.breakpoint_at) (stop_pc))
+	{
+	  if (the_low_target.set_pc != NULL)
+	    {
+	      if (debug_threads)
+		fprintf (stderr, "CB: breakpoint present, backing off PC.\n");
+	      (*the_low_target.set_pc) (stop_pc);
+	    }
+	  else
+	    {
+	      if (debug_threads)
+		fprintf (stderr, "CB: breakpoint present ignoring SIGTRAP.\n");
+	    }
+
+	  lwp->pending_is_breakpoint = 0;
+	  lwp->status_pending_p = 0;
+	  lwp->status_pending = 0;
+	  lwp->last_status = W_STOPCODE (0);
+
+	  current_inferior = saved_inferior;
+	  return 1;
+	}
+
+      current_inferior = saved_inferior;
+    }
+
+  return 0;
+}
+
+static int
+cancel_breakpoints_callback (struct inferior_list_entry *entry, void *data)
+{
+  struct lwp_info *lp = (struct lwp_info *) entry;
+  struct lwp_info *event_lp = data;
+
+  /* Leave the LWP that has been elected to receive a SIGTRAP alone.  */
+  if (lp == event_lp)
+    return 0;
 
-  linux_resume_one_process (&process->head, step, process->resume->sig, NULL);
+  /* If a LWP other than the LWP that we're reporting an event for has
+     hit a GDB breakpoint (as opposed to some random trap signal),
+     then just arrange for it to hit it again later.  We don't keep
+     the SIGTRAP status and don't forward the SIGTRAP signal to the
+     LWP.  We will handle the current event, eventually we will resume
+     all LWPs, and this one will get its breakpoint trap again.
+
+     If we do not do this, then we run the risk that the user will
+     delete or disable the breakpoint, but the LWP will have already
+     tripped on it.  */
 
-  process->resume = NULL;
+  cancel_breakpoint (lp);
+  return 0;
 }
 
 /* This function is called once per thread.  We check the thread's resume
    request, which will tell us whether to resume, step, or leave the thread
-   stopped; and what signal, if any, it should be sent.  We queue any needed
-   signals, since we won't actually resume.  We already have a pending event
-   to report, so we don't need to preserve any step requests; they should
-   be re-issued if necessary.  */
+   stopped; and what signal, if any, it should be sent.
 
-static void
-linux_queue_one_thread (struct inferior_list_entry *entry)
+   For threads which we aren't explicitly told otherwise, we preserve
+   the stepping flag; this is used for stepping over gdbserver-placed
+   breakpoints.
+
+   If pending_flags was set in any thread, we queue any needed
+   signals, since we won't actually resume.  We already have a pending
+   event to report, so we don't need to preserve any step requests;
+   they should be re-issued if necessary.  */
+
+static int
+linux_resume_one_thread (struct inferior_list_entry *entry, void *arg)
 {
-  struct process_info *process;
+  struct lwp_info *lwp;
   struct thread_info *thread;
+  int step;
+  int pending_flag = * (int *) arg;
 
   thread = (struct thread_info *) entry;
-  process = get_thread_process (thread);
+  lwp = get_thread_lwp (thread);
 
-  if (process->resume->leave_stopped)
-    return;
+  if (lwp->resume == NULL)
+    return 0;
 
-  /* If we have a new signal, enqueue the signal.  */
-  if (process->resume->sig != 0)
+  if (lwp->resume->kind == rk_stop)
     {
-      struct pending_signals *p_sig;
-      p_sig = malloc (sizeof (*p_sig));
-      p_sig->prev = process->pending_signals;
-      p_sig->signal = process->resume->sig;
-      memset (&p_sig->info, 0, sizeof (siginfo_t));
+      if (debug_threads)
+	fprintf (stderr, "suspending thread %s\n",
+		 target_pid_to_str (entry->id));
+
+      /* Do this before waiting for sigstop, as the thread may
+	 die.  */
+      /* TODO: how do we report that happening to GDB?  GDB and the
+	 user can get very confused if a thread exits without GDB
+	 being aware of it.  E.g, user tries to interrupts thread, but
+	 GDB doesn't reply back, The simplest seem to be to implement
+	 a thread exit stop reply.  Note that returning a generic
+	 error is not an option if we're handling a vCont.  The reply
+	 has already been sent at this point, and, the same vCont can
+	 hold multiple resumptions -- to which would the error
+	 apply?  */
+      lwp->resume = NULL;
+
+      /* To simplify things, we're waiting for the lwp to stop here,
+	 and pushing the stop reply to gdbserver's common code.  An
+	 alternative, would be to defer to linux_wait to do the wait,
+	 and notice that an lwp with the "suspended" flag but
+	 "!stopped", should leave any status pending, and report a
+	 sig0 stop status.  */
+
+      /* Do we have to distinguish internal stops from external stops,
+	 due to the support for gdbserver breakpoints?  If so, then
+	 thread_info needs to gain a "running" property.  */
+      if (!lwp->stopped)
+	{
+	  ptid_t ptid = entry->id;
+
+	  if (debug_threads)
+	    fprintf (stderr, "running -> suspending %s\n",
+		     target_pid_to_str (entry->id));
 
-      /* If this is the same signal we were previously stopped by,
-	 make sure to queue its siginfo.  We can ignore the return
-	 value of ptrace; if it fails, we'll skip
-	 PTRACE_SETSIGINFO.  */
-      if (WIFSTOPPED (process->last_status)
-	  && WSTOPSIG (process->last_status) == process->resume->sig)
-	ptrace (PTRACE_GETSIGINFO, process->lwpid, 0, &p_sig->info);
+	  lwp->suspended = 1;
+	  send_sigstop (&lwp->head);
+	  wait_for_sigstop (&lwp->head);
+	  if (!lwp->dead)
+	    {
+	      struct target_waitstatus status;
+	      status.kind = TARGET_WAITKIND_STOPPED;
+
+	      /* Cancel internal breakpoints, otherwise, the user will
+		 see a possibly invalid PC on decr_pc_after_break
+		 archs, because GDB can't tell there's a breakpoint
+		 there.  As long as we do it, might as well cancel GDB
+		 breakpoints too, although GDB will also adjust the PC
+		 if we don't in that case.  */
+
+	      /* Cancel breakpoints, but leave out finished steps and
+		 watchpoint hits.  */
+	      if (cancel_breakpoint (lwp))
+		/* The LWP hit a breakpoint while we tried to stop it,
+		   and we backed off the PC.  Report a SIG0.  */
+		status.value.sig = 0;
+	      else if (lwp->stopped
+		       && lwp->stepping
+		       && ((!lwp->status_pending_p
+			    && WIFSTOPPED (lwp->last_status)
+			    && WSTOPSIG (lwp->last_status) == SIGTRAP)
+			   || (lwp->status_pending_p
+			       && WIFSTOPPED (lwp->status_pending)
+			       && WSTOPSIG (lwp->status_pending) == SIGTRAP)))
+		{
+		  /* The LWP finished a hardware single-step; report
+		     the SIGTRAP to GDB.  */
+		  lwp->pending_is_breakpoint = 0;
+		  lwp->status_pending_p = 0;
+		  lwp->status_pending = 0;
+		  lwp->last_status = W_STOPCODE (SIGTRAP);
+		  /* Report the finished single-step.  When using
+		     displaced stepping, GDB needs this to be able to
+		     fixup the PC.  */
+		  status.value.sig = TARGET_SIGNAL_TRAP;
+		}
+	      else
+		/* Leave other signals pending.  */
+		status.value.sig = 0;
+
+	      /* Pass the stop reply back to GDB.  */
+	      push_event (ptid, &status);
+	    }
+	  else
+	    ;
+	}
+      else
+	{
+	  if (debug_threads)
+	    {
+	      if (lwp->suspended)
+		fprintf (stderr, "already stopped/suspended %s\n",
+			 target_pid_to_str (entry->id));
+	      else
+		fprintf (stderr, "already stopped/not suspended %s\n",
+			 target_pid_to_str (entry->id));
+	    }
 
-      process->pending_signals = p_sig;
+	  /* Make sure we leave the LWP suspended, so we don't try to
+	     resume it without GDB telling us to.  FIXME: The LWP may
+	     have been stopped in an internal event that was not meant
+	     to be notified back to GDB (e.g., gdbserver breakpoint),
+	     so we should be reporting a stop event in that case
+	     too.  */
+	  lwp->suspended = 1;
+	}
+      return 0;
     }
+  else
+    lwp->suspended = 0;
 
-  process->resume = NULL;
-}
+  /* If this thread which is about to be resumed has a pending status,
+     then don't resume any threads - we can just report the pending
+     status.  Make sure to queue any signals that would otherwise be
+     sent.  In all-stop mode, we do this decision based on if *any*
+     thread has a pending status.  */
+  if (non_stop)
+    resume_status_pending_p (&lwp->head, &pending_flag);
 
-/* Set DUMMY if this process has an interesting status pending.  */
-static int
-resume_status_pending_p (struct inferior_list_entry *entry, void *flag_p)
-{
-  struct process_info *process = (struct process_info *) entry;
+  if (!pending_flag)
+    {
+      if (debug_threads)
+	fprintf (stderr, "resuming thread %s\n",
+		 target_pid_to_str (entry->id));
 
-  /* Processes which will not be resumed are not interesting, because
-     we might not wait for them next time through linux_wait.  */
-  if (process->resume->leave_stopped)
-    return 0;
+      if (ptid_equal (lwp->resume->thread, minus_one_ptid))
+	step = lwp->stepping || (lwp->resume->kind == rk_step);
+      else
+	step = (lwp->resume->kind == rk_step);
 
-  /* If this thread has a removed breakpoint, we won't have any
-     events to report later, so check now.  check_removed_breakpoint
-     may clear status_pending_p.  We avoid calling check_removed_breakpoint
-     for any thread that we are not otherwise going to resume - this
-     lets us preserve stopped status when two threads hit a breakpoint.
-     GDB removes the breakpoint to single-step a particular thread
-     past it, then re-inserts it and resumes all threads.  We want
-     to report the second thread without resuming it in the interim.  */
-  if (process->status_pending_p)
-    check_removed_breakpoint (process);
+      linux_resume_one_lwp (&lwp->head, step, lwp->resume->sig, NULL);
+    }
+  else
+    {
+      if (debug_threads)
+	fprintf (stderr, "leaving thread %s stopped\n",
+		 target_pid_to_str (entry->id));
 
-  if (process->status_pending_p)
-    * (int *) flag_p = 1;
+      /* If we have a new signal, enqueue the signal.  */
+      if (lwp->resume->sig != 0)
+	{
+	  struct pending_signals *p_sig;
+	  p_sig = malloc (sizeof (*p_sig));
+	  p_sig->prev = lwp->pending_signals;
+	  p_sig->signal = lwp->resume->sig;
+	  memset (&p_sig->info, 0, sizeof (siginfo_t));
+
+	  /* If this is the same signal we were previously stopped by,
+	     make sure to queue its siginfo.  We can ignore the return
+	     value of ptrace; if it fails, we'll skip
+	     PTRACE_SETSIGINFO.  */
+	  if (WIFSTOPPED (lwp->last_status)
+	      && WSTOPSIG (lwp->last_status) == lwp->resume->sig)
+	    ptrace (PTRACE_GETSIGINFO, ptid_get_lwp (lwp->head.id), 0, &p_sig->info);
 
+	  lwp->pending_signals = p_sig;
+	}
+    }
+
+  lwp->resume = NULL;
   return 0;
 }
 
 static void
-linux_resume (struct thread_resume *resume_info)
+linux_resume (struct thread_resume *resume_info, size_t n)
 {
   int pending_flag;
+  struct resume_info info = { resume_info, n };
 
-  /* Yes, the use of a global here is rather ugly.  */
-  resume_ptr = resume_info;
+  if (debug_threads)
+    {
+      int idx;
+      fprintf (stderr, "linux_resume\n");
+      for (idx = 0; idx < n; idx++)
+	{
+	  fprintf (stderr, " thread(%s), kind(%d), sig(%d)\n",
+		   target_pid_to_str (resume_info[idx].thread),
+		   resume_info[idx].kind,
+		   resume_info[idx].sig);
+	  idx++;
+	}
+    }
 
-  for_each_inferior (&all_threads, linux_set_resume_request);
+  find_inferior (&all_threads, linux_set_resume_request, &info);
 
   /* If there is a thread which would otherwise be resumed, which
      has a pending status, then don't resume any threads - we can just
      report the pending status.  Make sure to queue any signals
      that would otherwise be sent.  */
+  /* This is only used in all-stop mode however.  In non-stop mode,
+     decide to leave pending based on the thread we're resuming itself
+     having a pending status already or not.  */
   pending_flag = 0;
-  find_inferior (&all_processes, resume_status_pending_p, &pending_flag);
+  if (!non_stop)
+    find_inferior (&all_lwps, resume_status_pending_p, &pending_flag);
 
   if (debug_threads)
     {
@@ -1358,10 +2291,7 @@ linux_resume (struct thread_resume *resu
 	fprintf (stderr, "Resuming, no pending status\n");
     }
 
-  if (pending_flag)
-    for_each_inferior (&all_threads, linux_queue_one_thread);
-  else
-    for_each_inferior (&all_threads, linux_continue_one_thread);
+  find_inferior (&all_threads, linux_resume_one_thread, &pending_flag);
 }
 
 #ifdef HAVE_LINUX_USRREGS
@@ -1402,7 +2332,7 @@ fetch_register (int regno)
     {
       errno = 0;
       *(PTRACE_XFER_TYPE *) (buf + i) =
-	ptrace (PTRACE_PEEKUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr, 0);
+	ptrace (PTRACE_PEEKUSER, inferior_lwpid, (PTRACE_ARG3_TYPE) regaddr, 0);
       regaddr += sizeof (PTRACE_XFER_TYPE);
       if (errno != 0)
 	{
@@ -1424,7 +2354,7 @@ fetch_register (int regno)
 error_exit:;
 }
 
-/* Fetch all registers, or just one, from the child process.  */
+/* Fetch all registers, or just one, from the child lwp.  */
 static void
 usr_fetch_inferior_registers (int regno)
 {
@@ -1470,13 +2400,13 @@ usr_store_inferior_registers (int regno)
       for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
 	{
 	  errno = 0;
-	  ptrace (PTRACE_POKEUSER, inferior_pid, (PTRACE_ARG3_TYPE) regaddr,
+	  ptrace (PTRACE_POKEUSER, inferior_lwpid, (PTRACE_ARG3_TYPE) regaddr,
 		  *(PTRACE_XFER_TYPE *) (buf + i));
 	  if (errno != 0)
 	    {
-	      /* At this point, ESRCH should mean the process is already gone, 
+	      /* At this point, ESRCH should mean the lwp is already gone,
 		 in which case we simply ignore attempts to change its registers.
-		 See also the related comment in linux_resume_one_process.  */
+		 See also the related comment in linux_resume_one_lwp.  */
 	      if (errno == ESRCH)
 		return;
 
@@ -1523,17 +2453,13 @@ regsets_fetch_inferior_registers ()
 	}
 
       buf = malloc (regset->size);
-#ifndef __sparc__
-      res = ptrace (regset->get_request, inferior_pid, 0, buf);
-#else
-      res = ptrace (regset->get_request, inferior_pid, buf, 0);
-#endif
+      res = ptrace (regset->get_request, inferior_lwpid, 0, buf);
       if (res < 0)
 	{
 	  if (errno == EIO)
 	    {
 	      /* If we get EIO on a regset, do not try it again for
-		 this process.  */
+		 this lwp.  */
 	      disabled_regsets[regset - target_regsets] = 1;
 	      continue;
 	    }
@@ -1541,7 +2467,7 @@ regsets_fetch_inferior_registers ()
 	    {
 	      char s[256];
 	      sprintf (s, "ptrace(regsets_fetch_inferior_registers) PID=%ld",
-		       inferior_pid);
+		       inferior_lwpid);
 	      perror (s);
 	    }
 	}
@@ -1580,11 +2506,7 @@ regsets_store_inferior_registers ()
       /* First fill the buffer with the current register set contents,
 	 in case there are any items in the kernel's regset that are
 	 not in gdbserver's regcache.  */
-#ifndef __sparc__
-      res = ptrace (regset->get_request, inferior_pid, 0, buf);
-#else
-      res = ptrace (regset->get_request, inferior_pid, buf, 0);
-#endif
+      res = ptrace (regset->get_request, inferior_lwpid, 0, buf);
 
       if (res == 0)
 	{
@@ -1592,11 +2514,7 @@ regsets_store_inferior_registers ()
 	  regset->fill_function (buf);
 
 	  /* Only now do we write the register set.  */
-#ifndef __sparc__
-          res = ptrace (regset->set_request, inferior_pid, 0, buf);
-#else
-          res = ptrace (regset->set_request, inferior_pid, buf, 0);
-#endif
+	  res = ptrace (regset->set_request, inferior_lwpid, 0, buf);
 	}
 
       if (res < 0)
@@ -1604,15 +2522,16 @@ regsets_store_inferior_registers ()
 	  if (errno == EIO)
 	    {
 	      /* If we get EIO on a regset, do not try it again for
-		 this process.  */
+		 this lwp.  */
 	      disabled_regsets[regset - target_regsets] = 1;
 	      continue;
 	    }
 	  else if (errno == ESRCH)
 	    {
-	      /* At this point, ESRCH should mean the process is already gone, 
+	      /* At this point, ESRCH should mean the lwp is already gone,
 		 in which case we simply ignore attempts to change its registers.
-		 See also the related comment in linux_resume_one_process.  */
+		 See also the related comment in linux_resume_one_lwp.  */
+	      free (buf);
 	      return 0;
 	    }
 	  else
@@ -1684,7 +2603,7 @@ linux_read_memory (CORE_ADDR memaddr, un
     {
       /* We could keep this file open and cache it - possibly one per
 	 thread.  That requires some juggling, but is even faster.  */
-      sprintf (filename, "/proc/%ld/mem", inferior_pid);
+      sprintf (filename, "/proc/%ld/mem", inferior_lwpid);
       fd = open (filename, O_RDONLY | O_LARGEFILE);
       if (fd == -1)
 	goto no_proc;
@@ -1712,7 +2631,7 @@ linux_read_memory (CORE_ADDR memaddr, un
   for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
     {
       errno = 0;
-      buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, 0);
+      buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_lwpid, (PTRACE_ARG3_TYPE) addr, 0);
       if (errno)
 	return errno;
     }
@@ -1747,13 +2666,13 @@ linux_write_memory (CORE_ADDR memaddr, c
 
   /* Fill start and end extra bytes of buffer with existing memory data.  */
 
-  buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid,
+  buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_lwpid,
 		      (PTRACE_ARG3_TYPE) addr, 0);
 
   if (count > 1)
     {
       buffer[count - 1]
-	= ptrace (PTRACE_PEEKTEXT, inferior_pid,
+	= ptrace (PTRACE_PEEKTEXT, inferior_lwpid,
 		  (PTRACE_ARG3_TYPE) (addr + (count - 1)
 				      * sizeof (PTRACE_XFER_TYPE)),
 		  0);
@@ -1768,7 +2687,7 @@ linux_write_memory (CORE_ADDR memaddr, c
   for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))
     {
       errno = 0;
-      ptrace (PTRACE_POKETEXT, inferior_pid, (PTRACE_ARG3_TYPE) addr, buffer[i]);
+      ptrace (PTRACE_POKETEXT, inferior_lwpid, (PTRACE_ARG3_TYPE) addr, buffer[i]);
       if (errno)
 	return errno;
     }
@@ -1776,8 +2695,6 @@ linux_write_memory (CORE_ADDR memaddr, c
   return 0;
 }
 
-static int linux_supports_tracefork_flag;
-
 /* Helper functions for linux_test_for_tracefork, called via clone ().  */
 
 static int
@@ -1803,21 +2720,6 @@ linux_tracefork_child (void *arg)
   _exit (0);
 }
 
-/* Wrapper function for waitpid which handles EINTR.  */
-
-static int
-my_waitpid (int pid, int *status, int flags)
-{
-  int ret;
-  do
-    {
-      ret = waitpid (pid, status, flags);
-    }
-  while (ret == -1 && errno == EINTR);
-
-  return ret;
-}
-
 /* Determine if PTRACE_O_TRACEFORK can be used to follow fork events.  Make
    sure that we can enable the option, and that it had the desired
    effect.  */
@@ -1914,10 +2816,15 @@ static void
 linux_look_up_symbols (void)
 {
 #ifdef USE_THREAD_DB
-  if (thread_db_active)
+  /* It would probably be cleaner now to move this whole function to
+     thread-db.c.  */
+
+  struct process_info *proc = current_process ();
+  if (proc->private->thread_db_active)
     return;
 
-  thread_db_active = thread_db_init (!linux_supports_tracefork_flag);
+  proc->private->thread_db_active
+    = thread_db_init (!linux_supports_tracefork_flag);
 #endif
 }
 
@@ -1926,12 +2833,15 @@ linux_request_interrupt (void)
 {
   extern unsigned long signal_pid;
 
-  if (cont_thread != 0 && cont_thread != -1)
+  if (!ptid_equal (cont_thread, null_ptid)
+      && !ptid_equal (cont_thread, minus_one_ptid))
     {
-      struct process_info *process;
+      struct lwp_info *lwp;
+      int lwpid;
 
-      process = get_thread_process (current_inferior);
-      kill_lwp (process->lwpid, SIGINT);
+      lwp = get_thread_lwp (current_inferior);
+      lwpid = ptid_get_lwp (lwp->head.id);
+      kill_lwp (lwpid, SIGINT);
     }
   else
     kill_lwp (signal_pid, SIGINT);
@@ -1946,7 +2856,7 @@ linux_read_auxv (CORE_ADDR offset, unsig
   char filename[PATH_MAX];
   int fd, n;
 
-  snprintf (filename, sizeof filename, "/proc/%ld/auxv", inferior_pid);
+  snprintf (filename, sizeof filename, "/proc/%ld/auxv", inferior_lwpid);
 
   fd = open (filename, O_RDONLY);
   if (fd < 0)
@@ -2012,6 +2922,12 @@ linux_stopped_data_address (void)
 #define PT_TEXT_END_ADDR  51*4
 #endif
 
+#if defined(__arm__)
+#ifndef PTRACE_GETPROCMAP
+#define PTRACE_GETPROCMAP 27
+#endif
+#endif
+
 /* Under uClinux, programs are loaded at non-zero offsets, which we need
    to tell gdb about.  */
 
@@ -2020,7 +2936,7 @@ linux_read_offsets (CORE_ADDR *text_p, C
 {
 #if defined(PT_TEXT_ADDR) && defined(PT_DATA_ADDR) && defined(PT_TEXT_END_ADDR)
   unsigned long text, text_end, data;
-  int pid = get_thread_process (current_inferior)->head.id;
+  int pid = pid_of (get_thread_lwp (current_inferior));
 
   errno = 0;
 
@@ -2045,10 +2961,95 @@ linux_read_offsets (CORE_ADDR *text_p, C
       return 1;
     }
 #endif
+#if defined(PTRACE_GETPROCMAP)
+  unsigned long data[6];
+  int pid = pid_of (get_thread_lwp (current_inferior));
+
+  if (ptrace (PTRACE_GETPROCMAP, pid, NULL, data) == 0)
+    {
+      /* GETPROCMAP returns text_start, text_end, data_start.  See above.  */
+      *text_p = data[0];
+      *data_p = data[2] - (data[1] - data[0]);
+      return 1;
+    }
+#endif
  return 0;
 }
 #endif
 
+/* SIGCHLD handler that serves two purposes: In non-stop/async mode,
+   so we notice when any child changes state; as the handler for the
+   sigsuspend in my_waitpid.  */
+
+static void
+sigchld_handler (int signo)
+{
+  int old_errno = errno;
+
+  if (debug_threads)
+    /* fprintf is not an async-signal-safe function, so call write
+       directly.  */
+    write (2, "sigchld_handler\n",
+	   strlen ("sigchld_handler\n"));
+
+  if (target_is_async_p ())
+    async_file_mark (); /* trigger a linux_wait */
+
+  errno = old_errno;
+}
+
+static int
+linux_async (int enable)
+{
+  int previous = (linux_event_pipe[0] != -1);
+
+  if (previous != enable)
+    {
+      sigset_t mask;
+      sigemptyset (&mask);
+      sigaddset (&mask, SIGCHLD);
+
+      sigprocmask (SIG_BLOCK, &mask, NULL);
+
+      if (enable)
+	{
+	  if (pipe (linux_event_pipe) == -1)
+	    internal_error ("creating event pipe failed.");
+
+	  fcntl (linux_event_pipe[0], F_SETFL, O_NONBLOCK);
+	  fcntl (linux_event_pipe[1], F_SETFL, O_NONBLOCK);
+
+	  /* Register the event loop handler.  */
+	  add_file_handler (linux_event_pipe[0],
+			    handle_target_event, NULL);
+
+	  /* Always trigger a linux_wait.  */
+	  async_file_mark ();
+	}
+      else
+	{
+	  delete_file_handler (linux_event_pipe[0]);
+
+	  close (linux_event_pipe[0]);
+	  close (linux_event_pipe[1]);
+	  linux_event_pipe[0] = -1;
+	  linux_event_pipe[1] = -1;
+	}
+
+      sigprocmask (SIG_UNBLOCK, &mask, NULL);
+    }
+
+  return previous;
+}
+
+static int
+linux_start_non_stop (int nonstop)
+{
+  /* Register or unregister from event-loop accordingly.  */
+  linux_async (nonstop);
+  return 0;
+}
+
 static struct target_ops linux_target_ops = {
   linux_create_inferior,
   linux_attach,
@@ -2081,6 +3082,9 @@ static struct target_ops linux_target_op
 #endif
   NULL,
   hostio_last_error_from_errno,
+  linux_pid_to_exec_file,
+  linux_async,
+  linux_start_non_stop,
 };
 
 static void
@@ -2094,7 +3098,8 @@ linux_init_signals ()
 void
 initialize_low (void)
 {
-  thread_db_active = 0;
+  struct sigaction sigchld_action;
+
   set_target_ops (&linux_target_ops);
   set_breakpoint_data (the_low_target.breakpoint,
 		       the_low_target.breakpoint_len);
@@ -2105,4 +3110,9 @@ initialize_low (void)
     ;
   disabled_regsets = malloc (num_regsets);
 #endif
+
+  sigchld_action.sa_handler = sigchld_handler;
+  sigemptyset (&sigchld_action.sa_mask);
+  sigchld_action.sa_flags = SA_RESTART;
+  sigaction (SIGCHLD, &sigchld_action, NULL);
 }
Index: src/gdb/gdbserver/linux-low.h
===================================================================
--- src.orig/gdb/gdbserver/linux-low.h	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/linux-low.h	2008-11-25 17:28:12.000000000 +0000
@@ -20,6 +20,8 @@
 #include <thread_db.h>
 #endif
 
+#include "gdb_proc_service.h"
+
 #ifdef HAVE_LINUX_REGSETS
 typedef void (*regset_fill_func) (void *);
 typedef void (*regset_store_func) (const void *);
@@ -40,6 +42,19 @@ struct regset_info
 extern struct regset_info target_regsets[];
 #endif
 
+struct process_info_private
+{
+  /* True if this process has loaded thread_db, and it is active.  */
+  int thread_db_active;
+
+  /* Structure that identifies the child process for the
+     <proc_service.h> interface.  */
+  struct ps_prochandle proc_handle;
+
+  /* Connection to the libthread_db library.  */
+  td_thragent_t *thread_agent;
+};
+
 struct linux_target_ops
 {
   /* Architecture-specific setup.  */
@@ -77,30 +92,37 @@ struct linux_target_ops
 
 extern struct linux_target_ops the_low_target;
 
-#define get_process(inf) ((struct process_info *)(inf))
-#define get_thread_process(thr) (get_process (inferior_target_data (thr)))
-#define get_process_thread(proc) ((struct thread_info *) \
+#define get_lwp(inf) ((struct lwp_info *)(inf))
+#define get_thread_lwp(thr) (get_lwp (inferior_target_data (thr)))
+#define get_lwp_thread(proc) ((struct thread_info *) \
 				  find_inferior_id (&all_threads, \
-				  get_process (proc)->lwpid))
+				  get_lwp (proc)->head.id))
 
-struct process_info
+struct lwp_info
 {
   struct inferior_list_entry head;
-  unsigned long lwpid;
 
   /* If this flag is set, the next SIGSTOP will be ignored (the
-     process will be immediately resumed).  This means that either we
+     lwp will be immediately resumed).  This means that either we
      sent the SIGSTOP to it ourselves and got some other pending event
      (so the SIGSTOP is still pending), or that we stopped the
      inferior implicitly via PTRACE_ATTACH and have not waited for it
      yet.  */
   int stop_expected;
 
-  /* If this flag is set, the process is known to be stopped right now (stop
+  /* True if this thread was suspended (with vCont;t).  */
+  int suspended;
+
+  /* If this flag is set, the lwp is known to be stopped right now (stop
      event already received in a wait()).  */
   int stopped;
 
-  /* When stopped is set, the last wait status recorded for this process.  */
+  /* If this flag is set, the lwp is known to be dead already (exit
+     event already received in a wait(), and is cached in
+     status_pending).  */
+  int dead;
+
+  /* When stopped is set, the last wait status recorded for this lwp.  */
   int last_status;
 
   /* If this flag is set, STATUS_PENDING is a waitstatus that has not yet
@@ -116,12 +138,12 @@ struct process_info
      stop (SIGTRAP stops only).  */
   CORE_ADDR bp_reinsert;
 
-  /* If this flag is set, the last continue operation on this process
+  /* If this flag is set, the last continue operation on this lwp
      was a single-step.  */
   int stepping;
 
   /* If this is non-zero, it points to a chain of signals which need to
-     be delivered to this process.  */
+     be delivered to this lwp.  */
   struct pending_signals *pending_signals;
 
   /* A link used when resuming.  It is initialized from the resume request,
@@ -136,12 +158,19 @@ struct process_info
      THREAD_KNOWN is set.  */
   td_thrhandle_t th;
 #endif
+
+  /* If WAITSTATUS->KIND is not TARGET_WAITKIND_IGNORE, the waitstatus
+     for this LWP's last event.  This may correspond to STATUS above,
+     or to an extended event (e.g., PTRACE_EVENT_FORK).  */
+  struct target_waitstatus waitstatus;
 };
 
-extern struct inferior_list all_processes;
+extern struct inferior_list all_lwps;
 
-void linux_attach_lwp (unsigned long pid);
+void linux_attach_lwp (unsigned long pid, int initial);
 
 int thread_db_init (int use_events);
 int thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
 			       CORE_ADDR load_module, CORE_ADDR *address);
+
+struct lwp_info *find_lwp_pid (ptid_t ptid);
Index: src/gdb/gdbserver/Makefile.in
===================================================================
--- src.orig/gdb/gdbserver/Makefile.in	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/Makefile.in	2008-11-25 17:28:12.000000000 +0000
@@ -133,7 +133,7 @@ TAGFILES = $(SOURCES) ${HFILES} ${ALLPAR
 
 OBS = inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
 	utils.o version.o \
-	mem-break.o hostio.o \
+	mem-break.o hostio.o event-loop.o \
 	$(XML_BUILTIN) \
 	$(DEPFILES) $(LIBOBJS)
 GDBREPLAY_OBS = gdbreplay.o version.o
@@ -283,6 +283,7 @@ server.o: server.c $(server_h)
 target.o: target.c $(server_h)
 thread-db.o: thread-db.c $(server_h) $(gdb_proc_service_h)
 utils.o: utils.c $(server_h)
+event-loop.o: event-loop.c $(server_h)
 gdbreplay.o: gdbreplay.c config.h
 
 signals.o: ../signals/signals.c $(server_h)
Index: src/gdb/gdbserver/mem-break.c
===================================================================
--- src.orig/gdb/gdbserver/mem-break.c	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/mem-break.c	2008-11-25 17:28:12.000000000 +0000
@@ -45,16 +45,56 @@ struct breakpoint
   int (*handler) (CORE_ADDR);
 };
 
-struct breakpoint *breakpoints;
+struct breakpoint_list
+{
+  struct inferior_list_entry head;
+
+  struct breakpoint *breakpoints;
+};
+
+/* ``all_breakpoints'' is keyed by process ID.  */
+
+struct inferior_list all_breakpoints;
+
+static struct breakpoint_list *
+get_breakpoint_list (int create)
+{
+  ptid_t ptid;
+  int pid;
+  struct inferior_list_entry *list;
+
+  ptid = ((struct inferior_list_entry *)current_inferior)->id;
+  pid = ptid_get_pid (ptid);
+
+  list = find_inferior_id (&all_breakpoints, pid_to_ptid (pid));
+
+  if (list == NULL && create)
+    {
+      list = calloc (1, sizeof (struct breakpoint_list));
+      list->id = pid_to_ptid (pid);
+      add_inferior_to_list (&all_breakpoints, list);
+    }
+
+  return (struct breakpoint_list *) list;
+}
+
+static void
+remove_breakpoint_list (struct breakpoint_list *list)
+{
+  remove_inferior (&all_breakpoints, &list->head);
+}
 
 void
 set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
 {
+  struct breakpoint_list *list;
   struct breakpoint *bp;
 
   if (breakpoint_data == NULL)
     error ("Target does not support breakpoints.");
 
+  list = get_breakpoint_list (1);
+
   bp = malloc (sizeof (struct breakpoint));
   memset (bp, 0, sizeof (struct breakpoint));
 
@@ -66,24 +106,30 @@ set_breakpoint_at (CORE_ADDR where, int 
   bp->pc = where;
   bp->handler = handler;
 
-  bp->next = breakpoints;
-  breakpoints = bp;
+  bp->next = list->breakpoints;
+  list->breakpoints = bp;
 }
 
 static void
 delete_breakpoint (struct breakpoint *bp)
 {
+  struct breakpoint_list *list;
   struct breakpoint *cur;
 
-  if (breakpoints == bp)
+  list = get_breakpoint_list (0);
+
+  if (list == NULL)
+    goto out;
+
+  if (list->breakpoints == bp)
     {
-      breakpoints = bp->next;
+      list->breakpoints = bp->next;
       (*the_target->write_memory) (bp->pc, bp->old_data,
 				   breakpoint_len);
       free (bp);
       return;
     }
-  cur = breakpoints;
+  cur = list->breakpoints;
   while (cur->next)
     {
       if (cur->next == bp)
@@ -95,13 +141,23 @@ delete_breakpoint (struct breakpoint *bp
 	  return;
 	}
     }
+
+ out:
   warning ("Could not find breakpoint in list.");
 }
 
 static struct breakpoint *
 find_breakpoint_at (CORE_ADDR where)
 {
-  struct breakpoint *bp = breakpoints;
+  struct breakpoint_list *list;
+  struct breakpoint *bp;
+
+  list = get_breakpoint_list (0);
+
+  if (list == NULL)
+    return NULL;
+
+  bp = list->breakpoints;
 
   while (bp != NULL)
     {
@@ -214,6 +270,14 @@ check_breakpoints (CORE_ADDR stop_pc)
     return 1;
 }
 
+int
+breakpoint_at (CORE_ADDR stop_pc)
+{
+  struct breakpoint *bp;
+  bp = find_breakpoint_at (stop_pc);
+  return (bp != NULL);
+}
+
 void
 set_breakpoint_data (const unsigned char *bp_data, int bp_len)
 {
@@ -224,8 +288,17 @@ set_breakpoint_data (const unsigned char
 void
 check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
 {
-  struct breakpoint *bp = breakpoints;
-  CORE_ADDR mem_end = mem_addr + mem_len;
+  struct breakpoint_list *list;
+  struct breakpoint *bp;
+  CORE_ADDR mem_end;
+
+  list = get_breakpoint_list (0);
+
+  if (list == NULL)
+    return;
+
+  bp = list->breakpoints;
+  mem_end = mem_addr + mem_len;
 
   for (; bp != NULL; bp = bp->next)
     {
@@ -257,8 +330,17 @@ check_mem_read (CORE_ADDR mem_addr, unsi
 void
 check_mem_write (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
 {
-  struct breakpoint *bp = breakpoints;
-  CORE_ADDR mem_end = mem_addr + mem_len;
+  struct breakpoint_list *list;
+  struct breakpoint *bp;
+  CORE_ADDR mem_end;
+
+  list = get_breakpoint_list (0);
+
+  if (list == NULL)
+    return;
+
+  bp = list->breakpoints;
+  mem_end = mem_addr + mem_len;
 
   for (; bp != NULL; bp = bp->next)
     {
@@ -294,6 +376,15 @@ check_mem_write (CORE_ADDR mem_addr, uns
 void
 delete_all_breakpoints (void)
 {
-  while (breakpoints)
-    delete_breakpoint (breakpoints);
+  struct breakpoint_list *list;
+
+  list = get_breakpoint_list (0);
+
+  if (list == NULL)
+    return;
+
+  while (list->breakpoints)
+    delete_breakpoint (list->breakpoints);
+
+  remove_breakpoint_list (list);
 }
Index: src/gdb/gdbserver/mem-break.h
===================================================================
--- src.orig/gdb/gdbserver/mem-break.h	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/mem-break.h	2008-11-25 17:28:12.000000000 +0000
@@ -54,6 +54,10 @@ void uninsert_breakpoint (CORE_ADDR wher
 
 int check_breakpoints (CORE_ADDR stop_pc);
 
+/* See if any breakpoint claims ownership of STOP_PC.  */
+
+int breakpoint_at (CORE_ADDR stop_pc);
+
 /* See if any breakpoints shadow the target memory area from MEM_ADDR
    to MEM_ADDR + MEM_LEN.  Update the data already read from the target
    (in BUF) if necessary.  */
Index: src/gdb/gdbserver/proc-service.c
===================================================================
--- src.orig/gdb/gdbserver/proc-service.c	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/proc-service.c	2008-11-25 17:28:12.000000000 +0000
@@ -99,15 +99,14 @@ ps_err_e
 ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
 {
 #ifdef HAVE_REGSETS
-  struct process_info *process;
+  struct lwp_info *lwp;
   struct thread_info *reg_inferior, *save_inferior;
 
-  process = (struct process_info *) find_inferior_id (&all_processes,
-						      lwpid);
-  if (process == NULL)
+  lwp = find_lwp_pid (pid_to_ptid (lwpid));
+  if (lwp == NULL)
     return PS_ERR;
 
-  reg_inferior = get_process_thread (process);
+  reg_inferior = get_lwp_thread (lwp);
   save_inferior = current_inferior;
   current_inferior = reg_inferior;
 
Index: src/gdb/gdbserver/regcache.c
===================================================================
--- src.orig/gdb/gdbserver/regcache.c	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/regcache.c	2008-11-25 17:28:12.000000000 +0000
@@ -91,9 +91,6 @@ new_register_cache (void)
 {
   struct inferior_regcache_data *regcache;
 
-  if (register_bytes == 0)
-    return NULL; /* The architecture hasn't been initialized yet.  */
-
   regcache = malloc (sizeof (*regcache));
 
   /* Make sure to zero-initialize the register cache when it is created,
@@ -114,11 +111,8 @@ free_register_cache (void *regcache_p)
   struct inferior_regcache_data *regcache
     = (struct inferior_regcache_data *) regcache_p;
 
-  if (regcache)
-    {
-      free (regcache->registers);
-      free (regcache);
-    }
+  free (regcache->registers);
+  free (regcache);
 }
 
 static void
Index: src/gdb/gdbserver/remote-utils.c
===================================================================
--- src.orig/gdb/gdbserver/remote-utils.c	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/remote-utils.c	2008-11-25 18:36:09.000000000 +0000
@@ -20,6 +20,7 @@
 
 #include "server.h"
 #include "terminal.h"
+#include "target.h"
 #include <stdio.h>
 #include <string.h>
 #if HAVE_SYS_IOCTL_H
@@ -78,14 +79,11 @@ typedef int socklen_t;
 /* A cache entry for a successfully looked-up symbol.  */
 struct sym_cache
 {
-  const char *name;
+  char *name;
   CORE_ADDR addr;
   struct sym_cache *next;
 };
 
-/* The symbol cache.  */
-static struct sym_cache *symbol_cache;
-
 /* If this flag has been set, assume cache misses are
    failures.  */
 int all_symbols_looked_up;
@@ -285,11 +283,16 @@ remote_open (char *name)
   fcntl (remote_desc, F_SETOWN, getpid ());
 #endif
 #endif
+
+  /* Register the event loop handler.  */
+  add_file_handler (remote_desc, handle_serial_event, NULL);
 }
 
 void
 remote_close (void)
 {
+  delete_file_handler (remote_desc);
+
 #ifdef USE_WIN32API
   closesocket (remote_desc);
 #else
@@ -311,6 +314,29 @@ fromhex (int a)
   return 0;
 }
 
+static const char hexchars[] = "0123456789abcdef";
+
+static int
+ishex (int ch, int *val)
+{
+  if ((ch >= 'a') && (ch <= 'f'))
+    {
+      *val = ch - 'a' + 10;
+      return 1;
+    }
+  if ((ch >= 'A') && (ch <= 'F'))
+    {
+      *val = ch - 'A' + 10;
+      return 1;
+    }
+  if ((ch >= '0') && (ch <= '9'))
+    {
+      *val = ch - '0';
+      return 1;
+    }
+  return 0;
+}
+
 int
 unhexify (char *bin, const char *hex, int count)
 {
@@ -517,12 +543,111 @@ try_rle (char *buf, int remaining, unsig
   return n + 1;
 }
 
+char *
+unpack_varlen_hex (char *buff,	/* packet to parse */
+		   ULONGEST *result)
+{
+  int nibble;
+  ULONGEST retval = 0;
+
+  while (ishex (*buff, &nibble))
+    {
+      buff++;
+      retval = retval << 4;
+      retval |= nibble & 0x0f;
+    }
+  *result = retval;
+  return buff;
+}
+
+/* Write a PTID to BUF.  Returns BUF+CHARACTERS_WRITTEN.  */
+
+char *
+write_ptid (char *buf, ptid_t ptid)
+{
+  int pid, tid;
+
+  if (multi_process)
+    {
+      pid = ptid_get_pid (ptid);
+      if (pid < 0)
+	buf += sprintf (buf, "p-%x.", -pid);
+      else
+	buf += sprintf (buf, "p%x.", pid);
+    }
+  tid = ptid_get_lwp (ptid);
+  if (tid < 0)
+    buf += sprintf (buf, "-%x", -tid);
+  else
+    buf += sprintf (buf, "%x", tid);
+
+  return buf;
+}
+
+ULONGEST
+hex_or_minus_one (char *buf, char **obuf)
+{
+  ULONGEST ret;
+
+  if (strncmp (buf, "-1", 2) == 0)
+    {
+      ret = (ULONGEST) -1;
+      buf += 2;
+    }
+  else
+    buf = unpack_varlen_hex (buf, &ret);
+
+  if (obuf)
+    *obuf = buf;
+
+  return ret;
+}
+
+/* Extract a PTID from BUF.  If non-null, OBUF is set to the to one
+   passed the last parsed char.  Returns null_ptid on error.  */
+ptid_t
+read_ptid (char *buf, char **obuf)
+{
+  char *p = buf;
+  char *pp;
+  ULONGEST pid = 0, tid = 0;
+
+  if (*p == 'p')
+    {
+      /* Multi-process ptid.  */
+      pp = unpack_varlen_hex (p + 1, &pid);
+      if (*pp != '.')
+	error ("invalid remote ptid: %s\n", p);
+
+      p = pp + 1;
+
+      tid = hex_or_minus_one (p, &pp);
+
+      if (obuf)
+	*obuf = pp;
+      /* TODO, we really need to gdbid vs target thread id after
+	 all.  */
+      return ptid_build (pid, tid, 0);
+    }
+
+  /* No multi-process.  Just a tid.  */
+  tid = hex_or_minus_one (p, &pp);
+
+  /* Since the stub is not sending a process id, then default to
+     what's in the current inferior.  */
+  pid = ptid_get_pid (((struct inferior_list_entry *) current_inferior)->id);
+
+  if (obuf)
+    *obuf = pp;
+  return ptid_build (pid, tid, 0);
+}
+
 /* Send a packet to the remote machine, with error checking.
    The data of the packet is in BUF, and the length of the
    packet is in CNT.  Returns >= 0 on success, -1 otherwise.  */
 
-int
-putpkt_binary (char *buf, int cnt)
+static int
+putpkt_binary_1 (char *buf, int cnt, int is_notif)
 {
   int i;
   unsigned char csum = 0;
@@ -536,7 +661,10 @@ putpkt_binary (char *buf, int cnt)
      and giving it a checksum.  */
 
   p = buf2;
-  *p++ = '$';
+  if (is_notif)
+    *p++ = '%';
+  else
+    *p++ = '$';
 
   for (i = 0; i < cnt;)
     i += try_rle (buf + i, cnt - i, &csum, &p);
@@ -560,12 +688,15 @@ putpkt_binary (char *buf, int cnt)
 	  return -1;
 	}
 
-      if (noack_mode)
+      if (noack_mode || is_notif)
 	{
 	  /* Don't expect an ack then.  */
 	  if (remote_debug)
 	    {
-	      fprintf (stderr, "putpkt (\"%s\"); [noack mode]\n", buf2);
+	      if (is_notif)
+		fprintf (stderr, "putpkt (\"%s\"); [notif]\n", buf2);
+	      else
+		fprintf (stderr, "putpkt (\"%s\"); [noack mode]\n", buf2);
 	      fflush (stderr);
 	    }
 	  break;
@@ -604,6 +735,12 @@ putpkt_binary (char *buf, int cnt)
   return 1;			/* Success! */
 }
 
+int
+putpkt_binary (char *buf, int cnt)
+{
+  return putpkt_binary_1 (buf, cnt, 0);
+}
+
 /* Send a packet to the remote machine, with error checking.  The data
    of the packet is in BUF, and the packet should be a NUL-terminated
    string.  Returns >= 0 on success, -1 otherwise.  */
@@ -614,6 +751,12 @@ putpkt (char *buf)
   return putpkt_binary (buf, strlen (buf));
 }
 
+int
+putpkt_notif (char *buf)
+{
+  return putpkt_binary_1 (buf, strlen (buf), 1);
+}
+
 /* Come here when we get an input interrupt from the remote side.  This
    interrupt should only be active while we are waiting for the child to do
    something.  About the only thing that should come through is a ^C, which
@@ -823,6 +966,11 @@ getpkt (char *buf)
 	  fflush (stderr);
 	}
     }
+  else if (remote_debug)
+    {
+      fprintf (stderr, "getpkt (\"%s\");  [noack mode] \n", buf);
+      fflush (stderr);
+    }
 
   return bp - buf;
 }
@@ -925,88 +1073,141 @@ dead_thread_notify (int id)
 }
 
 void
-prepare_resume_reply (char *buf, char status, unsigned char sig)
+prepare_resume_reply (char *buf, ptid_t ptid, struct target_waitstatus *status)
 {
-  int nib;
-
-  *buf++ = status;
-
-  nib = ((sig & 0xf0) >> 4);
-  *buf++ = tohex (nib);
-  nib = sig & 0x0f;
-  *buf++ = tohex (nib);
+  if (debug_threads)
+    fprintf (stderr, "Writing resume reply for %s:%d\n\n",
+	     target_pid_to_str (ptid), status->kind);
 
-  if (status == 'T')
+  switch (status->kind)
     {
-      const char **regp = gdbserver_expedite_regs;
-
-      if (the_target->stopped_by_watchpoint != NULL
-	  && (*the_target->stopped_by_watchpoint) ())
-	{
-	  CORE_ADDR addr;
-	  int i;
+    case TARGET_WAITKIND_STOPPED:
+      {
+	struct thread_info *saved_inferior;
+	const char **regp;
 
-	  strncpy (buf, "watch:", 6);
-	  buf += 6;
+	sprintf (buf, "T%02x", status->value.sig);
+	buf += strlen (buf);
 
-	  addr = (*the_target->stopped_data_address) ();
+	regp = gdbserver_expedite_regs;
 
-	  /* Convert each byte of the address into two hexadecimal chars.
-	     Note that we take sizeof (void *) instead of sizeof (addr);
-	     this is to avoid sending a 64-bit address to a 32-bit GDB.  */
-	  for (i = sizeof (void *) * 2; i > 0; i--)
-	    {
-	      *buf++ = tohex ((addr >> (i - 1) * 4) & 0xf);
-	    }
-	  *buf++ = ';';
-	}
+	saved_inferior = current_inferior;
+
+	current_inferior = find_thread_pid (ptid);
+
+	/* Check that the thread is still alive before trying to read
+	   registers or memory from it.  */
+	if (current_inferior != NULL && mythread_alive (ptid))
+	  {
+	    if (the_target->stopped_by_watchpoint != NULL
+		&& (*the_target->stopped_by_watchpoint) ())
+	      {
+		CORE_ADDR addr;
+		int i;
+
+		strncpy (buf, "watch:", 6);
+		buf += 6;
+
+		addr = (*the_target->stopped_data_address) ();
+
+		/* Convert each byte of the address into two hexadecimal chars.
+		   Note that we take sizeof (void *) instead of sizeof (addr);
+		   this is to avoid sending a 64-bit address to a
+		   32-bit GDB.  */
+		for (i = sizeof (void *) * 2; i > 0; i--)
+		  *buf++ = tohex ((addr >> (i - 1) * 4) & 0xf);
+		*buf++ = ';';
+	      }
+
+	    while (*regp)
+	      {
+		buf = outreg (find_regno (*regp), buf);
+		regp ++;
+	      }
+	  }
+
+	/* Formerly, if the debugger had not used any thread features
+	   we would not burden it with a thread status response.  This
+	   was for the benefit of GDB 4.13 and older.  However, in
+	   recent GDB versions the check (``if (cont_thread != 0)'')
+	   does not have the desired effect because of sillyness in
+	   the way that the remote protocol handles specifying a
+	   thread.  Since thread support relies on qSymbol support
+	   anyway, assume GDB can handle threads.  */
+
+	if (using_threads && !disable_packet_Tthread)
+	  {
+	    /* This if (1) ought to be unnecessary.  But remote_wait
+	       in GDB will claim this event belongs to inferior_ptid
+	       if we do not specify a thread, and there's no way for
+	       gdbserver to know what inferior_ptid is.  */
+	    if (1 || !ptid_equal (general_thread, ptid))
+	      {
+		/* In non-stop, don't change the general thread behind
+		   GDB's back.  */
+		if (!non_stop)
+		  general_thread = ptid;
+		sprintf (buf, "thread:");
+		buf += strlen (buf);
+		buf = write_ptid (buf, ptid);
+		strcat (buf, ";");
+		buf += strlen (buf);
+	      }
+	  }
+
+	/* FIXME: Can we make this be TARGET_WAITKIND_LOADED?  */
+	if (dlls_changed)
+	  {
+	    strcpy (buf, "library:;");
+	    buf += strlen (buf);
+	    dlls_changed = 0;
+	  }
 
-      while (*regp)
-	{
-	  buf = outreg (find_regno (*regp), buf);
-	  regp ++;
-	}
-
-      /* Formerly, if the debugger had not used any thread features we would not
-	 burden it with a thread status response.  This was for the benefit of
-	 GDB 4.13 and older.  However, in recent GDB versions the check
-	 (``if (cont_thread != 0)'') does not have the desired effect because of
-	 sillyness in the way that the remote protocol handles specifying a thread.
-	 Since thread support relies on qSymbol support anyway, assume GDB can handle
-	 threads.  */
-
-      if (using_threads && !disable_packet_Tthread)
-	{
-	  unsigned int gdb_id_from_wait;
+	current_inferior = saved_inferior;
+      }
+      break;
+    case TARGET_WAITKIND_EXITED:
+      if (multi_process)
+	sprintf (buf, "W%x;process:%x",
+		 status->value.integer, ptid_get_pid (ptid));
+      else
+	sprintf (buf, "W%02x", status->value.integer);
+      break;
+    case TARGET_WAITKIND_SIGNALLED:
+      if (multi_process)
+	sprintf (buf, "X%x;process:%x",
+		 status->value.sig, ptid_get_pid (ptid));
+      else
+	sprintf (buf, "X%02x", status->value.sig);
+      break;
+    case TARGET_WAITKIND_FORKED:
+    case TARGET_WAITKIND_VFORKED:
+      general_thread = ptid;
 
-	  /* FIXME right place to set this? */
-	  thread_from_wait = ((struct inferior_list_entry *)current_inferior)->id;
-	  gdb_id_from_wait = thread_to_gdb_id (current_inferior);
-
-	  if (debug_threads)
-	    fprintf (stderr, "Writing resume reply for %ld\n\n", thread_from_wait);
-	  /* This if (1) ought to be unnecessary.  But remote_wait in GDB
-	     will claim this event belongs to inferior_ptid if we do not
-	     specify a thread, and there's no way for gdbserver to know
-	     what inferior_ptid is.  */
-	  if (1 || old_thread_from_wait != thread_from_wait)
-	    {
-	      general_thread = thread_from_wait;
-	      sprintf (buf, "thread:%x;", gdb_id_from_wait);
-	      buf += strlen (buf);
-	      old_thread_from_wait = thread_from_wait;
-	    }
-	}
+      if (status->kind == TARGET_WAITKIND_FORKED)
+	sprintf (buf, "Y;fork;");
+      else
+	sprintf (buf, "Y;vfork;");
+      buf += strlen (buf);
+      buf = write_ptid (buf, ptid);
+      strcat (buf, ";");
+      buf += strlen (buf);
+      buf = write_ptid (buf, status->value.related_pid);
+      break;
+    case TARGET_WAITKIND_EXECD:
+      general_thread = ptid;
 
-      if (dlls_changed)
-	{
-	  strcpy (buf, "library:;");
-	  buf += strlen (buf);
-	  dlls_changed = 0;
-	}
+      sprintf (buf, "Y;exec;");
+      buf += strlen (buf);
+      buf = write_ptid (buf, ptid);
+      strcat (buf, ";");
+      buf += strlen (buf);
+      hexify (buf, status->value.execd_pathname, 0);
+      break;
+    default:
+      error ("unhandled waitkind");
+      break;
     }
-  /* For W and X, we're done.  */
-  *buf++ = 0;
 }
 
 void
@@ -1129,6 +1330,34 @@ decode_search_memory_packet (const char 
   return 0;
 }
 
+static void
+free_sym_cache (struct sym_cache *sym)
+{
+  if (sym != NULL)
+    {
+      free (sym->name);
+      free (sym);
+    }
+}
+
+void
+clear_symbol_cache (void)
+{
+  struct process_info *proc;
+  struct sym_cache *sym, *next;
+
+  proc = current_process ();
+
+  /* Check the cache first.  */
+  for (sym = proc->symbol_cache; sym; sym = next)
+    {
+      next = sym->next;
+      free_sym_cache (sym);
+    }
+
+  proc->symbol_cache = NULL;
+}
+
 /* Ask GDB for the address of NAME, and return it in ADDRP if found.
    Returns 1 if the symbol is found, 0 if it is not, -1 on error.  */
 
@@ -1138,9 +1367,12 @@ look_up_one_symbol (const char *name, CO
   char own_buf[266], *p, *q;
   int len;
   struct sym_cache *sym;
+  struct process_info *proc;
+
+  proc = current_process ();
 
   /* Check the cache first.  */
-  for (sym = symbol_cache; sym; sym = sym->next)
+  for (sym = proc->symbol_cache; sym; sym = sym->next)
     if (strcmp (name, sym->name) == 0)
       {
 	*addrp = sym->addr;
@@ -1152,7 +1384,7 @@ look_up_one_symbol (const char *name, CO
      in any libraries loaded after that point, only in symbols in
      libpthread.so.  It might not be an appropriate time to look
      up a symbol, e.g. while we're trying to fetch registers.  */
-  if (all_symbols_looked_up)
+  if (proc->all_symbols_looked_up)
     return 0;
 
   /* Send the request.  */
@@ -1212,8 +1444,8 @@ look_up_one_symbol (const char *name, CO
   sym = malloc (sizeof (*sym));
   sym->name = strdup (name);
   sym->addr = *addrp;
-  sym->next = symbol_cache;
-  symbol_cache = sym;
+  sym->next = proc->symbol_cache;
+  proc->symbol_cache = sym;
 
   return 1;
 }
Index: src/gdb/gdbserver/server.c
===================================================================
--- src.orig/gdb/gdbserver/server.c	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/server.c	2008-11-25 17:28:12.000000000 +0000
@@ -32,18 +32,19 @@
 #include <malloc.h>
 #endif
 
-unsigned long cont_thread;
-unsigned long general_thread;
-unsigned long step_thread;
-unsigned long thread_from_wait;
-unsigned long old_thread_from_wait;
+ptid_t cont_thread;
+ptid_t general_thread;
+ptid_t step_thread;
+
 int server_waiting;
 
 static int extended_protocol;
-static int attached;
 static int response_needed;
 static int exit_requested;
 
+int multi_process;
+int non_stop;
+
 static char **program_argv, **wrapper_argv;
 
 /* Enable miscellaneous debugging output.  The name is historical - it
@@ -87,6 +88,123 @@ int disable_packet_Tthread;
 int disable_packet_qC;
 int disable_packet_qfThreadInfo;
 
+/* Last status reported to GDB.  */
+static struct target_waitstatus last_status;
+static ptid_t last_ptid;
+
+static char *own_buf;
+static unsigned char *mem_buf;
+
+/* Structure holding information relative to a single stop reply.  We
+   keep a queue of these (realy a singly-linked list) to push to GDB
+   in non-stop mode.  */
+struct vstop_notif
+{
+  /* Pointer to next in list.  */
+  struct vstop_notif *next;
+
+  /* Thread or process that got the event.  */
+  ptid_t ptid;
+
+  /* Event info.  */
+  struct target_waitstatus status;
+};
+
+/* The pending stop replies list head.  */
+static struct vstop_notif *notif_queue = NULL;
+
+/* Put a stop reply to the stop reply queue.  */
+static void
+queue_stop_reply (ptid_t ptid, struct target_waitstatus *status)
+{
+  struct vstop_notif *new_notif;
+
+  new_notif = malloc (sizeof (*new_notif));
+  new_notif->next = NULL;
+  new_notif->ptid = ptid;
+  new_notif->status = *status;
+
+  if (notif_queue)
+    {
+      struct vstop_notif *tail;
+      for (tail = notif_queue;
+	   tail && tail->next;
+	   tail = tail->next)
+	;
+      tail->next = new_notif;
+    }
+  else
+    notif_queue = new_notif;
+
+  if (remote_debug)
+    {
+      int i = 0;
+      struct vstop_notif *tail;
+
+      for (tail = notif_queue; tail; tail = tail->next)
+	i++;
+
+      fprintf (stderr, "pending stop replies: %d\n", i);
+    }
+}
+
+/* Place an an event in the stop reply queue, and push a notification
+   if we aren't sending one yet.  */
+void
+push_event (ptid_t ptid, struct target_waitstatus *status)
+{
+  queue_stop_reply (ptid, status);
+
+  /* If this is the first stop reply in the queue, then inform GDB
+     about it, by sending a Stop notification.  */
+  if (notif_queue->next == NULL)
+    {
+      char *p = own_buf;
+      strcpy (p, "Stop:");
+      p += strlen (p);
+      prepare_resume_reply (p,
+			    notif_queue->ptid, &notif_queue->status);
+      putpkt_notif (own_buf);
+    }
+}
+
+/* Get rid of the currently pending stop replies.  */
+static void
+discard_queued_stop_replies (int pid)
+{
+  struct vstop_notif *prev = NULL, *reply, *next;
+
+  for (reply = notif_queue; reply; reply = next)
+    {
+      next = reply->next;
+
+      if (pid == -1
+	  || ptid_get_pid (reply->ptid) == pid)
+	{
+	  if (reply == notif_queue)
+	    notif_queue = next;
+	  else
+	    prev->next = reply->next;
+
+	  free (reply);
+	}
+      else
+	prev = reply;
+    }
+}
+
+/* If there are more stop replies to push, push one now.  */
+static void
+send_next_stop_reply (char *own_buf)
+{
+  if (notif_queue)
+    prepare_resume_reply (own_buf,
+			  notif_queue->ptid,
+			  &notif_queue->status);
+  else
+    write_ok (own_buf);
+}
+
 static int
 target_running (void)
 {
@@ -94,10 +212,9 @@ target_running (void)
 }
 
 static int
-start_inferior (char **argv, char *statusptr)
+start_inferior (char **argv)
 {
   char **new_argv = argv;
-  attached = 0;
 
   if (wrapper_argv != NULL)
     {
@@ -141,37 +258,39 @@ start_inferior (char **argv, char *statu
   if (wrapper_argv != NULL)
     {
       struct thread_resume resume_info;
-      int sig;
+      ptid_t ptid;
 
-      resume_info.thread = -1;
-      resume_info.step = 0;
+      resume_info.thread = pid_to_ptid (signal_pid);
+      resume_info.kind = rk_continue;
       resume_info.sig = 0;
-      resume_info.leave_stopped = 0;
 
-      sig = mywait (statusptr, 0);
-      if (*statusptr != 'T')
-	return sig;
+      ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
+
+      if (last_status.kind != TARGET_WAITKIND_STOPPED)
+	return signal_pid;
 
       do
 	{
-	  (*the_target->resume) (&resume_info);
+	  (*the_target->resume) (&resume_info, 1);
 
-	  sig = mywait (statusptr, 0);
-	  if (*statusptr != 'T')
-	    return sig;
+ 	  mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
+	  if (last_status.kind != TARGET_WAITKIND_STOPPED)
+	    return signal_pid;
 	}
-      while (sig != TARGET_SIGNAL_TRAP);
+      while (last_status.value.sig != TARGET_SIGNAL_TRAP);
 
-      return sig;
+      return signal_pid;
     }
 
-  /* Wait till we are at 1st instruction in program, return signal
-     number (assuming success).  */
-  return mywait (statusptr, 0);
+  /* Wait till we are at 1st instruction in program, return new pid
+     (assuming success).  */
+  last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
+
+  return signal_pid;
 }
 
 static int
-attach_inferior (int pid, char *statusptr, int *sigptr)
+attach_inferior (int pid)
 {
   /* myattach should return -1 if attaching is unsupported,
      0 if it succeeded, and call error() otherwise.  */
@@ -179,8 +298,6 @@ attach_inferior (int pid, char *statuspt
   if (myattach (pid) != 0)
     return -1;
 
-  attached = 1;
-
   fprintf (stderr, "Attached; pid = %d\n", pid);
   fflush (stderr);
 
@@ -189,13 +306,17 @@ attach_inferior (int pid, char *statuspt
      whichever we were told to attach to.  */
   signal_pid = pid;
 
-  *sigptr = mywait (statusptr, 0);
+  if (!non_stop)
+    {
+      last_ptid = mywait (pid_to_ptid (pid), &last_status, 0, 0);
 
-  /* GDB knows to ignore the first SIGSTOP after attaching to a running
-     process using the "attach" command, but this is different; it's
-     just using "target remote".  Pretend it's just starting up.  */
-  if (*statusptr == 'T' && *sigptr == TARGET_SIGNAL_STOP)
-    *sigptr = TARGET_SIGNAL_TRAP;
+      /* GDB knows to ignore the first SIGSTOP after attaching to a running
+	 process using the "attach" command, but this is different; it's
+	 just using "target remote".  Pretend it's just starting up.  */
+      if (last_status.kind == TARGET_WAITKIND_STOPPED
+	  && last_status.value.sig == TARGET_SIGNAL_STOP)
+	last_status.value.sig = TARGET_SIGNAL_TRAP;
+    }
 
   return 0;
 }
@@ -283,6 +404,43 @@ handle_general_set (char *own_buf)
       return;
     }
 
+  if (strncmp (own_buf, "QNonStop:", 9) == 0)
+    {
+      char *mode = own_buf + 9;
+      int req = -1;
+      char *req_str;
+
+      if (strcmp (mode, "0") == 0)
+	req = 0;
+      else if (strcmp (mode, "1") == 0)
+	req = 1;
+      else
+	{
+	  /* We don't know what this mode is, so complain to
+	     GDB.  */
+	  fprintf (stderr, "Unknown non-stop mode requested: %s\n",
+		   own_buf);
+	  write_enn (own_buf);
+	  return;
+	}
+
+      req_str = req ? "non-stop" : "all-stop";
+      if (start_non_stop (req) != 0)
+	{
+	  fprintf (stderr, "Setting %s mode failed\n", req_str);
+	  write_enn (own_buf);
+	  return;
+	}
+
+      non_stop = req;
+
+      if (remote_debug)
+	fprintf (stderr, "[%s mode enabled]\n", req_str);
+
+      write_ok (own_buf);
+      return;
+    }
+
   /* Otherwise we didn't know what packet it was.  Say we didn't
      understand it.  */
   own_buf[0] = 0;
@@ -501,10 +659,20 @@ handle_query (char *own_buf, int packet_
   /* Reply the current thread id.  */
   if (strcmp ("qC", own_buf) == 0 && !disable_packet_qC)
     {
+      ptid_t gdb_id;
       require_running (own_buf);
-      thread_ptr = all_threads.head;
-      sprintf (own_buf, "QC%x",
-	       thread_to_gdb_id ((struct thread_info *)thread_ptr));
+
+      if (!ptid_equal (general_thread, minus_one_ptid))
+	gdb_id = general_thread;
+      else
+	{
+	  thread_ptr = all_threads.head;
+	  gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
+	}
+
+      sprintf (own_buf, "QC");
+      own_buf += 2;
+      own_buf = write_ptid (own_buf, gdb_id);
       return;
     }
 
@@ -521,19 +689,28 @@ handle_query (char *own_buf, int packet_
     {
       if (strcmp ("qfThreadInfo", own_buf) == 0)
 	{
+	  ptid_t gdb_id;
+
 	  require_running (own_buf);
 	  thread_ptr = all_threads.head;
-	  sprintf (own_buf, "m%x", thread_to_gdb_id ((struct thread_info *)thread_ptr));
+
+	  *own_buf++ = 'm';
+	  gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
+	  write_ptid (own_buf, gdb_id);
 	  thread_ptr = thread_ptr->next;
 	  return;
 	}
 
       if (strcmp ("qsThreadInfo", own_buf) == 0)
 	{
+	  ptid_t gdb_id;
+
 	  require_running (own_buf);
 	  if (thread_ptr != NULL)
 	    {
-	      sprintf (own_buf, "m%x", thread_to_gdb_id ((struct thread_info *)thread_ptr));
+	      *own_buf++ = 'm';
+	      gdb_id = thread_to_gdb_id ((struct thread_info *)thread_ptr);
+	      write_ptid (own_buf, gdb_id);
 	      thread_ptr = thread_ptr->next;
 	      return;
 	    }
@@ -772,6 +949,21 @@ handle_query (char *own_buf, int packet_
   if (strncmp ("qSupported", own_buf, 10) == 0
       && (own_buf[10] == ':' || own_buf[10] == '\0'))
     {
+      char *p = &own_buf[10];
+
+      /* Process each feature being provided by GDB.  The first
+	 feature will follow a ':', and latter features will follow
+	 ';'.  */
+      if (*p == ':')
+	for (p = strtok (p + 1, ";");
+	     p != NULL;
+	     p = strtok (NULL, ";"))
+	  {
+	    /* Record if GDB knows about multiprocess support.  */
+	    if (strcmp (p, "multiprocess+") == 0)
+	      multi_process = 1;
+	  }
+
       sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1);
 
       /* We do not have any hook to indicate whether the target backend
@@ -792,6 +984,11 @@ handle_query (char *own_buf, int packet_
 
       if (transport_is_reliable)
 	strcat (own_buf, ";QStartNoAckMode+");
+
+      strcat (own_buf, ";multiprocess+");
+
+      strcat (own_buf, ";QNonStop+");
+
       return;
     }
 
@@ -800,8 +997,9 @@ handle_query (char *own_buf, int packet_
       && strncmp ("qGetTLSAddr:", own_buf, 12) == 0)
     {
       char *p = own_buf + 12;
-      CORE_ADDR parts[3], address = 0;
+      CORE_ADDR parts[2], address = 0;
       int i, err;
+      ptid_t ptid;
 
       require_running (own_buf);
 
@@ -825,7 +1023,10 @@ handle_query (char *own_buf, int packet_
 	      p2 = NULL;
 	    }
 
-	  decode_address (&parts[i], p, len);
+	  if (i == 0)
+	    ptid = read_ptid (p, NULL);
+	  else
+	    decode_address (&parts[i - 1], p, len);
 	  p = p2;
 	}
 
@@ -833,12 +1034,12 @@ handle_query (char *own_buf, int packet_
 	err = 1;
       else
 	{
-	  struct thread_info *thread = gdb_id_to_thread (parts[0]);
+	  struct thread_info *thread = find_thread_pid (ptid);
 
 	  if (thread == NULL)
 	    err = 2;
 	  else
-	    err = the_target->get_tls_address (thread, parts[1], parts[2],
+	    err = the_target->get_tls_address (thread, parts[0], parts[1],
 					       &address);
 	}
 
@@ -914,6 +1115,40 @@ handle_query (char *own_buf, int packet_
       return;
     }
 
+  if (the_target->pid_to_exec_file != NULL
+      && strncmp ("qExecFile:", own_buf, 10) == 0)
+    {
+      char *p = own_buf + 10;
+      int pid;
+      char *path;
+      size_t len;
+
+      pid = strtol (p, NULL, 16);
+
+      path = (*the_target->pid_to_exec_file) (pid);
+
+      if (!path)
+	{
+	  write_enn (own_buf);
+	  return;
+	}
+
+      len = strlen (path);
+
+      if (len * 2 >= PBUFSIZ - strlen (own_buf) - 2)
+	{
+	  /* File name too long for packet.  */
+	  write_enn (own_buf);
+	  return;
+	}
+
+      own_buf[0] = 'Q';
+      p = own_buf + strlen (own_buf);
+      *p++ = ';';
+      hexify (p, path, len);
+      return;
+    }
+
   /* Otherwise we didn't know what packet it was.  Say we didn't
      understand it.  */
   own_buf[0] = 0;
@@ -921,11 +1156,11 @@ handle_query (char *own_buf, int packet_
 
 /* Parse vCont packets.  */
 void
-handle_v_cont (char *own_buf, char *status, int *signal)
+handle_v_cont (char *own_buf)
 {
   char *p, *q;
   int n = 0, i = 0;
-  struct thread_resume *resume_info, default_action;
+  struct thread_resume *resume_info;
 
   /* Count the number of semicolons in the packet.  There should be one
      for every action.  */
@@ -936,28 +1171,20 @@ handle_v_cont (char *own_buf, char *stat
       p++;
       p = strchr (p, ';');
     }
-  /* Allocate room for one extra action, for the default remain-stopped
-     behavior; if no default action is in the list, we'll need the extra
-     slot.  */
-  resume_info = malloc ((n + 1) * sizeof (resume_info[0]));
-
-  default_action.thread = -1;
-  default_action.leave_stopped = 1;
-  default_action.step = 0;
-  default_action.sig = 0;
+
+  resume_info = malloc (n * sizeof (resume_info[0]));
 
   p = &own_buf[5];
-  i = 0;
   while (*p)
     {
       p++;
 
-      resume_info[i].leave_stopped = 0;
-
       if (p[0] == 's' || p[0] == 'S')
-	resume_info[i].step = 1;
+	resume_info[i].kind = rk_step;
       else if (p[0] == 'c' || p[0] == 'C')
-	resume_info[i].step = 0;
+	resume_info[i].kind = rk_continue;
+      else if (p[0] == 't')
+	resume_info[i].kind = rk_stop;
       else
 	goto err;
 
@@ -980,17 +1207,10 @@ handle_v_cont (char *own_buf, char *stat
 	}
 
       if (p[0] == 0)
-	{
-	  resume_info[i].thread = -1;
-	  default_action = resume_info[i];
-
-	  /* Note: we don't increment i here, we'll overwrite this entry
-	     the next time through.  */
-	}
+	resume_info[i].thread = minus_one_ptid;
       else if (p[0] == ':')
 	{
-	  unsigned int gdb_id = strtoul (p + 1, &q, 16);
-	  unsigned long thread_id;
+	  ptid_t ptid = read_ptid (p + 1, &q);
 
 	  if (p == q)
 	    goto err;
@@ -998,33 +1218,36 @@ handle_v_cont (char *own_buf, char *stat
 	  if (p[0] != ';' && p[0] != 0)
 	    goto err;
 
-	  thread_id = gdb_id_to_thread_id (gdb_id);
-	  if (thread_id)
-	    resume_info[i].thread = thread_id;
-	  else
-	    goto err;
-
-	  i++;
+	  resume_info[i].thread = ptid;
 	}
-    }
 
-  resume_info[i] = default_action;
+      i++;
+    }
 
   /* Still used in occasional places in the backend.  */
-  if (n == 1 && resume_info[0].thread != -1)
+  if (n == 1
+      && !ptid_equal (resume_info[0].thread, minus_one_ptid)
+      && resume_info[0].kind != rk_stop)
     cont_thread = resume_info[0].thread;
   else
-    cont_thread = -1;
+    cont_thread = minus_one_ptid;
   set_desired_inferior (0);
 
-  enable_async_io ();
-  (*the_target->resume) (resume_info);
+  if (!non_stop)
+    enable_async_io ();
+
+  (*the_target->resume) (resume_info, n);
 
   free (resume_info);
 
-  *signal = mywait (status, 1);
-  prepare_resume_reply (own_buf, *status, *signal);
-  disable_async_io ();
+  if (non_stop)
+    write_ok (own_buf);
+  else
+    {
+      last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
+      prepare_resume_reply (own_buf, last_ptid, &last_status);
+      disable_async_io ();
+    }
   return;
 
 err:
@@ -1035,19 +1258,32 @@ err:
 
 /* Attach to a new program.  Return 1 if successful, 0 if failure.  */
 int
-handle_v_attach (char *own_buf, char *status, int *signal)
+handle_v_attach (char *own_buf)
 {
   int pid;
 
   pid = strtol (own_buf + 8, NULL, 16);
-  if (pid != 0 && attach_inferior (pid, status, signal) == 0)
+  if (pid != 0 && attach_inferior (pid) == 0)
     {
       /* Don't report shared library events after attaching, even if
 	 some libraries are preloaded.  GDB will always poll the
 	 library list.  Avoids the "stopped by shared library event"
 	 notice on the GDB side.  */
       dlls_changed = 0;
-      prepare_resume_reply (own_buf, *status, *signal);
+
+      if (non_stop)
+	{
+	  /* In non-stop, we don't send a resume reply.  GDB will
+	     query for the current thread, so set it.  */
+	  general_thread = last_ptid;
+
+	  /* Stop events will follow up using the normal notification
+	     mechanism.  */
+	  write_ok (own_buf);
+	}
+      else
+	prepare_resume_reply (own_buf, last_ptid, &last_status);
+
       return 1;
     }
   else
@@ -1059,7 +1295,7 @@ handle_v_attach (char *own_buf, char *st
 
 /* Run a new program.  Return 1 if successful, 0 if failure.  */
 static int
-handle_v_run (char *own_buf, char *status, int *signal)
+handle_v_run (char *own_buf)
 {
   char *p, **pp, *next_p, **new_argv;
   int i, new_argc;
@@ -1096,36 +1332,58 @@ handle_v_run (char *own_buf, char *statu
 
   if (new_argv[0] == NULL)
     {
-      /* GDB didn't specify a program to run.  Try to use the argv
-	 from the last run: either from the last vRun with a non-empty
-	 argv, or from what the user specified if gdbserver was
-	 started as: `gdbserver :1234 PROG ARGS'.  */
-
       if (program_argv == NULL)
 	{
 	  write_enn (own_buf);
 	  return 0;
 	}
 
-      /* We can reuse the old args.  We don't need this then.  */
-      free (new_argv);
+      new_argv[0] = strdup (program_argv[0]);
+    }
+
+  /* Free the old argv.  */
+  if (program_argv)
+    {
+      for (pp = program_argv; *pp != NULL; pp++)
+	free (*pp);
+      free (program_argv);
+    }
+  program_argv = new_argv;
+
+  start_inferior (program_argv);
+  if (last_status.kind == TARGET_WAITKIND_STOPPED)
+    {
+      prepare_resume_reply (own_buf, last_ptid, &last_status);
+
+      /* In non-stop, sending a resume reply doesn't set the general
+	 thread, but GDB assumes a vRun sets it (this is so GDB can
+	 query which is the main thread of the new inferior.  */
+      if (non_stop)
+	general_thread = last_ptid;
+
+      return 1;
     }
   else
     {
-      /* Free the old argv.  */
-      if (program_argv)
-	{
-	  for (pp = program_argv; *pp != NULL; pp++)
-	    free (*pp);
-	  free (program_argv);
-	}
-      program_argv = new_argv;
+      write_enn (own_buf);
+      return 0;
     }
+}
+
+/* Attach to a new program.  Return 1 if successful, 0 if failure.  */
+int
+handle_v_kill (char *own_buf)
+{
+  int pid;
+  char *p = &own_buf[6];
 
-  *signal = start_inferior (program_argv, status);
-  if (*status == 'T')
+  pid = strtol (p, NULL, 16);
+  if (pid != 0 && kill_inferior (pid) == 0)
     {
-      prepare_resume_reply (own_buf, *status, *signal);
+      last_status.kind = TARGET_WAITKIND_SIGNALLED;
+      last_status.value.sig = TARGET_SIGNAL_KILL;
+      discard_queued_stop_replies (pid);
+      write_ok (own_buf);
       return 1;
     }
   else
@@ -1135,23 +1393,45 @@ handle_v_run (char *own_buf, char *statu
     }
 }
 
+/* Handle a 'vStopped' packet.  */
+static void
+handle_v_stopped (char *own_buf)
+{
+  /* If we're waiting for GDB to acknowledge a pending stop reply,
+     consider that done.  */
+  if (notif_queue)
+    {
+      struct vstop_notif *head;
+
+      if (remote_debug)
+	fprintf (stderr, "vStopped: acking %s\n",
+		 target_pid_to_str (notif_queue->ptid));
+
+      head = notif_queue;
+      notif_queue = notif_queue->next;
+      free (head);
+    }
+
+  /* Push another, or if there are no more left, and OK.  */
+  send_next_stop_reply (own_buf);
+}
+
 /* Handle all of the extended 'v' packets.  */
 void
-handle_v_requests (char *own_buf, char *status, int *signal,
-		   int packet_len, int *new_packet_len)
+handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
 {
   if (!disable_packet_vCont)
     {
       if (strncmp (own_buf, "vCont;", 6) == 0)
 	{
 	  require_running (own_buf);
-	  handle_v_cont (own_buf, status, signal);
+	  handle_v_cont (own_buf);
 	  return;
 	}
 
       if (strncmp (own_buf, "vCont?", 6) == 0)
 	{
-	  strcpy (own_buf, "vCont;c;C;s;S");
+	  strcpy (own_buf, "vCont;c;C;s;S;t");
 	  return;
 	}
     }
@@ -1162,25 +1442,43 @@ handle_v_requests (char *own_buf, char *
 
   if (strncmp (own_buf, "vAttach;", 8) == 0)
     {
-      if (target_running ())
+      if (!multi_process && target_running ())
 	{
 	  fprintf (stderr, "Already debugging a process\n");
 	  write_enn (own_buf);
 	  return;
 	}
-      handle_v_attach (own_buf, status, signal);
+      handle_v_attach (own_buf);
       return;
     }
 
   if (strncmp (own_buf, "vRun;", 5) == 0)
     {
-      if (target_running ())
+      if (!multi_process && target_running ())
 	{
 	  fprintf (stderr, "Already debugging a process\n");
 	  write_enn (own_buf);
 	  return;
 	}
-      handle_v_run (own_buf, status, signal);
+      handle_v_run (own_buf);
+      return;
+    }
+
+  if (strncmp (own_buf, "vKill;", 6) == 0)
+    {
+      if (!target_running ())
+	{
+	  fprintf (stderr, "No process to kill\n");
+	  write_enn (own_buf);
+	  return;
+	}
+      handle_v_kill (own_buf);
+      return;
+    }
+
+  if (strncmp (own_buf, "vStopped", 8) == 0)
+    {
+      handle_v_stopped (own_buf);
       return;
     }
 
@@ -1190,34 +1488,109 @@ handle_v_requests (char *own_buf, char *
   return;
 }
 
+/* Resume inferior and wait for another event.  In non-stop mode,
+   don't really wait here, but return immediatelly to the event
+   loop.  */
 void
-myresume (char *own_buf, int step, int *signalp, char *statusp)
+proceed (char *own_buf, int step, int siggnal)
 {
   struct thread_resume resume_info[2];
   int n = 0;
-  int sig = *signalp;
+  int valid_cont_thread;
 
   set_desired_inferior (0);
 
-  if (step || sig || (cont_thread != 0 && cont_thread != -1))
+  valid_cont_thread = (!ptid_equal (cont_thread, null_ptid)
+			 && !ptid_equal (cont_thread, minus_one_ptid));
+
+  if (step || siggnal || valid_cont_thread)
     {
       resume_info[0].thread
 	= ((struct inferior_list_entry *) current_inferior)->id;
-      resume_info[0].step = step;
-      resume_info[0].sig = sig;
-      resume_info[0].leave_stopped = 0;
+      if (step)
+	resume_info[0].kind = rk_step;
+      else
+	resume_info[0].kind = rk_continue;
+      resume_info[0].sig = siggnal;
       n++;
     }
-  resume_info[n].thread = -1;
-  resume_info[n].step = 0;
-  resume_info[n].sig = 0;
-  resume_info[n].leave_stopped = (cont_thread != 0 && cont_thread != -1);
-
-  enable_async_io ();
-  (*the_target->resume) (resume_info);
-  *signalp = mywait (statusp, 1);
-  prepare_resume_reply (own_buf, *statusp, *signalp);
-  disable_async_io ();
+
+  if (!valid_cont_thread)
+    {
+      resume_info[n].thread = minus_one_ptid;
+      resume_info[n].kind = rk_continue;
+      resume_info[n].sig = 0;
+    }
+
+  if (!non_stop)
+    enable_async_io ();
+
+  (*the_target->resume) (resume_info, n);
+
+  if (non_stop)
+    write_ok (own_buf);
+  else
+    {
+      last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
+      prepare_resume_reply (own_buf, last_ptid, &last_status);
+      disable_async_io ();
+    }
+}
+
+/* Callback for for_each_inferior.  Make a new stop reply for each
+   stopped thread.  */
+static int
+queue_stop_reply_callback (struct inferior_list_entry *entry, void *arg)
+{
+  int pid = * (int *) arg;
+
+  if (pid == -1
+      || ptid_get_pid (entry->id) == pid)
+    {
+      struct target_waitstatus status;
+
+      status.kind = TARGET_WAITKIND_STOPPED;
+      status.value.sig = TARGET_SIGNAL_TRAP;
+
+      /* Pass the last stop reply back to GDB, but don't notify.  */
+      queue_stop_reply (entry->id, &status);
+    }
+
+  return 0;
+}
+
+/* Status handler for the '?' packet.  */
+
+static void
+handle_status (char *own_buf)
+{
+  struct target_waitstatus status;
+  status.kind = TARGET_WAITKIND_STOPPED;
+  status.value.sig = TARGET_SIGNAL_TRAP;
+
+  /* In non-stop mode, we must send a stop reply for each stopped
+     thread.  In all-stop mode, just send one for the first stopped
+     thread we find.  */
+
+  if (non_stop)
+    {
+      int pid = -1;
+      discard_queued_stop_replies (pid);
+      find_inferior (&all_threads, queue_stop_reply_callback, &pid);
+
+      /* The first is sent immediatly.  OK is sent if there is no
+	 stopped thread, which is the same handling of the vStopped
+	 packet (by design).  */
+      send_next_stop_reply (own_buf);
+    }
+  else
+    {
+      if (all_threads.head)
+	prepare_resume_reply (own_buf,
+			      all_threads.head->id, &status);
+      else
+	strcpy (own_buf, "W00");
+    }
 }
 
 static void
@@ -1241,7 +1614,8 @@ gdbserver_usage (FILE *stream)
 	   "HOST:PORT to listen for a TCP connection.\n"
 	   "\n"
 	   "Options:\n"
-	   "  --debug\t\tEnable debugging output.\n"
+	   "  --debug\t\tEnable general debugging output.\n"
+	   "  --remote-debug\tEnable remote protocol debugging output.\n"
 	   "  --version\t\tDisplay version information and exit.\n"
 	   "  --wrapper WRAPPER --\tRun WRAPPER to start new programs.\n");
   if (REPORT_BUGS_TO[0] && stream == stdout)
@@ -1268,15 +1642,51 @@ gdbserver_show_disableable (FILE *stream
       break;					\
     }
 
+static int
+first_thread_of (struct inferior_list_entry *entry, void *args)
+{
+  int pid = * (int *) args;
+
+  if (ptid_get_pid (entry->id) == pid)
+    return 1;
+
+  return 0;
+}
+
+static void
+kill_inferior_callback (struct inferior_list_entry *entry)
+{
+  struct process_info *process = (struct process_info *) entry;
+  int pid = ptid_get_pid (process->head.id);
+
+  kill_inferior (pid);
+  discard_queued_stop_replies (pid);
+}
+
+static void
+detach_or_kill_inferior_callback (struct inferior_list_entry *entry)
+{
+  struct process_info *process = (struct process_info *) entry;
+  int pid = ptid_get_pid (process->head.id);
+
+  if (process->attached)
+    detach_inferior (pid);
+  else
+    kill_inferior (pid);
+
+  discard_queued_stop_replies (pid);
+}
+
+static void
+join_inferiors_callback (struct inferior_list_entry *entry)
+{
+  struct process_info *process = (struct process_info *) entry;
+  join_inferior (ptid_get_pid (process->head.id));
+}
+
 int
 main (int argc, char *argv[])
 {
-  char ch, status, *own_buf;
-  unsigned char *mem_buf;
-  int i = 0;
-  int signal;
-  unsigned int len;
-  CORE_ADDR mem_addr;
   int bad_attach;
   int pid;
   char *arg_end, *port;
@@ -1320,6 +1730,8 @@ main (int argc, char *argv[])
 	}
       else if (strcmp (*next_arg, "--debug") == 0)
 	debug_threads = 1;
+      else if (strcmp (*next_arg, "--remote-debug") == 0)
+	remote_debug = 1;
       else if (strcmp (*next_arg, "--disable-packet") == 0)
 	{
 	  gdbserver_show_disableable (stdout);
@@ -1409,6 +1821,7 @@ main (int argc, char *argv[])
       exit (1);
     }
 
+  initialize_inferiors ();
   initialize_async_io ();
   initialize_low ();
 
@@ -1426,7 +1839,7 @@ main (int argc, char *argv[])
       program_argv[i] = NULL;
 
       /* Wait till we are at first instruction in program.  */
-      signal = start_inferior (program_argv, &status);
+      start_inferior (program_argv);
 
       /* We are now (hopefully) stopped at the first instruction of
 	 the target process.  This assumes that the target process was
@@ -1434,15 +1847,16 @@ main (int argc, char *argv[])
     }
   else if (pid != 0)
     {
-      if (attach_inferior (pid, &status, &signal) == -1)
+      if (attach_inferior (pid) == -1)
 	error ("Attaching not supported on this target");
 
       /* Otherwise succeeded.  */
     }
   else
     {
-      status = 'W';
-      signal = 0;
+      last_status.kind = TARGET_WAITKIND_EXITED;
+      last_status.value.integer = 0;
+      last_ptid = minus_one_ptid;
     }
 
   /* Don't report shared library events on the initial connection,
@@ -1452,12 +1866,14 @@ main (int argc, char *argv[])
 
   if (setjmp (toplevel))
     {
-      fprintf (stderr, "Killing inferior\n");
-      kill_inferior ();
+      fprintf (stderr, "Killing all inferiors\n");
+      for_each_inferior (&all_processes,
+			 kill_inferior_callback);
       exit (1);
     }
 
-  if (status == 'W' || status == 'X')
+  if (last_status.kind == TARGET_WAITKIND_EXITED
+      || last_status.kind == TARGET_WAITKIND_SIGNALLED)
     was_running = 0;
   else
     was_running = 1;
@@ -1471,9 +1887,11 @@ main (int argc, char *argv[])
   while (1)
     {
       noack_mode = 0;
+      multi_process = 0;
+      non_stop = 0;
+
       remote_open (port);
 
-    restart:
       if (setjmp (toplevel) != 0)
 	{
 	  /* An error occurred.  */
@@ -1484,8 +1902,49 @@ main (int argc, char *argv[])
 	    }
 	}
 
+      /* Wait for events.  This will return when all event sources are
+	 removed from the event loop. */
+      start_event_loop ();
+
+      /* If an exit was requested (using the "monitor exit" command),
+	 terminate now.  The only other way to get here is for
+	 getpkt to fail; close the connection and reopen it at the
+	 top of the loop.  */
+
+      if (exit_requested)
+	{
+	  for_each_inferior (&all_processes,
+			     detach_or_kill_inferior_callback);
+	  exit (0);
+	}
+      else
+	fprintf (stderr, "Remote side has terminated connection.  "
+		 "GDBserver will reopen the connection.\n");
+    }
+}
+
+/* Event loop callback that handles a serial event.  The first byte in
+   the serial buffer gets us here.  We expect characters to arrive at
+   a brisk pace, so we read the rest of the packet with a blocking
+   getpkt call.  */
+static void
+process_serial_event (void)
+{
+  char ch;
+  int i = 0;
+  int signal;
+  unsigned int len;
+  CORE_ADDR mem_addr;
+  int pid;
+
+  /* Used to decide when gdbserver should exit in
+     multi-mode/remote.  */
+  static int have_ran = 0;
+
+  if (!have_ran)
+    have_ran = target_running ();
+
       disable_async_io ();
-      while (!exit_requested)
 	{
 	  unsigned char sig;
 	  int packet_len;
@@ -1494,7 +1953,11 @@ main (int argc, char *argv[])
 	  response_needed = 0;
 	  packet_len = getpkt (own_buf);
 	  if (packet_len <= 0)
-	    break;
+	    {
+	      target_async (0);
+	      remote_close ();
+	      return;
+	    }
 	  response_needed = 1;
 
 	  i = 0;
@@ -1509,29 +1972,46 @@ main (int argc, char *argv[])
 	      break;
 	    case 'D':
 	      require_running (own_buf);
-	      fprintf (stderr, "Detaching from inferior\n");
-	      if (detach_inferior () != 0)
+
+	      if (multi_process)
+		{
+		  i++; /* skip ';' */
+		  pid = strtol (&own_buf[i], NULL, 16);
+		}
+	      else
+		pid = ptid_get_pid (((struct inferior_list_entry *)current_inferior)->id);
+
+	      fprintf (stderr, "Detaching from process %d\n", pid);
+	      if (detach_inferior (pid) != 0)
 		write_enn (own_buf);
 	      else
 		{
+		  discard_queued_stop_replies (pid);
 		  write_ok (own_buf);
 
 		  if (extended_protocol)
 		    {
 		      /* Treat this like a normal program exit.  */
-		      signal = 0;
-		      status = 'W';
+		      last_status.kind = TARGET_WAITKIND_EXITED;
+		      last_status.value.integer = 0;
+		      last_ptid = pid_to_ptid (pid);
+
+		      current_inferior = NULL;
 		    }
 		  else
 		    {
 		      putpkt (own_buf);
 		      remote_close ();
 
-		      /* If we are attached, then we can exit.  Otherwise, we
-			 need to hang around doing nothing, until the child
-			 is gone.  */
-		      if (!attached)
-			join_inferior ();
+		      /* Usually, if we are attached, then we can
+			 exit.  Otherwise, we need to hang around
+			 doing nothing, until the child is gone.  The
+			 decision to join or not is left to the
+			 target, as some targets may have to join even
+			 if attached (e.g., Windows versions without
+			 DebugSetProcessKillOnExit).  */
+		      for_each_inferior (&all_processes,
+					 join_inferiors_callback);
 
 		      exit (0);
 		    }
@@ -1542,21 +2022,43 @@ main (int argc, char *argv[])
 	      write_ok (own_buf);
 	      break;
 	    case '?':
-	      prepare_resume_reply (own_buf, status, signal);
+	      handle_status (own_buf);
 	      break;
 	    case 'H':
 	      if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
 		{
-		  unsigned long gdb_id, thread_id;
+		  ptid_t gdb_id, thread_id;
+		  int pid;
 
 		  require_running (own_buf);
-		  gdb_id = strtoul (&own_buf[2], NULL, 16);
-		  if (gdb_id == 0 || gdb_id == -1)
-		    thread_id = gdb_id;
+
+		  gdb_id = read_ptid (&own_buf[2], NULL);
+
+		  pid = ptid_get_pid (gdb_id);
+
+		  if (ptid_equal (gdb_id, null_ptid)
+		      || ptid_equal (gdb_id, minus_one_ptid))
+		    thread_id = null_ptid;
+		  else if (pid != 0
+			   && ptid_equal (pid_to_ptid (pid),
+					  gdb_id))
+		    {
+		      struct thread_info *thread =
+			(struct thread_info *) find_inferior (&all_threads,
+							      first_thread_of,
+							      &pid);
+		      if (!thread)
+			{
+			  write_enn (own_buf);
+			  break;
+			}
+
+		      thread_id = ((struct inferior_list_entry *)thread)->id;
+		    }
 		  else
 		    {
 		      thread_id = gdb_id_to_thread_id (gdb_id);
-		      if (thread_id == 0)
+		      if (ptid_equal (thread_id, null_ptid))
 			{
 			  write_enn (own_buf);
 			  break;
@@ -1565,6 +2067,19 @@ main (int argc, char *argv[])
 
 		  if (own_buf[1] == 'g')
 		    {
+		      if (ptid_equal (thread_id, null_ptid))
+			{
+			  /* GDB is telling us to choose any thread.
+			     Check if the currently selected thread is
+			     still valid. If it is not, select the
+			     first available.  */
+			  struct thread_info *thread =
+			    (struct thread_info *) find_inferior_id (&all_threads,
+								     general_thread);
+			  if (thread == NULL)
+			    thread_id = all_threads.head->id;
+			}
+
 		      general_thread = thread_id;
 		      set_desired_inferior (1);
 		    }
@@ -1611,9 +2126,11 @@ main (int argc, char *argv[])
 	      break;
 	    case 'X':
 	      require_running (own_buf);
+
+	      /* If len == 0, GDB is probing for packet support.  */
 	      if (decode_X_packet (&own_buf[1], packet_len - 1,
 				   &mem_addr, &len, mem_buf) < 0
-		  || write_inferior_memory (mem_addr, mem_buf, len) != 0)
+		  || (len > 0 && write_inferior_memory (mem_addr, mem_buf, len) != 0))
 		write_enn (own_buf);
 	      else
 		write_ok (own_buf);
@@ -1625,7 +2142,7 @@ main (int argc, char *argv[])
 		signal = target_signal_to_host (sig);
 	      else
 		signal = 0;
-	      myresume (own_buf, 0, &signal, &status);
+	      proceed (own_buf, 0, signal);
 	      break;
 	    case 'S':
 	      require_running (own_buf);
@@ -1634,17 +2151,17 @@ main (int argc, char *argv[])
 		signal = target_signal_to_host (sig);
 	      else
 		signal = 0;
-	      myresume (own_buf, 1, &signal, &status);
+	      proceed (own_buf, 1, signal);
 	      break;
 	    case 'c':
 	      require_running (own_buf);
 	      signal = 0;
-	      myresume (own_buf, 0, &signal, &status);
+	      proceed (own_buf, 0, signal);
 	      break;
 	    case 's':
 	      require_running (own_buf);
 	      signal = 0;
-	      myresume (own_buf, 1, &signal, &status);
+	      proceed (own_buf, 1, signal);
 	      break;
 	    case 'Z':
 	      {
@@ -1713,20 +2230,19 @@ main (int argc, char *argv[])
 	      if (!target_running ())
 		/* The packet we received doesn't make sense - but we
 		   can't reply to it, either.  */
-		goto restart;
+		return;
 
-	      fprintf (stderr, "Killing inferior\n");
-	      kill_inferior ();
+	      fprintf (stderr, "Killing all inferiors\n");
+	      for_each_inferior (&all_processes, kill_inferior_callback);
 
 	      /* When using the extended protocol, we wait with no
 		 program running.  The traditional protocol will exit
 		 instead.  */
 	      if (extended_protocol)
 		{
-		  status = 'X';
-		  signal = TARGET_SIGNAL_KILL;
-		  was_running = 0;
-		  goto restart;
+		  last_status.kind = TARGET_WAITKIND_EXITED;
+		  last_status.value.sig = TARGET_SIGNAL_KILL;
+		  return;
 		}
 	      else
 		{
@@ -1735,12 +2251,13 @@ main (int argc, char *argv[])
 		}
 	    case 'T':
 	      {
-		unsigned long gdb_id, thread_id;
+		ptid_t gdb_id, thread_id;
 
 		require_running (own_buf);
-		gdb_id = strtoul (&own_buf[1], NULL, 16);
+
+		gdb_id = read_ptid (&own_buf[1], NULL);
 		thread_id = gdb_id_to_thread_id (gdb_id);
-		if (thread_id == 0)
+		if (ptid_equal (thread_id, null_ptid))
 		  {
 		    write_enn (own_buf);
 		    break;
@@ -1760,18 +2277,19 @@ main (int argc, char *argv[])
 	      if (extended_protocol)
 		{
 		  if (target_running ())
-		    kill_inferior ();
+		    for_each_inferior (&all_processes,
+				       kill_inferior_callback);
 		  fprintf (stderr, "GDBserver restarting\n");
 
 		  /* Wait till we are at 1st instruction in prog.  */
 		  if (program_argv != NULL)
-		    signal = start_inferior (program_argv, &status);
+		    start_inferior (program_argv);
 		  else
 		    {
-		      status = 'X';
-		      signal = TARGET_SIGNAL_KILL;
+		      last_status.kind = TARGET_WAITKIND_EXITED;
+		      last_status.value.sig = TARGET_SIGNAL_KILL;
 		    }
-		  goto restart;
+		  return;
 		}
 	      else
 		{
@@ -1783,8 +2301,7 @@ main (int argc, char *argv[])
 		}
 	    case 'v':
 	      /* Extended (long) request.  */
-	      handle_v_requests (own_buf, &status, &signal,
-				 packet_len, &new_packet_len);
+	      handle_v_requests (own_buf, packet_len, &new_packet_len);
 	      break;
 
 	    default:
@@ -1802,50 +2319,52 @@ main (int argc, char *argv[])
 
 	  response_needed = 0;
 
-	  if (was_running && (status == 'W' || status == 'X'))
+	  if (!extended_protocol && have_ran && !target_running ())
 	    {
-	      was_running = 0;
-
-	      if (status == 'W')
-		fprintf (stderr,
-			 "\nChild exited with status %d\n", signal);
-	      if (status == 'X')
-		fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
-			 target_signal_to_host (signal),
-			 target_signal_to_name (signal));
-
-	      if (extended_protocol)
-		goto restart;
-	      else
+	      /* In non-stop, defer exiting until GDB had a chance to
+		 query the whole vStopped list (until it gets an
+		 OK).  */
+	      if (!notif_queue)
 		{
 		  fprintf (stderr, "GDBserver exiting\n");
 		  exit (0);
 		}
 	    }
-
-	  if (status != 'W' && status != 'X')
-	    was_running = 1;
 	}
+}
 
-      /* If an exit was requested (using the "monitor exit" command),
-	 terminate now.  The only other way to get here is for
-	 getpkt to fail; close the connection and reopen it at the
-	 top of the loop.  */
+/* Event-loop callback for serial events.  */
+void
+handle_serial_event (int err, gdb_client_data client_data)
+{
+  if (debug_threads)
+    fprintf (stderr, "handling possible serial event\n");
 
-      if (exit_requested)
-	{
-	  remote_close ();
-	  if (attached && target_running ())
-	    detach_inferior ();
-	  else if (target_running ())
-	    kill_inferior ();
-	  exit (0);
-	}
-      else
-	{
-	  fprintf (stderr, "Remote side has terminated connection.  "
-			   "GDBserver will reopen the connection.\n");
-	  remote_close ();
-	}
-    }
+  /* Really handle it.  */
+  process_serial_event ();
+
+  /* Be sure to not change the selected inferior behind GDB's back.
+     Important in the non-stop mode asynchronous protocol.  */
+  set_desired_inferior (1);
+}
+
+/* Event-loop callback for the target events.  */
+void
+handle_target_event (int err, gdb_client_data client_data)
+{
+  if (debug_threads)
+    fprintf (stderr, "handling possible target event\n");
+
+  last_ptid = mywait (minus_one_ptid, &last_status,
+		      TARGET_WNOHANG, 1);
+
+  if (last_status.kind == TARGET_WAITKIND_IGNORE)
+    return; /* Nothing interesting found.  */
+
+  /* Something interesting.  Tell GDB about it.  */
+  push_event (last_ptid, &last_status);
+
+  /* Be sure to not change the selected inferior behind GDB's back.
+     Important in the non-stop mode asynchronous protocol.  */
+  set_desired_inferior (1);
 }
Index: src/gdb/gdbserver/server.h
===================================================================
--- src.orig/gdb/gdbserver/server.h	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/server.h	2008-11-25 19:15:35.000000000 +0000
@@ -77,6 +77,70 @@ typedef unsigned char gdb_byte;
    least the size of a (void *).  */
 typedef long long CORE_ADDR;
 
+typedef unsigned long long ULONGEST;
+
+/* The ptid struct is a collection of the various "ids" necessary
+   for identifying the inferior.  This consists of the process id
+   (pid), thread id (tid), and other fields necessary for uniquely
+   identifying the inferior process/thread being debugged.  When
+   manipulating ptids, the constructors, accessors, and predicate
+   declared in server.h should be used.  These are as follows:
+
+      ptid_build	- Make a new ptid from a pid, lwp, and tid.
+      pid_to_ptid	- Make a new ptid from just a pid.
+      ptid_get_pid	- Fetch the pid component of a ptid.
+      ptid_get_lwp	- Fetch the lwp component of a ptid.
+      ptid_get_tid	- Fetch the tid component of a ptid.
+      ptid_equal	- Test to see if two ptids are equal.
+
+   Please do NOT access the struct ptid members directly (except, of
+   course, in the implementation of the above ptid manipulation
+   functions).  */
+
+struct ptid
+  {
+    /* Process id */
+    int pid;
+
+    /* Lightweight process id */
+    long lwp;
+
+    /* Thread id */
+    long tid;
+  };
+
+typedef struct ptid ptid_t;
+
+/* The -1 ptid, often used to indicate either an error condition or a
+   "don't care" condition, i.e, "run all threads".  */
+extern ptid_t minus_one_ptid;
+
+/* The null or zero ptid, often used to indicate no process.  */
+extern ptid_t null_ptid;
+
+/* Attempt to find and return an existing ptid with the given PID,
+   LWP, and TID components.  If none exists, create a new one and
+   return that.  */
+ptid_t ptid_build (int pid, long lwp, long tid);
+
+/* Create a ptid from just a pid.  */
+ptid_t pid_to_ptid (int pid);
+
+/* Fetch the pid (process id) component from a ptid.  */
+int ptid_get_pid (ptid_t ptid);
+
+/* Fetch the lwp (lightweight process) component from a ptid.  */
+long ptid_get_lwp (ptid_t ptid);
+
+/* Fetch the tid (thread id) component from a ptid.  */
+long ptid_get_tid (ptid_t ptid);
+
+/* Compare two ptids to see if they are equal.  */
+extern int ptid_equal (ptid_t p1, ptid_t p2);
+
+/* Return true if this ptid represents a process id.  */
+extern int ptid_is_pid (ptid_t ptid);
+
 /* Generic information for tracking a list of ``inferiors'' - threads,
    processes, etc.  */
 struct inferior_list
@@ -86,7 +150,7 @@ struct inferior_list
 };
 struct inferior_list_entry
 {
-  unsigned long id;
+  ptid_t id;
   struct inferior_list_entry *next;
 };
 
@@ -100,6 +164,32 @@ struct dll_info
   CORE_ADDR base_addr;
 };
 
+struct sym_cache;
+struct process_info_private;
+
+struct process_info
+{
+  struct inferior_list_entry head;
+
+  int attached;
+
+  /* The symbol cache.  */
+  struct sym_cache *symbol_cache;
+
+  /* If this flag has been set, assume symbol cache misses are
+     failures.  */
+  int all_symbols_looked_up;
+
+  /* Private target data.  */
+  struct process_info_private *private;
+};
+
+/* Return a pointer to the process that corresponds to the current
+   thread (current_inferior).  It is an error to call this if there is
+   no current thread selected.  */
+
+extern struct process_info *current_process (void);
+
 #include "regcache.h"
 #include "gdb/signals.h"
 
@@ -112,22 +202,36 @@ void initialize_low ();
 
 /* From inferiors.c.  */
 
+extern struct inferior_list all_processes;
 extern struct inferior_list all_threads;
 extern struct inferior_list all_dlls;
 extern int dlls_changed;
 
+void initialize_inferiors (void);
+
 void add_inferior_to_list (struct inferior_list *list,
 			   struct inferior_list_entry *new_inferior);
 void for_each_inferior (struct inferior_list *list,
 			void (*action) (struct inferior_list_entry *));
+
+#define FOR_EACH_INFERIOR(TYPE, INF_LIST, INF)			\
+  for (INF = (TYPE *)(INF_LIST)->head;				\
+       INF != NULL;						\
+       INF = (TYPE *)((struct inferior_list_entry *)INF)->next)	\
+
 extern struct thread_info *current_inferior;
 void remove_inferior (struct inferior_list *list,
 		      struct inferior_list_entry *entry);
 void remove_thread (struct thread_info *thread);
-void add_thread (unsigned long thread_id, void *target_data, unsigned int);
-unsigned int thread_id_to_gdb_id (unsigned long);
-unsigned int thread_to_gdb_id (struct thread_info *);
-unsigned long gdb_id_to_thread_id (unsigned int);
+void add_thread (ptid_t ptid, void *target_data);
+
+struct process_info *add_process (int pid, int attached);
+
+struct thread_info *find_thread_pid (ptid_t ptid);
+
+ptid_t thread_id_to_gdb_id (ptid_t);
+ptid_t thread_to_gdb_id (struct thread_info *);
+ptid_t gdb_id_to_thread_id (ptid_t);
 struct thread_info *gdb_id_to_thread (unsigned int);
 void clear_inferiors (void);
 struct inferior_list_entry *find_inferior
@@ -136,7 +240,7 @@ struct inferior_list_entry *find_inferio
 		   void *),
       void *arg);
 struct inferior_list_entry *find_inferior_id (struct inferior_list *list,
-					      unsigned long id);
+					      ptid_t id);
 void *inferior_target_data (struct thread_info *);
 void set_inferior_target_data (struct thread_info *, void *);
 void *inferior_regcache_data (struct thread_info *);
@@ -149,11 +253,10 @@ void unloaded_dll (const char *name, COR
 
 /* Public variables in server.c */
 
-extern unsigned long cont_thread;
-extern unsigned long general_thread;
-extern unsigned long step_thread;
-extern unsigned long thread_from_wait;
-extern unsigned long old_thread_from_wait;
+extern ptid_t cont_thread;
+extern ptid_t general_thread;
+extern ptid_t step_thread;
+
 extern int server_waiting;
 extern int debug_threads;
 extern int pass_signals[];
@@ -165,6 +268,26 @@ extern int disable_packet_Tthread;
 extern int disable_packet_qC;
 extern int disable_packet_qfThreadInfo;
 
+extern int multi_process;
+extern int non_stop;
+
+/* Functions from event-loop.c.  */
+typedef void *gdb_client_data;
+typedef void (handler_func) (int, gdb_client_data);
+
+extern void delete_file_handler (int fd);
+extern void add_file_handler (int fd, handler_func *proc,
+			      gdb_client_data client_data);
+
+extern void start_event_loop (void);
+
+/* Functions from server.c.  */
+
+extern void handle_serial_event (int err, gdb_client_data client_data);
+extern void handle_target_event (int err, gdb_client_data client_data);
+
+extern void push_event (ptid_t ptid, struct target_waitstatus *status);
+
 /* Functions from hostio.c.  */
 extern int handle_vFile (char *, int, int *);
 
@@ -178,8 +301,12 @@ extern int all_symbols_looked_up;
 extern int noack_mode;
 extern int transport_is_reliable;
 
+ptid_t read_ptid (char *buf, char **obuf);
+char *write_ptid (char *buf, ptid_t ptid);
+
 int putpkt (char *buf);
 int putpkt_binary (char *buf, int len);
+int putpkt_notif (char *buf);
 int getpkt (char *buf);
 void remote_open (char *name);
 void remote_close (void);
@@ -193,7 +320,8 @@ void convert_ascii_to_int (char *from, u
 void convert_int_to_ascii (unsigned char *from, char *to, int n);
 void new_thread_notify (int id);
 void dead_thread_notify (int id);
-void prepare_resume_reply (char *buf, char status, unsigned char sig);
+void prepare_resume_reply (char *buf, ptid_t ptid,
+			   struct target_waitstatus *status);
 
 const char *decode_address_to_semicolon (CORE_ADDR *addrp, const char *start);
 void decode_address (CORE_ADDR *addrp, const char *start, int len);
@@ -236,6 +364,13 @@ void error (const char *string,...) ATTR
 void fatal (const char *string,...) ATTR_NORETURN ATTR_FORMAT (printf, 1, 2);
 void warning (const char *string,...) ATTR_FORMAT (printf, 1, 2);
 
+void internal_error_file_line (const char *file, int line,
+			       const char *string, ...)
+	ATTR_NORETURN ATTR_FORMAT (printf, 3, 4);
+
+#define internal_error(FMT, ...) \
+  internal_error_file_line (__FILE__, __LINE__, FMT, ##__VA_ARGS__)
+
 /* Maximum number of bytes to read/write at once.  The value here
    is chosen to fill up a packet (the headers account for the 32).  */
 #define MAXBUFBYTES(N) (((N)-32)/2)
Index: src/gdb/gdbserver/target.c
===================================================================
--- src.orig/gdb/gdbserver/target.c	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/target.c	2008-11-25 17:28:12.000000000 +0000
@@ -28,10 +28,7 @@ set_desired_inferior (int use_general)
   struct thread_info *found;
 
   if (use_general == 1)
-    {
-      found = (struct thread_info *) find_inferior_id (&all_threads,
-						       general_thread);
-    }
+    found = find_thread_pid (general_thread);
   else
     {
       found = NULL;
@@ -39,14 +36,14 @@ set_desired_inferior (int use_general)
       /* If we are continuing any (all) thread(s), use step_thread
 	 to decide which thread to step and/or send the specified
 	 signal to.  */
-      if ((step_thread != 0 && step_thread != -1)
-	  && (cont_thread == 0 || cont_thread == -1))
-	found = (struct thread_info *) find_inferior_id (&all_threads,
-							 step_thread);
+      if ((!ptid_equal (step_thread, null_ptid)
+	   && !ptid_equal (step_thread, minus_one_ptid))
+	  && (ptid_equal (cont_thread, null_ptid)
+	      || ptid_equal (cont_thread, minus_one_ptid)))
+	found = find_thread_pid (step_thread);
 
       if (found == NULL)
-	found = (struct thread_info *) find_inferior_id (&all_threads,
-							 cont_thread);
+	found = find_thread_pid (cont_thread);
     }
 
   if (found == NULL)
@@ -87,15 +84,28 @@ write_inferior_memory (CORE_ADDR memaddr
   return res;
 }
 
-unsigned char
-mywait (char *statusp, int connected_wait)
+ptid_t
+mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
+	int connected_wait)
 {
-  unsigned char ret;
+  ptid_t ret;
 
   if (connected_wait)
     server_waiting = 1;
 
-  ret = (*the_target->wait) (statusp);
+  ret = (*the_target->wait) (ptid, ourstatus, options);
+
+  if (ourstatus->kind == TARGET_WAITKIND_EXITED
+      || ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
+    {
+      if (ourstatus->kind == TARGET_WAITKIND_EXITED)
+	fprintf (stderr,
+		 "\nChild exited with status %d\n", ourstatus->value.sig);
+      if (ourstatus->kind == TARGET_WAITKIND_SIGNALLED)
+	fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
+		 target_signal_to_host (ourstatus->value.sig),
+		 target_signal_to_name (ourstatus->value.sig));
+    }
 
   if (connected_wait)
     server_waiting = 0;
@@ -103,9 +113,47 @@ mywait (char *statusp, int connected_wai
   return ret;
 }
 
+int
+start_non_stop (int nonstop)
+{
+  if (the_target->start_non_stop == NULL)
+    {
+      if (nonstop)
+	return -1;
+      else
+	return 0;
+    }
+
+  return (*the_target->start_non_stop) (nonstop);
+}
+
 void
 set_target_ops (struct target_ops *target)
 {
   the_target = (struct target_ops *) malloc (sizeof (*the_target));
   memcpy (the_target, target, sizeof (*the_target));
 }
+
+/* Convert pid to printable format.  */
+
+char *
+target_pid_to_str (ptid_t ptid)
+{
+  static char buf[80];
+
+  if (ptid_equal (ptid, minus_one_ptid))
+    snprintf (buf, sizeof (buf), "<all threads>");
+  else if (ptid_equal (ptid, null_ptid))
+    snprintf (buf, sizeof (buf), "<null thread>");
+  else if (ptid_get_tid (ptid) != 0)
+    snprintf (buf, sizeof (buf), "Thread %d.0x%lx",
+	      ptid_get_pid (ptid), ptid_get_tid (ptid));
+  else if (ptid_get_lwp (ptid) != 0)
+    snprintf (buf, sizeof (buf), "LWP %d.%ld",
+	      ptid_get_pid (ptid), ptid_get_lwp (ptid));
+  else
+    snprintf (buf, sizeof (buf), "Process %d",
+	      ptid_get_pid (ptid));
+
+  return buf;
+}
Index: src/gdb/gdbserver/target.h
===================================================================
--- src.orig/gdb/gdbserver/target.h	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/target.h	2008-11-25 17:28:12.000000000 +0000
@@ -22,25 +22,95 @@
 #ifndef TARGET_H
 #define TARGET_H
 
-/* This structure describes how to resume a particular thread (or
-   all threads) based on the client's request.  If thread is -1, then
-   this entry applies to all threads.  These are generally passed around
-   as an array, and terminated by a thread == -1 entry.  */
+/* This structure describes how to resume a particular thread (or all
+   threads) based on the client's request.  If thread is
+   minus_one_ptid, then this entry applies to all threads.  If the
+   thread points to a whole process, the this entry applies to all
+   threads of that process.  These are generally passed around as an
+   array, and terminated by a thread == minus_one_ptid entry.  */
 
-struct thread_resume
+enum resume_kind
 {
-  unsigned long thread;
+  /* Thread should be stopped.  */
+  rk_stop,
+
+  /* Thread should continue.  */
+  rk_continue,
 
-  /* If non-zero, leave this thread stopped.  */
-  int leave_stopped;
+  /* Thread should single-step.  */
+  rk_step
+};
 
-  /* If non-zero, we want to single-step.  */
-  int step;
+struct thread_resume
+{
+  ptid_t thread;
 
-  /* If non-zero, send this signal when we resume.  */
+  enum resume_kind kind;
+
+  /* If non-zero, send this signal when we resume, or to stop the
+     thread.  If stopping a thread, and this is 0, the target should
+     stop the thread however it needs.  */
   int sig;
 };
 
+/* Generally, what has the program done?  */
+enum target_waitkind
+  {
+    /* The program has exited.  The exit status is in value.integer.  */
+    TARGET_WAITKIND_EXITED,
+
+    /* The program has stopped with a signal.  Which signal is in
+       value.sig.  */
+    TARGET_WAITKIND_STOPPED,
+
+    /* The program has terminated with a signal.  Which signal is in
+       value.sig.  */
+    TARGET_WAITKIND_SIGNALLED,
+
+    /* The program is letting us know that it dynamically loaded something
+       (e.g. it called load(2) on AIX).  */
+    TARGET_WAITKIND_LOADED,
+
+    /* The program has forked.  A "related" process' PTID is in
+       value.related_pid.  I.e., if the child forks, value.related_pid
+       is the parent's ID.  */
+
+    TARGET_WAITKIND_FORKED,
+
+    /* The program has vforked.  A "related" process's PTID is in
+       value.related_pid.  */
+
+    TARGET_WAITKIND_VFORKED,
+
+    /* The program has exec'ed a new executable file.  The new file's
+       pathname is pointed to by value.execd_pathname.  */
+
+    TARGET_WAITKIND_EXECD,
+
+    /* An event has occured, but we should wait again.  In this case,
+       we want to go back to the event loop and wait there for another
+       event from the inferior.  */
+    TARGET_WAITKIND_IGNORE
+  };
+
+struct target_waitstatus
+  {
+    enum target_waitkind kind;
+
+    /* Forked child pid, execd pathname, exit status or signal number.  */
+    union
+      {
+	int integer;
+	enum target_signal sig;
+	ptid_t related_pid;
+	char *execd_pathname;
+      }
+    value;
+  };
+
+/* Options that can be passed to target_ops->wait.  */
+#define TARGET_WNOHANG 1
+
 struct target_ops
 {
   /* Start a new process.
@@ -64,36 +134,36 @@ struct target_ops
 
   int (*attach) (unsigned long pid);
 
-  /* Kill all inferiors.  */
+  /* Kill inferior PID.  Return -1 on failure, and 0 on success.  */
 
-  void (*kill) (void);
+  int (*kill) (int pid);
 
-  /* Detach from all inferiors.
-     Return -1 on failure, and 0 on success.  */
+  /* Detach from inferior PID. Return -1 on failure, and 0 on
+     success.  */
 
-  int (*detach) (void);
+  int (*detach) (int pid);
 
-  /* Wait for inferiors to end.  */
+  /* GDBServer is exiting, and may need to wait for inferior PID to
+     end.  */
 
-  void (*join) (void);
+  void (*join) (int pid);
 
   /* Return 1 iff the thread with process ID PID is alive.  */
 
-  int (*thread_alive) (unsigned long pid);
+  int (*thread_alive) (ptid_t pid);
 
   /* Resume the inferior process.  */
 
-  void (*resume) (struct thread_resume *resume_info);
-
-  /* Wait for the inferior process to change state.
+  void (*resume) (struct thread_resume *resume_info, size_t n);
 
-     STATUS will be filled in with a response code to send to GDB.
+  /* Wait for the inferior process or thread to change state.
 
-     Returns the signal which caused the process to stop, in the
-     remote protocol numbering (e.g. TARGET_SIGNAL_STOP), or the
-     exit code as an integer if *STATUS is 'W'.  */
-
-  unsigned char (*wait) (char *status);
+     PTID = -1 to wait for any pid to do something PTID(pid,0,0) to
+     wait for any thread of process pid to do something.  Return ptid
+     of child, or -1 in case of error; store status through argument
+     pointer STATUS.  OPTIONS is a bit set of options defined was
+     TARGET_W* above.  */
+  ptid_t (*wait) (ptid_t ptid, struct target_waitstatus *status, int options);
 
   /* Fetch registers from the inferior process.
 
@@ -188,6 +258,25 @@ struct target_ops
   /* Fill BUF with an hostio error packet representing the last hostio
      error.  */
   void (*hostio_last_error) (char *buf);
+
+  /* Attempts to find the pathname of the executable file
+     that was run to create a specified process.
+
+     If the executable file cannot be determined, NULL is returned.
+
+     Else, a pointer to a character string containing the pathname is
+     returned.  This string should be copied into a buffer by the
+     client if the string will not be immediately used, or if it must
+     persist.  */
+  char* (*pid_to_exec_file) (int pid);
+
+  /* Enables async target events.  Returns the previous enable
+     state.  */
+  int (*async) (int enable);
+
+  /* Switch to non-stop (1) or all-stop (0) mode.  Return 0 on
+     success, -1 otherwise.  */
+  int (*start_non_stop) (int);
 };
 
 extern struct target_ops *the_target;
@@ -200,11 +289,11 @@ void set_target_ops (struct target_ops *
 #define myattach(pid) \
   (*the_target->attach) (pid)
 
-#define kill_inferior() \
-  (*the_target->kill) ()
+#define kill_inferior(pid) \
+  (*the_target->kill) (pid)
 
-#define detach_inferior() \
-  (*the_target->detach) ()
+#define detach_inferior(pid) \
+  (*the_target->detach) (pid)
 
 #define mythread_alive(pid) \
   (*the_target->thread_alive) (pid)
@@ -215,10 +304,18 @@ void set_target_ops (struct target_ops *
 #define store_inferior_registers(regno) \
   (*the_target->store_registers) (regno)
 
-#define join_inferior() \
-  (*the_target->join) ()
+#define join_inferior(pid) \
+  (*the_target->join) (pid)
 
-unsigned char mywait (char *statusp, int connected_wait);
+#define target_async(enable) \
+  (the_target->async ? (*the_target->async) (enable) : 0)
+
+/* Start non-stop mode, returns 0 on success, -1 on failure.   */
+
+int start_non_stop (int nonstop);
+
+ptid_t mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
+	       int connected_wait);
 
 int read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len);
 
@@ -227,4 +324,6 @@ int write_inferior_memory (CORE_ADDR mem
 
 void set_desired_inferior (int id);
 
+char *target_pid_to_str (ptid_t);
+
 #endif /* TARGET_H */
Index: src/gdb/gdbserver/thread-db.c
===================================================================
--- src.orig/gdb/gdbserver/thread-db.c	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/thread-db.c	2008-11-25 17:28:12.000000000 +0000
@@ -35,15 +35,37 @@ static int thread_db_use_events;
 
 #include <stdint.h>
 
-/* Structure that identifies the child process for the
-   <proc_service.h> interface.  */
-static struct ps_prochandle proc_handle;
+static int find_one_thread (ptid_t);
+static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
 
-/* Connection to the libthread_db library.  */
-static td_thragent_t *thread_agent;
+static void
+fixup_proc_handle (void)
+{
+  ptid_t inferior_ptid;
+  struct process_info_private *proc = current_process ()->private;
 
-static int find_one_thread (int);
-static int find_new_threads_callback (const td_thrhandle_t *th_p, void *data);
+  /* FIXME drow/2004-10-16: This is the "overall process ID", which
+     GNU/Linux calls tgid, "thread group ID".  When we support
+     attaching to threads, the original thread may not be the correct
+     thread.  We would have to get the process ID from /proc for NPTL.
+     For LinuxThreads we could do something similar: follow the chain
+     of parent processes until we find the highest one we're attached
+     to, and use its tgid.
+
+     This isn't the only place in gdbserver that assumes that the first
+     process in the list is the thread group leader.  */
+
+  /* We're actually passing the current lwp to proc_services.  This is
+     because in non-stop mode, the tgid process may be running at this
+     point --- linux doesn't allow reading memory through running
+     LWPs.  At this point, I'm not sure if it's useful to actually
+     have a proc_handle.pid instead of just making proc_services
+     return current_inferior->id.pid directly.  */
+
+  inferior_ptid = ((struct inferior_list_entry *)current_inferior)->id;
+
+  proc->proc_handle.pid = ptid_get_lwp (inferior_ptid);
+}
 
 static char *
 thread_db_err_str (td_err_e err)
@@ -136,16 +158,18 @@ thread_db_create_event (CORE_ADDR where)
 {
   td_event_msg_t msg;
   td_err_e err;
-  struct process_info *process;
+  struct lwp_info *lwp;
 
   if (debug_threads)
     fprintf (stderr, "Thread creation event.\n");
 
+  fixup_proc_handle ();
+
   /* FIXME: This assumes we don't get another event.
      In the LinuxThreads implementation, this is safe,
      because all events come from the manager thread
      (except for its own creation, of course).  */
-  err = td_ta_event_getmsg (thread_agent, &msg);
+  err = td_ta_event_getmsg (current_process()->private->thread_agent, &msg);
   if (err != TD_OK)
     fprintf (stderr, "thread getmsg err: %s\n",
 	     thread_db_err_str (err));
@@ -153,9 +177,9 @@ thread_db_create_event (CORE_ADDR where)
   /* If we do not know about the main thread yet, this would be a good time to
      find it.  We need to do this to pick up the main thread before any newly
      created threads.  */
-  process = get_thread_process (current_inferior);
-  if (process->thread_known == 0)
-    find_one_thread (process->lwpid);
+  lwp = get_thread_lwp (current_inferior);
+  if (lwp->thread_known == 0)
+    find_one_thread (lwp->head.id);
 
   /* msg.event == TD_EVENT_CREATE */
 
@@ -181,6 +205,7 @@ thread_db_enable_reporting ()
   td_thr_events_t events;
   td_notify_t notify;
   td_err_e err;
+  struct process_info_private *proc = current_process()->private;
 
   /* Set the process wide mask saying which events we're interested in.  */
   td_event_emptyset (&events);
@@ -192,7 +217,7 @@ thread_db_enable_reporting ()
   td_event_addset (&events, TD_DEATH);
 #endif
 
-  err = td_ta_set_event (thread_agent, &events);
+  err = td_ta_set_event (proc->thread_agent, &events);
   if (err != TD_OK)
     {
       warning ("Unable to set global thread event mask: %s",
@@ -201,13 +226,14 @@ thread_db_enable_reporting ()
     }
 
   /* Get address for thread creation breakpoint.  */
-  err = td_ta_event_addr (thread_agent, TD_CREATE, &notify);
+  err = td_ta_event_addr (proc->thread_agent, TD_CREATE, &notify);
   if (err != TD_OK)
     {
       warning ("Unable to get location for thread creation breakpoint: %s",
 	       thread_db_err_str (err));
       return 0;
     }
+
   set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
 		     thread_db_create_event);
 
@@ -216,7 +242,7 @@ thread_db_enable_reporting ()
      with actual thread deaths (via wait).  */
 
   /* Get address for thread death breakpoint.  */
-  err = td_ta_event_addr (thread_agent, TD_DEATH, &notify);
+  err = td_ta_event_addr (proc->thread_agent, TD_DEATH, &notify);
   if (err != TD_OK)
     {
       warning ("Unable to get location for thread death breakpoint: %s",
@@ -231,21 +257,22 @@ thread_db_enable_reporting ()
 }
 
 static int
-find_one_thread (int lwpid)
+find_one_thread (ptid_t ptid)
 {
   td_thrhandle_t th;
   td_thrinfo_t ti;
   td_err_e err;
   struct thread_info *inferior;
-  struct process_info *process;
+  struct lwp_info *lwp;
+  int lwpid = ptid_get_lwp (ptid);
 
-  inferior = (struct thread_info *) find_inferior_id (&all_threads, lwpid);
-  process = get_thread_process (inferior);
-  if (process->thread_known)
+  inferior = (struct thread_info *) find_inferior_id (&all_threads, ptid);
+  lwp = get_thread_lwp (inferior);
+  if (lwp->thread_known)
     return 1;
 
   /* Get information about this thread.  */
-  err = td_ta_map_lwp2thr (thread_agent, process->lwpid, &th);
+  err = td_ta_map_lwp2thr (current_process()->private->thread_agent, lwpid, &th);
   if (err != TD_OK)
     error ("Cannot get thread handle for LWP %d: %s",
 	   lwpid, thread_db_err_str (err));
@@ -259,10 +286,10 @@ find_one_thread (int lwpid)
     fprintf (stderr, "Found thread %ld (LWP %d)\n",
 	     ti.ti_tid, ti.ti_lid);
 
-  if (process->lwpid != ti.ti_lid)
+  if (lwpid != ti.ti_lid)
     {
       warning ("PID mismatch!  Expected %ld, got %ld",
-	       (long) process->lwpid, (long) ti.ti_lid);
+	       (long) lwpid, (long) ti.ti_lid);
       return 0;
     }
 
@@ -279,9 +306,9 @@ find_one_thread (int lwpid)
   if (ti.ti_tid == 0)
     return 0;
 
-  process->thread_known = 1;
-  process->tid = ti.ti_tid;
-  process->th = th;
+  lwp->thread_known = 1;
+  lwp->tid = ti.ti_tid;
+  lwp->th = th;
 
   return 1;
 }
@@ -290,32 +317,27 @@ static void
 maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
 {
   td_err_e err;
-  struct thread_info *inferior;
-  struct process_info *process;
+  struct lwp_info *lwp;
 
-  inferior = (struct thread_info *) find_inferior_id (&all_threads,
-						      ti_p->ti_lid);
-  if (inferior != NULL)
+  lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
+  if (lwp != NULL)
     return;
 
   if (debug_threads)
     fprintf (stderr, "Attaching to thread %ld (LWP %d)\n",
 	     ti_p->ti_tid, ti_p->ti_lid);
-  linux_attach_lwp (ti_p->ti_lid);
-  inferior = (struct thread_info *) find_inferior_id (&all_threads,
-						      ti_p->ti_lid);
-  if (inferior == NULL)
+  linux_attach_lwp (ti_p->ti_lid, 0);
+  lwp = find_lwp_pid (pid_to_ptid (ti_p->ti_lid));
+  if (lwp == NULL)
     {
       warning ("Could not attach to thread %ld (LWP %d)\n",
 	       ti_p->ti_tid, ti_p->ti_lid);
       return;
     }
 
-  process = inferior_target_data (inferior);
-
-  process->tid = ti_p->ti_tid;
-  process->thread_known = 1;
-  process->th = *th_p;
+  lwp->tid = ti_p->ti_tid;
+  lwp->thread_known = 1;
+  lwp->th = *th_p;
 
   if (thread_db_use_events)
     {
@@ -349,15 +371,22 @@ static void
 thread_db_find_new_threads (void)
 {
   td_err_e err;
+  ptid_t ptid = ((struct inferior_list_entry *)current_inferior)->id;
 
   /* This function is only called when we first initialize thread_db.
      First locate the initial thread.  If it is not ready for
      debugging yet, then stop.  */
-  if (find_one_thread (all_threads.head->id) == 0)
+  /* Is there any harm done in using the current inferior for
+     this?  */
+  if (find_one_thread (ptid) == 0)
     return;
 
+  /* Make sure we give thread_db the right lwp to talk to.  */
+  fixup_proc_handle ();
+
   /* Iterate over all user-space threads to discover new threads.  */
-  err = td_ta_thr_iter (thread_agent, find_new_threads_callback, NULL,
+  err = td_ta_thr_iter (current_process()->private->thread_agent,
+			find_new_threads_callback, NULL,
 			TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
 			TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
   if (err != TD_OK)
@@ -386,18 +415,21 @@ thread_db_get_tls_address (struct thread
 #if HAVE_TD_THR_TLS_GET_ADDR
   psaddr_t addr;
   td_err_e err;
-  struct process_info *process;
+  struct lwp_info *lwp;
+
+  /* Make sure we give thread_db the right lwp to talk to.  */
+  fixup_proc_handle ();
 
-  process = get_thread_process (thread);
-  if (!process->thread_known)
-    find_one_thread (process->lwpid);
-  if (!process->thread_known)
+  lwp = get_thread_lwp (thread);
+  if (!lwp->thread_known)
+    find_one_thread (lwp->head.id);
+  if (!lwp->thread_known)
     return TD_NOTHR;
 
   /* Note the cast through uintptr_t: this interface only works if
      a target address fits in a psaddr_t, which is a host pointer.
      So a 32-bit debugger can not access 64-bit TLS through this.  */
-  err = td_thr_tls_get_addr (&process->th, (psaddr_t) (uintptr_t) load_module,
+  err = td_thr_tls_get_addr (&lwp->th, (psaddr_t) (uintptr_t) load_module,
 			     offset, &addr);
   if (err == TD_OK)
     {
@@ -415,25 +447,17 @@ int
 thread_db_init (int use_events)
 {
   int err;
+  struct process_info *proc = current_process ();
+  struct process_info_private *priv = proc->private;
 
-  /* FIXME drow/2004-10-16: This is the "overall process ID", which
-     GNU/Linux calls tgid, "thread group ID".  When we support
-     attaching to threads, the original thread may not be the correct
-     thread.  We would have to get the process ID from /proc for NPTL.
-     For LinuxThreads we could do something similar: follow the chain
-     of parent processes until we find the highest one we're attached
-     to, and use its tgid.
-
-     This isn't the only place in gdbserver that assumes that the first
-     process in the list is the thread group leader.  */
-  proc_handle.pid = ((struct inferior_list_entry *)current_inferior)->id;
+  fixup_proc_handle ();
 
   /* Allow new symbol lookups.  */
-  all_symbols_looked_up = 0;
+  proc->all_symbols_looked_up = 0;
 
   thread_db_use_events = use_events;
 
-  err = td_ta_new (&proc_handle, &thread_agent);
+  err = td_ta_new (&priv->proc_handle, &priv->thread_agent);
   switch (err)
     {
     case TD_NOLIBTHREAD:
@@ -447,7 +471,7 @@ thread_db_init (int use_events)
 	return 0;
       thread_db_find_new_threads ();
       thread_db_look_up_symbols ();
-      all_symbols_looked_up = 1;
+      proc->all_symbols_looked_up = 1;
       return 1;
 
     default:
Index: src/gdb/gdbserver/utils.c
===================================================================
--- src.orig/gdb/gdbserver/utils.c	2008-11-25 17:28:10.000000000 +0000
+++ src/gdb/gdbserver/utils.c	2008-11-25 17:28:12.000000000 +0000
@@ -96,3 +96,25 @@ warning (const char *string,...)
   fprintf (stderr, "\n");
   va_end (args);
 }
+
+ATTR_NORETURN static void
+internal_verror (const char *file, int line, const char *fmt, va_list ap)
+{
+  fprintf (stderr, "\
+%s:%d: \n\
+A problem internal to gdbserver has been detected,\n\
+further debugging may prove unreliable.", file, line);
+  vfprintf (stderr, fmt, ap);
+  fprintf (stderr, "aborting.\n");
+
+  abort (); /* NOTE: gdbserver has only one call to abort().  */
+}
+
+void
+internal_error_file_line (const char *file, int line, const char *string, ...)
+{
+  va_list ap;
+  va_start (ap, string);
+  internal_verror (file, line, string, ap);
+  va_end (ap);
+}
2008-11-25  Pedro Alves  <pedro@codesourcery.com>

	2008-11-25  Pedro Alves  <pedro@codesourcery.com>

	* linux-fork.c (detach_fork): Delete declaration.
	(_initialize_linux_fork): Move "set detach-on-fork"
	command to ...
	* infrun.c (_initialize_infrun): ... here.
	* inferior.h (detach_fork): Declare.

	2008-11-10  Pedro Alves  <pedro@codesourcery.com>

	* remote.c (read_ptid): If we don't know about any inferior yet,
	use the pid of magic_null_ptid.
	(remote_start_remote): Don't set inferior_ptid to magic_null_ptid
	here.

	2008-10-14  Pedro Alves  <pedro@codesourcery.com>

	* remote.c (remote_start_remote): Mask async mode while collecting
	the initial event, use notice_new_inferior.

	2008-10-12  Pedro Alves  <pedro@codesourcery.com>

	* infcmd.c (attach_command_post_wait): Set the inferior exec here.
	(attach_command): Don't set the inferior exec here.
	(notice_new_inferior): New.
	* inferior.h (notice_new_inferior): Declare.
	* remote.c (notice_new_inferiors): Add `stopping' argument.  Add
	the inferior before adding the threads.  Call notice_new_inferior.
	(record_currthread): Adjust.
	(remote_threads_info): Add the inferior before adding the thread.
	Call notice_new_inferior.

	2008-10-09  Pedro Alves  <pedro@codesourcery.com>

	* remote.c (notice_new_inferiors): If there's only one exec, set
	it in the new inferior.
	(set_thread): If setting the thread failed, assume the thread has
	terminated.

	2008-09-17  Pedro Alves  <pedro@codesourcery.com>

	* inferior.c (delete_inferior_1): Free the inferior after freeing
	its threads.

	2008-09-16  Pedro Alves  <pedro@codesourcery.com>

	* inferior.h (discard_all_inferiors): Declare.
	* inferior.c (delete_inferior): Rename to...
	(delete_inferior_1): ...this.  Add 'silent' argument.  If this
	inferior is has pid not zero, delete its threads.
	(delete_inferior): New, as wrapper around delete_inferior_1.
	(delete_inferior_by_pid_1): Reimplement.
	(discard_all_inferiors): New.

	2008-09-15  Pedro Alves  <pedro@codesourcery.com>

	* remote.c (extended_remote_attach_1): Don't set target_attach_no_wait.

	2008-09-15  Pedro Alves  <pedro@codesourcery.com>

	* frame.c (get_current_frame, has_stack_frames): Check for
	null_ptid.
	* top.c (execute_command): Likewise.

	2008-08-29  Pedro Alves  <pedro@codesourcery.com>

	* inferior.c (have_real_inferiors): New.
	* inferior.h (have_real_inferiors): Declare.
	* remote.c (extended_remote_mourn_1): Use it.
	* top.c (quit_target): Use it.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* remote.c (parse_stop_reply): Handle Y;exec.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* infcmd.c (struct exec_file_attach_wrapper_args): New.
	(exec_file_attach_wrapper): New.
	(attach_command_post_wait): If there's a sysroot, prepend it to
	the target reported exec file path.  Continue attaching to the
	inferior event if attaching to the exec file fails.

	* remote.c (remote_pid_to_exec_file): Rebustify.  Expect
	"QExecFile:PID;" in the reply.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* remote.c (record_currthread): If setting the current thread to
	minus_one_ptid, don't pass that to the stub.
	(remote_parse_stop_reply): Handle 'Y' stop reply.
	(remote_wait_as): Likewise.  If remote process exited, invalidate
	the current thread.
	(remote_detach_pid): New.
	(remote_follow_fork): New.
	(init_remote_ops): Register it.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* remote.c (remote_pid_to_exec_file): New.
	(init_remote_ops): Register it.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* infcmd.c (kill_if_already_running): If target supports
	multi-process, allow multi-runs.

	2008-08-28  Pedro Alves  <pedro@codesourcery.com>

	* remote.c (extended_remote_create_inferior_1): Don't clear the
	thread list.

---
 gdb/exec.c       |    2 
 gdb/frame.c      |    5 
 gdb/infcmd.c     |  160 +++++++++++++++----
 gdb/inferior.c   |  100 ++++++++----
 gdb/inferior.h   |   12 +
 gdb/infrun.c     |    6 
 gdb/linux-fork.c |   10 -
 gdb/remote.c     |  458 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 gdb/stack.c      |    3 
 gdb/top.c        |    4 
 10 files changed, 632 insertions(+), 128 deletions(-)

Index: src/gdb/infrun.c
===================================================================
--- src.orig/gdb/infrun.c	2008-11-25 19:45:04.000000000 +0000
+++ src/gdb/infrun.c	2008-11-25 19:53:07.000000000 +0000
@@ -5307,6 +5307,12 @@ By default, the debugger will follow the
 			show_follow_fork_mode_string,
 			&setlist, &showlist);
 
+  add_setshow_boolean_cmd ("detach-on-fork", class_run, &detach_fork, _("\
+Set whether gdb will detach the child of a fork."), _("\
+Show whether gdb will detach the child of a fork."), _("\
+Tells gdb whether to detach the child of a fork."),
+			   NULL, NULL, &setlist, &showlist);
+
   add_setshow_enum_cmd ("scheduler-locking", class_run, 
 			scheduler_enums, &scheduler_mode, _("\
 Set mode for locking scheduler during execution."), _("\
Index: src/gdb/remote.c
===================================================================
--- src.orig/gdb/remote.c	2008-11-25 19:45:04.000000000 +0000
+++ src/gdb/remote.c	2008-11-25 19:53:07.000000000 +0000
@@ -1126,53 +1126,87 @@ static ptid_t general_thread;
 static ptid_t continue_thread;
 
 static void
-notice_new_inferiors (ptid_t currthread)
+notice_new_inferiors (ptid_t currthread, int running)
 {
+  struct remote_state *rs = get_remote_state ();
+  struct inferior *inf = NULL;
+
   /* If this is a new thread, add it to GDB's thread list.
      If we leave it up to WFI to do this, bad things will happen.  */
 
   if (in_thread_list (currthread) && is_exited (currthread))
     {
+      int pid = ptid_get_pid (currthread);
+      if (!in_inferior_list (pid))
+	{
+	  inf = add_inferior (pid);
+
+	  /* This may be the first inferior we hear about.  */
+	  if (!target_has_execution)
+	    {
+	      if (rs->extended)
+		target_mark_running (&extended_remote_ops);
+	      else
+		target_mark_running (&remote_ops);
+	    }
+	}
+
       /* We're seeing an event on a thread id we knew had exited.
 	 This has to be a new thread reusing the old id.  Add it.  */
       add_thread (currthread);
-      return;
-    }
 
-  if (!in_thread_list (currthread))
+      set_executing (currthread, running);
+      set_running (currthread, running);
+    }
+  else if (!in_thread_list (currthread))
     {
       if (ptid_equal (pid_to_ptid (ptid_get_pid (currthread)), inferior_ptid))
 	{
 	  /* inferior_ptid has no thread member yet.  This can happen
 	     with the vAttach -> remote_wait,"TAAthread:" path if the
 	     stub doesn't support qC.  This is the first stop reported
-	     after an attach, so this is the main thread.  Update the
-	     ptid in the thread list.  */
-  	  thread_change_ptid (inferior_ptid, currthread);
- 	  return;
+	     after an attach, so this is the main thread.  */
+	  thread_change_ptid (inferior_ptid, currthread);
 	}
-
-      if (ptid_equal (magic_null_ptid, inferior_ptid))
+      else if (ptid_equal (magic_null_ptid, inferior_ptid))
 	{
 	  /* inferior_ptid is not set yet.  This can happen with the
 	     vRun -> remote_wait,"TAAthread:" path if the stub
 	     doesn't support qC.  This is the first stop reported
 	     after an attach, so this is the main thread.  Update the
 	     ptid in the thread list.  */
-  	  thread_change_ptid (inferior_ptid, currthread);
-	  return;
+	  thread_change_ptid (inferior_ptid, currthread);
 	}
+      else
+	{
+	  /* When connecting to a target remote, or to a target
+	     extended-remote which already was debugging an inferior, we
+	     may not know about it yet.  Add it before adding its child
+	     thread, so notifications are emitted in a sensible order.  */
+	  if (!in_inferior_list (ptid_get_pid (currthread)))
+	    {
+	      inf = add_inferior (ptid_get_pid (currthread));
 
-      /* When connecting to a target remote, or to a target
-	 extended-remote which already was debugging an inferior, we
-	 may not know about it yet.  Add it before adding its child
-	 thread, so notifications are emitted in a sensible order.  */
-      if (!in_inferior_list (ptid_get_pid (currthread)))
-	add_inferior (ptid_get_pid (currthread));
+	      /* This may be the first inferior we hear about.  */
+	      if (!target_has_execution)
+		{
+		  if (rs->extended)
+	        target_mark_running (&extended_remote_ops);
+		  else
+		    target_mark_running (&remote_ops);
+		}
+	    }
 
-      /* This is really a new thread.  Add it.  */
-      add_thread (currthread);
+	  /* This is really a new thread.  Add it.  */
+	  add_thread (currthread);
+	  set_executing (currthread, running);
+	  set_running (currthread, running);
+	}
     }
+
+  if (inf)
+    /* Do whatever is needed to do with a new inferior.  */
+    notice_new_inferior (currthread, !running, 0);
 }
 
 /* Call this function as a result of
@@ -1190,7 +1224,7 @@ record_currthread (ptid_t currthread)
     /* We're just invalidating the local thread mirror.  */
     return;
 
-  notice_new_inferiors (currthread);
+  notice_new_inferiors (currthread, 0);
 }
 
 static char *last_pass_packet;
@@ -1279,6 +1313,23 @@ set_thread (struct ptid ptid, int gen)
     write_ptid (buf, endbuf, ptid);
   putpkt (rs->buf);
   getpkt (&rs->buf, &rs->buf_size, 0);
+
+  if (rs->buf[0]
+      && strcmp (rs->buf, "OK") != 0)
+    {
+      /* If we get an error setting a thread, it's because it is no
+	 longer valid.  */
+      if (!ptid_equal (minus_one_ptid, ptid)
+	  && !ptid_equal (null_ptid, ptid)
+	  && !ptid_equal (any_thread_ptid, ptid)
+	  && !ptid_is_pid (ptid))
+	{
+	  int num = pid_to_thread_id (ptid);
+	  delete_thread (ptid);
+	  error (_("Thread ID %d has terminated."), num);
+	}
+    }
+
   if (gen)
     general_thread = ptid;
   else
@@ -1525,8 +1576,13 @@ read_ptid (char *buf, char **obuf)
   pp = unpack_varlen_hex (p, &tid);
 
   /* Since the stub is not sending a process id, then default to
-     what's in inferior_ptid.  */
-  pid = ptid_get_pid (inferior_ptid);
+     what's in inferior_ptid, unless it's null at this point.  If so,
+     then since there's no way to know the pid of the reported
+     threads, use the magic number.  */
+  if (ptid_equal (inferior_ptid, null_ptid))
+    pid = ptid_get_pid (magic_null_ptid);
+  else
+    pid = ptid_get_pid (inferior_ptid);
 
   if (obuf)
     *obuf = pp;
@@ -2148,27 +2204,15 @@ remote_threads_info (void)
 	      do
 		{
 		  new_thread = read_ptid (bufp, &bufp);
-		  if (!ptid_equal (new_thread, null_ptid)
-		      && (!in_thread_list (new_thread)
-			  || is_exited (new_thread)))
+		  if (!ptid_equal (new_thread, null_ptid))
 		    {
-		      /* When connected to a multi-process aware stub,
-			 "info threads" may show up threads of
-			 inferiors we didn't know about yet.  Add them
-			 now, and before adding any of its child
-			 threads, so notifications are emitted in a
-			 sensible order.  */
-		      if (!in_inferior_list (ptid_get_pid (new_thread)))
-			add_inferior (ptid_get_pid (new_thread));
-
-		      add_thread (new_thread);
-
 		      /* In non-stop mode, we assume new found threads
-			 are running until we proven otherwise with a
+			 are running until proven otherwise with a
 			 stop reply.  In all-stop, we can only get
 			 here if all threads are stopped.  */
-		      set_executing (new_thread, non_stop ? 1 : 0);
-		      set_running (new_thread, non_stop ? 1 : 0);
+		      int running = non_stop ? 1 : 0;
+
+		      notice_new_inferiors (new_thread, running);
 		    }
 		}
 	      while (*bufp++ == ',');	/* comma-separated list */
@@ -2576,12 +2620,6 @@ remote_start_remote (struct ui_out *uiou
 	 The '?' query below will then tell us about which threads are
 	 stopped.  */
 
-      /* If we're not using the multi-process extensions, there's no
-	 way to know the pid of the reported threads; use the magic
-	 number.  */
-      if (!remote_multi_process_p (rs))
-	inferior_ptid = magic_null_ptid;
-
       remote_threads_info ();
     }
   else if (rs->non_stop_aware)
@@ -2601,6 +2639,8 @@ remote_start_remote (struct ui_out *uiou
 
   if (!non_stop)
     {
+      int saved_async = 0;
+
       if (rs->buf[0] == 'W' || rs->buf[0] == 'X')
 	{
 	  if (args->extended_p)
@@ -2638,11 +2678,12 @@ remote_start_remote (struct ui_out *uiou
       /* Now, if we have thread information, update inferior_ptid.  */
       inferior_ptid = remote_current_thread (inferior_ptid);
 
-      add_inferior (ptid_get_pid (inferior_ptid));
+      inf = add_inferior (ptid_get_pid (inferior_ptid));
 
       /* Always add the main thread.  */
       add_thread_silent (inferior_ptid);
 
+      /* TODO: This should be done in notice_new_inferiors.  */
       get_offsets ();		/* Get text, data & bss offsets.  */
 
       /* Use the previously fetched status.  */
@@ -2651,7 +2692,37 @@ remote_start_remote (struct ui_out *uiou
       rs->cached_wait_status = 1;
 
       immediate_quit--;
-      start_remote (args->from_tty); /* Initialize gdb process mechanisms.  */
+      init_wait_for_inferior ();
+
+      /* We know the inferior is stopped already, as we have a pending
+	 wait status.  We need to force this event through
+	 handle_inferior_event.  Pretend the inferior is running, so
+	 notice_new_inferior will force a target_stop and a
+	 target_wait, to collect the event.  remote_stop_as
+	 (target_stop) will notice we have a cached wait status and
+	 will not pass the request to the remote.  */
+      {
+	struct cleanup *old_chain;
+	old_chain = make_cleanup_restore_integer (&suppress_resume_observer);
+
+	/* Don't output '*running'.  */
+	suppress_resume_observer = 1;
+
+	set_executing (inferior_ptid, 1);
+	set_running (inferior_ptid, 1);
+
+	suppress_resume_observer = 0;
+      }
+
+      /* Collect the pending event synchronously, instead of going
+	 through the event loop.  */
+      if (target_can_async_p ())
+	saved_async = target_async_mask (0);
+
+      notice_new_inferior (inferior_ptid, 1, args->from_tty);
+
+      if (saved_async)
+	target_async_mask (saved_async);
     }
   else
     {
@@ -2710,10 +2781,13 @@ remote_start_remote (struct ui_out *uiou
       if (ptid_equal (inferior_ptid, minus_one_ptid))
 	error (_("remote didn't report the current thread in non-stop mode"));
 
+      /* TODO: This should be done whenever we notice a new
+	 inferior.  */
       get_offsets ();		/* Get text, data & bss offsets.  */
 
       /* In non-stop mode, any cached wait status will be stored in
-	 the stop reply queue.  */
+	 the stop reply queue.  Also, we can only reach here if
+	 threads were found.  */
       gdb_assert (wait_status == NULL);
     }
 
@@ -4384,7 +4458,65 @@ Packet: '%s'\n"),
 	else
 	  error (_("unknown stop reply packet: %s"), buf);
 	event->ptid = pid_to_ptid (pid);
+	break;
       }
+    case 'Y':
+      {
+	char *p = buf + 1;
+	if (*p != ';')
+	  error (_("unknown stop reply packet: %s"), buf);
+
+	p++;
+	if (strncmp (p, "fork;", 5) == 0)
+	  {
+	    p += 5;
+	    event->ws.kind = TARGET_WAITKIND_FORKED;
+	  }
+	else if (strncmp (p, "vfork;", 6) == 0)
+	  {
+	    p += 6;
+	    event->ws.kind = TARGET_WAITKIND_VFORKED;
+	  }
+	else if (strncmp (p, "exec;", 5) == 0)
+	  {
+	    p += 5;
+	    event->ws.kind = TARGET_WAITKIND_EXECD;
+	  }
+	else
+	  error (_("unknown stop reply packet: %s"), buf);
+
+	event->ptid = read_ptid (p, &p);
+
+	if (*p != ';')
+	  error (_("unknown stop reply packet: %s"), buf);
+	p++;
+
+	if (event->ws.kind == TARGET_WAITKIND_EXECD)
+	  {
+	    struct cleanup *old_chain;
+	    int result;
+	    char *buf;
+
+	    buf = xmalloc (strlen (p) + 1);
+	    result = hex2bin (p, (gdb_byte *) buf, strlen (p));
+	    buf [result] = '\0';
+	    event->ws.value.execd_pathname = buf;
+
+	    /* At this point, all inserted breakpoints are gone.
+	       Doing this as soon as we detect an exec prevents the
+	       badness of deleting a breakpoint writing the current
+	       "shadow contents" to lift the bp.  That shadow is NOT
+	       valid after an exec.  */
+
+	    old_chain = save_inferior_ptid ();
+	    inferior_ptid = event->ptid;
+	    mark_breakpoints_out ();
+	    do_cleanups (old_chain);
+	  }
+	else
+	  event->ws.value.related_pid = read_ptid (p, &p);
+      }
+
       break;
     }
 
@@ -4504,7 +4636,7 @@ process_stop_reply (struct stop_reply *s
       delete_inferior (pid);
     }
   else
-    notice_new_inferiors (ptid);
+    notice_new_inferiors (ptid, 0);
 
   /* Expedited registers.  */
   if (stop_reply->regcache)
@@ -4655,7 +4787,7 @@ remote_wait_as (ptid_t ptid, struct targ
     case 'F':		/* File-I/O request.  */
       remote_fileio_request (buf);
       break;
-    case 'T': case 'S': case 'X': case 'W':
+    case 'T': case 'S': case 'X': case 'W': case 'Y':
       {
 	struct stop_reply *stop_reply;
 	struct cleanup *old_chain;
@@ -4681,7 +4813,7 @@ remote_wait_as (ptid_t ptid, struct targ
 	     remote system doesn't support it.  */
 	  target_terminal_ours_for_output ();
 	  printf_filtered
-	    ("Can't send signals to this remote system.  %s not sent.\n",
+	    ("Can't send signals to this remote system.	 %s not sent.\n",
 	     target_signal_to_name (last_sent_signal));
 	  last_sent_signal = TARGET_SIGNAL_0;
 	  target_terminal_inferior ();
@@ -6550,7 +6682,7 @@ extended_remote_mourn_1 (struct target_o
   /* Unlike "target remote", we do not want to unpush the target; then
      the next time the user says "run", we won't be connected.  */
 
-  if (have_inferiors ())
+  if (have_real_inferiors ())
     {
       extern void nullify_last_target_wait_ptid ();
       /* Multi-process case.  The current process has exited, but
@@ -6691,11 +6823,15 @@ extended_remote_create_inferior_1 (char 
       extended_remote_restart ();
     }
 
+#if 0
+  /* FIXME: How does this look with itsets?  */
+
   /* Clean up from the last time we ran, before we mark the target
      running again.  This will mark breakpoints uninserted, and
      get_offsets may insert breakpoints.  */
   init_thread_list ();
   init_wait_for_inferior ();
+#endif
 
   /* Now mark the inferior as running before we do anything else.  */
   inferior_ptid = magic_null_ptid;
@@ -6716,7 +6852,7 @@ extended_remote_create_inferior_1 (char 
 }
 
 static void
-extended_remote_create_inferior (struct target_ops *ops, 
+extended_remote_create_inferior (struct target_ops *ops,
 				 char *exec_file, char *args,
 				 char **env, int from_tty)
 {
@@ -7263,7 +7399,6 @@ remote_xfer_partial (struct target_ops *
   char *p2;
   char query_type;
 
-  
   if (tmp_inf && tmp_inf->pid != ptid_get_pid (inferior_ptid))
     {
       ptid_t tmp_ptid;
@@ -8635,6 +8770,217 @@ remote_supports_multi_process (void)
   return remote_multi_process_p (rs);
 }
 
+char *
+remote_pid_to_exec_file (int pid)
+{
+  struct remote_state *rs;
+
+  rs = get_remote_state ();
+
+  sprintf (rs->buf, "qExecFile:%x", pid);
+  putpkt (rs->buf);
+  getpkt (&rs->buf, &rs->buf_size, 0);
+  if (*rs->buf == '\0')
+    /* Not supported */ ;
+  else if (strncmp (rs->buf, "QExecFile:", 10) == 0)
+    {
+      static char *buf = NULL;
+      int n, result;
+      char *p;
+
+      p = strchr (rs->buf + 10, ';');
+
+      if (p == NULL)
+	{
+	  warning (_("Invalid qExecFile reply: %s"), rs->buf);
+	  return NULL;
+	}
+
+      p++;
+
+      if (buf == NULL)
+	make_final_cleanup (xfree, buf);
+      else
+	xfree (buf);
+
+      buf = xmalloc (strlen (p) + 1);
+      result = hex2bin (p, (gdb_byte *) buf, strlen (p));
+      buf [result] = '\0';
+
+      return buf;
+    }
+  else if (*rs->buf == 'E')
+    ;
+  else
+    warning (_("Invalid qExecFile reply: %s"), rs->buf);
+
+  return NULL;
+}
+
+static void
+remote_detach_pid (int pid)
+{
+  struct remote_state *rs = get_remote_state ();
+
+  /* Tell the remote target to detach.  */
+  sprintf (rs->buf, "D;%x", pid);
+
+  putpkt (rs->buf);
+  getpkt (&rs->buf, &rs->buf_size, 0);
+
+  if (strcmp (rs->buf, "OK") == 0)
+    ;
+  else if (rs->buf[0] == '\0')
+    error (_("Remote doesn't know how to detach"));
+  else
+    error (_("Can't detach process."));
+}
+
+static int
+remote_follow_fork (struct target_ops *ops, int follow_child)
+{
+  ptid_t last_ptid;
+  struct target_waitstatus last_status;
+  int has_vforked;
+  int parent_pid, child_pid;
+
+  get_last_target_status (&last_ptid, &last_status);
+  has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED);
+  parent_pid = ptid_get_tid (last_ptid);
+  if (parent_pid == 0)
+    parent_pid = ptid_get_pid (last_ptid);
+  child_pid = PIDGET (last_status.value.related_pid);
+
+  if (! follow_child)
+    {
+      /* We're already attached to the parent, by default.  */
+
+      /* Before detaching from the child, remove all breakpoints from
+         it.  (This won't actually modify the breakpoint list, but
+         will physically remove the breakpoints from the child.)  */
+      /* If we vforked this will remove the breakpoints from the
+	 parent also, but they'll be reinserted below.  */
+      set_general_thread (last_status.value.related_pid);
+      detach_breakpoints (child_pid);
+
+      /* Detach new forked process?  */
+      if (detach_fork)
+	{
+	  if (info_verbose || remote_debug)
+	    {
+	      target_terminal_ours ();
+	      fprintf_filtered (gdb_stdlog,
+				"Detaching after fork from child process %d.\n",
+				child_pid);
+	    }
+
+	  /* Tell the remote target to detach.  */
+	  remote_detach_pid (child_pid);
+	}
+      else
+	{
+	  /* Add process to GDB's tables.  */
+	  add_inferior (child_pid);
+	}
+
+      set_general_thread (last_ptid);
+
+      if (has_vforked)
+	{
+	  /* TODO here: Wait for linux's VFORK_DONE, or HPUX's
+	     TTEVT_VFORK, or equivalent.  */
+
+	  /* Since we vforked, breakpoints were removed in the parent
+	     too.  Put them back.  */
+	  reattach_breakpoints (parent_pid);
+	}
+    }
+  else
+    {
+      struct thread_info *last_tp = find_thread_pid (last_ptid);
+      struct thread_info *tp;
+
+      /* Copy user stepping state to the new inferior thread.  */
+      struct breakpoint *step_resume_breakpoint = last_tp->step_resume_breakpoint;
+      CORE_ADDR step_range_start = last_tp->step_range_start;
+      CORE_ADDR step_range_end = last_tp->step_range_end;
+      struct frame_id step_frame_id = last_tp->step_frame_id;
+
+      last_tp->step_range_start = 0;
+      last_tp->step_range_end = last_tp->step_range_end  = 0;
+      last_tp->step_frame_id = null_frame_id;
+
+      /* Otherwise, deleting the parent would get rid of this
+	 breakpoint.  */
+      last_tp->step_resume_breakpoint = NULL;
+
+      /* Needed to keep the breakpoint lists in sync.  */
+      if (! has_vforked)
+	{
+	  set_general_thread (last_status.value.related_pid);
+	  detach_breakpoints (child_pid);
+	}
+
+      /* Before detaching from the parent, remove all breakpoints from it. */
+      set_general_thread (last_ptid);
+      remove_breakpoints ();
+
+      if (info_verbose || remote_debug)
+	{
+	  target_terminal_ours ();
+	  fprintf_filtered (gdb_stdlog,
+			    "Attaching after fork to child process %d.\n",
+			    child_pid);
+	}
+
+      /* If we're vforking, we may want to hold on to the parent until
+	 the child exits or execs.  At exec time we can remove the old
+	 breakpoints from the parent and detach it; at exit time we
+	 could do the same (or even, sneakily, resume debugging it - the
+	 child's exec has failed, or something similar).
+
+	 The holding part is very easy if we have VFORKDONE events;
+	 but keeping track of both processes is beyond GDB at the
+	 moment.  So we don't expose the parent to the rest of GDB.
+	 Instead we quietly hold onto it until such time as we can
+	 safely resume it.  */
+
+      if (has_vforked)
+	{
+	  /* TODO: handle this correctly.
+
+	  remote_fork_parent_pid = parent_pid;
+
+	  */
+	  detach_inferior (parent_pid);
+	}
+      else if (detach_fork)
+	{
+	  remote_detach_pid (parent_pid);
+	  detach_inferior (parent_pid);
+	}
+
+      add_inferior (child_pid);
+
+      inferior_ptid = ptid_build (child_pid, 0, 0);
+      set_general_thread (inferior_ptid);
+      inferior_ptid = remote_current_thread (inferior_ptid);
+      set_general_thread (inferior_ptid);
+
+      tp = add_thread (inferior_ptid);
+
+      tp->step_resume_breakpoint = step_resume_breakpoint;
+      tp->step_range_start = step_range_start;
+      tp->step_range_end = step_range_end;
+      tp->step_frame_id = step_frame_id;
+
+      /* Reset breakpoints in the child as appropriate.  */
+      follow_inferior_reset_breakpoints ();
+    }
+
+  return 0;
+}
+
 static void
 init_remote_ops (void)
 {
@@ -8698,6 +9044,8 @@ Specify the serial device it is connecte
   remote_ops.to_terminal_ours = remote_terminal_ours;
   remote_ops.to_supports_non_stop = remote_supports_non_stop;
   remote_ops.to_supports_multi_process = remote_supports_multi_process;
+  remote_ops.to_pid_to_exec_file = remote_pid_to_exec_file;
+  remote_ops.to_follow_fork = remote_follow_fork;
 }
 
 /* Set up the extended remote vector by making a copy of the standard
Index: src/gdb/infcmd.c
===================================================================
--- src.orig/gdb/infcmd.c	2008-11-25 19:45:04.000000000 +0000
+++ src/gdb/infcmd.c	2008-11-25 19:53:07.000000000 +0000
@@ -553,11 +553,14 @@ kill_if_already_running (int from_tty)
 	 restart it.  */
       target_require_runnable ();
 
-      if (from_tty
-	  && !query ("The program being debugged has been started already.\n\
+      if (!target_supports_multi_process ())
+	{
+	  if (from_tty
+	      && !query ("The program being debugged has been started already.\n\
 Start it from the beginning? "))
-	error (_("Program not restarted."));
-      target_kill ();
+	    error (_("Program not restarted."));
+	  target_kill ();
+	}
     }
 }
 
@@ -574,6 +577,7 @@ run_command_1 (char *args, int from_tty,
 
   kill_if_already_running (from_tty);
 
+  /* This is bad.  */
   init_wait_for_inferior ();
   clear_breakpoint_hit_counts ();
 
@@ -2206,6 +2210,23 @@ proceed_after_attach (int pid)
   do_cleanups (old_chain);
 }
 
+struct exec_file_attach_wrapper_args
+{
+  char *path;
+  int from_tty;
+};
+
+static int
+exec_file_attach_wrapper (struct ui_out *ui_out, void *args)
+{
+  struct exec_file_attach_wrapper_args *a = args;
+
+  exec_file_attach (a->path, a->from_tty);
+  symbol_file_add_main (a->path, a->from_tty);
+
+  return 0;
+}
+
 /*
  * TODO:
  * Should save/restore the tty state since it might be that the
@@ -2241,19 +2262,47 @@ attach_command_post_wait (char *args, in
       exec_file = target_pid_to_exec_file (PIDGET (inferior_ptid));
       if (exec_file)
 	{
-	  /* It's possible we don't have a full path, but rather just a
-	     filename.  Some targets, such as HP-UX, don't provide the
-	     full path, sigh.
-
-	     Attempt to qualify the filename against the source path.
-	     (If that fails, we'll just fall back on the original
-	     filename.  Not much more we can do...)
-	   */
-	  if (!source_full_path_of (exec_file, &full_exec_path))
-	    full_exec_path = savestring (exec_file, strlen (exec_file));
+	  struct exec_file_attach_wrapper_args args;
+
+	  if (gdb_sysroot && *gdb_sysroot)
+	    {
+	      char *name = xmalloc (strlen (gdb_sysroot)
+				   + strlen (exec_file)
+				   + 1);
+	      strcpy (name, gdb_sysroot);
+	      strcat (name, exec_file);
+	      full_exec_path = name;
+	    }
+	  else
+	    {
+	      /* It's possible we don't have a full path, but rather just a
+		 filename.  Some targets, such as HP-UX, don't provide the
+		 full path, sigh.
+
+		 Attempt to qualify the filename against the source path.
+		 (If that fails, we'll just fall back on the original
+		 filename.  Not much more we can do...)
+	      */
+	      if (!source_full_path_of (exec_file, &full_exec_path))
+		full_exec_path = savestring (exec_file, strlen (exec_file));
+	    }
+
+	  args.path = full_exec_path;
+	  args.from_tty = from_tty;
 
-	  exec_file_attach (full_exec_path, from_tty);
-	  symbol_file_add_main (full_exec_path, from_tty);
+	  /* Don't let failing to find symbols prevent trying to
+	     finish the attach.  */
+	  catch_exceptions (uiout, exec_file_attach_wrapper, &args,
+			    RETURN_MASK_ERROR);
+
+	  /* Try to use the exec we (hopefully) just pulled in as the
+	     inferior's exec.  */
+	  if (!inferior->exec)
+	    {
+	      exec = find_exec_by_name (full_exec_path);
+	      if (exec)
+		set_inferior_exec (inferior, exec);
+	    }
 	}
     }
   else
@@ -2262,6 +2311,14 @@ attach_command_post_wait (char *args, in
       reread_symbols ();
     }
 
+  /* As a heuristic, if there is no exec assigned to the attached
+     inferior, but only one exec known to GDB, guess that it is the
+     exec for the the process just attached. (If GDB has guessed
+     wrong, it will be up to the user to use set-exec to fix
+     matters.)  */
+  if (!inferior->exec && number_of_execs () == 1)
+    set_inferior_exec (inferior, first_exec);
+
   /* Take any necessary post-attaching actions for this platform.  */
   target_post_attach (PIDGET (inferior_ptid));
 
@@ -2275,7 +2332,7 @@ attach_command_post_wait (char *args, in
       /* The user requested an `attach&', so be sure to leave threads
 	 that didn't get a signal running.  */
 
-      /* Immediatelly resume all suspended threads of this inferior,
+      /* Immediately resume all suspended threads of this inferior,
 	 and this inferior only.  This should have no effect on
 	 already running threads.  If a thread has been stopped with a
 	 signal, leave it be.  */
@@ -2395,6 +2452,8 @@ attach_command (char *args, int from_tty
 
   /* Set up execution context to know that we should return from
      wait_for_inferior as soon as the target reports a stop.  */
+
+  /* NOTE, NOTE, this is wrong in multi-process... */
   init_wait_for_inferior ();
   clear_proceed_status ();
 
@@ -2446,19 +2505,64 @@ attach_command (char *args, int from_tty
 
   attach_command_post_wait (args, from_tty, async_exec);
 
-  /* As a heuristic, if there is no exec assigned to the attached
-     inferior, but only one exec known to GDB, guess that it is the
-     exec for the the process just attached. (If GDB has guessed
-     wrong, it will be up to the user to use set-exec to fix
-     matters.)  */
-  {
-    struct inferior *inferior = current_inferior ();
+}
+
+/* We had just found out that the target was already attached to an
+   inferior.  PTID points at a thread of this new inferior, that is
+   the most likelly to be stopped right now, but not necessarily so.
+   The new inferior has already been added to the inferior list at
+   this point.  */
+
+void
+notice_new_inferior (ptid_t ptid, int stopping, int from_tty)
+{
+  struct cleanup* old_chain;
+  struct inferior *inferior;
+  int async_exec;
+
+  old_chain = make_cleanup (null_cleanup, NULL);
+
+  /* If in non-stop, leave threads as running as they were.  If
+     they're stopped for some reason other than us telling it to, it
+     should report a signal != TARGET_SIGNAL_0.  */
+  async_exec = non_stop;
 
-    if (!inferior->exec && number_of_execs () == 1)
-      set_inferior_exec (inferior, first_exec);
-  }
+  if (!ptid_equal (inferior_ptid, null_ptid))
+    make_cleanup_restore_current_thread ();
 
-  discard_cleanups (back_to);
+  switch_to_thread (ptid);
+
+  inferior = current_inferior ();
+
+  if (is_executing (inferior_ptid))
+    {
+      target_stop (inferior_ptid);
+
+      if (!non_stop)
+	inferior->stop_soon = STOP_QUIETLY_REMOTE;
+
+      if (target_can_async_p ())
+	{
+	  /* sync_execution mode.  Wait for stop.  */
+	  struct attach_command_continuation_args *a;
+
+	  a = xmalloc (sizeof (*a));
+	  a->args = xstrdup ("");
+	  a->from_tty = from_tty;
+	  a->async_exec = async_exec;
+	  add_inferior_continuation (attach_command_continuation, a,
+				     attach_command_continuation_free_args);
+
+	  do_cleanups (old_chain);
+	  return;
+	}
+      else
+	wait_for_inferior (0);
+    }
+
+  attach_command_post_wait ("" /* args */, from_tty, !stopping);
+
+  do_cleanups (old_chain);
 }
 
 /*
Index: src/gdb/inferior.c
===================================================================
--- src.orig/gdb/inferior.c	2008-11-25 19:45:04.000000000 +0000
+++ src/gdb/inferior.c	2008-11-25 19:53:07.000000000 +0000
@@ -94,6 +94,8 @@ add_inferior_silent (int pid)
   memset (inf, 0, sizeof (*inf));
   inf->pid = pid;
 
+  inf->stop_soon = NO_STOP_QUIETLY;
+
   inf->num = ++highest_inferior_num;
   inf->next = inferior_list;
   inferior_list = inf;
@@ -138,16 +140,17 @@ delete_thread_of_inferior (struct thread
 
 /* If SILENT then be quiet -- don't announce a inferior death, or the
    exit of its threads.  */
-static void
-delete_inferior_1 (int pid, int silent)
+
+void
+delete_inferior_struct (struct inferior *inftodel, int silent)
 {
   struct inferior *inf, *infprev;
-  struct delete_thread_of_inferior_arg arg = { pid, silent };
+  struct delete_thread_of_inferior_arg arg;
 
   infprev = NULL;
 
   for (inf = inferior_list; inf; infprev = inf, inf = inf->next)
-    if (inf->pid == pid)
+    if (inf == inftodel)
       break;
 
   if (!inf)
@@ -158,38 +161,42 @@ delete_inferior_1 (int pid, int silent)
   else
     inferior_list = inf->next;
 
-  free_inferior (inf);
-
-  arg.pid = pid;
-  arg.silent = silent;
-
-  iterate_over_threads (delete_thread_of_inferior, &arg);
+  if (inf->pid != 0)
+    {
+      arg.pid = inf->pid;
+      arg.silent = silent;
+      iterate_over_threads (delete_thread_of_inferior, &arg);
+    }
 
-  observer_notify_inferior_exit (pid);
+  observer_notify_inferior_exit (inf->pid);
+  free_inferior (inf);
 }
 
 void
-delete_inferior (int pid)
+delete_inferior_id (int num)
 {
-  delete_inferior_1 (pid, 0);
-
-  if (print_inferior_events)
-    printf_unfiltered (_("[Inferior %d exited]\n"), pid);
+  struct inferior *inf = find_inferior_id (num);
+  delete_inferior_struct (inf, 0);
 }
 
 void
-delete_inferior_silent (int pid)
+delete_inferior (int pid)
 {
-  delete_inferior_1 (pid, 1);
+  struct inferior *inf = find_inferior_pid (pid);
+  if (inf)
+    {
+      delete_inferior_struct (inf, 0);
+      if (print_inferior_events)
+	printf_unfiltered (_("[Inferior %d exited]\n"), pid);
+    }
 }
 
 void
-detach_inferior (int pid)
+delete_inferior_silent (int pid)
 {
-  delete_inferior_1 (pid, 1);
-
-  if (print_inferior_events)
-    printf_unfiltered (_("[Inferior %d detached]\n"), pid);
+  struct inferior *inf = find_inferior_pid (pid);
+  if (inf)
+    delete_inferior_struct (inf, 1);
 }
 
 void
@@ -200,7 +207,20 @@ discard_all_inferiors (void)
   for (inf = inferior_list; inf; inf = infnext)
     {
       infnext = inf->next;
-      delete_inferior_silent (inf->pid);
+      if (inf->pid != 0)
+	delete_inferior_struct (inf, 1);
+    }
+}
+
+void
+detach_inferior (int pid)
+{
+  struct inferior *inf = find_inferior_pid (pid);
+  if (inf)
+    {
+      delete_inferior_struct (inf, 1);
+      if (print_inferior_events)
+	printf_unfiltered (_("[Inferior %d detached]\n"), pid);
     }
 }
 
@@ -309,6 +329,18 @@ have_inferiors (void)
   return inferior_list != NULL;
 }
 
+/* Returns true if there are any non-proto inferiors.  */
+int
+have_real_inferiors (void)
+{
+  struct inferior *inf;
+
+  for (inf = inferior_list; inf; inf = inf->next)
+    if (inf->pid != 0)
+      return 1;
+  return 0;
+}
+
 int
 number_of_inferiors (void)
 {
@@ -383,15 +415,21 @@ print_inferior (struct ui_out *uiout, in
 	      ui_out_field_string (uiout, "io_terminal", "term=Y");
 	    }
 	}
+
 #if 0
-      extra_info = target_extra_inferior_info (inf);
-      if (extra_info)
+      /* Only query the target about real inferiors.  */
+      if (inf->pid != 0)
 	{
-	  ui_out_text (uiout, " (");
-	  ui_out_field_string (uiout, "details", extra_info);
-	  ui_out_text (uiout, ")");
+	  extra_info = target_extra_inferior_info (inf);
+	  if (extra_info)
+	    {
+	      ui_out_text (uiout, " (");
+	      ui_out_field_string (uiout, "details", extra_info);
+	      ui_out_text (uiout, ")");
+	    }
 	}
 #endif
+
       ui_out_text (uiout, "\n");
       do_cleanups (chain2);
     }
@@ -491,11 +529,9 @@ remove_inferior_command (char *args, int
 
   for (ix = 0; VEC_iterate (itset_entry, itset->inferiors, ix, entry); ++ix)
     {
-#if 0
       if (entry->inferior->removable)
-	delete_inferior (entry->inferior);
+	delete_inferior_struct (entry->inferior, 0);
       /* (should remove threads?) */
-#endif
     }
 }
 
Index: src/gdb/exec.c
===================================================================
--- src.orig/gdb/exec.c	2008-11-25 19:45:04.000000000 +0000
+++ src/gdb/exec.c	2008-11-25 19:53:07.000000000 +0000
@@ -151,7 +151,7 @@ exec_close (int quitting)
 	{
 	  /* We don't free objfiles because other code does it.  */
 	  if (ex->inferior)
-	    delete_inferior (ex->inferior->pid);
+	    delete_inferior_id (ex->inferior->num);
 	}
 #if 0
       VEC_block_remove (exec_p, execs, 0, VEC_length (exec_p, execs));
Index: src/gdb/inferior.h
===================================================================
--- src.orig/gdb/inferior.h	2008-11-25 19:45:04.000000000 +0000
+++ src/gdb/inferior.h	2008-11-25 19:53:07.000000000 +0000
@@ -274,6 +274,8 @@ extern void interrupt_target_1 (int all_
 
 extern void detach_command (char *, int);
 
+extern void notice_new_inferior (ptid_t, int, int);
+
 /* Address at which inferior stopped.  */
 
 extern CORE_ADDR stop_pc;
@@ -366,6 +368,8 @@ extern int suppress_stop_observer;
 /* When set, no calls to target_resumed observer will be made.  */
 extern int suppress_resume_observer;
 
+extern int detach_fork;
+
 
 /* Possible values for gdbarch_call_dummy_location.  */
 #define ON_STACK 1
@@ -532,6 +536,9 @@ extern void delete_inferior_silent (int 
 /* Delete an existing inferior list entry, due to inferior detaching.  */
 extern void detach_inferior (int pid);
 
+/* Delete inferior with GDB inferior id NUM.  */
+extern void delete_inferior_id (int num);
+
 /* Get rid of all inferiors.  */
 extern void discard_all_inferiors (void);
 
@@ -550,9 +557,12 @@ extern int in_inferior_list (int pid);
    not the system's).  */
 extern int valid_inferior_id (int num);
 
-/* Search function to lookup a inferior by target 'pid'.  */
+/* Search function to lookup an inferior by target 'pid'.  */
 extern struct inferior *find_inferior_pid (int pid);
 
+/* Search function to lookup an inferior by GDB 'num'.  */
+extern struct inferior *find_inferior_id (int num);
+
 /* Inferior iterator function.
 
    Calls a callback function once for each inferior, so long as the
Index: src/gdb/linux-fork.c
===================================================================
--- src.orig/gdb/linux-fork.c	2008-11-25 19:45:04.000000000 +0000
+++ src/gdb/linux-fork.c	2008-11-25 19:53:07.000000000 +0000
@@ -34,8 +34,6 @@
 #include "gdb_dirent.h"
 #include <ctype.h>
 
-extern int detach_fork;
-
 struct fork_info *fork_list;
 static int highest_fork_num;
 
@@ -670,14 +668,6 @@ _initialize_linux_fork (void)
 {
   init_fork_list ();
 
-  /* Set/show detach-on-fork: user-settable mode.  */
-
-  add_setshow_boolean_cmd ("detach-on-fork", class_obscure, &detach_fork, _("\
-Set whether gdb will detach the child of a fork."), _("\
-Show whether gdb will detach the child of a fork."), _("\
-Tells gdb whether to detach the child of a fork."), 
-			   NULL, NULL, &setlist, &showlist);
-
   /* Set/show restart-auto-finish: user-settable count.  Causes the
      first "restart" of a fork to do some number of "finish" commands
      before returning to user.
Index: src/gdb/frame.c
===================================================================
--- src.orig/gdb/frame.c	2008-11-25 19:45:04.000000000 +0000
+++ src/gdb/frame.c	2008-11-25 19:53:36.000000000 +0000
@@ -982,6 +982,8 @@ get_current_frame (void)
     error (_("No stack."));
   if (!target_has_memory)
     error (_("No memory."));
+  if (ptid_equal (inferior_ptid, null_ptid))
+    error (_("No current inferior."));
   if (is_executing (inferior_ptid))
     error (_("Target is executing."));
 
@@ -1011,6 +1013,9 @@ has_stack_frames (void)
   if (!target_has_registers || !target_has_stack || !target_has_memory)
     return 0;
 
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return 0;
+
   /* If the current thread is executing, don't try to read from
      it.  */
   if (is_executing (inferior_ptid))
Index: src/gdb/stack.c
===================================================================
--- src.orig/gdb/stack.c	2008-11-25 19:45:04.000000000 +0000
+++ src/gdb/stack.c	2008-11-25 19:53:07.000000000 +0000
@@ -1639,6 +1639,9 @@ get_selected_block (CORE_ADDR *addr_in_b
   if (!target_has_stack)
     return 0;
 
+  if (ptid_equal (inferior_ptid, null_ptid))
+    return 0;
+
   if (is_exited (inferior_ptid))
     return 0;
 
Index: src/gdb/top.c
===================================================================
--- src.orig/gdb/top.c	2008-11-25 19:45:04.000000000 +0000
+++ src/gdb/top.c	2008-11-25 19:53:07.000000000 +0000
@@ -481,7 +481,9 @@ Cannot execute this command without a li
   /* FIXME:  This should be cacheing the frame and only running when
      the frame changes.  */
 
-  if (target_has_stack && is_stopped (inferior_ptid))
+  if (target_has_stack
+      && !ptid_equal (inferior_ptid, null_ptid)
+      && is_stopped (inferior_ptid))
     {
       flang = get_frame_language ();
       if (!warned

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]