home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / glibc-1.06 / hurd / hurd.h < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-22  |  15.7 KB  |  508 lines

  1. /* Copyright (C) 1993 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3.  
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of the
  7. License, or (at your option) any later version.
  8.  
  9. The GNU C Library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12. Library General Public License for more details.
  13.  
  14. You should have received a copy of the GNU Library General Public
  15. License along with the GNU C Library; see the file COPYING.LIB.  If
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #ifndef    _HURD_H
  20.  
  21. #define    _HURD_H    1
  22.  
  23. #define    _GNU_SOURCE
  24. #include <features.h>
  25.  
  26. #include <mach.h>
  27. #include <hurd/hurd_types.h>
  28. #include <hurd/process.h>
  29. #include <hurd/fs.h>
  30. #include <hurd/io.h>
  31. #include <errno.h>
  32.  
  33. #define    __hurd_fail(err)    (errno = (err), -1)
  34.  
  35. /* Lightweight user references for ports.  */
  36.  
  37. /* Structure describing a cell containing a port.
  38.    With the lock held, a user extracts PORT, and sets USER_DEALLOC to point
  39.    to a word in his local storage.  PORT can then safely be used.  When
  40.    PORT is no longer needed, with the lock held, the user examines
  41.    USER_DEALLOC.  If it is the same address that user stored there, he
  42.    extracts *USER_DEALLOC, clears USER_DEALLOC to NULL, and releases the
  43.    lock.  If *USER_DEALLOC is set, the user deallocates the port he used.  */
  44. struct _hurd_port
  45.   {
  46.     spin_lock_t lock;        /* Locks rest.  */
  47.     mach_port_t port;        /* Port. */
  48.     int *user_dealloc;        /* If not NULL, points to user's flag word.  */
  49.   };
  50.  
  51. /* Evaluate EXPR with the variable `port' bound to the port in PORTCELL.  */
  52. #define    _HURD_PORT_USE(portcell, expr)                          \
  53.   ({ struct _hurd_port *const __p = &(portcell);                  \
  54.      int __dealloc;                                  \
  55.      const mach_port_t port = _hurd_port_get (__p, &__dealloc);              \
  56.      __typeof(expr) __result = (expr);                          \
  57.      _hurd_port_free (__p, &__dealloc);                          \
  58.      __result; })
  59.  
  60. /* Initialize *PORT to INIT.  */
  61. static inline void
  62. _hurd_port_init (struct _hurd_port *port, mach_port_t init)
  63. {
  64.   __spin_lock_init (&port->lock);
  65.   port->port = init;
  66.   port->user_dealloc = NULL;
  67. }
  68.  
  69. /* Get a reference to *PORT, which is locked.
  70.    Pass return value and MYFLAG to _hurd_port_free when done.  */
  71. static inline mach_port_t
  72. _hurd_port_locked_get (struct _hurd_port *port, int *myflag)
  73. {
  74.   mach_port_t result;
  75.   result = port->port;
  76.   if (result != MACH_PORT_NULL)
  77.     {
  78.       port->user_dealloc = myflag;
  79.       *myflag = 0;
  80.     }
  81.   __spin_unlock (&port->lock);
  82.   return result;
  83. }
  84.  
  85. /* Same, but locks PORT first.  */
  86. static inline mach_port_t
  87. _hurd_port_get (struct _hurd_port *port, int *myflag)
  88. {
  89.   __spin_lock (&port->lock);
  90.   return _hurd_port_locked_get (port, myflag);
  91. }
  92.  
  93. /* Free a reference gotten with
  94.    `USED_PORT = _hurd_port_get (PORT, MYFLAG);' */
  95. static inline void
  96. _hurd_port_free (struct _hurd_port *port,
  97.          int *myflag, mach_port_t used_port)
  98. {
  99.   __spin_lock (&port->lock);
  100.   if (port->user_dealloc == myflag)
  101.     port->user_dealloc = NULL;
  102.   __spin_unlock (&port->lock);
  103.   if (*myflag)
  104.     __mach_port_deallocate (__mach_task_self (), used_port);
  105. }
  106.  
  107. /* Set *PORT's port to NEWPORT.  PORT is locked.  */
  108. static inline void
  109. _hurd_port_locked_set (struct _hurd_port *port, mach_port_t newport)
  110. {
  111.   mach_port_t old;
  112.   if (port->user_dealloc == NULL)
  113.     old = port->port;
  114.   else
  115.     {
  116.       old = MACH_PORT_NULL;
  117.       *port->user_dealloc = 1;
  118.     }
  119.   port->port = newport;
  120.   __spin_unlock (&port->lock);
  121.   if (old != MACH_PORT_NULL)
  122.     __mach_port_deallocate (__mach_task_self (), old);
  123. }
  124.  
  125. /* Same, but locks PORT first.  */
  126. static inline void
  127. _hurd_port_set (struct _hurd_port *port, mach_port_t newport)
  128. {
  129.   __spin_lock (&port->lock);
  130.   return _hurd_port_locked_set (port, newport);
  131. }
  132.  
  133. /* Basic ports and info, initialized by startup.  */
  134. extern struct _hurd_port _hurd_proc, _hurd_auth;
  135. extern struct _hurd_port _hurd_ccdir, _hurd_cwdir, _hurd_crdir;
  136. extern volatile mode_t _hurd_umask;
  137.  
  138. extern struct mutex _hurd_ctty_lock;
  139. extern int _hurd_ctty_fstype;
  140. extern fsid_t _hurd_ctty_fsid;
  141. extern ino_t _hurd_ctty_fileid;
  142.  
  143. extern vm_address_t _hurd_stack_low, _hurd_stack_high; /* Not locked.  */
  144.  
  145. extern thread_t _hurd_msgport_thread;
  146. extern mach_port_t _hurd_msgport; /* Locked by _hurd_siglock.  */
  147.  
  148. /* Not locked.  If we are using a real dtable,
  149.    these are turned into that and then cleared at startup.
  150.    If not, these are never changed after startup.  */
  151. extern mach_port_t *_hurd_init_dtable;
  152. extern size_t _hurd_init_dtablesize;
  153.  
  154. /* File descriptor table.  */
  155. struct _hurd_fd
  156.   {
  157.     struct _hurd_port port;
  158.     int flags;            /* fcntl flags; locked by port.lock.  */
  159.  
  160.     /* Normal port to the ctty.  Also locked by port.lock.
  161.        (The ctty.lock is only ever used when the port.lock is held.)  */
  162.     struct _hurd_port ctty;
  163.   };
  164.  
  165. struct _hurd_dtable
  166.   {
  167.     int size;            /* Number of elts in `d' array.  */
  168.  
  169.     /* Uses of individual descriptors are not locked.  It is up to the user
  170.        to synchronize descriptor operations on a single descriptor.  */
  171.  
  172.     struct _hurd_fd *d;
  173.   };
  174. extern struct mutex _hurd_dtable_lock; /* Locks next two.  */
  175. extern struct _hurd_dtable _hurd_dtable;
  176. extern int _hurd_dtable_rlimit;
  177.  
  178. /* If not NULL, pointed-to word is set when _hurd_dtable.d changes.
  179.    User who set `user_dealloc' should free the _hurd_dtable.d value
  180.    he used if his word is set when he is finished.
  181.    If NULL, the old value of _hurd_dtable.d is freed by the setter.  */
  182. int *_hurd_dtable_user_dealloc;
  183.  
  184. static inline struct _hurd_dtable
  185. _hurd_dtable_use (int *dealloc)
  186. {
  187.   struct _hurd_dtable dtable;
  188.   __mutex_lock (&_hurd_dtable_lock);
  189.   _hurd_dtable_user_dealloc = dealloc;
  190.   dtable = _hurd_dtable;
  191.   __mutex_unlock (&_hurd_dtable_lock);
  192.   return dtable;
  193. }
  194.  
  195. struct _hurd_dtable_resizes
  196.   {
  197.     size_t n;
  198.     void (*free) (void *);
  199.     void *terminator;
  200.   };
  201. extern const struct _hurd_dtable_resizes _hurd_dtable_resizes;
  202.  
  203. static inline void
  204. _hurd_dtable_done (struct _hurd_dtable dtable, int *dealloc)
  205. {
  206.   __mutex_lock (&_hurd_dtable_lock);
  207.   if (_hurd_dtable_user_dealloc == dealloc)
  208.     _hurd_dtable_user_dealloc = NULL;
  209.   __mutex_unlock (&_hurd_dtable_lock);
  210.   if (*dealloc)
  211.     /* _hurd_dtable_resizes is a symbol set.
  212.        setdtablesize.c gives it one element: free.
  213.        If setdtablesize is not linked in, *DEALLOC
  214.        will never get set, so we will never get here.
  215.        This hair avoids linking in free if we don't need it.  */
  216.     (*_hurd_dtable_resizes.free) (dtable);
  217. }
  218.  
  219.  
  220. /* Allocate a new file descriptor and set it to PORT.
  221.    If the table is full, deallocate PORT, set errno, and return -1.  */
  222. static inline int
  223. _hurd_dalloc (io_t port, io_t ctty, int flags)
  224. {
  225.   int i;
  226.   __mutex_lock (&hurd_dtable_lock);
  227.   for (i = 0; i < _hurd_dtable.size; ++i)
  228.     {
  229.       struct _hurd_fd *d = &_hurd_dtable.d[i];
  230.       __spin_lock (&d->port.lock);
  231.       if (d->port.port == MACH_PORT_NULL)
  232.     {
  233.       d->port.port = port;
  234.       d->port.user_dealloc = NULL;
  235.       d->ctty.port = ctty;
  236.       d->ctty.user_dealloc = NULL;
  237.       d->flags = flags;
  238.       __spin_unlock (&d->port.lock);
  239.       __mutex_unlock (&hurd_dtable_lock);
  240.       return i;
  241.     }
  242.       __spin_unlock (&d->port.lock);
  243.     }
  244.   __mutex_unlock (&hurd_dtable_lock);
  245.   __mach_port_deallocate (__mach_task_self (), port);
  246.   __mach_port_deallocate (__mach_task_self (), ctty);
  247.   errno = EMFILE;
  248.   return -1;
  249. }
  250.  
  251. /* Returns the descriptor cell for FD in DTABLE, locked.  */
  252. static inline struct _hurd_fd *
  253. _hurd_dtable_fd (int fd, struct _hurd_dtable dtable)
  254. {
  255.   if (fd < 0 || fd >= dtable.size)
  256.     return NULL;
  257.   else
  258.     {
  259.       struct _hurd_fd *cell = &dtable.d[fd];
  260.       __spin_lock (&cell->port.lock);
  261.       if (cell->port.port == MACH_PORT_NULL)
  262.     {
  263.       __spin_unlock (&cell->port.lock);
  264.       return NULL;
  265.     }
  266.       return cell;
  267.     }
  268. }
  269.  
  270. struct _hurd_fd_user
  271.   {
  272.     struct _hurd_dtable dtable;
  273.     struct _hurd_fd *d;
  274.   };
  275.  
  276. /* Returns the descriptor cell for FD, locked.  */
  277. static inline struct _hurd_fd_user
  278. _hurd_fd (int fd, int *dealloc)
  279. {
  280.   struct _hurd_fd_user d;
  281.   d.dtable = _hurd_dtable_use (dealloc);
  282.   d.d = _hurd_dtable_fd (fd, dtable);
  283.   if (d.d == NULL)
  284.     _hurd_dtable_done (d.dtable, dealloc);
  285.   return d;
  286. }
  287.  
  288. static inline void
  289. _hurd_fd_done (struct _hurd_fd_user d, int *dealloc)
  290. {
  291.   _hurd_dtable_done (d->dtable, dealloc);
  292. }
  293.  
  294. /* Evaluate EXPR with the variable `port' bound to the port to FD,
  295.    and `ctty' bound to the ctty port.  */
  296.    
  297. #define    _HURD_DPORT_USE(fd, expr)                          \
  298.   ({ int __dealloc_dt;                                  \
  299.      struct _hurd_fd_user __d = _hurd_fd (fd, &__dealloc_dt);              \
  300.      if (__d.cell == NULL)                              \
  301.        EBADF;                                      \
  302.      else                                      \
  303.        {                                      \
  304.      int __dealloc = 0, __dealloc_ctty = 0;                      \
  305.      io_t port = _hurd_port_locked_get (&__d.d->port, &__dealloc);          \
  306.      io_t ctty = _hurd_port_locked_get (&__d.d->ctty, &__dealloc_ctty);   \
  307.      __typeof (expr) __result;                          \
  308.      __result = (expr);                              \
  309.      _hurd_port_free (&__d.d->port, port, &__dealloc);              \
  310.      if (ctty != MACH_PORT_NULL)                          \
  311.        _hurd_port_free (&__d.d->ctty, ctty, &__dealloc_ctty);          \
  312.      _hurd_fd_done (__d, &__dealloc_dt);                      \
  313.      __result;                                  \
  314.        }                                      \
  315.    })                                          \
  316.  
  317. static inline int
  318. _hurd_dfail (int fd, error_t err)
  319. {
  320.   int signo;
  321.   switch (err)
  322.     {
  323.     case MACH_SEND_INVALID_DEST: /* The server has disappeared!  */
  324.       _hurd_raise_signal (NULL, SIGLOST, fd);
  325.       break;
  326.     case EPIPE:
  327.       _hurd_raise_signal (NULL, SIGPIPE, fd);
  328.       break;
  329.     }
  330.   return __hurd_fail (err);
  331. }
  332.  
  333. /* Return the socket server for sockaddr domain DOMAIN.  */
  334. extern socket_t _hurd_socket_server (int domain);
  335.  
  336. /* Return a receive right which will not be sent to.  */
  337. extern mach_port_t _hurd_dead_recv (void);
  338.  
  339.  
  340. /* Current process IDs.  */
  341. extern pid_t _hurd_pid, _hurd_ppid, _hurd_pgrp;
  342. extern int _hurd_orphaned;
  343.  
  344.  
  345. /* User and group IDs.  */
  346. extern mutex_t _hurd_idlock;
  347. extern int _hurd_id_valid;    /* Nonzero if _hurd_id is valid.  */
  348. extern idblock_t _hurd_id;
  349. extern auth_t _hurd_rid_auth;    /* Cache used by access.  */
  350.  
  351.  
  352. /* Unix `data break', for brk and sbrk.
  353.    If brk and sbrk are not used, this info will not be initialized or used.  */
  354. extern vm_address_t _hurd_brk;    /* Data break.  */
  355. extern vm_address_t _hurd_data_end; /* End of allocated space.  */
  356. extern struct mutex _hurd_brk_lock; /* Locks brk and data_end.  */
  357. extern int _hurd_set_data_limit (const struct rlimit *);
  358.  
  359. /* Set the data break; the brk lock must
  360.    be held, and is released on return.  */
  361. extern int _hurd_set_brk (vm_address_t newbrk);
  362.  
  363. /* Resource limit on core file size.  Enforced by hurdsig.c.  */
  364. extern int _hurd_core_limit;
  365.  
  366. #include <signal.h>
  367.  
  368. /* Per-thread signal state.  */
  369. struct _hurd_sigstate
  370.   {
  371.     thread_t thread;
  372.     struct _hurd_sigstate *next; /* Linked-list of thread sigstates.  */
  373.  
  374.     struct mutex lock;        /* Locks the rest of this structure.  */
  375.     sigset_t blocked;
  376.     sigset_t pending;
  377.     struct sigaction actions[NSIG];
  378.     struct sigaltstack sigaltstack;
  379.     int sigcodes[NSIG];        /* Codes for pending signals.  */
  380.  
  381.     int suspended;        /* If nonzero, sig_post signals `arrived'.  */
  382.     struct condition arrived;
  383.  
  384. #if 0
  385.     int vforked;        /* Nonzero if this thread is a vfork child.  */
  386.     struct
  387.       {
  388.     process_t proc;
  389.     file_t ccdir, cwdir, crdir, auth;
  390.     mode_t umask;
  391.     int ctty_fstype;
  392.     fsid_t ctty_fsid;
  393.     ino_t ctty_fileid;
  394.     struct _hurd_dtable *dtable;
  395.     jmp_buf continuation;
  396.       } *vfork_saved;
  397. #endif
  398.  
  399.     /* Not locked.  Used only by this thread,
  400.        or by signal thread with this thread suspended.  */
  401.     volatile mach_port_t intr_port; /* Port interruptible RPC was sent on.  */
  402.     volatile int intr_restart;    /* If nonzero, restart interrupted RPC.  */
  403.   };
  404. /* Linked list of states of all threads
  405.    whose state has been inquired about.  */
  406. extern struct _hurd_sigstate *_hurd_sigstates;
  407. extern struct mutex _hurd_siglock; /* Locks _hurd_sigstates.  */
  408. /* Get the sigstate of a given thread, taking its lock.  */
  409. extern struct _hurd_sigstate *_hurd_thread_sigstate (thread_t);
  410.  
  411. /* Thread to receive process-global signals.  */
  412. extern thread_t _hurd_sigthread;
  413.  
  414. /* Called by the machine-dependent exception handler.  */
  415. extern void _hurd_exc_post_signal (thread_t, int sig, int code);
  416.  
  417. /* SS->lock is held on entry, and released before return.  */
  418. extern void _hurd_internal_post_signal (struct _hurd_sigstate *ss,
  419.                     int signo, int sigcode,
  420.                     sigset_t *restore_blocked);
  421.  
  422. /* Function run by the signal thread to receive from the signal port.  */
  423. extern void _hurd_msgport_receive (void);
  424.  
  425.  
  426. /* Perform interruptible RPC CALL on PORT.
  427.    The args in CALL should be constant or local variable refs.
  428.    They may be evaluated many times, and must not change.
  429.    PORT must not be deallocated before this RPC is finished.  */
  430. #define    HURD_EINTR_RPC(port, call) \
  431.   ({
  432.     error_t __err;
  433.     struct _hurd_sigstate *__ss
  434.       = _hurd_thread_sigstate (__mach_thread_self ());
  435.     __mutex_unlock (&__ss->lock); /* Lock not needed.  */
  436.     /* If we get a signal and should return EINTR, the signal thread will
  437.        clear this.  The RPC might return EINTR when some other thread gets
  438.        a signal, in which case we want to restart our call.  */
  439.     __ss->intr_restart = 1;
  440.     /* This one needs to be last.  A signal can arrive before here,
  441.        and if intr_port were set before intr_restart is
  442.        initialized, the signal thread would get confused.  */
  443.     __ss->intr_port = (port);
  444.     /* A signal may arrive here, after intr_port is set,
  445.        but before the mach_msg system call.  The signal handler might do an
  446.        interruptible RPC, and clobber intr_port; then it would not be set
  447.        properly when we actually did send the RPC, and a later signal
  448.        wouldn't interrupt that RPC.  So, _hurd_run_sighandler saves
  449.        intr_port in the sigcontext, and sigreturn restores it.  */
  450.   __do_call:
  451.     switch (__err = (call))
  452.       {
  453.       case EINTR:        /* RPC went out and was interrupted.  */
  454.       case MACH_SEND_INTERRUPTED: /* RPC didn't get out.  */
  455.     if (__ss->intr_restart)
  456.       /* Restart the interrupted call.  */
  457.       goto __do_call;
  458.     /* FALLTHROUGH */
  459.       case MACH_RCV_PORT_DIED:
  460.     /* Server didn't respond to interrupt_operation,
  461.        so the signal thread destroyed the reply port.  */
  462.     __err = EINTR;
  463.     break;
  464.       }
  465.     __ss->intr_port = MACH_PORT_NULL;
  466.     __err;
  467.   })
  468.  
  469. /* Calls to get and set basic ports.  */
  470. extern process_t getproc (void);
  471. extern file_t getccdir (void), getcwdir (void), getcrdir (void);
  472. extern auth_t getauth (void);
  473. extern int setproc (process_t);
  474. extern int setccdir (file_t), setcwdir (file_t), setcrdir (file_t);
  475.  
  476. /* Does reauth with the proc server and fd io servers.  */
  477. extern int __setauth (auth_t), setauth (auth_t);
  478. #define    setauth    __setauth
  479.  
  480.  
  481. extern error_t __hurd_path_split (file_t crdir, file_t cwdir,
  482.                   const char *file,
  483.                   file_t *dir, const char **name);
  484. #define    hurd_path_split    __hurd_path_split
  485. extern error_t __hurd_path_lookup (file_t crdir, file_t cwdir,
  486.                    const char *file,
  487.                    int flags, mode_t mode,
  488.                    file_t *file);
  489. #define    hurd_path_lookup __hurd_path_lookup
  490.  
  491. /* Returns a port to the directory, and sets *NAME to the file name.  */
  492. extern file_t __path_split (const char *file, const char **name);
  493. #define    path_split    __path_split
  494.  
  495. /* Looks up FILE with the given FLAGS and MODE (as for dir_pathtrans).  */
  496. extern file_t __path_lookup (const char *file, int flags, mode_t mode);
  497. #define path_lookup __path_lookup
  498.  
  499. /* Open a file descriptor on a port.  */
  500. extern int openport (io_t port);
  501.  
  502. /* Inform the proc server we have exitted with STATUS, and kill the
  503.    task thoroughly.  This function never returns, no matter what.  */
  504. extern volatile void _hurd_exit (int status);
  505.  
  506.  
  507. #endif    /* hurd.h */
  508.