aboutsummaryrefslogtreecommitdiff
path: root/proc
diff options
context:
space:
mode:
Diffstat (limited to 'proc')
-rw-r--r--proc/ChangeLog867
-rw-r--r--proc/Makefile4
-rw-r--r--proc/cpu-types.c38
-rw-r--r--proc/hash.c53
-rw-r--r--proc/host.c371
-rw-r--r--proc/info.c285
-rw-r--r--proc/main.c70
-rw-r--r--proc/mgt.c484
-rw-r--r--proc/msg.c55
-rw-r--r--proc/notify.c12
-rw-r--r--proc/pgrp.c115
-rw-r--r--proc/primes.c135
-rw-r--r--proc/proc.h77
-rw-r--r--proc/stubs.c208
-rw-r--r--proc/wait.c183
15 files changed, 1137 insertions, 1820 deletions
diff --git a/proc/ChangeLog b/proc/ChangeLog
deleted file mode 100644
index 0b5159c4..00000000
--- a/proc/ChangeLog
+++ /dev/null
@@ -1,867 +0,0 @@
-Sun Jul 28 22:57:03 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * info.c (get_string_array): Correctly adjust NEWSIZE when
- reallocating to add very long strings.
-
-Sat Jul 20 10:08:05 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * msg.c (S_proc_getmsgport): Deal with PID dying while we're waiting.
-
-Fri Jul 19 18:22:46 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * msg.c (S_proc_setmsgport): Bother to request DEAD_NAME
- notification on new message port being installed.
-
-Thu Jul 18 13:23:51 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * msg.c (S_proc_setmsgport): Use MOVE_SEND, not COPY_SEND, to
- return the old message port to the caller.
-
- * mgt.c (S_proc_handle_exceptions): Release newly created reference
- on E when we are done with it.
- (S_proc_child): Deallocate our ref on childt once we know we will
- return success.
- (S_proc_reassign): Likewise for NEWT.
-
- * main.c (main): Don't wire proc anymore. It's not necessary or
- useful.
-
-Thu Jul 18 04:15:49 1996 Roland McGrath <roland@baalperazim.frob.com>
-
- * mgt.c (add_tasks): Fix vm_deallocate call to use mach_task_self ()
- instead of mach_host_self ().
-
-Tue Jul 16 11:34:34 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * wait.c (EWOULDBLOCK): Define to work around new libc bug.
-
-Sun Jul 7 21:04:03 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * mgt.c (S_proc_reauthenticate): Don't use unsafe MOVE_SEND in
- user-side interruptible RPC.
-
-Wed Jul 3 14:44:00 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * mgt.c (process_has_exited): When reparenting children to init,
- if one of them is dead, alert init.
-
-Fri Jun 28 11:54:21 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * proc.h (check_owner): Return true any time PROC1 has root.
-
-Thu May 30 19:11:31 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * pgrp.c (S_proc_getsidport): MAKE_SEND_ONCE -> MAKE_SEND.
-
-Wed May 29 11:35:37 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * info.c (S_proc_getprocinfo): Get rid of temp hack for strnlen.
-
-Fri May 24 15:50:14 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * info.c (S_proc_getprocinfo): Set PI->exitstatus and PI->sigcode.
-
- * mgt.c (process_has_exited): Don't call alert_parent if P->p_task
- is null (which happens only if this is the stub process in
- proc_reassign). This because the parent is uninvolved in the
- death of stubp.
-
-Wed May 22 17:47:15 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * stubs.c (send_signal): Send sigcode in message.
-
- * msg.c (S_proc_setmsgport): Add OLDMSGPORT_TYPE param.
-
-Tue May 14 22:50:49 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * proc.h (check_owner): New inline function.
- * info.c (S_proc_pid2task, S_proc_pid2proc): Use check_owner.
-
-Sun May 12 13:22:04 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * info.c (PI_FETCH_THREAD_DETAILS): New macro.
- (S_proc_getprocinfo): Only allocate thread detail storage if we're
- actually returning thread details (a lone PI_FETCH_THREADS simply
- means "number of threads"). React to errors somewhat more gracefully.
-
- * info.c (S_proc_getprocinfo): Add comment.
-
-Fri May 10 16:32:17 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * info.c (S_proc_get_tty): New function.
-
-Fri May 10 09:26:53 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * mgt.c (S_proc_exception_raise): Fetch sigcode from correctly
- named member of HSD.
-
-Thu May 9 19:13:14 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * mgt.c (S_proc_reauthenticate): Use new authentication
- interface.
-
- * mgt.c (S_proc_setowner): Expect and interpret new CLEAR parm.
-
- * info.c (S_proc_getprocinfo): FLAGS is now an in-out parameter.
-
- * proc.h (struct proc): Add p_sigcode.
- * wait.c (S_proc_wait): New parm SIGCODE; return p_sigcode in it.
- (S_proc_mark_stop): New parm SIGCODE; record it.
- (S_proc_mark_exit): Likewise.
- (alert_parent): Set P->p_sigcode if process is dying irregularly.
- * mgt.c (S_proc_exception_raise): Set P->p_sigcode; use new
- _hurd_exception2signal args.
-
-Mon May 6 14:23:11 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * proc.h (OUR_VERSION): Upgrade to 0.0.
-
-Tue Apr 30 16:48:49 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * info.c (S_proc_getprocinfo): Release GLOBAL_LOCK around time
- consuming bits, and more importantly, potential calls to P's
- msgport, which can block.
- Fix test when appending to WAITS.
-
-Mon Apr 29 16:58:24 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * info.c (S_proc_getprocinfo): Install temporary hack so things at
- least compile. Turned on thread_waits code.
-
-Mon Apr 15 13:51:41 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * mgt.c (process_has_exited): Clear p->p_waited.
-
-Fri Mar 29 09:38:28 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * wait.c (S_proc_wait): When looking for a specific pid, use
- pid_find_allow_zombie, not ordinary pid_find.
-
- * mgt.c (S_proc_reassign): Use new ports_transfer_right call
- instead of claim/install sequence; the latter has leaves the port
- out of any hash table for a time, which produces a race with
- incoming messages.
-
-Thu Mar 28 09:21:16 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * mgt.c (S_proc_reassign): Make send once right directly from
- value in P->p_pi, don't use ports_get_right.
-
- * mgt.c (process_has_exited): Inhibit this call from happening
- twice.
-
- * info.c (S_proc_pid2task): Return MACH_PORT_NULL for a zombie.
- (S_proc_pid2proc): Likewise.
-
- * Makefile (mutated_ourmsg_U.h): New target.
- * mgt.c: Include mutated_ourmsg_U.h instead of ourmsg_U.h.
- * pgrp.c: Likewise.
-
- * wait.c: Don't include ourmsg_U.h or process_reply_U.h.
- * msg.c: Don't include process_reply_U.h.
-
- * msg.c (S_proc_getmsgport): Allow call to be made for dead
- processes; they'll return null. Thank you, Mr. Posix.
- * mgt.c (process_has_exited): Null out P->p_msgport and drop
- reference.
-
- * wait.c (S_proc_wait): Return EOPNOTSUPP if RPC destination is
- not a valid process.
- (S_proc_mark_stop): Likewise.
- (S_proc_mark_exit): Likewise.
- (S_proc_mark_cont): Likewise.
- (S_proc_mark_traced): Likewise.
- (S_proc_mod_stopchild): Likewise.
- * msg.c (S_proc_setmsgport): Likewise.
- (S_proc_getmsgport): Likewise.
- * pgrp.c (S_proc_setsid): Likewise.
- (S_proc_getsidport): Likewise.
- (S_proc_setpgrp): Likewise.
- (S_proc_mark_exec): Likewise.
- * mgt.c (S_proc_reauthenticate): Likewise.
- (S_proc_child): Likewise.
- (S_proc_reassign): Likewise.
- (S_proc_setowner): Likewise.
- (S_proc_getpids): Likewise.
- (S_proc_set_arg_locations): Likewise.
- (S_proc_dostop): Likewise.
- * info.c (S_proc_pid2task): Likewise.
- (S_proc_proc2task): Likewise.
- (S_proc_pid2proc): Likewise.
- (S_proc_make_login_coll): Likewise.
- (S_proc_setlogin): Likewise.
- (S_proc_getlogin): Likewise.
- * host.c (S_proc_sethostid): Likewise.
- (S_proc_sethostname): Likewise.
- (S_proc_getprivports): Likewise.
- (S_proc_setexecdata): Likewise.
-
- * proc.h (process_drop): New (inline) function.
- * hash.c (reqport_find): Only deallocate newly found reference
- if process is dead.
- * Makefile (MIGSTUBS): Delete process_replyUser.c.
- (MIGSFLAGS): Provide new definition.
- * msg.c (S_proc_setmsgport): Spawn thread to tickle init instead
- of sending reply here.
- (tickle_init): New function.
-
-Mon Mar 25 17:02:04 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * Makefile (proc): Add libshouldbeinlibc.a.
- * main.c: Include <wire.h>.
- (main): Use wire_task_self instead of doing it ourselves.
-
-Thu Mar 21 11:59:29 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * wait.c (S_proc_wait) [child_ready]: Flip test of waited flag.
- * mgt.c (new_proc): Oops, reinstall code to request dead name
- notification on the task port.
-
-Wed Mar 20 10:41:01 1996 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * pgrp.c (S_proc_setpgrp): Delete bletcherous hack from July 22,
- 1995.
-
- -- All these changes get rid of zombies and integrate them
- into the regular process tables. --
- * proc.h (struct zombie): Delete type.
- (zombie_list): Delete variable.
- * hash.c (pid_find): Return 0 if process is dead.
- (task_find): Likewise.
- (task_find_nocreate): Likewise.
- (pidfree): Don't call zombie_check_pid. Call
- pid_find_allow_zombie instead of pid_find.
- (pid_find_allow_zombie): New function.
- (prociterate): Don't call FUN for dead processes.
- * mgt.c (new_proc): Initialize P->p_dead.
- (process_has_exited): Don't call reparent_zombies. Set P->p_dead.
- Don't remove from hash tables here, delete ref to task port or
- remove from parent's list of children (now in
- complete_exit). Don't remove from pgrp here.
- (complete_exit): New function.
- * wait.c (alert_parent): Don't create zombie.
- (reparent_zombies): Delete function.
- (S_proc_wait): Don't scan zombie list; check dead children at the
- same time as stopped children. When completing wait on a dead
- child, call complete_exit after we've finished work.
- (zombie_check_pid): Delete function.
- * proc.h (complete_exit): Provide prototype.
-
- -- All these changes make proc multithreaded
- and use the ports library in the usual fashion
- (well, almost the usual fashion) --
- * Makefile (proc): Mention ../libports/libports.a.
- * hash.c (porthash, exchash): Delete variables.
- (reqport_find): Use ports library instead of porthash.
- (add_proc_to_hash): Don't add to porthash.
- (remove_proc_from_hash): Don't remove from porthash.
- (exc_find, remove_exc_from_hash): Delete functions.
- * mgt.c (new_proc): Allocate new proc structure with
- ports_create_port. Don't frob P->p_reqport.
- (process_has_exited): Don't frob P->p_reqport, cal
- ports_destry_right instead.
- * proc.h (proc_bucket, proc_class): New variables.
- (request_portset): Delete variable.
- * proc.h (struct proc): Delete members `p_reqport' and
- p_porthashloc. Add member `p_pi'.
- * Makefile (MIGSFLAGS): Delete variable.
- * proc.h (global_lock): New variable.
- * main.c (global_lock): Provide definition.
- (message_demuxer): Lock global_lock around work.
- (main): Initialize proc_bucket and proc_class instead of
- request_portset. Initialize generic_port through ports
- library calls. Fetch startup procserver port through ports
- library instead of reading p_reqport. Initialize exc_class.
- * mgt.c (S_proc_reauthenticate) Likewise.
-
- * proc.h: Include <hurd/ports.h> and <cthreads.h>.
- * info.c (S_proc_task2proc): Use ports_get_right instead
- of p_reqport.
- (S_proc_pid2proc): Likewise.
- * proc.h (exc_port_class): New variable.
- (struct exc): Add member `pi'. Remove member `excport'.
- * mgt.c (S_proc_handle_exceptions): Allocate using
- ports library.
- (S_proc_exception_raise): Use ports library to manage
- structure.
- (exc_clean): New function.
-
-
-***
-
- -- All these changes switch to using condition variables
- for wakeup instead of explicit block code --
- * mgt.c (new_proc): Initialize P->p_wakeup.
- * wait.c (waiting_parent_cares): Delete function.
- * Makefile (MIGSTUBS): Delete interruptServer.o.
- * main.c (message_demuxer): Remove call to interrupt_server.
- Add call to ports_interrupt_server.
- * wait.c: Don't include "interrupt_S.h".
- (alent_parent): Unconditionally enqueue zombie.
- (S_interrupt_operation): Delete function.
- (abort_wait): Delete function.
- * msg.c (abort_getmsgport): Delete function.
- * wait.c (alert_parent): Use condition_broadcast instead of
- continuation stuff.
- (reparent_zombies): Likewise.
- (S_proc_mark_stop): Likewise.
- * msg.c (check_message_return): Likewise.
- (check_message_dying): Likewise.
- * wait.c (S_proc_wait): Use condition_wait instead of continuation
- stuff; never return EBUSY.
- * msg.c (S_proc_getmsgport): Likewise.
- * proc.h (struct proc): New member `p_wakeup'. Delete member
- `p_continuation'.
-
-
-
-Mon Feb 12 14:13:55 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * info.c (S_proc_getprocinfo): Fail reasonably for #ifdef'd-out
- thread waits code.
-
-Fri Feb 9 15:45:07 1996 Miles Bader <miles@gnu.ai.mit.edu>
-
- * info.c (S_proc_getprocinfo): Support returning wait strings.
-
-Fri Feb 9 15:19:14 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * mgt.c (S_proc_exception_raise): Rewritten.
- (S_proc_handle_exceptions): Don't set E->replyport.
- (S_proc_exception_raise_reply): Function removed.
- * main.c (message_demuxer): Don't call proc_excrepl_server.
- * proc_excrepl.defs: File removed.
- * Makefile (DIST_FILES): Remove proc_excrepl.defs.
- (MIGSTUBS): Remove its objects.
- * proc_exc.defs: Add msgoption arg.
- Use integer_t where appropriate.
- * notify.c (do_mach_notify_no_senders): Don't use E->replyport.
- * proc.h (struct exc): Removed useless members `replyport',
- `replyporttype'.
-
-Wed Dec 20 17:29:13 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * mgt.c (S_proc_reassign): Have notifications sent to the correct
- request port.
- Once we've given STUBP's request port to P, don't leave it in
- STUBP, so process_has_exited() doesn't dealloc it.
-
- * pgrp.c (S_proc_getsidport): Add and use new arg sessport_type.
-
-Wed Dec 20 13:31:01 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * mgt.c (new_proc): Don't set P->p_noowner for processes 0 and 1.
-
-Wed Dec 20 13:09:04 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * info.c (get_vector): Rewritten without arbitrary limits.
-
-Tue Dec 19 18:14:30 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * pgrp.c (free_session): Correctly get rid of the receive right
- we're holding.
- (S_proc_getsidport): Return errors.
-
-Tue Dec 19 13:58:59 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * info.c (get_string_array): Fix stupid bug in copying to newly
- allocated space.
-
-Tue Dec 19 13:17:46 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * mgt.c (S_proc_reauthenticate): Reverse miles' last change.
-
-Mon Dec 18 19:56:03 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * mgt.c (S_proc_reauthenticate): Don't return 0 for the new port.
-
-Tue Nov 21 13:50:30 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * wait.c (S_interrupt_operation): Include new seqno parameter.
-
-Tue Nov 14 13:15:55 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * wait.c (S_proc_wait): `p->msgportwait' ==> `p->p_msgportwait'
- typo fix.
-
-Thu Nov 9 13:01:28 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * msg.c (S_proc_setmsgport): Only do the RPC reply by hand for
- init. Also, return the correct port in that by-hand reply.
-
- * msg.c (S_proc_getmsgport): Also return EBUSY if P->waiting,
- because both share the same memory in the proc structure.
- * wait.c (S_proc_wait): Likewise, mutatis mutandis.
-
-Wed Nov 8 13:10:27 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * info.c (S_proc_getprocinfo): Don't attempt msg_report_wait if
- P->p_msgport is not valid.
-
- * info.c (S_proc_getprocinfo): Inhibit PI_FETCH_THREAD_WAITS for
- now.
-
-Tue Nov 7 19:49:32 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * info.c (S_proc_getprocinfo): Calculate the size of the returned
- structure correctly.
-
-Sun Nov 5 02:05:10 1995 Miles Bader <miles@gnu.ai.mit.edu>
-
- * proc.h: Include <sys/resource.h>.
-
- * info.c (S_proc_getprocinfo): Add NOISE and NOISE_LEN args.
- Fix various typos. Initialize ERR.
-
-Tue Oct 31 14:19:04 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * wait.c (struct zombie): Deleted; now in proc.h.
- (zombie_list): Likewise.
- * proc.h (struct zombie): New type.
- (zombie_list): New variable.
-
- * info.c (S_proc_getprocinfo): Implement all the rest of the PI
- flags except PI_ZOMBIE.
-
-Mon Oct 30 16:22:49 1995 Michael I. Bushnell, p/BSG <mib@gnu.ai.mit.edu>
-
- * info.c (S_proc_getprocinfo): Support new FETCH flags; support
- new msg_report_wait call; improve organization.
-
- * info.c (S_proc_getprocenv): Removed #ifdef notyet; fixed args to
- get_string_array.
-
-Sat Sep 16 12:57:31 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * ourmsg.defs: New file.
- * Makefile (DIST_FILES): Added ourmsg.defs.
- (ourmsg_U.h ourmsgUser.c, ourmsg.defs): Targets removed.
-
-Thu Aug 24 10:38:58 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
-
- * Makefile (MIGSTUBS): New variable.
- (OBJS): Get the mig stubs from $(MIGSTUBS).
-
-Wed Aug 23 14:25:30 1995 Miles Bader <miles@churchy.gnu.ai.mit.edu>
-
- * Makefile (proc): Put all dependencies here.
- (HURDLIBS, REMHDRS): Removed.
- (OBJS): Calculate the appropiate bits from $(SRCS).
-
-Sat Jul 22 15:04:52 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * wait.c (zombie_check_pid): Examine Z->pgrp too.
-
- * pgrp.c (S_proc_setpgrp): Install bletcherous hack.
-
-Thu Jul 6 15:41:22 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
-
- * hash.c: "ihash.h" -> <hurd/ihash.h>.
-
- * Makefile (ourmsg_U.h ourmsgUser.c): Use local ourmsg.defs
- instead of include file directly.
- (ourmsg.defs): New target.
-
- * Makefile: Removed dependencies that are now automatically
- generated.
-
-Tue Jun 27 12:02:47 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
-
- * mgt.c (S_proc_dostop): Remove assigments from inside if tests.
-
-Tue Jun 6 13:24:51 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
-
- * Makefile (OBJS): Removed ihash.o and primes.o.
- (CPPFLAGS): Deleted addition of -I../lib.
- (vpath): Deleted spec.
- (REMHDRS): Added ../libihash/ihash.h.
- (HURDLIBS): Added libihash.
-
-Wed Apr 26 14:32:19 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
-
- * wait.c (S_proc_wait): Use `waiter_cares', not
- `waiting_parent_cares' in zombie check.
-
-Tue Apr 18 09:30:13 1995 Michael I Bushnell <mib@churchy.gnu.ai.mit.edu>
-
- * wait.c (reparent_zombies): Send SIGCHLD signal to init.
-
- * wait.c (S_proc_wait): Don't return ESRCH; return ECHILD.
-
-Wed Apr 12 14:36:30 1995 Michael I Bushnell <mib@duality.gnu.ai.mit.edu>
-
- * Makefile (SRCS): Omit primes.c (it's moved to the lib dir).
-
-Thu Apr 6 14:29:06 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * info.c (S_proc_getprocinfo): New var `tp'. Bother to set
- PI->logincollection.
-
-Wed Apr 5 20:32:02 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * wait.c (waiter_cares, waiting_parent_cares): New functions.
- (alert_parent, reparent_zombies, S_proc_wait, S_proc_mark_stop):
- Use them.
-
-Tue Apr 4 14:36:36 1995 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * main.c (main): Wire text and data segment on startup to avoid
- failure mode during non-standalone pseudo-crash.
-
-Tue Mar 14 11:55:00 1995 Miles Bader <miles@geech.gnu.ai.mit.edu>
-
- * hash.c (addhash, findhash): Moved to ihash.c (which is has a more
- generic interface) and renamed ihash_add & ihash_find; all callers
- changed. Other changes: struct htable becomes struct ihash, and
- all routines that previously deleted things explicitly use
- ihash_locp_remove instead.
-
-Thu Jan 19 02:01:14 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * pgrp.c (S_proc_setpgrp): Use nowait_msg_proc_newids instead of
- nowait_proc_newids.
- * mgt.c (S_proc_child): Likewise.
-
-Tue Jan 17 17:48:32 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * mgt.c (check_uid): Return true if P has root.
-
- * proc.h (struct proc): Make `argv' and `envp' members
- `vm_address_t'.
-
-Thu Nov 3 12:13:49 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * mgt.c (S_proc_getallpids): Don't dereference PIDS in call
- to vm_allocate.
-
- * info.c (S_proc_getprocinfo): Don't take address of PIARRAY
- in call to vm_allocate. Dereference PIARRAY in call to
- vm_deallocate.
-
-Fri Oct 14 04:54:46 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * mgt.c (new_proc): Don't assume MACH_PORT_NULL is zero.
- (genpid): Deal with all pids between STAR_OVER and WRAP_AROUND
- being used.
-
-Mon Oct 10 14:23:00 1994 Jim Blandy <jimb@geech.gnu.ai.mit.edu>
-
- * primes.c (nextprime): Doc fix.
-
-Mon Oct 10 02:18:02 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * host.c (rebuild_uname): If all the server versions after [0]
- (the microkernel) match, merge them all into one "Hurd-VERSION"
- element in the uname version string.
-
-Sun Oct 2 20:36:57 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * host.c (S_proc_sethostname): Don't write off end of
- uname_info.nodename.
- (rebuild_uname): Rewritten.
- (initialize_version_info): Write Mach version info as first
- element of server_versions.
- (machversion): Variable removed.
-
-Sat Sep 10 11:37:32 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * mgt.c (make_ids): Copy from UIDS and GIDS into newly allocated
- space, not vice versa.
-
-Wed Aug 31 11:03:13 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * mgt.c (S_proc_reassign): Rather than getting a new request port,
- preserve STUBP's request port. This is more convenient for
- users (and equally good security), and it's what the protocol spec
- says anyway.
-
-Tue Aug 30 12:44:37 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * primes.c: Replaced file with new version from Jim Blandy
- (jimb@gnu.ai.mit.edu), David Carlton (carlton@math.mit.edu).
-
- * proc.h (check_dead_execdata_notify): Add prototype.
-
-Mon Aug 29 12:53:27 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * mgt.c (S_proc_reauthenticate): Use new authentication protocol.
-
-Tue Aug 23 11:41:26 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * pgrp.c (S_proc_setpgrp): If we don't actually change the pgrp,
- still send proc_newids; the library depends on always getting it.
-
-Mon Aug 22 17:09:21 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * wait.c (S_proc_mark_stop): Removed now meaningless assert.
-
- * info.c (S_proc_getloginpids): Compute size in realloc correctly.
-
-Mon Aug 22 13:29:21 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * wait.c (S_proc_mod_stopchild): Negate VALUE; sense of
- p_nostopcld flag is opposite of flag value described in process.defs.
-
-Fri Aug 19 10:21:57 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * pgrp.c (S_proc_getpgrppids): Understand PGID of zero as meaning
- caller's pgrp.
-
- * mgt.c (S_proc_child): Check CHILDP->p_msgport against
- MACH_PORT_NULL explicitly.
-
- * pgrp.c (join_pgrp): If pg->pg_orphcnt has significantly changed,
- then notify all the processes in the pgrp.
- (leave_pgrp): Only send newids message if ip->p_msgport is set.
- * mgt.c (S_proc_child): Becase join_pgrp now always sends
- newids; don't do it here if we called join_pgrp.
-
-Fri Aug 19 04:53:04 1994 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
-
- * pgrp.c (leave_pgrp): Fix swapped args to nowait_proc_newids.
- (join_pgrp): Call nowait_proc_newids to notify the process.
-
-Thu Aug 18 10:40:13 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * mgt.c (S_proc_reauthenticate): Use MACH_MSG_TYPE_MAKE_SEND
- to create a send right from P->p_reqport.
-
- * main.c (main): Removed var `authhandle'. Use global
- `authserver' instead.
-
-Wed Aug 17 14:02:31 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * host.c (init_stdarrays): Removed function.
- (S_proc_execdata_notify): Never call init_stdarrays.
- Only call exec_setexecdata if std_port_array is set.
- (S_proc_getexecdata): Return error if there is no std_port_array.
-
-Mon Aug 15 16:12:22 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * host.c (check_dead_execdata_notify): New function.
- * notify.c (do_mach_notify_dead_name): For notifications sent
- to GENERIC_PORT, call check_dead_execdata_notify.
- * main.c (main): Create GENERIC_PORT and put it in
- REQUEST_PORTSET.
-
- * host.c (init_stdarrays): New function.
- (S_proc_execdata_notify): Call init_stdarrays the first time.
- (S_proc_getexecdata): Likewise.
-
- * host.c: Include <hurd.h> for various frobs. Include
- <unistd.h> for getpid.
-
-Fri Jul 22 11:01:53 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * Makefile: Rewritten in accord with new scheme.
- * wait.c: Include "ourmsg_U.h" instead of "msg.h".
- Include "process_reply_U.h" instead of "process_reply.h".
- Include "process_S.h" instead of "proc_S.h".
- * mgt.c: Include "proc_exc_U.h" instead of "proc_exc.h".
- Include "proc_excrepl_U.h" insted of "proc_excrepl.h".
- Include "ourmsg_U.h" instead of "msg.h".
- Include "process_S.h" instead of "proc_S.h".
- * pgrp.c: Include "process_S.h" instead of "proc_S.h".
- Include "ourmsg_U.h" instead of "msg.h".
- * msg.c: Include "process_reply_U.h" instead of "process_reply.h".
- * host.c: Include "process_S.h" instead of "proc_S.h".
- * info.c: Likewise.
-
-Wed Jul 20 16:18:31 1994 Michael I Bushnell <mib@geech.gnu.ai.mit.edu>
-
- * wait.c (alert_parent): Delete unused variable `err'.
-
-Tue Jul 19 12:45:43 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
-
- * Makefile (proc): Don't use variable $(link) anymore.
-
-Mon Jul 11 14:32:17 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
-
- * pgrp.c (leave_pgrp): When pulling process off of pgrp list,
- mutate *both* links.
- (free_pgrp): When pulling pgrp off of session list, mutate
- *both* links.
-
-Tue Jul 5 14:23:21 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
-
- * Makefile (TAGSLIBS, TAGSHDRS): New variables.
-
-Fri Jul 1 10:57:07 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
-
- * stubs.c (send_signal): Rewrote to be machine independent
- and cleaner.
-
-Thu Jun 30 14:05:21 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
-
- * stubs.c: New file.
- * wait.c (alert_parent): Call send_signal instead of nowait_sig_post.
- (S_proc_mark_stop): Likewise.
- * pgrp.c (leave_pgrp): Likewise.
- * proc.h (send_signal): New prototype.
- * Makefile (OBJS): Added stubs.o.
- (SRCS): Added stubs.c.
- (LIBS): New var to get cthreads library.
-
- * wait.c (alert_parent): Eliminate pointless assert with confusingly
- incorrect comment.
-
- * hash.c (findhash): If we find a slot with ID matching the
- one we're looking for, but it has been deleted, then return
- 0 rather than HASH_DEL.
-
- * wait.c (S_proc_wait, reparent_zombies, alert_parent): Use
- macros WAIT_ANY and WAIT_MYPGRP instead of magic values -1
- and 0.
-
- * wait.c (S_proc_wait): Implement correct interpretation of PID
- argument: -1 means any child; 0 means child in the same pgrp.
- [Incorrect semantics were in loop to search zombies, and loop
- looking for stopped children]
- (reparent_zombies): Likewise. [Incorrect semantics were in
- PID check before returning startup_proc's wait.]
- (alert_parent): Likewise. [Incorrect semantics were in
- PID check before returning P->p_parent's wait.]
-
- * wait.c (S_proc_wait): Only return wait on stopped child if
- it passes the PID test.
-
- * pgrp.c (S_proc_setpgrp): Don't do process group change if we are
- changing into our own process group.
- * mgt.c (S_proc_child): Likewise.
-
- * pgrp.c (S_proc_setpgrp): When PID is zero, act on calling
- process; when PGID is zero, use pid of affected process.
- (S_proc_setpgrp): EPERM check should succeed if pgid is the
- affected process's *pid*, not pgrp.
-
-Thu Jun 30 08:40:35 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
-
- * mgt.c (S_proc_dostop): Use the proper allocation for task_threads.
- Check for errors. Deallocate the send right from CONTTHREAD too.
-
- * wait.c (alert_parent): Send SIGCHLD to the parent.
-
-Tue Jun 28 18:12:43 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
-
- * primes.c: Include <assert.h>.
- (nextprime): Use calloc instead of alloca, bzero. P might be
- bigger than will fit on the stack. Assert non-null return
- from calloc and realloc.
-
-Tue Jun 28 13:57:08 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
-
- * main.c (main): Set priority of proc server to 2 so that we
- get more CPU than ordinary programs.
-
-Fri Jun 24 17:29:55 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
-
- * hash.c (struct htable): New member `locps'.
- (addhash): Store LOCP into hash table for use during rehash.
- During rehash, then provide correct LOCP parm for old elements.
- Allocate and free HT->locps as appropriate.
-
-Fri Jun 24 04:15:16 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
-
- * mgt.c (S_proc_setprocargs): Renamed to S_proc_set_arg_locations.
- (S_proc_get_arg_locations): New function.
-
-Mon Jun 20 15:07:00 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
-
- * Makefile (install): Use $(INSTALL_BIN) instead of cp.
-
-Fri Jun 17 13:00:27 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
-
- * mgt.c (S_proc_child): Reverse Roland's change of June 11.
-
-Sat Jun 11 11:20:16 1994 Roland McGrath (roland@geech.gnu.ai.mit.edu)
-
- * mgt.c (S_proc_child): Inherit the argv and envp values from the
- parent.
-
-Fri May 27 16:03:53 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
-
- * primes.c: Doc fix, with appreciation to Jim Blandy.
-
-Fri May 13 16:58:13 1994 Michael I Bushnell (mib@churchy.gnu.ai.mit.edu)
-
- * info.c (S_proc_getprocinfo): Only scan through the threads
- if task_info succeeds.
-
- * info.c (S_proc_getprocinfo): Behave properly if one of the
- threads has died in between the call to task_threads and the
- calls to thread_info (just pretend it never existed).
-
- * info.c (get_string, get_vector, S_proc_getprocinfo): If the task
- has died (there's a race between pending requests and processing
- of dead-name notifications) then convert MACH_SEND_INVALID_DEST to
- ESRCH.
-
-Thu May 12 00:59:03 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
-
- * main.c (main): Take three args. Store ARGV and ENVP in SELF_PROC.
-
- * info.c (S_proc_getprocargs): Remove `#ifdef notyet's.
- (get_string, get_vector, get_string_array): Functions exposed.
- (get_string_array): Set BP before the loop. Use a for loop that
- iterates over elts in VECTOR. Fix check of LEN to reallocate buffer.
- (S_proc_getprocargs): Cast BUF to vm_address_t * for get_string_array.
- (get_vector): Fix pointer arithmetic; break out of loop when done.
- Check for error from malloc.
- (get_string): Use memchr for scanning. Check for error from
- malloc. Pass READLEN correctly to vm_deallocate.
-
- * msg.c (S_proc_setmsgport): Take new reply port args.
- Send reply before trying startup_essential_task.
- Include <hurd/startup.h> to declare startup_essential_task.
-
- * cpu-types.c: New file.
- * Makefile (SRCS, OBJS): Add it.
- * host.c: Include <stdio.h> for sprintf.
- (rebuild_uname): Removed unused variable J.
- (S_proc_register_version): Fix arg types.
- Use master_host_port, not host_priv.
- Remove unused variable J.
- (server_versions): Fix syntax errors in struct definition.
- (S_proc_uname): Fixed type of first arg.
- (rebuild_uname): Fix typo.
- (initialize_version_info): Cast args to host_info.
- (initialize_version_info): Allocate space for machversion.
-
-Mon May 9 14:32:37 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
-
- * mgt.c (new_proc): Regard init as having a dead message
- port initially.
-
- * msg.c (S_proc_setmsgport): When init chimes in, tell it
- we are essential.
-
- * proc.h (OUR_VERSION, OUR_SERVER_NAME): New macros.
- * host.c (uname_info, machversion, server_versions,
- nserver_versions, server_version_nalloc): New variables.
- (S_proc_register_version, rebuild_uname, initialize_version_info,
- S_proc_uname): New functions.
- (S_proc_sethostname): Also set uname_info.nodename.
- * main.c (main): Call initialize_version_info.
-
-Fri May 6 13:00:36 1994 Michael I Bushnell (mib@geech.gnu.ai.mit.edu)
-
- * host.c (S_proc_gethostname): If HOSTNAME is null, return
- an empty hostname instead of crashing.
- (S_proc_gethostname): Test buffer length properly; allocate
- space for the null too.
-
- * mgt.c (process_has_exited): delete unused variable LAST.
- * msg.c (check_message_return): delete unused variables I,
- MSGPORTS, and CP. Changed type of second arg to `void *'
- so that the function type is appropriate for the first arg
- to prociterate.
- (check_message_dying): delete unused variable I.
-
- * wait.c, host.c, info.c, mgt.c, notify.c, pgrp.c: Changed MiG
- server stubs' return types from error_t to kern_return_t; the
- types are incompatible right now.
-
-Thu May 5 07:50:24 1994 Roland McGrath (roland@churchy.gnu.ai.mit.edu)
-
- * Makefile: Change uses of $(headers) to $(includedir).
-
diff --git a/proc/Makefile b/proc/Makefile
index b666c4f7..a1159700 100644
--- a/proc/Makefile
+++ b/proc/Makefile
@@ -31,9 +31,7 @@ MIGSFLAGS="-DPROCESS_INTRAN=pstruct_t reqport_find (process_t)" \
MIGSTUBS = processServer.o notifyServer.o \
ourmsgUser.o proc_excUser.o proc_excServer.o
OBJS = $(SRCS:.c=.o) $(MIGSTUBS)
-
-proc: $(OBJS) ../libthreads/libthreads.a ../libihash/libihash.a \
- ../libports/libports.a ../libshouldbeinlibc/libshouldbeinlibc.a
+HURDLIBS=threads ihash ports shouldbeinlibc
include ../Makeconf
diff --git a/proc/cpu-types.c b/proc/cpu-types.c
index f15387c7..7bcaa928 100644
--- a/proc/cpu-types.c
+++ b/proc/cpu-types.c
@@ -21,6 +21,18 @@ const char *const mach_cpu_types[] =
[CPU_TYPE_SPARC] = "sparc",
[CPU_TYPE_I860] = "i860",
[CPU_TYPE_ALPHA] = "alpha",
+#ifdef CPU_TYPE_I486
+ [CPU_TYPE_I486] = "i486",
+#endif
+#ifdef CPU_TYPE_PENTIUM
+ [CPU_TYPE_PENTIUM] = "i586",
+#endif
+#ifdef CPU_TYPE_PENTIUMPRO
+ [CPU_TYPE_PENTIUMPRO] = "i686",
+#endif
+#ifdef CPU_TYPE_POWERPC
+ [CPU_TYPE_POWERPC] = "powerpc",
+#endif
};
const char *const mach_cpu_subtypes[][32] =
@@ -67,14 +79,24 @@ const char *const mach_cpu_subtypes[][32] =
[CPU_SUBTYPE_MMAX_XPC] = "MMAX_XPC",
[CPU_SUBTYPE_PC532] = "PC532",
},
- [CPU_TYPE_I386] =
- {
- [CPU_SUBTYPE_AT386] = "AT386",
- [CPU_SUBTYPE_EXL] = "EXL",
- [CPU_SUBTYPE_iPSC386] = "iPSC386",
- [CPU_SUBTYPE_SYMMETRY] = "SYMMETRY",
- [CPU_SUBTYPE_PS2] = "PS2",
- },
+#define Ix86_SUBTYPES \
+ { \
+ [CPU_SUBTYPE_AT386] = "AT386", \
+ [CPU_SUBTYPE_EXL] = "EXL", \
+ [CPU_SUBTYPE_iPSC386] = "iPSC386", \
+ [CPU_SUBTYPE_SYMMETRY] = "SYMMETRY", \
+ [CPU_SUBTYPE_PS2] = "PS2", \
+ }
+ [CPU_TYPE_I386] = Ix86_SUBTYPES,
+#ifdef CPU_TYPE_I486
+ [CPU_TYPE_I486] = Ix86_SUBTYPES,
+#endif
+#ifdef CPU_TYPE_PENTIUM
+ [CPU_TYPE_PENTIUM] = Ix86_SUBTYPES,
+#endif
+#ifdef CPU_TYPE_PENTIUMPRO
+ [CPU_TYPE_PENTIUMPRO] = Ix86_SUBTYPES,
+#endif
[CPU_TYPE_MIPS] =
{
[CPU_SUBTYPE_MIPS_R2300] = "R2300",
diff --git a/proc/hash.c b/proc/hash.c
index 85eb7c5d..ed670a16 100644
--- a/proc/hash.c
+++ b/proc/hash.c
@@ -1,5 +1,5 @@
/* Hash table functions
- Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation
+ Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation
This file is part of the GNU Hurd.
@@ -20,6 +20,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Written by Michael I. Bushnell. */
#include <mach.h>
+#include <stddef.h>
#include <sys/types.h>
#include <hurd/hurd_types.h>
#include <string.h>
@@ -29,15 +30,23 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "proc.h"
#include <hurd/ihash.h>
-static struct ihash pghash, pidhash, taskhash, sidhash;
+static struct hurd_ihash pghash
+ = HURD_IHASH_INITIALIZER (offsetof (struct pgrp, pg_hashloc));
+static struct hurd_ihash pidhash
+ = HURD_IHASH_INITIALIZER (offsetof (struct proc, p_pidhashloc));
+static struct hurd_ihash taskhash
+ = HURD_IHASH_INITIALIZER (offsetof (struct proc, p_taskhashloc));
+static struct hurd_ihash sidhash
+ = HURD_IHASH_INITIALIZER (offsetof (struct session, s_hashloc));
+
/* Find the process corresponding to a given pid. */
struct proc *
pid_find (pid_t pid)
{
struct proc *p;
- p = ihash_find (&pidhash, pid);
- return p->p_dead ? 0 : p;
+ p = hurd_ihash_find (&pidhash, pid);
+ return (!p || p->p_dead) ? 0 : p;
}
/* Find the process corresponding to a given pid. Return it even if
@@ -45,7 +54,7 @@ pid_find (pid_t pid)
struct proc *
pid_find_allow_zombie (pid_t pid)
{
- return ihash_find (&pidhash, pid);
+ return hurd_ihash_find (&pidhash, pid);
}
/* Find the process corresponding to a given task. */
@@ -53,8 +62,8 @@ struct proc *
task_find (task_t task)
{
struct proc *p;
- p = ihash_find (&taskhash, task) ? : add_tasks (task);
- return p->p_dead ? 0 : p;
+ p = hurd_ihash_find (&taskhash, task) ? : add_tasks (task);
+ return (!p || p->p_dead) ? 0 : p;
}
/* Find the process corresponding to a given task, but
@@ -63,8 +72,8 @@ struct proc *
task_find_nocreate (task_t task)
{
struct proc *p;
- p = ihash_find (&taskhash, task);
- return p->p_dead ? 0 : p;
+ p = hurd_ihash_find (&taskhash, task);
+ return (!p || p->p_dead) ? 0 : p;
}
/* Find the process corresponding to a given request port. */
@@ -75,65 +84,65 @@ reqport_find (mach_port_t reqport)
p = ports_lookup_port (proc_bucket, reqport, proc_class);
if (p && p->p_dead)
ports_port_deref (p);
- return p->p_dead ? 0 : p;
+ return (!p || p->p_dead) ? 0 : p;
}
/* Find the process group corresponding to a given pgid. */
struct pgrp *
pgrp_find (pid_t pgid)
{
- return ihash_find (&pghash, pgid);
+ return hurd_ihash_find (&pghash, pgid);
}
/* Find the session corresponding to a given sid. */
struct session *
session_find (pid_t sid)
{
- return ihash_find (&sidhash, sid);
+ return hurd_ihash_find (&sidhash, sid);
}
/* Add a new process to the various hash tables. */
void
add_proc_to_hash (struct proc *p)
{
- ihash_add (&pidhash, p->p_pid, p, &p->p_pidhashloc);
- ihash_add (&taskhash, p->p_task, p, &p->p_taskhashloc);
+ hurd_ihash_add (&pidhash, p->p_pid, p);
+ hurd_ihash_add (&taskhash, p->p_task, p);
}
/* Add a new process group to the various hash tables. */
void
add_pgrp_to_hash (struct pgrp *pg)
{
- ihash_add (&pghash, pg->pg_pgid, pg, &pg->pg_hashloc);
+ hurd_ihash_add (&pghash, pg->pg_pgid, pg);
}
/* Add a new session to the various hash tables. */
void
add_session_to_hash (struct session *s)
{
- ihash_add (&sidhash, s->s_sid, s, &s->s_hashloc);
+ hurd_ihash_add (&sidhash, s->s_sid, s);
}
/* Remove a process group from the various hash tables. */
void
remove_pgrp_from_hash (struct pgrp *pg)
{
- ihash_locp_remove(0, pg->pg_hashloc);
+ hurd_ihash_locp_remove (&pghash, pg->pg_hashloc);
}
/* Remove a process from the various hash tables. */
void
remove_proc_from_hash (struct proc *p)
{
- ihash_locp_remove(0, p->p_pidhashloc);
- ihash_locp_remove(0, p->p_taskhashloc);
+ hurd_ihash_locp_remove (&pidhash, p->p_pidhashloc);
+ hurd_ihash_locp_remove (&taskhash, p->p_taskhashloc);
}
/* Remove a session from the various hash tables. */
void
remove_session_from_hash (struct session *s)
{
- ihash_locp_remove(0, s->s_hashloc);
+ hurd_ihash_locp_remove (&sidhash, s->s_hashloc);
}
/* Call function FUN of two args for each process. FUN's first arg is
@@ -141,14 +150,12 @@ remove_session_from_hash (struct session *s)
void
prociterate (void (*fun) (struct proc *, void *), void *arg)
{
- error_t thunk(void *value)
+ HURD_IHASH_ITERATE (&pidhash, value)
{
struct proc *p = value;
if (!p->p_dead)
(*fun)(p, arg);
- return 0;
}
- ihash_iterate(&pidhash, thunk);
}
/* Tell if a pid is available for use */
diff --git a/proc/host.c b/proc/host.c
index 3b1e03c8..2b3c4f3c 100644
--- a/proc/host.c
+++ b/proc/host.c
@@ -1,5 +1,5 @@
/* Proc server host management calls
- Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation
+ Copyright (C) 1992,93,94,96,97,2001,02 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -8,7 +8,7 @@ it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-The GNU Hurd is distributed in the hope that it will be useful,
+The GNU Hurd 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.
@@ -31,13 +31,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <hurd/exec.h>
#include <unistd.h>
#include <assert.h>
+#include <version.h>
+#include <sys/mman.h>
#include "proc.h"
#include "process_S.h"
-static long hostid;
-static char *hostname;
-static int hostnamelen;
static mach_port_t *std_port_array;
static int *std_int_array;
static int n_std_ports, n_std_ints;
@@ -47,93 +46,17 @@ struct server_version
{
char *name;
char *version;
- char *release;
} *server_versions;
int nserver_versions, server_versions_nalloc;
-struct execdata_notify
+struct execdata_notify
{
mach_port_t notify_port;
struct execdata_notify *next;
} *execdata_notifys;
-/* Implement proc_sethostid as described in <hurd/proc.defs>. */
-kern_return_t
-S_proc_sethostid (struct proc *p,
- int newhostid)
-{
- if (!p)
- return EOPNOTSUPP;
-
- if (! check_uid (p, 0))
- return EPERM;
-
- hostid = newhostid;
-
- return 0;
-}
-
-/* Implement proc_gethostid as described in <hurd/proc.defs>. */
-kern_return_t
-S_proc_gethostid (struct proc *p,
- int *outhostid)
-{
- /* No need to check P here; we don't use it. */
- *outhostid = hostid;
- return 0;
-}
-/* Implement proc_sethostname as described in <hurd/proc.defs>. */
-kern_return_t
-S_proc_sethostname (struct proc *p,
- char *newhostname,
- u_int newhostnamelen)
-{
- int len;
- if (!p)
- return EOPNOTSUPP;
-
- if (! check_uid (p, 0))
- return EPERM;
-
- if (hostname)
- free (hostname);
-
- hostname = malloc (newhostnamelen + 1);
- hostnamelen = newhostnamelen;
-
- bcopy (newhostname, hostname, newhostnamelen);
- hostname[newhostnamelen] = '\0';
-
- len = newhostnamelen + 1;
- if (len > sizeof uname_info.nodename)
- len = sizeof uname_info.nodename;
- bcopy (hostname, uname_info.nodename, len);
- uname_info.nodename[sizeof uname_info.nodename - 1] = '\0';
-
- return 0;
-}
-
-/* Implement proc_gethostname as described in <hurd/proc.defs>. */
-kern_return_t
-S_proc_gethostname (struct proc *p,
- char **outhostname,
- u_int *outhostnamelen)
-{
- /* No need to check P here; we don't use it. */
-
- if (*outhostnamelen < hostnamelen + 1)
- vm_allocate (mach_task_self (), (vm_address_t *)outhostname,
- hostnamelen + 1, 1);
- *outhostnamelen = hostnamelen + 1;
- if (hostname)
- bcopy (hostname, *outhostname, hostnamelen + 1);
- else
- **outhostname = '\0';
- return 0;
-}
-
-/* Implement proc_getprivports as described in <hurd/proc.defs>. */
+/* Implement proc_getprivports as described in <hurd/process.defs>. */
kern_return_t
S_proc_getprivports (struct proc *p,
mach_port_t *hostpriv,
@@ -141,33 +64,47 @@ S_proc_getprivports (struct proc *p,
{
if (!p)
return EOPNOTSUPP;
-
+
if (! check_uid (p, 0))
return EPERM;
-
+
*hostpriv = master_host_port;
*devpriv = master_device_port;
return 0;
}
-/* Implement proc_setexecdata as described in <hurd/proc.defs>. */
+/* Implement proc_setexecdata as described in <hurd/process.defs>. */
kern_return_t
S_proc_setexecdata (struct proc *p,
mach_port_t *ports,
- u_int nports,
+ size_t nports,
int *ints,
- u_int nints)
+ size_t nints)
{
int i;
struct execdata_notify *n;
-
+ mach_port_t *std_port_array_new;
+ int *std_int_array_new;
+
if (!p)
return EOPNOTSUPP;
-
+
if (!check_uid (p, 0))
return EPERM;
-
+
+ /* Allocate memory up front. */
+ std_port_array_new = malloc (sizeof (mach_port_t) * nports);
+ if (! std_port_array_new)
+ return ENOMEM;
+
+ std_int_array_new = malloc (sizeof (int) * nints);
+ if (! std_int_array_new)
+ {
+ free (std_port_array_new);
+ return ENOMEM;
+ }
+
if (std_port_array)
{
for (i = 0; i < n_std_ports; i++)
@@ -176,75 +113,98 @@ S_proc_setexecdata (struct proc *p,
}
if (std_int_array)
free (std_int_array);
-
- std_port_array = malloc (sizeof (mach_port_t) * nports);
+
+ std_port_array = std_port_array_new;
n_std_ports = nports;
- bcopy (ports, std_port_array, sizeof (mach_port_t) * nports);
-
- std_int_array = malloc (sizeof (int) * nints);
+ memcpy (std_port_array, ports, sizeof (mach_port_t) * nports);
+
+ std_int_array = std_int_array_new;
n_std_ints = nints;
- bcopy (ints, std_int_array, sizeof (int) * nints);
-
+ memcpy (std_int_array, ints, sizeof (int) * nints);
+
for (n = execdata_notifys; n; n = n->next)
exec_setexecdata (n->notify_port, std_port_array, MACH_MSG_TYPE_COPY_SEND,
n_std_ports, std_int_array, n_std_ints);
-
+
return 0;
}
-/* Implement proc_getexecdata as described in <hurd/proc.defs>. */
-kern_return_t
+/* Implement proc_getexecdata as described in <hurd/process.defs>. */
+kern_return_t
S_proc_getexecdata (struct proc *p,
mach_port_t **ports,
mach_msg_type_name_t *portspoly,
- u_int *nports,
+ size_t *nports,
int **ints,
- u_int *nints)
+ size_t *nints)
{
+ int i;
+ int ports_allocated = 0;
/* No need to check P here; we don't use it. */
- /* XXX memory leak here */
-
if (!std_port_array)
return ENOENT;
if (*nports < n_std_ports)
- *ports = malloc (n_std_ports * sizeof (mach_port_t));
- bcopy (std_port_array, *ports, n_std_ports * sizeof (mach_port_t));
+ {
+ *ports = mmap (0, round_page (n_std_ports * sizeof (mach_port_t)),
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ if (*ports == MAP_FAILED)
+ return ENOMEM;
+ ports_allocated = 1;
+ }
+ memcpy (*ports, std_port_array, n_std_ports * sizeof (mach_port_t));
*nports = n_std_ports;
-
+
if (*nints < n_std_ints)
- *ints = malloc (n_std_ints * sizeof (mach_port_t));
- bcopy (std_int_array, *ints, n_std_ints * sizeof (int));
+ {
+ *ints = mmap (0, round_page (n_std_ints * sizeof (int)),
+ PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ if (*ints == MAP_FAILED)
+ {
+ if (ports_allocated)
+ munmap (*ports, round_page (n_std_ports * sizeof (mach_port_t)));
+ return ENOMEM;
+ }
+ }
+ memcpy (*ints, std_int_array, n_std_ints * sizeof (int));
*nints = n_std_ints;
+ for (i = 0; i < n_std_ports; i++)
+ mach_port_mod_refs (mach_task_self (), std_port_array[i], MACH_PORT_RIGHT_SEND, 1);
+ *portspoly = MACH_MSG_TYPE_MOVE_SEND;
+
return 0;
}
-/* Implement proc_execdata_notify as described in <hurd/proc.defs>. */
+/* Implement proc_execdata_notify as described in <hurd/process.defs>. */
kern_return_t
S_proc_execdata_notify (struct proc *p,
mach_port_t notify)
{
- struct execdata_notify *n = malloc (sizeof (struct execdata_notify));
+ struct execdata_notify *n;
mach_port_t foo;
/* No need to check P here; we don't use it. */
+ n = malloc (sizeof (struct execdata_notify));
+ if (! n)
+ return ENOMEM;
+
n->notify_port = notify;
n->next = execdata_notifys;
execdata_notifys = n;
- mach_port_request_notification (mach_task_self (), notify,
+ mach_port_request_notification (mach_task_self (), notify,
MACH_NOTIFY_DEAD_NAME, 1,
generic_port, MACH_MSG_TYPE_MAKE_SEND_ONCE,
&foo);
if (foo)
mach_port_deallocate (mach_task_self (), foo);
-
+
if (std_port_array)
- exec_setexecdata (n->notify_port, std_port_array, MACH_MSG_TYPE_COPY_SEND,
+ exec_setexecdata (n->notify_port, std_port_array, MACH_MSG_TYPE_COPY_SEND,
n_std_ports, std_int_array, n_std_ints);
return 0;
}
@@ -255,7 +215,7 @@ void
check_dead_execdata_notify (mach_port_t port)
{
struct execdata_notify *en, **prevp;
-
+
for (en = execdata_notifys, prevp = &execdata_notifys; en; en = *prevp)
{
if (en->notify_port == port)
@@ -271,14 +231,17 @@ check_dead_execdata_notify (mach_port_t port)
/* Version information handling.
- A server registers its name, release, and version with
- startup_register_version. The uname version string is composed of all
- the server names and versions. The uname release is composed of the
- differing server releases in order of decreasing popularity (just one if
- they all agree).
+ A server registers its name and version with
+ startup_register_version.
+
+ The uname release is the most popular version number.
+
+ The uname version string is composed of all the server names and
+ versions, omitting special mention of those which match the uname
+ release, plus the kernel version string. */
+
+char *kernel_name, *kernel_version;
- The Hurd release comes from <hurd/hurd_types.h> and
- is compiled into proc as well as the other servers. */
/* Rebuild the uname version string. */
static void
@@ -314,72 +277,58 @@ rebuild_uname (void)
*p++ = '/';
}
- /* Collect all the differing release strings and count how many
+ /* Collect all the differing version strings and count how many
servers use each. */
- struct release
+ struct version
{
- const char *release;
+ const char *version;
unsigned int count;
- } releases[nserver_versions];
- int compare_releases (const void *a, const void *b)
+ } versions[nserver_versions];
+ int compare_versions (const void *a, const void *b)
{
- return (((const struct release *) b)->count -
- ((const struct release *) a)->count);
+ return (((const struct version *) b)->count -
+ ((const struct version *) a)->count);
}
- unsigned int nreleases = 0;
+ unsigned int nversions = 0;
for (i = 0; i < nserver_versions; ++i)
{
- for (j = 0; j < nreleases; ++j)
- if (! strcmp (releases[j].release, server_versions[i].release))
+ for (j = 0; j < nversions; ++j)
+ if (! strcmp (versions[j].version, server_versions[i].version))
{
- ++releases[j].count;
+ ++versions[j].count;
break;
}
- if (j == nreleases)
+ if (j == nversions)
{
- releases[nreleases].release = server_versions[i].release;
- releases[nreleases].count = 1;
- ++nreleases;
+ versions[nversions].version = server_versions[i].version;
+ versions[nversions].count = 1;
+ ++nversions;
}
}
- /* Sort the releases in order of decreasing popularity. */
- qsort (releases, nreleases, sizeof (struct release), compare_releases);
+ /* Sort the versions in order of decreasing popularity. */
+ qsort (versions, nversions, sizeof (struct version), compare_versions);
/* Now build the uname strings. */
- initstr (uname_info.release);
- for (i = 0; i < nreleases; ++i)
- addstr (NULL, releases[i].release);
+ /* release is the most popular version */
+ strcpy (uname_info.release, versions[0].version);
- if (p > end)
-#ifdef notyet
- syslog (LOG_EMERG,
- "_UTSNAME_LENGTH %u too short; inform bug-glibc@prep.ai.mit.edu\n",
- p - end)
-#endif
- ;
- else
- p[-1] = '\0';
- end[-1] = '\0';
+ initstr (uname_info.version);
- for (i = 2; i < nserver_versions; i++)
- if (strcmp (server_versions[i].version, server_versions[1].version))
- break;
+ addstr (kernel_name, kernel_version);
- initstr (uname_info.version);
+ if (versions[0].count > 1)
+ addstr ("Hurd", versions[0].version);
- if (i == nserver_versions)
- {
- /* All the servers after [0] (the microkernel version)
- are the same, so just write one "hurd" version. */
- addstr (server_versions[0].name, server_versions[0].version);
- addstr ("Hurd", server_versions[1].version);
- }
- else
+ /* Now, for any which differ (if there might be any), write it out
+ separately. */
+ if (versions[0].count != nserver_versions)
for (i = 0; i < nserver_versions; i++)
- addstr (server_versions[i].name, server_versions[i].version);
+ if (versions[0].count == 1
+ || strcmp (server_versions[i].version, versions[0].version))
+ addstr (server_versions[i].name, server_versions[i].version);
if (p > end)
#ifdef notyet
@@ -393,52 +342,58 @@ rebuild_uname (void)
end[-1] = '\0';
}
-
void
initialize_version_info (void)
{
extern const char *const mach_cpu_types[];
extern const char *const mach_cpu_subtypes[][32];
- kernel_version_t kernel_version;
+ kernel_version_t kv;
char *p;
struct host_basic_info info;
- unsigned int n = sizeof info;
+ size_t n = sizeof info;
error_t err;
/* Fill in fixed slots sysname and machine. */
strcpy (uname_info.sysname, "GNU");
- err = host_info (mach_host_self (), HOST_BASIC_INFO, (int *) &info, &n);
+ err = host_info (mach_host_self (), HOST_BASIC_INFO,
+ (host_info_t) &info, &n);
assert (! err);
- snprintf (uname_info.machine, sizeof uname_info.machine, "%s/%s",
+ snprintf (uname_info.machine, sizeof uname_info.machine, "%s-%s",
mach_cpu_types[info.cpu_type],
mach_cpu_subtypes[info.cpu_type][info.cpu_subtype]);
/* Notice Mach's and our own version and initialize server version
- varables. */
+ variables. */
server_versions = malloc (sizeof (struct server_version) * 10);
+ assert (server_versions);
server_versions_nalloc = 10;
- err = host_kernel_version (mach_host_self (), kernel_version);
+ err = host_kernel_version (mach_host_self (), kv);
assert (! err);
- p = index (kernel_version, ':');
+ /* Make sure the result is null-terminated, as the kernel doesn't
+ guarantee it. */
+ kv[sizeof (kv) - 1] = '\0';
+ p = index (kv, ':');
if (p)
*p = '\0';
- p = index (kernel_version, ' ');
+ p = index (kv, ' ');
if (p)
*p = '\0';
- server_versions[0].name = strdup (p ? kernel_version : "mach");
- server_versions[0].release = strdup (HURD_RELEASE);
- server_versions[0].version = strdup (p ? p + 1 : kernel_version);
+ kernel_name = strdup (p ? kv : "mach");
+ assert (kernel_name);
+ kernel_version = strdup (p ? p + 1 : kv);
+ assert (kernel_version);
- server_versions[1].name = strdup (OUR_SERVER_NAME);
- server_versions[1].release = strdup (HURD_RELEASE);
- server_versions[1].version = strdup (OUR_VERSION);
+ server_versions[0].name = strdup ("proc");
+ assert (server_versions[0].name);
+ server_versions[0].version = strdup (HURD_VERSION);
+ assert (server_versions[0].version);
- nserver_versions = 2;
+ nserver_versions = 1;
rebuild_uname ();
-
+
uname_info.nodename[0] = '\0';
}
@@ -455,9 +410,10 @@ kern_return_t
S_proc_register_version (pstruct_t server,
mach_port_t credential,
char *name,
- char *release,
+ char *release,
char *version)
{
+ error_t err = 0;
int i;
/* No need to check SERVER here; we don't use it. */
@@ -465,17 +421,19 @@ S_proc_register_version (pstruct_t server,
if (credential != master_host_port)
/* Must be privileged to register for uname. */
return EPERM;
-
+
for (i = 0; i < nserver_versions; i++)
if (!strcmp (name, server_versions[i].name))
{
/* Change this entry. */
free (server_versions[i].version);
- free (server_versions[i].release);
server_versions[i].version = malloc (strlen (version) + 1);
- server_versions[i].release = malloc (strlen (version) + 1);
+ if (! server_versions[i].version)
+ {
+ err = ENOMEM;
+ goto out;
+ }
strcpy (server_versions[i].version, version);
- strcpy (server_versions[i].release, release);
break;
}
if (i == nserver_versions)
@@ -483,23 +441,40 @@ S_proc_register_version (pstruct_t server,
/* Didn't find it; extend. */
if (nserver_versions == server_versions_nalloc)
{
+ void *new = realloc (server_versions,
+ sizeof (struct server_version) *
+ server_versions_nalloc * 2);
+ if (! new)
+ {
+ err = ENOMEM;
+ goto out;
+ }
+
server_versions_nalloc *= 2;
- server_versions = realloc (server_versions,
- sizeof (struct server_version) *
- server_versions_nalloc);
+ server_versions = new;
}
server_versions[nserver_versions].name = malloc (strlen (name) + 1);
- server_versions[nserver_versions].version = malloc (strlen (version)
- + 1);
- server_versions[nserver_versions].release = malloc (strlen (release)
+ if (! server_versions[nserver_versions].name)
+ {
+ err = ENOMEM;
+ goto out;
+ }
+ server_versions[nserver_versions].version = malloc (strlen (version)
+ 1);
+ if (! server_versions[nserver_versions].version)
+ {
+ free (server_versions[nserver_versions].name);
+ err = ENOMEM;
+ goto out;
+ }
strcpy (server_versions[nserver_versions].name, name);
strcpy (server_versions[nserver_versions].version, version);
- strcpy (server_versions[nserver_versions].release, release);
nserver_versions++;
}
-
+
rebuild_uname ();
- mach_port_deallocate (mach_task_self (), credential);
- return 0;
+out:
+ if (!err)
+ mach_port_deallocate (mach_task_self (), credential);
+ return err;
}
diff --git a/proc/info.c b/proc/info.c
index c44bde6a..f35ad166 100644
--- a/proc/info.c
+++ b/proc/info.c
@@ -1,5 +1,5 @@
/* Process information queries
- Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation
+ Copyright (C) 1992,93,94,95,96,99,2000,01,02 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -21,6 +21,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <mach.h>
#include <sys/types.h>
+#include <sys/mman.h>
#include <hurd/hurd_types.h>
#include <stdlib.h>
#include <errno.h>
@@ -32,17 +33,32 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "proc.h"
#include "process_S.h"
-/* Implement S_proc_pid2task as described in <hurd/proc.defs>. */
+
+/* Returns true if PROC1 has `owner' privileges over PROC2 (and can thus get
+ its task port &c). If PROC2 has an owner, then PROC1 must have that uid;
+ otherwise, both must be in the same login collection. */
+static inline int
+check_owner (struct proc *proc1, struct proc *proc2)
+{
+ return
+ proc2->p_noowner
+ ? check_uid (proc1, 0) || proc1->p_login == proc2->p_login
+ : check_uid (proc1, proc2->p_owner);
+}
+
+
+/* Implement S_proc_pid2task as described in <hurd/process.defs>. */
kern_return_t
S_proc_pid2task (struct proc *callerp,
- pid_t pid,
- task_t *t)
+ pid_t pid,
+ task_t *t)
{
- struct proc *p = pid_find_allow_zombie (pid);
+ struct proc *p;
if (!callerp)
return EOPNOTSUPP;
+ p = pid_find_allow_zombie (pid);
if (!p)
return ESRCH;
@@ -55,16 +71,17 @@ S_proc_pid2task (struct proc *callerp,
if (! check_owner (callerp, p))
return EPERM;
+ assert (MACH_PORT_VALID (p->p_task));
*t = p->p_task;
return 0;
}
-/* Implement proc_task2pid as described in <hurd/proc.defs>. */
+/* Implement proc_task2pid as described in <hurd/process.defs>. */
kern_return_t
S_proc_task2pid (struct proc *callerp,
- task_t t,
- pid_t *pid)
+ task_t t,
+ pid_t *pid)
{
struct proc *p = task_find (t);
@@ -78,11 +95,11 @@ S_proc_task2pid (struct proc *callerp,
return 0;
}
-/* Implement proc_task2proc as described in <hurd/proc.defs>. */
+/* Implement proc_task2proc as described in <hurd/process.defs>. */
kern_return_t
S_proc_task2proc (struct proc *callerp,
- task_t t,
- mach_port_t *outproc)
+ task_t t,
+ mach_port_t *outproc)
{
struct proc *p = task_find (t);
@@ -96,10 +113,10 @@ S_proc_task2proc (struct proc *callerp,
return 0;
}
-/* Implement proc_proc2task as described in <hurd/proc.defs>. */
+/* Implement proc_proc2task as described in <hurd/process.defs>. */
kern_return_t
S_proc_proc2task (struct proc *p,
- task_t *t)
+ task_t *t)
{
if (!p)
return EOPNOTSUPP;
@@ -107,17 +124,18 @@ S_proc_proc2task (struct proc *p,
return 0;
}
-/* Implement proc_pid2proc as described in <hurd/proc.defs>. */
+/* Implement proc_pid2proc as described in <hurd/process.defs>. */
kern_return_t
S_proc_pid2proc (struct proc *callerp,
- pid_t pid,
- mach_port_t *outproc)
+ pid_t pid,
+ mach_port_t *outproc)
{
- struct proc *p = pid_find_allow_zombie (pid);
+ struct proc *p;
if (!callerp)
return EOPNOTSUPP;
+ p = pid_find_allow_zombie (pid);
if (!p)
return ESRCH;
@@ -136,18 +154,18 @@ S_proc_pid2proc (struct proc *callerp,
/* Read a string starting at address ADDR in task T; set *STR to point at
- newly malloced storage holding it. */
+ newly malloced storage holding it, and *LEN to its length with null. */
static error_t
get_string (task_t t,
vm_address_t addr,
- char **str)
+ char **str, size_t *len)
{
/* This version assumes that a string is never more than one
page in length. */
vm_address_t readaddr;
vm_address_t data;
- u_int readlen;
+ size_t readlen;
error_t err;
char *c;
@@ -168,15 +186,15 @@ get_string (task_t t,
else
{
c++; /* Include the null. */
- *str = malloc (c - (char *)(data + (addr - readaddr)));
+ *len = c - (char *) (data + (addr - readaddr));
+ *str = malloc (*len);
if (*str == NULL)
err = ENOMEM;
else
- bcopy ((char *)(data + (addr - readaddr)), *str,
- c - (char *)(data + (addr - readaddr)));
+ memcpy (*str, (char *) data + (addr - readaddr), *len);
}
- vm_deallocate (mach_task_self (), data, readlen);
+ munmap ((caddr_t) data, readlen);
return err;
}
@@ -210,8 +228,6 @@ get_vector (task_t task,
if (err)
return err;
- /* XXX fault bad here */
-
/* Scan for a null. */
for (t = (vm_address_t *) (data + (scanned - readaddr));
t < (vm_address_t *) (data + readlen);
@@ -223,15 +239,15 @@ get_vector (task_t task,
if (*vec == NULL)
err = ENOMEM;
else
- bcopy ((char *)(data + (addr - readaddr)), *vec,
+ memcpy (*vec, (char *)(data + (addr - readaddr)),
(char *)t - (char *)(data + (addr - readaddr)));
break;
}
/* If we didn't find the null terminator, then we will loop
to read an additional page. */
- scanned = data + readlen;
- vm_deallocate (mach_task_self (), data, readlen);
+ scanned = readaddr + readlen;
+ munmap ((caddr_t) data, readlen);
} while (!err && *vec == NULL);
return err;
@@ -243,7 +259,7 @@ static error_t
get_string_array (task_t t,
vm_address_t loc,
vm_address_t *buf,
- u_int *buflen)
+ size_t *buflen)
{
char *bp;
int *vector, *vp;
@@ -258,62 +274,65 @@ get_string_array (task_t t,
for (vp = vector; *vp; ++vp)
{
char *string;
- int len;
+ size_t len;
- err = get_string (t, *vp, &string);
+ err = get_string (t, *vp, &string, &len);
if (err)
{
free (vector);
if (*buf != origbuf)
- vm_deallocate (mach_task_self (), *buf, *buflen);
+ munmap ((caddr_t) *buf, *buflen);
return err;
}
- len = strlen (string) + 1;
- if (len > *(char **)buf + *buflen - bp)
+ if (len > (char *) *buf + *buflen - bp)
{
- vm_address_t newbuf;
- vm_size_t prev_len = bp - *(char **)buf;
+ char *newbuf;
+ vm_size_t prev_len = bp - (char *) *buf;
vm_size_t newsize = *buflen * 2;
if (newsize < prev_len + len)
- newsize = prev_len + len;
+ /* Since we will mmap whole pages anyway,
+ notice how much space we really have. */
+ newsize = round_page (prev_len + len);
- err = vm_allocate (mach_task_self (), &newbuf, newsize, 1);
- if (err)
+ newbuf = mmap (0, newsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ if (newbuf == MAP_FAILED)
{
+ err = errno;
free (string);
free (vector);
if (*buf != origbuf)
- vm_deallocate (mach_task_self (), *buf, *buflen);
+ munmap ((caddr_t) *buf, *buflen);
return err;
}
- bcopy (*(char **) buf, (char *) newbuf, prev_len);
- bp = (char *)newbuf + prev_len;
+ memcpy (newbuf, (char *) *buf, prev_len);
+ bp = newbuf + prev_len;
if (*buf != origbuf)
- vm_deallocate (mach_task_self (), *buf, *buflen);
+ munmap ((caddr_t) *buf, *buflen);
- *buf = newbuf;
+ *buf = (vm_address_t) newbuf;
*buflen = newsize;
}
- bcopy (string, bp, len);
+ memcpy (bp, string, len);
bp += len;
free (string);
}
+
free (vector);
*buflen = bp - (char *) *buf;
return 0;
}
-/* Implement proc_getprocargs as described in <hurd/proc.defs>. */
+/* Implement proc_getprocargs as described in <hurd/process.defs>. */
kern_return_t
S_proc_getprocargs (struct proc *callerp,
pid_t pid,
char **buf,
- u_int *buflen)
+ size_t *buflen)
{
struct proc *p = pid_find (pid);
@@ -325,12 +344,12 @@ S_proc_getprocargs (struct proc *callerp,
return get_string_array (p->p_task, p->p_argv, (vm_address_t *) buf, buflen);
}
-/* Implement proc_getprocenv as described in <hurd/proc.defs>. */
+/* Implement proc_getprocenv as described in <hurd/process.defs>. */
kern_return_t
S_proc_getprocenv (struct proc *callerp,
pid_t pid,
char **buf,
- u_int *buflen)
+ size_t *buflen)
{
struct proc *p = pid_find (pid);
@@ -346,18 +365,18 @@ S_proc_getprocenv (struct proc *callerp,
#define PI_FETCH_THREAD_DETAILS \
(PI_FETCH_THREAD_SCHED | PI_FETCH_THREAD_BASIC | PI_FETCH_THREAD_WAITS)
-/* Implement proc_getprocinfo as described in <hurd/proc.defs>. */
+/* Implement proc_getprocinfo as described in <hurd/process.defs>. */
kern_return_t
S_proc_getprocinfo (struct proc *callerp,
pid_t pid,
int *flags,
int **piarray,
- u_int *piarraylen,
+ size_t *piarraylen,
char **waits, mach_msg_type_number_t *waits_len)
{
struct proc *p = pid_find (pid);
struct procinfo *pi;
- int nthreads;
+ size_t nthreads;
thread_t *thds;
error_t err = 0;
size_t structsize;
@@ -365,7 +384,7 @@ S_proc_getprocinfo (struct proc *callerp,
int pi_alloced = 0, waits_alloced = 0;
/* The amount of WAITS we've filled in so far. */
mach_msg_type_number_t waits_used = 0;
- u_int tkcount, thcount;
+ size_t tkcount, thcount;
struct proc *tp;
task_t task; /* P's task port. */
mach_port_t msgport; /* P's msgport, or MACH_PORT_NULL if none. */
@@ -376,7 +395,9 @@ S_proc_getprocinfo (struct proc *callerp,
return ESRCH;
task = p->p_task;
- msgport = p->p_deadmsg ? MACH_PORT_NULL : p->p_msgport;
+
+ check_msgport_death (p);
+ msgport = p->p_msgport;
if (*flags & PI_FETCH_THREAD_DETAILS)
*flags |= PI_FETCH_THREADS;
@@ -398,7 +419,18 @@ S_proc_getprocinfo (struct proc *callerp,
if (structsize / sizeof (int) > *piarraylen)
{
- vm_allocate (mach_task_self (), (vm_address_t *)piarray, structsize, 1);
+ *piarray = mmap (0, structsize, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
+ if (*piarray == MAP_FAILED)
+ {
+ err = errno;
+ if (*flags & PI_FETCH_THREADS)
+ {
+ for (i = 0; i < nthreads; i++)
+ mach_port_deallocate (mach_task_self (), thds[i]);
+ munmap (thds, nthreads * sizeof (thread_t));
+ }
+ return err;
+ }
pi_alloced = 1;
}
*piarraylen = structsize / sizeof (int);
@@ -424,7 +456,7 @@ S_proc_getprocinfo (struct proc *callerp,
assert (tp);
pi->logincollection = tp->p_pid;
if (p->p_dead || p->p_stopped)
- {
+ {
pi->exitstatus = p->p_status;
pi->sigcode = p->p_sigcode;
}
@@ -440,9 +472,37 @@ S_proc_getprocinfo (struct proc *callerp,
if (*flags & PI_FETCH_TASKINFO)
{
tkcount = TASK_BASIC_INFO_COUNT;
- err = task_info (task, TASK_BASIC_INFO, (int *)&pi->taskinfo, &tkcount);
+ err = task_info (task, TASK_BASIC_INFO,
+ (task_info_t) &pi->taskinfo, &tkcount);
if (err == MACH_SEND_INVALID_DEST)
err = ESRCH;
+#ifdef TASK_SCHED_TIMESHARE_INFO
+ if (!err)
+ {
+ tkcount = TASK_SCHED_TIMESHARE_INFO_COUNT;
+ err = task_info (task, TASK_SCHED_TIMESHARE_INFO,
+ (int *)&pi->timeshare_base_info, &tkcount);
+ if (err == KERN_INVALID_POLICY)
+ {
+ pi->timeshare_base_info.base_priority = -1;
+ err = 0;
+ }
+ }
+#endif
+ }
+ if (*flags & PI_FETCH_TASKEVENTS)
+ {
+ tkcount = TASK_EVENTS_INFO_COUNT;
+ err = task_info (task, TASK_EVENTS_INFO,
+ (task_info_t) &pi->taskevents, &tkcount);
+ if (err == MACH_SEND_INVALID_DEST)
+ err = ESRCH;
+ if (err)
+ {
+ /* Something screwy, give up on this bit of info. */
+ *flags &= ~PI_FETCH_TASKEVENTS;
+ err = 0;
+ }
}
for (i = 0; i < nthreads; i++)
@@ -453,7 +513,7 @@ S_proc_getprocinfo (struct proc *callerp,
{
thcount = THREAD_BASIC_INFO_COUNT;
err = thread_info (thds[i], THREAD_BASIC_INFO,
- (int *)&pi->threadinfos[i].pis_bi,
+ (thread_info_t) &pi->threadinfos[i].pis_bi,
&thcount);
if (err == MACH_SEND_INVALID_DEST)
{
@@ -473,7 +533,7 @@ S_proc_getprocinfo (struct proc *callerp,
{
thcount = THREAD_SCHED_INFO_COUNT;
err = thread_info (thds[i], THREAD_SCHED_INFO,
- (int *)&pi->threadinfos[i].pis_si,
+ (thread_info_t) &pi->threadinfos[i].pis_si,
&thcount);
if (err == MACH_SEND_INVALID_DEST)
{
@@ -482,15 +542,15 @@ S_proc_getprocinfo (struct proc *callerp,
continue;
}
if (err)
- /* Something screwy, give up o nthis bit of info. */
+ /* Something screwy, give up on this bit of info. */
{
*flags &= ~PI_FETCH_THREAD_SCHED;
err = 0;
}
}
- /* Note that there are thread wait entries only for threads not marked
- dead. */
+ /* Note that there are thread wait entries only for those threads
+ not marked dead. */
if (*flags & PI_FETCH_THREAD_WAITS)
{
@@ -517,18 +577,18 @@ S_proc_getprocinfo (struct proc *callerp,
mach_msg_type_number_t new_len =
round_page (waits_used + desc_len + 1);
- err = vm_allocate (mach_task_self (),
- (vm_address_t *)&new_waits, new_len,1);
+ new_waits = mmap (0, new_len, PROT_READ|PROT_WRITE,
+ MAP_ANON, 0, 0);
+ err = (new_waits == MAP_FAILED) ? errno : 0;
if (err)
/* Just don't return any more waits information. */
*flags &= ~PI_FETCH_THREAD_WAITS;
else
{
if (waits_used > 0)
- bcopy (*waits, new_waits, waits_used);
+ memcpy (new_waits, *waits, waits_used);
if (*waits_len > 0 && waits_alloced)
- vm_deallocate (mach_task_self (),
- (vm_address_t)*waits, *waits_len);
+ munmap (*waits, *waits_len);
*waits = new_waits;
*waits_len = new_len;
waits_alloced = 1;
@@ -538,7 +598,7 @@ S_proc_getprocinfo (struct proc *callerp,
if (waits_used + desc_len + 1 <= *waits_len)
/* Append DESC to WAITS. */
{
- bcopy (desc, *waits + waits_used, desc_len);
+ memcpy (*waits + waits_used, desc, desc_len);
waits_used += desc_len;
(*waits)[waits_used++] = '\0';
}
@@ -549,14 +609,11 @@ S_proc_getprocinfo (struct proc *callerp,
}
if (*flags & PI_FETCH_THREADS)
- {
- vm_deallocate (mach_task_self (),
- (vm_address_t)thds, nthreads * sizeof (thread_t));
- }
+ munmap (thds, nthreads * sizeof (thread_t));
if (err && pi_alloced)
- vm_deallocate (mach_task_self (), (u_int) *piarray, structsize);
+ munmap (*piarray, structsize);
if (err && waits_alloced)
- vm_deallocate (mach_task_self (), (vm_address_t)*waits, *waits_len);
+ munmap (*waits, *waits_len);
else
*waits_len = waits_used;
@@ -602,8 +659,9 @@ kern_return_t
S_proc_getloginpids (struct proc *callerp,
pid_t id,
pid_t **pids,
- u_int *npids)
+ size_t *npids)
{
+ error_t err = 0;
struct proc *l = pid_find (id);
struct proc *p;
struct proc **tail, **new, **parray;
@@ -618,6 +676,9 @@ S_proc_getloginpids (struct proc *callerp,
/* Simple breadth first search of the children of L. */
parraysize = 50;
parray = malloc (sizeof (struct proc *) * parraysize);
+ if (! parray)
+ return ENOMEM;
+
parray[0] = l;
for (tail = parray, new = &parray[1]; tail != new; tail++)
{
@@ -630,6 +691,12 @@ S_proc_getloginpids (struct proc *callerp,
struct proc **newparray;
newparray = realloc (parray, ((parraysize *= 2)
* sizeof (struct proc *)));
+ if (! newparray)
+ {
+ free (parray);
+ return ENOMEM;
+ }
+
tail = newparray + (tail - parray);
new = newparray + (new - parray);
parray = newparray;
@@ -639,19 +706,28 @@ S_proc_getloginpids (struct proc *callerp,
}
if (*npids < new - parray)
- vm_allocate (mach_task_self (), (vm_address_t *) pids,
- (new - parray) * sizeof (pid_t), 1);
- *npids = new - parray;
- for (i = 0; i < *npids; i++)
- (*pids)[i] = parray[i]->p_pid;
+ {
+ *pids = mmap (0, (new - parray) * sizeof (pid_t), PROT_READ|PROT_WRITE,
+ MAP_ANON, 0, 0);
+ if (*pids == MAP_FAILED)
+ err = errno;
+ }
+
+ if (! err)
+ {
+ *npids = new - parray;
+ for (i = 0; i < *npids; i++)
+ (*pids)[i] = parray[i]->p_pid;
+ }
+
free (parray);
- return 0;
+ return err;
}
-/* Implement proc_setlogin as described in <hurd/proc.defs>. */
+/* Implement proc_setlogin as described in <hurd/process.defs>. */
kern_return_t
S_proc_setlogin (struct proc *p,
- char *login)
+ char *login)
{
struct login *l;
@@ -662,6 +738,9 @@ S_proc_setlogin (struct proc *p,
return EPERM;
l = malloc (sizeof (struct login) + strlen (login) + 1);
+ if (! l)
+ return ENOMEM;
+
l->l_refcnt = 1;
strcpy (l->l_name, login);
if (!--p->p_login->l_refcnt)
@@ -670,10 +749,10 @@ S_proc_setlogin (struct proc *p,
return 0;
}
-/* Implement proc_getlogin as described in <hurd/proc.defs>. */
+/* Implement proc_getlogin as described in <hurd/process.defs>. */
kern_return_t
S_proc_getlogin (struct proc *p,
- char *login)
+ char *login)
{
if (!p)
return EOPNOTSUPP;
@@ -681,10 +760,42 @@ S_proc_getlogin (struct proc *p,
return 0;
}
-/* Implement proc_get_tty as described in <hurd/proc.defs>. */
+/* Implement proc_get_tty as described in <hurd/process.defs>. */
kern_return_t
S_proc_get_tty (struct proc *p, pid_t pid,
mach_port_t *tty, mach_msg_type_name_t *tty_type)
{
return EOPNOTSUPP; /* XXX */
}
+
+/* Implement proc_getnports as described in <hurd/process.defs>. */
+kern_return_t
+S_proc_getnports (struct proc *callerp,
+ pid_t pid,
+ mach_msg_type_number_t *nports)
+{
+ struct proc *p = pid_find (pid);
+ mach_port_array_t names;
+ mach_msg_type_number_t ncount;
+ mach_port_type_array_t types;
+ mach_msg_type_number_t tcount;
+ error_t err = 0;
+
+ /* No need to check CALLERP here; we don't use it. */
+
+ if (!p)
+ return ESRCH;
+
+ err = mach_port_names (p->p_task, &names, &ncount, &types, &tcount);
+ if (err == KERN_INVALID_TASK)
+ err = ESRCH;
+
+ if (!err) {
+ *nports = ncount;
+
+ munmap (names, ncount * sizeof (mach_port_t));
+ munmap (types, tcount * sizeof (mach_port_type_t));
+ }
+
+ return err;
+}
diff --git a/proc/main.c b/proc/main.c
index 1292cea0..f2cdfdf5 100644
--- a/proc/main.c
+++ b/proc/main.c
@@ -1,5 +1,5 @@
/* Initialization of the proc server
- Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation
+ Copyright (C) 1993,94,95,96,97,99,2000,01 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -23,11 +23,16 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <hurd/hurd_types.h>
#include <hurd.h>
#include <hurd/startup.h>
+#include <device/device.h>
#include <assert.h>
-#include <wire.h>
+#include <argp.h>
+#include <error.h>
+#include <version.h>
#include "proc.h"
+const char *argp_program_version = STANDARD_HURD_VERSION (proc);
+
int
message_demuxer (mach_msg_header_t *inp,
mach_msg_header_t *outp)
@@ -56,64 +61,79 @@ main (int argc, char **argv, char **envp)
mach_port_t pset, psetcntl;
void *genport;
process_t startup_port;
- volatile int hold = 0;
-
- while (hold);
-
+ struct argp argp = { 0, 0, 0, "Hurd process server" };
+
+ argp_parse (&argp, argc, argv, 0, 0, 0);
initialize_version_info ();
- task_get_bootstrap_port (mach_task_self (), &boot);
+ err = task_get_bootstrap_port (mach_task_self (), &boot);
+ assert_perror (err);
+ if (boot == MACH_PORT_NULL)
+ error (2, 0, "proc server can only be run by init during boot");
proc_bucket = ports_create_bucket ();
proc_class = ports_create_class (0, 0);
generic_port_class = ports_create_class (0, 0);
exc_class = ports_create_class (exc_clean, 0);
- ports_create_port (generic_port_class, proc_bucket,
+ ports_create_port (generic_port_class, proc_bucket,
sizeof (struct port_info), &genport);
generic_port = ports_get_right (genport);
- /* new_proc depends on these assignments which must occur in this order. */
- self_proc = new_proc (mach_task_self ()); /* proc 0 is the procserver */
- startup_proc = new_proc (MACH_PORT_NULL); /* proc 1 is init */
+ /* Create the initial proc object for init (PID 1). */
+ startup_proc = create_startup_proc ();
+
+ /* Create our own proc object (we are PID 0). */
+ self_proc = allocate_proc (mach_task_self ());
+ assert (self_proc);
+
+ complete_proc (self_proc, 0);
- startup_port = ports_get_right (startup_proc);
- mach_port_insert_right (mach_task_self (), startup_port,
- startup_port, MACH_MSG_TYPE_MAKE_SEND);
+ startup_port = ports_get_send_right (startup_proc);
err = startup_procinit (boot, startup_port, &startup_proc->p_task,
&authserver, &master_host_port, &master_device_port);
- assert (!err);
+ assert_perror (err);
mach_port_deallocate (mach_task_self (), startup_port);
mach_port_mod_refs (mach_task_self (), authserver, MACH_PORT_RIGHT_SEND, 1);
_hurd_port_set (&_hurd_ports[INIT_PORT_AUTH], authserver);
mach_port_deallocate (mach_task_self (), boot);
- add_proc_to_hash (self_proc);
- add_proc_to_hash (startup_proc);
+ proc_death_notify (startup_proc);
+ add_proc_to_hash (startup_proc); /* Now that we have the task port. */
/* Set our own argv and envp locations. */
- self_proc->p_argv = (int) argv;
- self_proc->p_envp = (int) envp;
+ self_proc->p_argv = (vm_address_t) argv;
+ self_proc->p_envp = (vm_address_t) envp;
/* Give ourselves good scheduling performance, because we are so
important. */
err = thread_get_assignment (mach_thread_self (), &pset);
- assert (!err);
+ assert_perror (err);
err = host_processor_set_priv (master_host_port, pset, &psetcntl);
- assert (!err);
+ assert_perror (err);
thread_max_priority (mach_thread_self (), psetcntl, 0);
- assert (!err);
+ assert_perror (err);
err = task_priority (mach_task_self (), 2, 1);
- assert (!err);
+ assert_perror (err);
mach_port_deallocate (mach_task_self (), pset);
mach_port_deallocate (mach_task_self (), psetcntl);
-/* wire_task_self (); */
+ {
+ /* Get our stderr set up to print on the console, in case we have
+ to panic or something. */
+ mach_port_t cons;
+ error_t err;
+ err = device_open (master_device_port, D_READ|D_WRITE, "console", &cons);
+ assert_perror (err);
+ stdin = mach_open_devstream (cons, "r");
+ stdout = stderr = mach_open_devstream (cons, "w");
+ mach_port_deallocate (mach_task_self (), cons);
+ }
while (1)
ports_manage_port_operations_multithread (proc_bucket,
message_demuxer,
- 0, 0, 0, 0);
+ 0, 0, 0);
}
diff --git a/proc/mgt.c b/proc/mgt.c
index e8af38d4..1180c700 100644
--- a/proc/mgt.c
+++ b/proc/mgt.c
@@ -1,5 +1,5 @@
/* Process management
- Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1992,93,94,95,96,99,2000,01,02 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -21,6 +21,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <mach.h>
#include <sys/types.h>
+#include <sys/mman.h>
#include <errno.h>
#include <hurd/hurd_types.h>
#include <stdlib.h>
@@ -41,29 +42,34 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Create a new id structure with the given genuine uids and gids. */
static inline struct ids *
-make_ids (uid_t *uids, int nuids, uid_t *gids, int ngids)
+make_ids (const uid_t *uids, size_t nuids)
{
struct ids *i;
- i = malloc (sizeof (struct ids));
+ i = malloc (sizeof (struct ids) + sizeof (uid_t) * nuids);;
+ if (! i)
+ return NULL;
+
i->i_nuids = nuids;
- i->i_ngids = ngids;
- i->i_uids = malloc (sizeof (uid_t) * nuids);
- i->i_gids = malloc (sizeof (uid_t) * ngids);
i->i_refcnt = 1;
- memcpy (i->i_uids, uids, sizeof (uid_t) * nuids);
- memcpy (i->i_gids, gids, sizeof (uid_t) * ngids);
+ memcpy (&i->i_uids, uids, sizeof (uid_t) * nuids);
return i;
}
+static inline void
+ids_ref (struct ids *i)
+{
+ i->i_refcnt ++;
+}
+
/* Free an id structure. */
static inline void
-free_ids (struct ids *i)
+ids_rele (struct ids *i)
{
- free (i->i_uids);
- free (i->i_gids);
- free (i);
+ i->i_refcnt --;
+ if (i->i_refcnt == 0)
+ free (i);
}
/* Tell if process P has uid UID, or has root. */
@@ -77,15 +83,14 @@ check_uid (struct proc *p, uid_t uid)
return 0;
}
-
-/* Implement proc_reathenticate as described in <hurd/proc.defs>. */
+/* Implement proc_reathenticate as described in <hurd/process.defs>. */
kern_return_t
S_proc_reauthenticate (struct proc *p, mach_port_t rendport)
{
error_t err;
uid_t gubuf[50], aubuf[50], ggbuf[50], agbuf[50];
uid_t *gen_uids, *aux_uids, *gen_gids, *aux_gids;
- u_int ngen_uids, naux_uids, ngen_gids, naux_gids;
+ size_t ngen_uids, naux_uids, ngen_gids, naux_gids;
if (!p)
return EOPNOTSUPP;
@@ -95,10 +100,13 @@ S_proc_reauthenticate (struct proc *p, mach_port_t rendport)
gen_gids = ggbuf;
aux_gids = agbuf;
- ngen_uids = naux_uids = 50;
- ngen_gids = naux_gids = 50;
-
+ ngen_uids = sizeof (gubuf) / sizeof (uid_t);
+ naux_uids = sizeof (aubuf) / sizeof (uid_t);
+ ngen_gids = sizeof (ggbuf) / sizeof (uid_t);
+ naux_gids = sizeof (agbuf) / sizeof (uid_t);
+ /* Release the global lock while blocking on the auth server and client. */
+ mutex_unlock (&global_lock);
err = auth_server_authenticate (authserver,
rendport, MACH_MSG_TYPE_COPY_SEND,
MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND,
@@ -106,40 +114,48 @@ S_proc_reauthenticate (struct proc *p, mach_port_t rendport)
&aux_uids, &naux_uids,
&gen_gids, &ngen_gids,
&aux_gids, &naux_gids);
+ mutex_lock (&global_lock);
+
if (err)
return err;
- mach_port_deallocate (mach_task_self (), rendport);
- if (!--p->p_id->i_refcnt)
- free_ids (p->p_id);
- p->p_id = make_ids (gen_uids, ngen_uids, gen_gids, ngen_gids);
+ if (p->p_dead)
+ /* The process died while we had the lock released.
+ Its p_id field is no longer valid and we shouldn't touch it. */
+ err = EAGAIN;
+ else
+ {
+ ids_rele (p->p_id);
+ p->p_id = make_ids (gen_uids, ngen_uids);
+ if (! p->p_id)
+ err = ENOMEM;
+ }
if (gen_uids != gubuf)
- vm_deallocate (mach_task_self (), (u_int) gen_uids,
- ngen_uids * sizeof (uid_t));
+ munmap (gen_uids, ngen_uids * sizeof (uid_t));
if (aux_uids != aubuf)
- vm_deallocate (mach_task_self (), (u_int) aux_uids,
- naux_uids * sizeof (uid_t));
+ munmap (aux_uids, naux_uids * sizeof (uid_t));
if (gen_gids != ggbuf)
- vm_deallocate (mach_task_self (), (u_int) gen_gids,
- ngen_gids * sizeof (uid_t));
+ munmap (gen_gids, ngen_gids * sizeof (uid_t));
if (aux_gids != agbuf)
- vm_deallocate (mach_task_self (), (u_int) aux_gids,
- naux_gids * sizeof (uid_t));
+ munmap (aux_gids, naux_gids * sizeof (uid_t));
- return 0;
+ if (!err)
+ mach_port_deallocate (mach_task_self (), rendport);
+ return err;
}
-/* Implement proc_child as described in <hurd/proc.defs>. */
+/* Implement proc_child as described in <hurd/process.defs>. */
kern_return_t
S_proc_child (struct proc *parentp,
task_t childt)
{
- struct proc *childp = task_find (childt);
+ struct proc *childp;
if (!parentp)
return EOPNOTSUPP;
+ childp = task_find (childt);
if (!childp)
return ESRCH;
@@ -160,10 +176,9 @@ S_proc_child (struct proc *parentp,
childp->p_owner = parentp->p_owner;
childp->p_noowner = parentp->p_noowner;
- if (!--childp->p_id->i_refcnt)
- free_ids (childp->p_id);
+ ids_rele (childp->p_id);
+ ids_ref (parentp->p_id);
childp->p_id = parentp->p_id;
- childp->p_id->i_refcnt++;
/* Process hierarchy. Remove from our current location
and place us under our new parent. Sanity check to make sure
@@ -197,17 +212,17 @@ S_proc_child (struct proc *parentp,
return 0;
}
-/* Implement proc_reassign as described in <hurd/proc.defs>. */
+/* Implement proc_reassign as described in <hurd/process.defs>. */
kern_return_t
S_proc_reassign (struct proc *p,
task_t newt)
{
- struct proc *stubp = task_find (newt);
- mach_port_t foo;
+ struct proc *stubp;
if (!p)
return EOPNOTSUPP;
+ stubp = task_find (newt);
if (!stubp)
return ESRCH;
@@ -219,20 +234,12 @@ S_proc_reassign (struct proc *p,
remove_proc_from_hash (p);
task_terminate (p->p_task);
- mach_port_deallocate (mach_task_self (), p->p_task);
+ mach_port_destroy (mach_task_self (), p->p_task);
p->p_task = stubp->p_task;
- /* For security, we need use the request port from STUBP */
+ /* For security, we need to use the request port from STUBP */
ports_transfer_right (p, stubp);
- /* Redirect the task-death notification to the new receive right. */
- mach_port_request_notification (mach_task_self (), p->p_task,
- MACH_NOTIFY_DEAD_NAME, 1,
- p->p_pi.port_right,
- MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo);
- if (foo)
- mach_port_deallocate (mach_task_self (), foo);
-
/* Enqueued messages might refer to the old task port, so
destroy them. */
if (p->p_msgport != MACH_PORT_NULL)
@@ -247,7 +254,7 @@ S_proc_reassign (struct proc *p,
p->p_envp = stubp->p_envp;
/* Destroy stubp */
- stubp->p_task = 0; /* block deallocation */
+ stubp->p_task = MACH_PORT_NULL;/* block deallocation */
process_has_exited (stubp);
stubp->p_waited = 1; /* fake out complete_exit */
complete_exit (stubp);
@@ -257,7 +264,7 @@ S_proc_reassign (struct proc *p,
return 0;
}
-/* Implement proc_setowner as described in <hurd/proc.defs>. */
+/* Implement proc_setowner as described in <hurd/process.defs>. */
kern_return_t
S_proc_setowner (struct proc *p,
uid_t owner,
@@ -280,7 +287,7 @@ S_proc_setowner (struct proc *p,
return 0;
}
-/* Implement proc_getpids as described in <hurd/proc.defs>. */
+/* Implement proc_getpids as described in <hurd/process.defs>. */
kern_return_t
S_proc_getpids (struct proc *p,
pid_t *pid,
@@ -295,7 +302,7 @@ S_proc_getpids (struct proc *p,
return 0;
}
-/* Implement proc_set_arg_locations as described in <hurd/proc.defs>. */
+/* Implement proc_set_arg_locations as described in <hurd/process.defs>. */
kern_return_t
S_proc_set_arg_locations (struct proc *p,
vm_address_t argv,
@@ -308,7 +315,7 @@ S_proc_set_arg_locations (struct proc *p,
return 0;
}
-/* Implement proc_get_arg_locations as described in <hurd/proc.defs>. */
+/* Implement proc_get_arg_locations as described in <hurd/process.defs>. */
kern_return_t
S_proc_get_arg_locations (struct proc *p,
vm_address_t *argv,
@@ -319,13 +326,14 @@ S_proc_get_arg_locations (struct proc *p,
return 0;
}
-/* Implement proc_dostop as described in <hurd/proc.defs>. */
+/* Implement proc_dostop as described in <hurd/process.defs>. */
kern_return_t
S_proc_dostop (struct proc *p,
thread_t contthread)
{
thread_t threadbuf[2], *threads = threadbuf;
- unsigned int nthreads = 2, i;
+ size_t nthreads = sizeof (threadbuf) / sizeof (thread_t);
+ int i;
error_t err;
if (!p)
@@ -336,16 +344,21 @@ S_proc_dostop (struct proc *p,
return err;
err = task_threads (p->p_task, &threads, &nthreads);
if (err)
- return err;
+ {
+ task_resume (p->p_task);
+ return err;
+ }
+ /* We can not compare the thread ports with CONTTHREAD, as CONTTHREAD
+ might be a proxy port (for example in rpctrace). For this reason
+ we suspend all threads and then resume CONTTHREAD. */
for (i = 0; i < nthreads; i++)
{
if (threads[i] != contthread)
- err = thread_suspend (threads[i]);
+ thread_suspend (threads[i]);
mach_port_deallocate (mach_task_self (), threads[i]);
}
if (threads != threadbuf)
- vm_deallocate (mach_task_self (), (vm_address_t) threads,
- nthreads * sizeof (thread_t));
+ munmap (threads, nthreads * sizeof (thread_t));
err = task_resume (p->p_task);
if (err)
return err;
@@ -372,7 +385,7 @@ S_proc_handle_exceptions (struct proc *p,
mach_msg_type_number_t statecnt)
{
struct exc *e;
- error_t err;
+ error_t err;
/* No need to check P here; we don't use it. */
@@ -385,7 +398,7 @@ S_proc_handle_exceptions (struct proc *p,
e->forwardport = forwardport;
e->flavor = flavor;
e->statecnt = statecnt;
- bcopy (new_state, e->thread_state, statecnt * sizeof (natural_t));
+ memcpy (e->thread_state, new_state, statecnt * sizeof (natural_t));
ports_port_deref (e);
return 0;
}
@@ -399,9 +412,9 @@ S_proc_exception_raise (mach_port_t excport,
mach_msg_type_name_t reply_type,
mach_port_t thread,
mach_port_t task,
- int exception,
- int code,
- int subcode)
+ integer_t exception,
+ integer_t code,
+ integer_t subcode)
{
error_t err;
struct proc *p;
@@ -421,8 +434,6 @@ S_proc_exception_raise (mach_port_t excport,
err = proc_exception_raise (e->forwardport,
reply, reply_type, MACH_SEND_NOTIFY,
thread, task, exception, code, subcode);
- mach_port_deallocate (mach_task_self (), thread);
- mach_port_deallocate (mach_task_self (), task);
switch (err)
{
@@ -435,19 +446,21 @@ S_proc_exception_raise (mach_port_t excport,
dequeue that message. */
err = thread_set_state (thread, e->flavor, e->thread_state, e->statecnt);
ports_port_deref (e);
+ mach_port_deallocate (mach_task_self (), thread);
+ mach_port_deallocate (mach_task_self (), task);
return MIG_NO_REPLY;
default:
/* Some unexpected error in forwarding the message. */
/* FALLTHROUGH */
- case MACH_SEND_INVALID_NOTIFY:
- /* The port's queue is full, meaning the thread didn't receive
+ case MACH_SEND_NOTIFY_IN_PROGRESS:
+ /* The port's queue is full; this means the thread didn't receive
the exception message we forwarded last time it faulted.
Declare that signal thread hopeless and the task crashed. */
/* Translate the exception code into a signal number
- and mark the process has dying that way. */
+ and mark the process as having died that way. */
hsd.exc = exception;
hsd.exc_code = code;
hsd.exc_subcode = subcode;
@@ -456,20 +469,46 @@ S_proc_exception_raise (mach_port_t excport,
p->p_status = W_EXITCODE (0, signo);
p->p_sigcode = hsd.code;
- /* Nuke the task; we will get a notification message and report it
- died with SIGNO. */
+ /* Nuke the task; we will get a notification message and report that
+ it died with SIGNO. */
task_terminate (task);
ports_port_deref (e);
- return 0;
+
+ /* In the MACH_SEND_NOTIFY_IN_PROGRESS case, the kernel did a
+ pseudo-receive of the RPC request message that may have added user
+ refs to these send rights. But we have lost track because the MiG
+ stub did not save the message buffer that was modified by the
+ pseudo-receive.
+
+ Fortunately, we can be sure that we don't need the THREAD send
+ right for anything since this task is now dead; there would be a
+ potential race here with another exception_raise message arriving
+ with the same thread, but we expect that this won't happen since
+ the thread will still be waiting for our reply. XXX We have no
+ secure knowledge that this is really from the kernel, so a
+ malicious user could confuse us and induce a race where we clobber
+ another port put on the THREAD name after the destroy; also, a
+ user just doing thread_set_state et al could arrange that we get a
+ second legitimate exception_raise for the same thread and have the
+ first race mentioned above!
+
+ There are all manner of race problems if we destroy the TASK
+ right. Fortunately, since we've terminated the task we know that
+ we will shortly be getting a dead-name notifiction and that will
+ call mach_port_destroy in TASK when it is safe to do so. */
+
+ mach_port_destroy (mach_task_self (), thread);
+
+ return MIG_NO_REPLY;
}
}
-/* Implement proc_getallpids as described in <hurd/proc.defs>. */
+/* Implement proc_getallpids as described in <hurd/process.defs>. */
kern_return_t
S_proc_getallpids (struct proc *p,
pid_t **pids,
- u_int *pidslen)
+ size_t *pidslen)
{
int nprocs;
pid_t *loc;
@@ -491,8 +530,12 @@ S_proc_getallpids (struct proc *p,
prociterate (count_up, &nprocs);
if (nprocs > *pidslen)
- vm_allocate (mach_task_self (), (vm_address_t *) pids,
- nprocs * sizeof (pid_t), 1);
+ {
+ *pids = mmap (0, nprocs * sizeof (pid_t), PROT_READ|PROT_WRITE,
+ MAP_ANON, 0, 0);
+ if (*pids == MAP_FAILED)
+ return ENOMEM;
+ }
loc = *pids;
prociterate (store_pid, &loc);
@@ -500,141 +543,151 @@ S_proc_getallpids (struct proc *p,
*pidslen = nprocs;
return 0;
}
-
+
/* Create a process for TASK, which is not otherwise known to us.
- The task will be placed as a child of init and in init's pgrp. */
+ The PID/parentage/job-control fields are not yet filled in,
+ and the proc is not entered into any hash table. */
struct proc *
-new_proc (task_t task)
+allocate_proc (task_t task)
{
+ error_t err;
struct proc *p;
- mach_port_t foo;
-
- /* Because these have a reference count of one before starting,
- they can never be freed, so we're safe. */
- static struct login *nulllogin;
- static struct ids nullids = {0, 0, 0, 0, 1};
-
- if (!nulllogin)
- {
- nulllogin = malloc (sizeof (struct login) + 7);
- nulllogin->l_refcnt = 1;
- strcpy (nulllogin->l_name, "<none>");
- }
/* Pid 0 is us; pid 1 is init. We handle those here specially;
all other processes inherit from init here (though proc_child
will move them to their actual parent usually). */
- ports_create_port (proc_class, proc_bucket, sizeof (struct proc), &p);
+ err = ports_create_port (proc_class, proc_bucket, sizeof (struct proc), &p);
+ if (err)
+ return NULL;
- p->p_pid = genpid ();
+ memset (&p->p_pi + 1, 0, sizeof *p - sizeof p->p_pi);
p->p_task = task;
+ p->p_msgport = MACH_PORT_NULL;
- mach_port_request_notification (mach_task_self (), p->p_task,
- MACH_NOTIFY_DEAD_NAME, 1, p->p_pi.port_right,
- MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo);
- if (foo != MACH_PORT_NULL)
- mach_port_deallocate (mach_task_self (), foo);
+ condition_init (&p->p_wakeup);
- switch (p->p_pid)
- {
- case 0:
- p->p_login = malloc (sizeof (struct login) + 5);
- p->p_login->l_refcnt = 1;
- strcpy (p->p_login->l_name, "root");
- break;
+ return p;
+}
- case 1:
- p->p_login = self_proc->p_login;
- p->p_login->l_refcnt++;
- break;
+/* Allocate and initialize the proc structure for init (PID 1),
+ the original parent of all other procs. */
+struct proc *
+create_startup_proc (void)
+{
+ static const uid_t zero;
+ struct proc *p;
+ const char *rootsname = "root";
- default:
- p->p_login = nulllogin;
- p->p_login->l_refcnt++;
- }
+ p = allocate_proc (MACH_PORT_NULL);
+ assert (p);
- p->p_owner = 0;
+ p->p_pid = 1;
- if (p->p_pid == 0)
- {
- uid_t foo = 0;
- p->p_id = make_ids (&foo, 1, &foo, 1);
- p->p_parent = p;
- p->p_sib = 0;
- p->p_prevsib = &p->p_ochild;
- p->p_ochild = p;
- p->p_loginleader = 1;
- p->p_parentset = 1;
- p->p_noowner = 0;
- }
- else if (p->p_pid == 1)
- {
- p->p_id = self_proc->p_id;
- p->p_id->i_refcnt++;
- p->p_parent = self_proc;
-
- p->p_sib = self_proc->p_ochild;
- p->p_prevsib = &self_proc->p_ochild;
- if (p->p_sib)
- p->p_sib->p_prevsib = &p->p_sib;
- self_proc->p_ochild = p;
- p->p_loginleader = 1;
- p->p_ochild = 0;
- p->p_parentset = 1;
- p->p_noowner = 0;
- }
- else
- {
- p->p_id = &nullids;
- p->p_id->i_refcnt++;
-
- /* Our parent is init for now */
- p->p_parent = startup_proc;
-
- p->p_sib = startup_proc->p_ochild;
- p->p_prevsib = &startup_proc->p_ochild;
- if (p->p_sib)
- p->p_sib->p_prevsib = &p->p_sib;
- startup_proc->p_ochild = p;
- p->p_loginleader = 0;
- p->p_ochild = 0;
- p->p_parentset = 0;
- p->p_noowner = 1;
- }
+ p->p_parent = p;
+ p->p_sib = 0;
+ p->p_prevsib = &p->p_ochild;
+ p->p_ochild = p;
+ p->p_parentset = 1;
- if (p->p_pid < 2)
- boot_setsid (p);
- else
- p->p_pgrp = startup_proc->p_pgrp;
+ p->p_deadmsg = 1; /* Force initial "re-"fetch of msgport. */
- p->p_msgport = MACH_PORT_NULL;
+ p->p_noowner = 0;
+ p->p_id = make_ids (&zero, 1);
+ assert (p->p_id);
- condition_init (&p->p_wakeup);
+ p->p_loginleader = 1;
+ p->p_login = malloc (sizeof (struct login) + strlen (rootsname) + 1);
+ assert (p->p_login);
- p->p_argv = p->p_envp = p->p_status = 0;
+ p->p_login->l_refcnt = 1;
+ strcpy (p->p_login->l_name, rootsname);
- p->p_exec = 0;
- p->p_stopped = 0;
- p->p_waited = 0;
- p->p_exiting = 0;
- p->p_waiting = 0;
- p->p_traced = 0;
- p->p_nostopcld = 0;
- p->p_deadmsg = (p->p_pid == 1);
- p->p_checkmsghangs = 0;
- p->p_msgportwait = 0;
- p->p_dead = 0;
-
- if (p->p_pid > 1)
+ boot_setsid (p);
+
+ return p;
+}
+
+/* Request a dead-name notification for P's task port. */
+
+void
+proc_death_notify (struct proc *p)
+{
+ error_t err;
+ mach_port_t old;
+
+ err = mach_port_request_notification (mach_task_self (), p->p_task,
+ MACH_NOTIFY_DEAD_NAME, 1,
+ p->p_pi.port_right,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &old);
+ assert_perror (err);
+
+ if (old != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), old);
+}
+
+/* Complete a new process that has been allocated but not entirely initialized.
+ This gets called for every process except startup_proc (PID 1). */
+void
+complete_proc (struct proc *p, pid_t pid)
+{
+ /* Because these have a reference count of one before starting,
+ they can never be freed, so we're safe. */
+ static struct login *nulllogin;
+ static struct ids nullids = { i_refcnt : 1, i_nuids : 0};
+ const char nullsname [] = "<none>";
+
+ if (!nulllogin)
{
- add_proc_to_hash (p);
- join_pgrp (p);
+ nulllogin = malloc (sizeof (struct login) + sizeof (nullsname) + 1);
+ nulllogin->l_refcnt = 1;
+ strcpy (nulllogin->l_name, nullsname);
}
- return p;
+ p->p_pid = pid;
+
+ ids_ref (&nullids);
+ p->p_id = &nullids;
+
+ p->p_login = nulllogin;
+ p->p_login->l_refcnt++;
+
+ /* Our parent is init for now. */
+ p->p_parent = startup_proc;
+
+ p->p_sib = startup_proc->p_ochild;
+ p->p_prevsib = &startup_proc->p_ochild;
+ if (p->p_sib)
+ p->p_sib->p_prevsib = &p->p_sib;
+ startup_proc->p_ochild = p;
+ p->p_loginleader = 0;
+ p->p_ochild = 0;
+ p->p_parentset = 0;
+
+ p->p_noowner = 1;
+
+ p->p_pgrp = startup_proc->p_pgrp;
+
+ proc_death_notify (p);
+ add_proc_to_hash (p);
+ join_pgrp (p);
}
+
+/* Create a process for TASK, which is not otherwise known to us
+ and initialize it in the usual ways. */
+static struct proc *
+new_proc (task_t task)
+{
+ struct proc *p;
+
+ p = allocate_proc (task);
+ if (p)
+ complete_proc (p, genpid ());
+ return p;
+}
+
/* The task associated with process P has died. Drop most state,
and then record us as dead. Our parent will eventually complete the
deallocation. */
@@ -657,20 +710,19 @@ process_has_exited (struct proc *p)
prociterate ((void (*) (struct proc *, void *))check_message_dying, p);
- /* Nuke external send rights and the (possible) associated reference */
+ /* Nuke external send rights and the (possible) associated reference. */
ports_destroy_right (p);
if (!--p->p_login->l_refcnt)
free (p->p_login);
- if (!--p->p_id->i_refcnt)
- free_ids (p->p_id);
+ ids_rele (p->p_id);
/* Reparent our children to init by attaching the head and tail
- of our list onto init's. */
+ of our list onto init's. */
if (p->p_ochild)
{
- struct proc *tp; /* will point to the last one */
+ struct proc *tp; /* will point to the last one. */
int isdead = 0;
/* first tell them their parent is changing */
@@ -690,7 +742,7 @@ process_has_exited (struct proc *p)
!tp->p_pgrp->pg_orphcnt);
tp->p_parent = startup_proc;
- /* And now nappend the lists. */
+ /* And now append the lists. */
tp->p_sib = startup_proc->p_ochild;
if (tp->p_sib)
tp->p_sib->p_prevsib = &tp->p_sib;
@@ -707,6 +759,9 @@ process_has_exited (struct proc *p)
condition_broadcast (&p->p_wakeup);
p->p_dead = 1;
+
+ /* Cancel any outstanding RPCs done on behalf of the dying process. */
+ ports_interrupt_rpcs (p);
}
void
@@ -717,7 +772,7 @@ complete_exit (struct proc *p)
remove_proc_from_hash (p);
if (p->p_task != MACH_PORT_NULL)
- mach_port_deallocate (mach_task_self (), p->p_task);
+ mach_port_destroy (mach_task_self (), p->p_task);
/* Remove us from our parent's list of children. */
if (p->p_sib)
@@ -740,7 +795,7 @@ struct proc *
add_tasks (task_t task)
{
mach_port_t *psets;
- u_int npsets;
+ size_t npsets;
int i;
struct proc *foundp = 0;
@@ -749,7 +804,7 @@ add_tasks (task_t task)
{
mach_port_t psetpriv;
mach_port_t *tasks;
- u_int ntasks;
+ size_t ntasks;
int j;
if (!foundp)
@@ -759,6 +814,12 @@ add_tasks (task_t task)
for (j = 0; j < ntasks; j++)
{
int set = 0;
+
+ /* The kernel can deliver us an array with null slots in the
+ middle, e.g. if a task died during the call. */
+ if (! MACH_PORT_VALID (tasks[j]))
+ continue;
+
if (!foundp)
{
struct proc *p = task_find_nocreate (tasks[j]);
@@ -773,19 +834,16 @@ add_tasks (task_t task)
if (!set)
mach_port_deallocate (mach_task_self (), tasks[j]);
}
- vm_deallocate (mach_task_self (), (vm_address_t) tasks,
- ntasks * sizeof (task_t));
+ munmap (tasks, ntasks * sizeof (task_t));
mach_port_deallocate (mach_task_self (), psetpriv);
}
mach_port_deallocate (mach_task_self (), psets[i]);
}
- vm_deallocate (mach_task_self (), (vm_address_t) psets,
- npsets * sizeof (mach_port_t));
+ munmap (psets, npsets * sizeof (mach_port_t));
return foundp;
}
-/* Allocate a new pid. The first two times this is called it must return
- 0 and 1 in order; after that it must simply return an unused pid.
+/* Allocate a new unused PID.
(Unused means it is neither the pid nor pgrp of any relevant data.) */
int
genpid ()
@@ -795,24 +853,16 @@ genpid ()
static int nextpid = 0;
static int wrap = WRAP_AROUND;
- int wrapped = 0;
-
- while (!pidfree (nextpid))
+ while (nextpid < wrap && !pidfree (nextpid))
+ ++nextpid;
+ if (nextpid >= wrap)
{
- ++nextpid;
- if (nextpid > wrap)
- {
- if (wrapped)
- {
- wrap *= 2;
- wrapped = 0;
- }
- else
- {
- nextpid = START_OVER;
- wrapped = 1;
- }
- }
+ nextpid = START_OVER;
+ while (!pidfree (nextpid))
+ nextpid++;
+
+ while (nextpid > wrap)
+ wrap *= 2;
}
return nextpid++;
diff --git a/proc/msg.c b/proc/msg.c
index fe173b68..ff1dbc54 100644
--- a/proc/msg.c
+++ b/proc/msg.c
@@ -1,5 +1,5 @@
/* Message port manipulations
- Copyright (C) 1994, 1995, 1996 Free Software Foundation
+ Copyright (C) 1994, 1995, 1996, 1999, 2001 Free Software Foundation
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -50,7 +50,6 @@ S_proc_setmsgport (struct proc *p,
mach_port_t *oldmsgport,
mach_msg_type_name_t *oldmsgport_type)
{
- mach_port_t foo;
if (!p)
return EOPNOTSUPP;
@@ -63,12 +62,6 @@ S_proc_setmsgport (struct proc *p,
prociterate (check_message_return, p);
p->p_checkmsghangs = 0;
- mach_port_request_notification (mach_task_self (), msgport,
- MACH_NOTIFY_DEAD_NAME, 1, p->p_pi.port_right,
- MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo);
- if (foo)
- mach_port_deallocate (mach_task_self (), foo);
-
if (p == startup_proc)
/* Init is single threaded, so we can't delay our reply for
the essential task RPC; spawn a thread to do it. */
@@ -89,6 +82,32 @@ check_message_dying (struct proc *p, struct proc *dyingp)
}
}
+/* Check if the message port of process P has died. Return nonzero if
+ this has indeed happened. */
+int
+check_msgport_death (struct proc *p)
+{
+ /* Only check if the message port passed away, if we know that it
+ was ever alive. */
+ if (p->p_msgport != MACH_PORT_NULL)
+ {
+ mach_port_type_t type;
+ error_t err;
+
+ err = mach_port_type (mach_task_self (), p->p_msgport, &type);
+ if (err || (type & MACH_PORT_TYPE_DEAD_NAME))
+ {
+ /* The port appears to be dead; throw it away. */
+ mach_port_deallocate (mach_task_self (), p->p_msgport);
+ p->p_msgport = MACH_PORT_NULL;
+ p->p_deadmsg = 1;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
error_t
S_proc_getmsgport (struct proc *callerp,
mach_port_t reply_port,
@@ -97,11 +116,14 @@ S_proc_getmsgport (struct proc *callerp,
mach_port_t *msgport)
{
int cancel;
- struct proc *p = pid_find_allow_zombie (pid);
+ struct proc *p;
if (!callerp)
return EOPNOTSUPP;
-
+
+ p = pid_find_allow_zombie (pid);
+
+restart:
while (p && p->p_deadmsg && !p->p_dead)
{
callerp->p_msgportwait = 1;
@@ -119,15 +141,10 @@ S_proc_getmsgport (struct proc *callerp,
if (!p)
return ESRCH;
+ if (check_msgport_death (p))
+ goto restart;
+
*msgport = p->p_msgport;
- return 0;
-}
-void
-message_port_dead (struct proc *p)
-{
- mach_port_deallocate (mach_task_self (), p->p_msgport);
- p->p_msgport = MACH_PORT_NULL;
- p->p_deadmsg = 1;
+ return 0;
}
-
diff --git a/proc/notify.c b/proc/notify.c
index 9d48d945..5a112b07 100644
--- a/proc/notify.c
+++ b/proc/notify.c
@@ -1,5 +1,5 @@
/* Handle notifications
- Copyright (C) 1992, 1993, 1994, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1992, 1993, 1994, 1996, 1999 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -44,6 +44,7 @@ do_mach_notify_dead_name (mach_port_t notify,
if (notify == generic_port)
{
check_dead_execdata_notify (deadport);
+ mach_port_deallocate (mach_task_self (), deadport);
return 0;
}
@@ -52,16 +53,11 @@ do_mach_notify_dead_name (mach_port_t notify,
if (!p)
return EOPNOTSUPP;
- if (p->p_msgport == deadport)
- {
- message_port_dead (p);
- ports_port_deref (p);
- return 0;
- }
- else if (p->p_task == deadport)
+ if (p->p_task == deadport)
{
process_has_exited (p);
ports_port_deref (p);
+ mach_port_deallocate (mach_task_self (), deadport);
return 0;
}
else
diff --git a/proc/pgrp.c b/proc/pgrp.c
index 224f7e52..2d6ca93a 100644
--- a/proc/pgrp.c
+++ b/proc/pgrp.c
@@ -1,5 +1,5 @@
-/* Session and process group manipulation
- Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+/* Session and process group manipulation
+ Copyright (C) 1992,93,94,95,96,99,2001,02 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -8,7 +8,7 @@ it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-The GNU Hurd is distributed in the hope that it will be useful,
+The GNU Hurd 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.
@@ -25,6 +25,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <sys/errno.h>
#include <stdlib.h>
#include <signal.h>
+#include <assert.h>
#include "proc.h"
#include "process_S.h"
@@ -37,19 +38,22 @@ new_pgrp (pid_t pgid,
struct session *sess)
{
struct pgrp *pg;
-
+
pg = malloc (sizeof (struct pgrp));
+ if (! pg)
+ return NULL;
+
pg->pg_plist = 0;
pg->pg_pgid = pgid;
pg->pg_orphcnt = 0;
-
+
pg->pg_session = sess;
pg->pg_next = sess->s_pgrps;
if (pg->pg_next)
pg->pg_next->pg_prevp = &pg->pg_next;
sess->s_pgrps = pg;
pg->pg_prevp = &sess->s_pgrps;
-
+
add_pgrp_to_hash (pg);
return pg;
}
@@ -59,14 +63,17 @@ static inline struct session *
new_session (struct proc *p)
{
struct session *sess;
-
+
sess = malloc (sizeof (struct session));
+ if (! sess)
+ return NULL;
+
sess->s_sid = p->p_pid;
sess->s_pgrps = 0;
sess->s_sessionid = MACH_PORT_NULL;
add_session_to_hash (sess);
-
+
return sess;
}
@@ -93,21 +100,21 @@ free_pgrp (struct pgrp *pg)
remove_pgrp_from_hash (pg);
free (pg);
}
-
-/* Implement proc_setsid as described in <hurd/proc.defs>. */
+
+/* Implement proc_setsid as described in <hurd/process.defs>. */
kern_return_t
S_proc_setsid (struct proc *p)
{
struct session *sess;
-
+
if (!p)
return EOPNOTSUPP;
-
+
if (p->p_pgrp->pg_pgid == p->p_pid || pgrp_find (p->p_pid))
return EPERM;
-
+
leave_pgrp (p);
-
+
sess = new_session (p);
p->p_pgrp= new_pgrp (p->p_pid, sess);
join_pgrp (p);
@@ -120,14 +127,15 @@ void
boot_setsid (struct proc *p)
{
struct session *sess;
-
+
sess = new_session (p);
p->p_pgrp = new_pgrp (p->p_pid, sess);
+ assert (p->p_pgrp);
join_pgrp (p);
return;
}
-/* Implement proc_getsid as described in <hurd/proc.defs>. */
+/* Implement proc_getsid as described in <hurd/process.defs>. */
kern_return_t
S_proc_getsid (struct proc *callerp,
pid_t pid,
@@ -143,12 +151,12 @@ S_proc_getsid (struct proc *callerp,
return 0;
}
-/* Implement proc_getsessionpids as described in <hurd/proc.defs>. */
+/* Implement proc_getsessionpids as described in <hurd/process.defs>. */
kern_return_t
S_proc_getsessionpids (struct proc *callerp,
pid_t sid,
pid_t **pids,
- u_int *npidsp)
+ size_t *npidsp)
{
int count;
struct pgrp *pg;
@@ -156,13 +164,13 @@ S_proc_getsessionpids (struct proc *callerp,
struct session *s;
pid_t *pp = *pids;
u_int npids = *npidsp;
-
+
/* No need to check CALLERP; we don't use it. */
s = session_find (sid);
if (!s)
return ESRCH;
-
+
count = 0;
for (pg = s->s_pgrps; pg; pg = pg->pg_next)
for (p = pg->pg_plist; p; p = p->p_gnext)
@@ -170,12 +178,15 @@ S_proc_getsessionpids (struct proc *callerp,
if (++count <= npids)
*pp++ = p->p_pid;
}
-
+
if (count > npids)
/* They didn't all fit */
{
- vm_allocate (mach_task_self (), (vm_address_t *)pids,
- count * sizeof (pid_t), 1);
+ *pids = mmap (0, count * sizeof (pid_t), PROT_READ|PROT_WRITE,
+ MAP_ANON, 0, 0);
+ if (*pids == MAP_FAILED)
+ return errno;
+
pp = *pids;
for (pg = s->s_pgrps; pg; pg = pg->pg_next)
for (p = pg->pg_plist; p; p = p->p_gnext)
@@ -192,14 +203,14 @@ kern_return_t
S_proc_getsessionpgids (struct proc *callerp,
pid_t sid,
pid_t **pgids,
- u_int *npgidsp)
+ size_t *npgidsp)
{
int count;
struct pgrp *pg;
struct session *s;
pid_t *pp = *pgids;
int npgids = *npgidsp;
-
+
/* No need to check CALLERP; we don't use it. */
s = session_find (sid);
@@ -210,12 +221,15 @@ S_proc_getsessionpgids (struct proc *callerp,
for (pg = s->s_pgrps; pg; pg = pg->pg_next)
if (++count <= npgids)
*pp++ = pg->pg_pgid;
-
+
if (count > npgids)
/* They didn't all fit. */
{
- vm_allocate (mach_task_self (), (vm_address_t *)pgids,
- count * sizeof (pid_t), 1);
+ *pgids = mmap (0, count * sizeof (pid_t), PROT_READ|PROT_WRITE,
+ MAP_ANON, 0, 0);
+ if (*pgids == MAP_FAILED)
+ return errno;
+
pp = *pgids;
for (pg = s->s_pgrps; pg; pg = pg->pg_next)
*pp++ = pg->pg_pgid;
@@ -230,14 +244,14 @@ kern_return_t
S_proc_getpgrppids (struct proc *callerp,
pid_t pgid,
pid_t **pids,
- u_int *npidsp)
+ size_t *npidsp)
{
struct proc *p;
struct pgrp *pg;
pid_t *pp = *pids;
unsigned int npids = *npidsp, count;
-
+
/* No need to check CALLERP; we don't use it. */
if (pgid == 0)
@@ -253,12 +267,15 @@ S_proc_getpgrppids (struct proc *callerp,
for (p = pg->pg_plist; p; p = p->p_gnext)
if (++count <= npids)
*pp++ = p->p_pid;
-
+
if (count > npids)
/* They didn't all fit. */
{
- vm_allocate (mach_task_self (), (vm_address_t *)pids,
- count * sizeof (pid_t), 1);
+ *pids = mmap (0, count * sizeof (pid_t), PROT_READ|PROT_WRITE,
+ MAP_ANON, 0, 0);
+ if (*pids == MAP_FAILED)
+ return errno;
+
pp = *pids;
for (p = pg->pg_plist; p; p = p->p_gnext)
*pp++ = p->p_pid;
@@ -268,13 +285,13 @@ S_proc_getpgrppids (struct proc *callerp,
return 0;
}
-/* Implement proc_getsidport as described in <hurd/proc.defs>. */
+/* Implement proc_getsidport as described in <hurd/process.defs>. */
kern_return_t
S_proc_getsidport (struct proc *p,
mach_port_t *sessport, mach_msg_type_name_t *sessport_type)
{
error_t err = 0;
-
+
if (!p)
return EOPNOTSUPP;
@@ -291,7 +308,7 @@ S_proc_getsidport (struct proc *p,
return err;
}
-/* Implement proc_setpgrp as described in <hurd/proc.defs>. */
+/* Implement proc_setpgrp as described in <hurd/process.defs>. */
kern_return_t
S_proc_setpgrp (struct proc *callerp,
pid_t pid,
@@ -299,7 +316,7 @@ S_proc_setpgrp (struct proc *callerp,
{
struct proc *p;
struct pgrp *pg;
-
+
if (!callerp)
return EOPNOTSUPP;
@@ -307,10 +324,10 @@ S_proc_setpgrp (struct proc *callerp,
if (!p || (p != callerp && p->p_parent != callerp))
return ESRCH;
-
+
if (p->p_parent == callerp && p->p_exec)
return EACCES;
-
+
if (!pgid)
pgid = p->p_pid;
pg = pgrp_find (pgid);
@@ -320,7 +337,7 @@ S_proc_setpgrp (struct proc *callerp,
|| ((pgid != p->p_pid
&& (!pg || pg->pg_session != callerp->p_pgrp->pg_session))))
return EPERM;
-
+
if (p->p_pgrp != pg)
{
leave_pgrp (p);
@@ -330,11 +347,11 @@ S_proc_setpgrp (struct proc *callerp,
else
nowait_msg_proc_newids (p->p_msgport, p->p_task, p->p_parent->p_pid,
pg->pg_pgid, !pg->pg_orphcnt);
-
+
return 0;
}
-/* Implement proc_getpgrp as described in <hurd/proc.defs>. */
+/* Implement proc_getpgrp as described in <hurd/process.defs>. */
kern_return_t
S_proc_getpgrp (struct proc *callerp,
pid_t pid,
@@ -343,17 +360,17 @@ S_proc_getpgrp (struct proc *callerp,
struct proc *p = pid_find (pid);
/* No need to check CALLERP; we don't use it. */
-
+
if (!p)
return ESRCH;
-
+
if (p->p_pgrp)
*pgid = p->p_pgrp->pg_pgid;
-
+
return 0;
}
-/* Implement proc_mark_exec as described in <hurd/proc.defs>. */
+/* Implement proc_mark_exec as described in <hurd/process.defs>. */
kern_return_t
S_proc_mark_exec (struct proc *p)
{
@@ -375,7 +392,7 @@ leave_pgrp (struct proc *p)
*p->p_gprevp = p->p_gnext;
if (p->p_gnext)
p->p_gnext->p_gprevp = p->p_gprevp;
-
+
/* If we were the last member of our pgrp, free it */
if (!pg->pg_plist)
free_pgrp (pg);
@@ -387,7 +404,7 @@ leave_pgrp (struct proc *p)
an orphaned process group -- do the orphaning gook */
struct proc *ip;
int dosignal = 0;
-
+
for (ip = pg->pg_plist; ip; ip = ip->p_gnext)
{
if (ip->p_stopped)
@@ -418,7 +435,7 @@ join_pgrp (struct proc *p)
if (pg->pg_plist)
pg->pg_plist->p_gprevp = &p->p_gnext;
pg->pg_plist = p;
-
+
origorphcnt = !!pg->pg_orphcnt;
if (p->p_parent->p_pgrp != pg
&& p->p_parent->p_pgrp->pg_session == pg->pg_session)
diff --git a/proc/primes.c b/proc/primes.c
deleted file mode 100644
index d0fc4d0c..00000000
--- a/proc/primes.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Prime number generation
- Copyright (C) 1994 Free Software Foundation
-
- 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 2, 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, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include <stdlib.h>
-#include <limits.h>
-#include <string.h>
-#include <assert.h>
-
-#define BITS_PER_UNSIGNED (8 * sizeof (unsigned))
-#define SQRT_INT_MAX (1 << (BITS_PER_UNSIGNED / 2))
-
-/* Return the next prime greater than or equal to N. */
-int
-nextprime (unsigned n)
-{
- /* Among other things, We guarantee that, for all i (0 <= i < primes_len),
- primes[i] is a prime,
- next_multiple[i] is a multiple of primes[i],
- next_multiple[i] > primes[primes_len - 1],
- next_multiple[i] is not a multiple of two unless primes[i] == 2, and
- next_multiple[i] is the smallest such value. */
- static unsigned *primes, *next_multiple;
- static int primes_len;
- static int primes_size;
- static unsigned next_sieve; /* always even */
- unsigned max_prime;
-
- if (! primes)
- {
- primes_size = 128;
- primes = (unsigned *) malloc (primes_size * sizeof (*primes));
- next_multiple = (unsigned *) malloc (primes_size
- * sizeof (*next_multiple));
-
- primes[0] = 2; next_multiple[0] = 6;
- primes[1] = 3; next_multiple[1] = 9;
- primes[2] = 5; next_multiple[2] = 15;
- primes_len = 3;
-
- next_sieve = primes[primes_len - 1] + 1;
- }
-
- if (n <= primes[0])
- return primes[0];
-
- while (n > (max_prime = primes[primes_len - 1]))
- {
- /* primes doesn't contain any prime large enough. Sieve from
- max_prime + 1 to 2 * max_prime, looking for more primes. */
- unsigned start = next_sieve;
- unsigned end = start + max_prime + 1;
- char *sieve = (char *) alloca ((end - start) * sizeof (*sieve));
- int i;
-
- assert (sieve);
-
- bzero (sieve, (end - start) * sizeof (*sieve));
-
- /* Make the sieve indexed by prime number, rather than
- distance-from-start-to-the-prime-number. When we're done,
- sieve[P] will be zero iff P is prime.
-
- ANSI C doesn't define what this means. Fuck them. */
- sieve -= start;
-
- /* Set sieve[i] for all composites i, start <= i < end.
- Ignore multiples of 2. */
- for (i = 1; i < primes_len; i++)
- {
- unsigned twice_prime = 2 * primes[i];
- unsigned multiple;
-
- for (multiple = next_multiple[i];
- multiple < end;
- multiple += twice_prime)
- sieve[multiple] = 1;
- next_multiple[i] = multiple;
- }
-
- for (i = start + 1; i < end; i += 2)
- if (! sieve[i])
- {
- if (primes_len >= primes_size)
- {
- primes_size *= 2;
- primes = (int *) realloc (primes,
- primes_size * sizeof (*primes));
- next_multiple
- = (int *) realloc (next_multiple,
- primes_size * sizeof (*next_multiple));
- }
- primes[primes_len] = i;
- if (i >= SQRT_INT_MAX)
- next_multiple[primes_len] = INT_MAX;
- else
- next_multiple[primes_len] = i * i;
- primes_len++;
- }
-
- next_sieve = end;
- }
-
- /* Now we have at least one prime >= n. Find the smallest such. */
- {
- int bottom = 0;
- int top = primes_len;
-
- while (bottom < top)
- {
- int mid = (bottom + top) / 2;
-
- if (primes[mid] < n)
- bottom = mid + 1;
- else
- top = mid;
- }
-
- return primes[top];
- }
-}
-
diff --git a/proc/proc.h b/proc/proc.h
index 30886487..7943e0be 100644
--- a/proc/proc.h
+++ b/proc/proc.h
@@ -1,5 +1,5 @@
/* Process server definitions
- Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1992,93,94,95,96,99,2000,01 Free Software Foundation, Inc.
This file is part of the GNU Hurd.
@@ -23,7 +23,9 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define PROC_H_INCLUDED
#include <sys/resource.h>
+#include <sys/mman.h>
#include <hurd/ports.h>
+#include <hurd/ihash.h>
#include <cthreads.h>
struct proc
@@ -34,8 +36,8 @@ struct proc
struct proc *p_gnext, **p_gprevp; /* process group */
/* Hash table pointers that point here */
- void **p_pidhashloc; /* by pid */
- void **p_taskhashloc; /* by task port */
+ hurd_ihash_locp_t p_pidhashloc; /* by pid */
+ hurd_ihash_locp_t p_taskhashloc; /* by task port */
/* Identification of this process */
task_t p_task;
@@ -64,28 +66,31 @@ struct proc
vm_address_t p_argv, p_envp;
int p_status; /* to return via wait */
int p_sigcode;
-
- int p_exec:1; /* has called proc_mark_exec */
- int p_stopped:1; /* has called proc_mark_stop */
- int p_waited:1; /* stop has been reported to parent */
- int p_exiting:1; /* has called proc_mark_exit */
- int p_waiting:1; /* blocked in wait */
- int p_traced:1; /* has called proc_mark_traced */
- int p_nostopcld:1; /* has called proc_mark_nostopchild */
- int p_parentset:1; /* has had a parent set with proc_child */
- int p_deadmsg:1; /* hang on requests for a message port */
- int p_checkmsghangs:1; /* someone is currently hanging on us */
- int p_msgportwait:1; /* blocked in getmsgport */
- int p_noowner:1; /* has no owner known */
- int p_loginleader:1; /* leader of login collection */
- int p_dead:1; /* process is dead */
+ struct rusage p_rusage; /* my usage if I'm dead, to return via wait */
+
+ struct rusage p_child_rusage; /* accumulates p_rusage of all dead children */
+
+ unsigned int p_exec:1; /* has called proc_mark_exec */
+ unsigned int p_stopped:1; /* has called proc_mark_stop */
+ unsigned int p_waited:1; /* stop has been reported to parent */
+ unsigned int p_exiting:1; /* has called proc_mark_exit */
+ unsigned int p_waiting:1; /* blocked in wait */
+ unsigned int p_traced:1; /* has called proc_mark_traced */
+ unsigned int p_nostopcld:1; /* has called proc_mark_nostopchild */
+ unsigned int p_parentset:1; /* has had a parent set with proc_child */
+ unsigned int p_deadmsg:1; /* hang on requests for a message port */
+ unsigned int p_checkmsghangs:1; /* someone is currently hanging on us */
+ unsigned int p_msgportwait:1; /* blocked in getmsgport */
+ unsigned int p_noowner:1; /* has no owner known */
+ unsigned int p_loginleader:1; /* leader of login collection */
+ unsigned int p_dead:1; /* process is dead */
};
typedef struct proc *pstruct_t;
struct pgrp
{
- void **pg_hashloc;
+ hurd_ihash_locp_t pg_hashloc;
struct proc *pg_plist; /* member processes */
struct pgrp *pg_next, **pg_prevp; /* list of pgrps in session */
pid_t pg_pgid;
@@ -95,7 +100,7 @@ struct pgrp
struct session
{
- void **s_hashloc;
+ hurd_ihash_locp_t s_hashloc;
pid_t s_sid;
struct pgrp *s_pgrps; /* list of member pgrps */
mach_port_t s_sessionid; /* receive right */
@@ -109,10 +114,9 @@ struct login
struct ids
{
- int i_nuids, i_ngids;
- uid_t *i_uids;
- gid_t *i_gids;
int i_refcnt;
+ int i_nuids;
+ uid_t i_uids[0];
};
/* Structure for an exception port we are listening on. */
@@ -143,11 +147,7 @@ mach_port_t generic_port; /* messages not related to a specific proc */
struct mutex global_lock;
-/* Our name for version system */
-#define OUR_SERVER_NAME "proc"
-#define OUR_VERSION "0.0"
-
-extern inline void
+static inline void __attribute__ ((unused))
process_drop (struct proc *p)
{
if (p)
@@ -156,7 +156,6 @@ process_drop (struct proc *p)
/* Forward declarations */
void complete_wait (struct proc *, int);
-int nextprime (int);
int check_uid (struct proc *, uid_t);
void addalltasks (void);
void prociterate (void (*)(struct proc *, void *), void *);
@@ -169,7 +168,7 @@ int genpid ();
void abort_getmsgport (struct proc *);
int zombie_check_pid (pid_t);
void check_message_dying (struct proc *, struct proc *);
-void message_port_dead (struct proc *);
+int check_msgport_death (struct proc *);
void check_dead_execdata_notify (mach_port_t);
void add_proc_to_hash (struct proc *);
@@ -194,7 +193,10 @@ void exc_clean (void *);
struct proc *add_tasks (task_t);
int pidfree (pid_t);
-struct proc *new_proc (task_t);
+struct proc *create_startup_proc (void);
+struct proc *allocate_proc (task_t);
+void proc_death_notify (struct proc *);
+void complete_proc (struct proc *, pid_t);
void leave_pgrp (struct proc *);
void join_pgrp (struct proc *);
@@ -208,17 +210,6 @@ void complete_exit (struct proc *);
void initialize_version_info (void);
void send_signal (mach_port_t, int, mach_port_t);
-
-/* Returns true if PROC1 has `owner' privileges over PROC2 (and can thus get
- its task port &c). If PROC2 has an owner, then PROC1 must have that uid;
- otherwise, both must be in the same login collection. */
-extern inline int
-check_owner (struct proc *proc1, struct proc *proc2)
-{
- return
- proc2->p_noowner
- ? check_uid (proc1, 0) || proc1->p_login == proc2->p_login
- : check_uid (proc1, proc2->p_owner);
-}
+
#endif
diff --git a/proc/stubs.c b/proc/stubs.c
index d43f2ea5..de3a9b11 100644
--- a/proc/stubs.c
+++ b/proc/stubs.c
@@ -1,5 +1,5 @@
/* By-hand stubs for some RPC calls
- Copyright (C) 1994, 1996 Free Software Foundation
+ Copyright (C) 1994,96,99,2000 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -20,28 +20,55 @@
#include <hurd/hurd_types.h>
#include <mach/message.h>
#include <string.h>
+#include <assert.h>
#include "proc.h"
/* From hurd/msg.defs: */
#define RPCID_SIG_POST 23000
-struct msg_spec
+
+struct msg_sig_post_request
{
- int len;
- void *contents;
+ mach_msg_header_t head;
+ mach_msg_type_t signaltype;
+ int signal;
+ mach_msg_type_t sigcode_type;
+ natural_t sigcode;
+ mach_msg_type_t refporttype;
+ mach_port_t refport;
};
-/* Send the Mach message indicated by msg_spec; call cthread_exit
+/* Send the Mach message indicated by msg_spec. call cthread_exit
when it has been delivered. */
-static void
-blocking_message_send (struct msg_spec *message)
+static any_t
+blocking_message_send (any_t arg)
{
- cthread_wire ();
- mach_msg ((mach_msg_header_t *)message->contents, MACH_SEND_MSG,
- message->len, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
- MACH_PORT_NULL);
- cthread_exit (0);
+ struct msg_sig_post_request *const req = arg;
+ error_t err;
+
+ err = mach_msg (&req->head, MACH_SEND_MSG, sizeof *req, 0,
+ MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+
+ switch (err)
+ {
+ /* These are the codes that mean a pseudo-receive modified
+ the message buffer and we might need to clean up the send rights.
+ None of them should be possible in our usage. */
+ case MACH_SEND_TIMED_OUT:
+ case MACH_SEND_INTERRUPTED:
+ case MACH_SEND_INVALID_NOTIFY:
+ case MACH_SEND_NO_NOTIFY:
+ case MACH_SEND_NOTIFY_IN_PROGRESS:
+ assert_perror (err);
+ break;
+
+ default: /* Other errors are safe to ignore. */
+ break;
+ }
+
+
+ return 0;
}
/* Send signal SIGNO to MSGPORT with REFPORT as reference. Don't
@@ -53,84 +80,89 @@ send_signal (mach_port_t msgport,
{
error_t err;
- static struct
+ /* This message buffer might be modified by mach_msg in some error cases,
+ so we cannot safely use a shared static buffer. */
+ struct msg_sig_post_request message =
+ {
{
- mach_msg_header_t head;
- mach_msg_type_t signaltype;
- int signal;
- mach_msg_type_t sigcode_type;
- natural_t sigcode;
- mach_msg_type_t refporttype;
- mach_port_t refport;
- }
- message =
+ /* Message header: */
+ (MACH_MSGH_BITS_COMPLEX
+ | MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE)), /* msgh_bits */
+ sizeof message, /* msgh_size */
+ msgport, /* msgh_remote_port */
+ MACH_PORT_NULL, /* msgh_local_port */
+ 0, /* msgh_seqno */
+ RPCID_SIG_POST, /* msgh_id */
+ },
{
- {
- /* Message header: */
- (MACH_MSGH_BITS_COMPLEX
- | MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND,
- MACH_MSG_TYPE_MAKE_SEND_ONCE)), /* msgh_bits */
- sizeof message, /* msgh_size */
- 0, /* msgh_remote_port */
- MACH_PORT_NULL, /* msgh_local_port */
- 0, /* msgh_seqno */
- RPCID_SIG_POST, /* msgh_id */
- },
- {
- /* Type descriptor for signo */
- MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
- 32, /* msgt_size */
- 1, /* msgt_number */
- 1, /* msgt_inline */
- 0, /* msgt_longform */
- 0, /* msgt_deallocate */
- 0, /* msgt_unused */
- },
- /* Signal number */
- 0,
- /* Type descriptor for sigcode */
- {
- MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
- 32, /* msgt_size */
- 1, /* msgt_number */
- 1, /* msgt_inline */
- 0, /* msgt_longform */
- 0, /* msgt_deallocate */
- 0, /* msgt_unused */
- },
- /* Sigcode */
- 0,
- {
- /* Type descriptor for refport */
- MACH_MSG_TYPE_COPY_SEND, /* msgt_name */
- 32, /* msgt_size */
- 1, /* msgt_number */
- 1, /* msgt_unline */
- 0, /* msgt_longform */
- 0, /* msgt_deallocate */
- 0, /* msgt_unused */
- },
- /* Reference port */
- MACH_PORT_NULL,
- };
-
- message.head.msgh_remote_port = msgport;
- message.signal = signal;
- message.refport = refport;
-
- err = mach_msg((mach_msg_header_t *)&message,
- MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof message, 0,
- MACH_PORT_NULL, 0, MACH_PORT_NULL);
-
- if (err == MACH_SEND_TIMEOUT)
+ /* Type descriptor for signo */
+ MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
+ 32, /* msgt_size */
+ 1, /* msgt_number */
+ 1, /* msgt_inline */
+ 0, /* msgt_longform */
+ 0, /* msgt_deallocate */
+ 0, /* msgt_unused */
+ },
+ /* Signal number */
+ signal,
+ /* Type descriptor for sigcode */
+ {
+ MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
+ 32, /* msgt_size */
+ 1, /* msgt_number */
+ 1, /* msgt_inline */
+ 0, /* msgt_longform */
+ 0, /* msgt_deallocate */
+ 0, /* msgt_unused */
+ },
+ /* Sigcode */
+ 0,
{
- struct msg_spec *msg_spec = malloc (sizeof (struct msg_spec));
-
- msg_spec->len = sizeof message;
- msg_spec->contents = malloc (sizeof message);
- bcopy (&message, msg_spec->contents, sizeof message);
-
- cthread_detach (cthread_fork ((cthread_fn_t) blocking_message_send,
- msg_spec));
+ /* Type descriptor for refport */
+ MACH_MSG_TYPE_COPY_SEND, /* msgt_name */
+ 32, /* msgt_size */
+ 1, /* msgt_number */
+ 1, /* msgt_inline */
+ 0, /* msgt_longform */
+ 0, /* msgt_deallocate */
+ 0, /* msgt_unused */
+ },
+ refport
+ };
+
+ err = mach_msg ((mach_msg_header_t *)&message,
+ MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof message, 0,
+ MACH_PORT_NULL, 0, MACH_PORT_NULL);
+ switch (err)
+ {
+ case MACH_SEND_TIMED_OUT:
+ /* The send could not complete immediately, and we do not want to
+ block. We'll fork off another thread to do the blocking send.
+ The message buffer was modified by a pseudo-receive operation, so
+ we need to copy its modified contents into a malloc'd buffer. */
+ {
+ struct msg_sig_post_request *copy = malloc (sizeof *copy);
+ if (copy)
+ {
+ memcpy (copy, &message, sizeof message);
+ cthread_detach (cthread_fork (blocking_message_send, copy));
+ }
+ break;
+ }
+
+ /* These are the other codes that mean a pseudo-receive modified
+ the message buffer and we might need to clean up the send rights.
+ None of them should be possible in our usage. */
+ case MACH_SEND_INTERRUPTED:
+ case MACH_SEND_INVALID_NOTIFY:
+ case MACH_SEND_NO_NOTIFY:
+ case MACH_SEND_NOTIFY_IN_PROGRESS:
+ assert_perror (err);
+ break;
+
+ default: /* Other errors are safe to ignore. */
+ break;
}
}
diff --git a/proc/wait.c b/proc/wait.c
index 60ec58ff..6fc94e83 100644
--- a/proc/wait.c
+++ b/proc/wait.c
@@ -1,5 +1,5 @@
/* Implementation of wait
- Copyright (C) 1994, 1995, 1996 Free Software Foundation
+ Copyright (C) 1994, 1995, 1996, 2001 Free Software Foundation
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -19,6 +19,8 @@
#include <sys/types.h>
#include <hurd/hurd_types.h>
#include <sys/resource.h>
+#include <sys/time.h>
+#include <mach/task_info.h>
#include "proc.h"
@@ -32,7 +34,95 @@
#include "process_S.h"
#include <mach/mig_errors.h>
-#define EWOULDBLOCK EAGAIN /* XXX */
+static inline void
+rusage_add (struct rusage *acc, const struct rusage *b)
+{
+ timeradd (&acc->ru_utime, &b->ru_utime, &acc->ru_utime);
+ timeradd (&acc->ru_stime, &b->ru_stime, &acc->ru_stime);
+
+ /* Check <bits/resource.h> definition of `struct rusage'
+ to make sure this gets all the fields. */
+ acc->ru_maxrss += b->ru_maxrss;
+ acc->ru_ixrss += b->ru_ixrss;
+ acc->ru_idrss += b->ru_idrss;
+ acc->ru_isrss += b->ru_isrss;
+ acc->ru_minflt += b->ru_minflt;
+ acc->ru_majflt += b->ru_majflt;
+ acc->ru_nswap += b->ru_nswap;
+ acc->ru_inblock += b->ru_inblock;
+ acc->ru_oublock += b->ru_oublock;
+ acc->ru_msgsnd += b->ru_msgsnd;
+ acc->ru_msgrcv += b->ru_msgrcv;
+ acc->ru_nsignals += b->ru_nsignals;
+ acc->ru_nvcsw += b->ru_nvcsw;
+ acc->ru_nivcsw += b->ru_nivcsw;
+}
+
+/* XXX This is real half-assed.
+
+ We want to collect usage statistics from dead processes to return to its
+ parent for its proc_wait calls and its aggregate child statistics.
+
+ The microkernel provides no access to this information once the task is
+ terminated. So the best we can do is take a sample at some time while
+ the task is still alive but not too long before it dies. Our results
+ are always inaccurate, because they don't account for the final part of
+ the task's lifetime. But perhaps it's better than nothing at all.
+
+ The obvious place to take this sample is in proc_mark_exit, which in
+ normal circumstances a task is calling immediately before terminating
+ itself. So in the best of cases, our data omits only the interval in
+ which our RPC returns to the task and it calls task_terminate. We could
+ take samples in other places just to have something rather than nothing
+ if the task dies unexpectedly (e.g. SIGKILL); but it may not be worthwhile
+ since the end result is never going to be accurate anyway.
+
+ The only way to get correct results is by adding some microkernel
+ feature to report the task statistics data post-mortem. */
+
+void
+sample_rusage (struct proc *p)
+{
+ struct task_basic_info bi;
+ struct task_events_info ei;
+ struct task_thread_times_info tti;
+ mach_msg_type_number_t count;
+ error_t err;
+
+ count = TASK_BASIC_INFO_COUNT;
+ err = task_info (p->p_task, TASK_BASIC_INFO,
+ (task_info_t) &bi, &count);
+ if (err)
+ memset (&bi, 0, sizeof bi);
+
+ count = TASK_EVENTS_INFO_COUNT;
+ err = task_info (p->p_task, TASK_EVENTS_INFO,
+ (task_info_t) &ei, &count);
+ if (err)
+ memset (&ei, 0, sizeof ei);
+
+ count = TASK_THREAD_TIMES_INFO_COUNT;
+ err = task_info (p->p_task, TASK_THREAD_TIMES_INFO,
+ (task_info_t) &tti, &count);
+ if (err)
+ memset (&tti, 0, sizeof tti);
+
+ time_value_add (&bi.user_time, &tti.user_time);
+ time_value_add (&bi.system_time, &tti.system_time);
+
+ memset (&p->p_rusage, 0, sizeof (struct rusage));
+
+ p->p_rusage.ru_utime.tv_sec = bi.user_time.seconds;
+ p->p_rusage.ru_utime.tv_usec = bi.user_time.microseconds;
+ p->p_rusage.ru_stime.tv_sec = bi.system_time.seconds;
+ p->p_rusage.ru_stime.tv_usec = bi.system_time.microseconds;
+
+ /* These statistics map only approximately. */
+ p->p_rusage.ru_majflt = ei.pageins;
+ p->p_rusage.ru_minflt = ei.faults - ei.pageins;
+ p->p_rusage.ru_msgsnd = ei.messages_sent; /* Mach IPC, not SysV IPC */
+ p->p_rusage.ru_msgrcv = ei.messages_received; /* ditto */
+}
/* Return nonzero if a `waitpid' on WAIT_PID by a process
in MYPGRP cares about the death of PID/PGRP. */
@@ -46,11 +136,14 @@ waiter_cares (pid_t wait_pid, pid_t mypgrp,
(wait_pid == WAIT_MYPGRP && pgrp == mypgrp));
}
-/* A process is dying. Send SIGCHLD to the parent. Wake the parent
-if it is waiting for us to exit. */
+/* A process is dying. Send SIGCHLD to the parent.
+ Wake the parent if it is waiting for us to exit. */
void
alert_parent (struct proc *p)
{
+ /* We accumulate the aggregate usage stats of all our dead children. */
+ rusage_add (&p->p_parent->p_child_rusage, &p->p_rusage);
+
send_signal (p->p_parent->p_msgport, SIGCHLD, p->p_parent->p_task);
if (!p->p_exiting)
@@ -78,73 +171,59 @@ S_proc_wait (struct proc *p,
pid_t *pid_status)
{
int cancel;
-
- int child_ready (struct proc *child)
+
+ int reap (struct proc *child)
{
- if (child->p_waited)
+ if (child->p_waited
+ || (!child->p_dead
+ && (!child->p_stopped
+ || !(child->p_traced || (options & WUNTRACED)))))
return 0;
+ child->p_waited = 1;
+ *status = child->p_status;
+ *sigcode = child->p_sigcode;
+ *ru = child->p_rusage; /* all zeros if !p_dead */
+ *pid_status = child->p_pid;
if (child->p_dead)
- return 1;
- if (!child->p_stopped)
- return 0;
- if (child->p_traced || (options & WUNTRACED))
- return 1;
- return 0;
+ complete_exit (child);
+ return 1;
}
if (!p)
return EOPNOTSUPP;
-
+
start_over:
/* See if we can satisfy the request with a stopped
child; also check for invalid arguments here. */
- if (!p->p_ochild)
+ if (!p->p_ochild)
return ECHILD;
-
+
if (pid > 0)
{
struct proc *child = pid_find_allow_zombie (pid);
if (!child || child->p_parent != p)
return ECHILD;
- if (child_ready (child))
- {
- child->p_waited = 1;
- *status = child->p_status;
- *sigcode = child->p_sigcode;
- if (child->p_dead)
- complete_exit (child);
- bzero (ru, sizeof (struct rusage));
- *pid_status = pid;
- return 0;
- }
+ if (reap (child))
+ return 0;
}
else
{
struct proc *child;
int had_a_match = pid == 0;
-
+
for (child = p->p_ochild; child; child = child->p_sib)
if (waiter_cares (pid, p->p_pgrp->pg_pgid,
child->p_pid, child->p_pgrp->pg_pgid))
{
+ if (reap (child))
+ return 0;
had_a_match = 1;
- if (child_ready (child))
- {
- child->p_waited = 1;
- *status = child->p_status;
- *sigcode = child->p_sigcode;
- *pid_status = child->p_pid;
- if (child->p_dead)
- complete_exit (child);
- bzero (ru, sizeof (struct rusage));
- return 0;
- }
}
if (!had_a_match)
return ECHILD;
}
-
+
if (options & WNOHANG)
return EWOULDBLOCK;
@@ -157,7 +236,7 @@ S_proc_wait (struct proc *p,
goto start_over;
}
-/* Implement proc_mark_stop as described in <hurd/proc.defs>. */
+/* Implement proc_mark_stop as described in <hurd/process.defs>. */
kern_return_t
S_proc_mark_stop (struct proc *p,
int signo,
@@ -170,20 +249,20 @@ S_proc_mark_stop (struct proc *p,
p->p_status = W_STOPCODE (signo);
p->p_sigcode = sigcode;
p->p_waited = 0;
-
+
if (p->p_parent->p_waiting)
{
condition_broadcast (&p->p_parent->p_wakeup);
p->p_parent->p_waiting = 0;
}
-
+
if (!p->p_parent->p_nostopcld)
send_signal (p->p_parent->p_msgport, SIGCHLD, p->p_parent->p_task);
return 0;
}
-/* Implement proc_mark_exit as described in <hurd/proc.defs>. */
+/* Implement proc_mark_exit as described in <hurd/process.defs>. */
kern_return_t
S_proc_mark_exit (struct proc *p,
int status,
@@ -191,17 +270,22 @@ S_proc_mark_exit (struct proc *p,
{
if (!p)
return EOPNOTSUPP;
-
+
if (WIFSTOPPED (status))
return EINVAL;
-
+
+ sample_rusage (p); /* See comments above sample_rusage. */
+
+ if (p->p_exiting)
+ return EBUSY;
+
p->p_exiting = 1;
p->p_status = status;
p->p_sigcode = sigcode;
return 0;
}
-/* Implement proc_mark_cont as described in <hurd/proc.defs>. */
+/* Implement proc_mark_cont as described in <hurd/process.defs>. */
kern_return_t
S_proc_mark_cont (struct proc *p)
{
@@ -211,7 +295,7 @@ S_proc_mark_cont (struct proc *p)
return 0;
}
-/* Implement proc_mark_traced as described in <hurd/proc.defs>. */
+/* Implement proc_mark_traced as described in <hurd/process.defs>. */
kern_return_t
S_proc_mark_traced (struct proc *p)
{
@@ -221,7 +305,7 @@ S_proc_mark_traced (struct proc *p)
return 0;
}
-/* Implement proc_mark_nostopchild as described in <hurd/proc.defs>. */
+/* Implement proc_mark_nostopchild as described in <hurd/process.defs>. */
kern_return_t
S_proc_mod_stopchild (struct proc *p,
int value)
@@ -232,4 +316,3 @@ S_proc_mod_stopchild (struct proc *p,
p->p_nostopcld = ! value;
return 0;
}
-