diff options
Diffstat (limited to 'REORG.TODO/hurd/hurd')
-rw-r--r-- | REORG.TODO/hurd/hurd/fd.h | 275 | ||||
-rw-r--r-- | REORG.TODO/hurd/hurd/id.h | 54 | ||||
-rw-r--r-- | REORG.TODO/hurd/hurd/ioctl.h | 81 | ||||
-rw-r--r-- | REORG.TODO/hurd/hurd/lookup.h | 190 | ||||
-rw-r--r-- | REORG.TODO/hurd/hurd/port.h | 158 | ||||
-rw-r--r-- | REORG.TODO/hurd/hurd/resource.h | 51 | ||||
-rw-r--r-- | REORG.TODO/hurd/hurd/signal.h | 364 | ||||
-rw-r--r-- | REORG.TODO/hurd/hurd/sigpreempt.h | 102 | ||||
-rw-r--r-- | REORG.TODO/hurd/hurd/threadvar.h | 116 | ||||
-rw-r--r-- | REORG.TODO/hurd/hurd/userlink.h | 147 | ||||
-rw-r--r-- | REORG.TODO/hurd/hurd/xattr.h | 34 |
11 files changed, 1572 insertions, 0 deletions
diff --git a/REORG.TODO/hurd/hurd/fd.h b/REORG.TODO/hurd/hurd/fd.h new file mode 100644 index 0000000000..8954be0d50 --- /dev/null +++ b/REORG.TODO/hurd/hurd/fd.h @@ -0,0 +1,275 @@ +/* File descriptors. + Copyright (C) 1993-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_FD_H + +#define _HURD_FD_H 1 +#include <features.h> + +#include <cthreads.h> + +#include <hurd/hurd_types.h> +#include <hurd/port.h> +#include <sys/socket.h> + + +/* Structure representing a file descriptor. */ + +struct hurd_fd + { + struct hurd_port port; /* io server port. */ + int flags; /* fcntl flags; locked by port.lock. */ + + /* Normal port to the ctty. When `port' is our ctty, this is a port to + the same io object but which never returns EBACKGROUND; when not, + this is nil. */ + struct hurd_port ctty; + }; + + +/* Current file descriptor table. */ + +extern int _hurd_dtablesize; +extern struct hurd_fd **_hurd_dtable; +extern struct mutex _hurd_dtable_lock; /* Locks those two variables. */ + +#include <hurd/signal.h> + +#ifndef _HURD_FD_H_EXTERN_INLINE +#define _HURD_FD_H_EXTERN_INLINE __extern_inline +#endif + +/* Returns the descriptor cell for FD. If FD is invalid or unused, return + NULL. The cell is unlocked; when ready to use it, lock it and check for + it being unused. */ + +_HURD_FD_H_EXTERN_INLINE struct hurd_fd * +_hurd_fd_get (int fd) +{ + struct hurd_fd *descriptor; + + HURD_CRITICAL_BEGIN; + __mutex_lock (&_hurd_dtable_lock); + if (fd < 0 || fd >= _hurd_dtablesize) + descriptor = NULL; + else + { + struct hurd_fd *cell = _hurd_dtable[fd]; + if (cell == NULL) + /* No descriptor allocated at this index. */ + descriptor = NULL; + else + { + __spin_lock (&cell->port.lock); + if (cell->port.port == MACH_PORT_NULL) + /* The descriptor at this index has no port in it. + This happens if it existed before but was closed. */ + descriptor = NULL; + else + descriptor = cell; + __spin_unlock (&cell->port.lock); + } + } + __mutex_unlock (&_hurd_dtable_lock); + HURD_CRITICAL_END; + + return descriptor; +} + + +/* Evaluate EXPR with the variable `descriptor' bound to a pointer to the + file descriptor structure for FD. */ + +#define HURD_FD_USE(fd, expr) \ + ({ struct hurd_fd *descriptor = _hurd_fd_get (fd); \ + descriptor == NULL ? EBADF : (expr); }) + +/* Evaluate EXPR with the variable `port' bound to the port to FD, and + `ctty' bound to the ctty port. */ + +#define HURD_DPORT_USE(fd, expr) \ + HURD_FD_USE ((fd), HURD_FD_PORT_USE (descriptor, (expr))) + +/* Likewise, but FD is a pointer to the file descriptor structure. */ + +#define HURD_FD_PORT_USE(fd, expr) \ + ({ error_t __result; \ + struct hurd_fd *const __d = (fd); \ + struct hurd_userlink __ulink, __ctty_ulink; \ + io_t port, ctty; \ + void *crit = _hurd_critical_section_lock (); \ + __spin_lock (&__d->port.lock); \ + if (__d->port.port == MACH_PORT_NULL) \ + { \ + __spin_unlock (&__d->port.lock); \ + _hurd_critical_section_unlock (crit); \ + __result = EBADF; \ + } \ + else \ + { \ + ctty = _hurd_port_get (&__d->ctty, &__ctty_ulink); \ + port = _hurd_port_locked_get (&__d->port, &__ulink); \ + _hurd_critical_section_unlock (crit); \ + __result = (expr); \ + _hurd_port_free (&__d->port, &__ulink, port); \ + if (ctty != MACH_PORT_NULL) \ + _hurd_port_free (&__d->ctty, &__ctty_ulink, ctty); \ + } \ + __result; }) + +#include <errno.h> + +/* Check if ERR should generate a signal. + Returns the signal to take, or zero if none. */ + +_HURD_FD_H_EXTERN_INLINE int +_hurd_fd_error_signal (error_t err) +{ + switch (err) + { + case EMACH_SEND_INVALID_DEST: + case EMIG_SERVER_DIED: + /* The server has disappeared! */ + return SIGLOST; + case EPIPE: + return SIGPIPE; + default: + /* Having a default case avoids -Wenum-switch warnings. */ + return 0; + } +} + +/* Handle an error from an RPC on a file descriptor's port. You should + always use this function to handle errors from RPCs made on file + descriptor ports. Some errors are translated into signals. */ + +_HURD_FD_H_EXTERN_INLINE error_t +_hurd_fd_error (int fd, error_t err) +{ + int signo = _hurd_fd_error_signal (err); + if (signo) + { + const struct hurd_signal_detail detail + = { code: fd, error: err, exc: 0 }; + _hurd_raise_signal (NULL, signo, &detail); + } + return err; +} + +/* Handle error code ERR from an RPC on file descriptor FD's port. + Set `errno' to the appropriate error code, and always return -1. */ + +_HURD_FD_H_EXTERN_INLINE int +__hurd_dfail (int fd, error_t err) +{ + errno = _hurd_fd_error (fd, err); + return -1; +} + +/* Likewise, but do not raise SIGPIPE on EPIPE if flags contain + MSG_NOSIGNAL. */ + +_HURD_FD_H_EXTERN_INLINE int +__hurd_sockfail (int fd, int flags, error_t err) +{ + if (!(flags & MSG_NOSIGNAL) || err != EPIPE) + err = _hurd_fd_error (fd, err); + errno = err; + return -1; +} + +/* Set up *FD to have PORT its server port, doing appropriate ctty magic. + Does no locking or unlocking. */ + +extern void _hurd_port2fd (struct hurd_fd *fd, io_t port, int flags); + +/* Allocate a new file descriptor and install PORT in it (doing any + appropriate ctty magic); consumes a user reference on PORT. FLAGS are + as for `open'; only O_IGNORE_CTTY and O_CLOEXEC are meaningful, but all are + saved. + + If the descriptor table is full, set errno, and return -1. + If DEALLOC is nonzero, deallocate PORT first. */ + +extern int _hurd_intern_fd (io_t port, int flags, int dealloc); + +/* Allocate a new file descriptor in the table and return it, locked. The + new descriptor number will be no less than FIRST_FD. If the table is + full, set errno to EMFILE and return NULL. If FIRST_FD is negative or + bigger than the size of the table, set errno to EINVAL and return NULL. */ + +extern struct hurd_fd *_hurd_alloc_fd (int *fd_ptr, int first_fd); + +/* Allocate a new file descriptor structure and initialize its port cells + with PORT and CTTY. (This does not affect the descriptor table.) */ + +extern struct hurd_fd *_hurd_new_fd (io_t port, io_t ctty); + +/* Close a file descriptor, making it available for future reallocation. */ + +extern error_t _hurd_fd_close (struct hurd_fd *fd); + +/* Read and write data from a file descriptor; just like `read' and `write' + if OFFSET is -1, or like `pread' and `pwrite' if OFFSET is not -1. + If successful, stores the amount actually read or written in *NBYTES. */ + +extern error_t _hurd_fd_read (struct hurd_fd *fd, + void *buf, size_t *nbytes, loff_t offset); +extern error_t _hurd_fd_write (struct hurd_fd *fd, + const void *buf, size_t *nbytes, loff_t offset); + + +/* Call *RPC on PORT and/or CTTY; if a call on CTTY returns EBACKGROUND, + generate SIGTTIN/SIGTTOU or EIO as appropriate. */ + +extern error_t _hurd_ctty_input (io_t port, io_t ctty, error_t (*rpc) (io_t)); +extern error_t _hurd_ctty_output (io_t port, io_t ctty, error_t (*rpc) (io_t)); + + +/* The guts of `select' and `poll'. Check the first NFDS descriptors + either in POLLFDS (if nonnull) or in each of READFDS, WRITEFDS, + EXCEPTFDS that is nonnull. If TIMEOUT is not NULL, time out after + waiting the interval specified therein. If SIGMASK is nonnull, + the set of blocked signals is temporarily set to that during this call. + Returns the number of ready descriptors, or -1 for errors. */ +struct pollfd; +struct timespec; +extern int _hurd_select (int nfds, struct pollfd *pollfds, + fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + const struct timespec *timeout, + const sigset_t *sigmask); + +/* Variant of file_name_lookup used in *at function implementations. + AT_FLAGS may only contain AT_SYMLINK_FOLLOW or AT_SYMLINK_NOFOLLOW, + which will remove and add O_NOLINK from FLAGS respectively. + Other bits cause EINVAL. */ +extern file_t __file_name_lookup_at (int fd, int at_flags, + const char *file_name, + int flags, mode_t mode); + +/* Variant of file_name_split used in *at function implementations. */ +extern file_t __file_name_split_at (int fd, const char *file_name, + char **name); + +/* Variant of directory_name_split used in *at function implementations. */ +extern file_t __directory_name_split_at (int fd, const char *directory_name, + char **name); + + + +#endif /* hurd/fd.h */ diff --git a/REORG.TODO/hurd/hurd/id.h b/REORG.TODO/hurd/hurd/id.h new file mode 100644 index 0000000000..ef1292ebe8 --- /dev/null +++ b/REORG.TODO/hurd/hurd/id.h @@ -0,0 +1,54 @@ +/* User and group IDs. + Copyright (C) 1993-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_ID_H + +#define _HURD_ID_H 1 +#include <features.h> + +#include <cthreads.h> /* For `struct mutex'. */ + +/* Structure describing authorization data for the process. */ + +struct hurd_id_data + { + struct mutex lock; + + int valid; /* If following data are up to date. */ + + struct + { + uid_t *uids; + gid_t *gids; + mach_msg_type_number_t nuids, ngids; + } gen, aux; + + auth_t rid_auth; /* Cache used by access. */ + }; + +/* Current data. */ + +extern struct hurd_id_data _hurd_id; + + +/* Update _hurd_id (caller should be holding the lock). */ + +extern error_t _hurd_check_ids (void); + + +#endif /* hurd/id.h */ diff --git a/REORG.TODO/hurd/hurd/ioctl.h b/REORG.TODO/hurd/hurd/ioctl.h new file mode 100644 index 0000000000..0423b8cb9f --- /dev/null +++ b/REORG.TODO/hurd/hurd/ioctl.h @@ -0,0 +1,81 @@ +/* User-registered handlers for specific `ioctl' requests. + Copyright (C) 1993-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_IOCTL_H +#define _HURD_IOCTL_H 1 + +#define __need___va_list +#include <stdarg.h> +#include <bits/ioctls.h> + + +/* Type of handler function, called like ioctl to do its entire job. */ +typedef int (*ioctl_handler_t) (int fd, int request, void *arg); + +/* Structure that records an ioctl handler. */ +struct ioctl_handler + { + /* Range of handled _IOC_NOTYPE (REQUEST) values. */ + int first_request, last_request; + + /* Handler function, called like ioctl to do its entire job. */ + ioctl_handler_t handler; + + struct ioctl_handler *next; /* Next handler. */ + }; + + +/* Register HANDLER to handle ioctls with REQUEST values between + FIRST_REQUEST and LAST_REQUEST inclusive. Returns zero if successful. + Return nonzero and sets `errno' for an error. */ + +extern int hurd_register_ioctl_handler (int first_request, int last_request, + ioctl_handler_t handler); + + +/* Define a library-internal handler for ioctl commands between FIRST and + LAST inclusive. The last element gratuitously references HANDLER to + avoid `defined but not used' warnings. */ + +#define _HURD_HANDLE_IOCTLS_1(handler, first, last, moniker) \ + static const struct ioctl_handler handler##_ioctl_handler##moniker \ + __attribute__ ((__unused__)) = \ + { _IOC_NOTYPE (first), _IOC_NOTYPE (last), \ + (ioctl_handler_t) (handler), NULL }; \ + text_set_element (_hurd_ioctl_handler_lists, \ + handler##_ioctl_handler##moniker) +#define _HURD_HANDLE_IOCTLS(handler, first, last) \ + _HURD_HANDLE_IOCTLS_1 (handler, first, last, first##_to_##last) + +/* Define a library-internal handler for a single ioctl command. */ + +#define _HURD_HANDLE_IOCTL(handler, ioctl) \ + _HURD_HANDLE_IOCTLS_1 (handler, ioctl, ioctl, ioctl##_only) + + +/* Install a new CTTYID port, atomically updating the dtable appropriately. + This consumes the send right passed in. */ + +void _hurd_locked_install_cttyid (mach_port_t cttyid); + +/* Lookup the handler for the given ioctl request. */ + +ioctl_handler_t _hurd_lookup_ioctl_handler (int request); + + +#endif /* hurd/ioctl.h */ diff --git a/REORG.TODO/hurd/hurd/lookup.h b/REORG.TODO/hurd/hurd/lookup.h new file mode 100644 index 0000000000..99052994c7 --- /dev/null +++ b/REORG.TODO/hurd/hurd/lookup.h @@ -0,0 +1,190 @@ +/* Declarations of file name translation functions for the GNU Hurd. + Copyright (C) 1995-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_LOOKUP_H +#define _HURD_LOOKUP_H 1 + +/* These functions all take two callback functions as the first two arguments. + The first callback function USE_INIT_PORT is called as follows: + + error_t use_init_port (int which, error_t (*operate) (mach_port_t)); + + WHICH is nonnegative value less than INIT_PORT_MAX, indicating which + init port is required. The callback function should call *OPERATE + with a send right to the appropriate init port. No user reference + is consumed; the right will only be used after *OPERATE returns if + *OPERATE has added its own user reference. + + LOOKUP is a function to do the actual filesystem lookup. It is passed the + same arguments that the dir_lookup rpc accepts, and if 0, __dir_lookup is + used. + + The second callback function GET_DTABLE_PORT should behave like `getdport'. + + All these functions return zero on success or an error code on failure. */ + + +/* Open a port to FILE with the given FLAGS and MODE (see <fcntl.h>). If + successful, returns zero and store the port to FILE in *PORT; otherwise + returns an error code. */ + +error_t __hurd_file_name_lookup (error_t (*use_init_port) + (int which, + error_t (*operate) (mach_port_t)), + file_t (*get_dtable_port) (int fd), + error_t (*lookup) + (file_t dir, char *name, int flags, mode_t mode, + retry_type *do_retry, string_t retry_name, + mach_port_t *result), + const char *file_name, + int flags, mode_t mode, + file_t *result); +error_t hurd_file_name_lookup (error_t (*use_init_port) + (int which, + error_t (*operate) (mach_port_t)), + file_t (*get_dtable_port) (int fd), + error_t (*lookup) + (file_t dir, char *name, int flags, mode_t mode, + retry_type *do_retry, string_t retry_name, + mach_port_t *result), + const char *file_name, + int flags, mode_t mode, + file_t *result); + + +/* Split FILE into a directory and a name within the directory. Look up a + port for the directory and store it in *DIR; store in *NAME a pointer + into FILE where the name within directory begins. */ + +error_t __hurd_file_name_split (error_t (*use_init_port) + (int which, + error_t (*operate) (mach_port_t)), + file_t (*get_dtable_port) (int fd), + error_t (*lookup) (file_t dir, char *name, + int flags, mode_t mode, + retry_type *do_retry, string_t retry_name, + mach_port_t *result), + const char *file_name, + file_t *dir, char **name); +error_t hurd_file_name_split (error_t (*use_init_port) + (int which, + error_t (*operate) (mach_port_t)), + file_t (*get_dtable_port) (int fd), + error_t (*lookup) (file_t dir, char *name, + int flags, mode_t mode, + retry_type *do_retry, string_t retry_name, + mach_port_t *result), + const char *file_name, + file_t *dir, char **name); + +/* Split DIRECTORY into a parent directory and a name within the directory. + This is the same as hurd_file_name_split, but ignores trailing slashes. */ + +error_t __hurd_directory_name_split (error_t (*use_init_port) + (int which, + error_t (*operate) (mach_port_t)), + file_t (*get_dtable_port) (int fd), + error_t (*lookup) (file_t dir, char *name, + int flags, mode_t mode, + retry_type *do_retry, string_t retry_name, + mach_port_t *result), + const char *directory_name, + file_t *dir, char **name); +error_t hurd_directory_name_split (error_t (*use_init_port) + (int which, + error_t (*operate) (mach_port_t)), + file_t (*get_dtable_port) (int fd), + error_t (*lookup) (file_t dir, char *name, + int flags, mode_t mode, + retry_type *do_retry, string_t retry_name, + mach_port_t *result), + const char *directory_name, + file_t *dir, char **name); + + +/* Process the values returned by `dir_lookup' et al, and loop doing + `dir_lookup' calls until one returns FS_RETRY_NONE. The arguments + should be those just passed to and/or returned from `dir_lookup', + `fsys_getroot', or `file_invoke_translator'. This function consumes the + reference in *RESULT even if it returns an error. */ + +error_t __hurd_file_name_lookup_retry (error_t (*use_init_port) + (int which, + error_t (*operate) (mach_port_t)), + file_t (*get_dtable_port) (int fd), + error_t (*lookup) + (file_t dir, char *name, + int flags, mode_t mode, + retry_type *do_retry, + string_t retry_name, + mach_port_t *result), + enum retry_type doretry, + char retryname[1024], + int flags, mode_t mode, + file_t *result); +error_t hurd_file_name_lookup_retry (error_t (*use_init_port) + (int which, + error_t (*operate) (mach_port_t)), + file_t (*get_dtable_port) (int fd), + error_t (*lookup) + (file_t dir, char *name, + int flags, mode_t mode, + retry_type *do_retry, + string_t retry_name, + mach_port_t *result), + enum retry_type doretry, + char retryname[1024], + int flags, mode_t mode, + file_t *result); + + +/* If FILE_NAME contains a '/', or PATH is NULL, call FUN with FILE_NAME, and + return the result (if PREFIXED_NAME is non-NULL, setting *PREFIXED_NAME to + NULL). Otherwise, call FUN repeatedly with FILE_NAME prefixed with each + successive `:' separated element of PATH, returning whenever FUN returns + 0 (if PREFIXED_NAME is non-NULL, setting *PREFIXED_NAME to the resulting + prefixed path). If FUN never returns 0, return the first non-ENOENT + return value, or ENOENT if there is none. */ +error_t file_name_path_scan (const char *file_name, const char *path, + error_t (*fun)(const char *name), + char **prefixed_name); + +/* Lookup FILE_NAME and return the node opened with FLAGS & MODE in result + (see hurd_file_name_lookup for details), but a simple filename (without + any directory prefixes) will be consecutively prefixed with the pathnames + in the `:' separated list PATH until one succeeds in a successful lookup. + If none succeed, then the first error that wasn't ENOENT is returned, or + ENOENT if no other errors were returned. If PREFIXED_NAME is non-NULL, + then if RESULT is looked up directly, *PREFIXED_NAME is set to NULL, and + if it is looked up using a prefix from PATH, *PREFIXED_NAME is set to + malloced storage containing the prefixed name. */ +error_t hurd_file_name_path_lookup (error_t (*use_init_port) + (int which, + error_t (*operate) (mach_port_t)), + file_t (*get_dtable_port) (int fd), + error_t (*lookup) + (file_t dir, char *name, + int flags, mode_t mode, + retry_type *do_retry, + string_t retry_name, + mach_port_t *result), + const char *file_name, const char *path, + int flags, mode_t mode, + file_t *result, char **prefixed_name); + +#endif /* hurd/lookup.h */ diff --git a/REORG.TODO/hurd/hurd/port.h b/REORG.TODO/hurd/hurd/port.h new file mode 100644 index 0000000000..94874f8f25 --- /dev/null +++ b/REORG.TODO/hurd/hurd/port.h @@ -0,0 +1,158 @@ +/* Lightweight user references for ports. + Copyright (C) 1993-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_PORT_H + +#define _HURD_PORT_H 1 +#include <features.h> + +#include <mach.h> +#include <hurd/userlink.h> +#include <spin-lock.h> +#include <hurd/signal.h> + + +/* Structure describing a cell containing a port. With the lock held, a + user extracts PORT, and attaches his own link (in local storage) to the + USERS chain. PORT can then safely be used. When PORT is no longer + needed, with the lock held, the user removes his link from the chain. + If his link is the last, and PORT has changed since he fetched it, the + user deallocates the port he used. See <hurd/userlink.h>. */ + +struct hurd_port + { + spin_lock_t lock; /* Locks rest. */ + struct hurd_userlink *users; /* Chain of users; see below. */ + mach_port_t port; /* Port. */ + }; + + +/* Evaluate EXPR with the variable `port' bound to the port in PORTCELL. */ + +#define HURD_PORT_USE(portcell, expr) \ + ({ struct hurd_port *const __p = (portcell); \ + struct hurd_userlink __link; \ + const mach_port_t port = _hurd_port_get (__p, &__link); \ + __typeof(expr) __result = (expr); \ + _hurd_port_free (__p, &__link, port); \ + __result; }) + + +#ifndef _HURD_PORT_H_EXTERN_INLINE +#define _HURD_PORT_H_EXTERN_INLINE __extern_inline +#endif + + +/* Initialize *PORT to INIT. */ + +_HURD_PORT_H_EXTERN_INLINE void +_hurd_port_init (struct hurd_port *port, mach_port_t init) +{ + __spin_lock_init (&port->lock); + port->users = NULL; + port->port = init; +} + + +/* Cleanup function for non-local exits. */ +extern void _hurd_port_cleanup (void *, jmp_buf, int); + +/* Get a reference to *PORT, which is locked. + Pass return value and LINK to _hurd_port_free when done. */ + +_HURD_PORT_H_EXTERN_INLINE mach_port_t +_hurd_port_locked_get (struct hurd_port *port, + struct hurd_userlink *link) +{ + mach_port_t result; + result = port->port; + if (result != MACH_PORT_NULL) + { + link->cleanup = &_hurd_port_cleanup; + link->cleanup_data = (void *) result; + _hurd_userlink_link (&port->users, link); + } + __spin_unlock (&port->lock); + return result; +} + +/* Same, but locks PORT first. */ + +_HURD_PORT_H_EXTERN_INLINE mach_port_t +_hurd_port_get (struct hurd_port *port, + struct hurd_userlink *link) +{ + mach_port_t result; + HURD_CRITICAL_BEGIN; + __spin_lock (&port->lock); + result = _hurd_port_locked_get (port, link); + HURD_CRITICAL_END; + return result; +} + + +/* Free a reference gotten with `USED_PORT = _hurd_port_get (PORT, LINK);' */ + +_HURD_PORT_H_EXTERN_INLINE void +_hurd_port_free (struct hurd_port *port, + struct hurd_userlink *link, + mach_port_t used_port) +{ + int dealloc; + if (used_port == MACH_PORT_NULL) + /* When we fetch an empty port cell with _hurd_port_get, + it does not link us on the users chain, since there is + no shared resource. */ + return; + HURD_CRITICAL_BEGIN; + __spin_lock (&port->lock); + dealloc = _hurd_userlink_unlink (link); + __spin_unlock (&port->lock); + HURD_CRITICAL_END; + if (dealloc) + __mach_port_deallocate (__mach_task_self (), used_port); +} + + +/* Set *PORT's port to NEWPORT. NEWPORT's reference is consumed by PORT->port. + PORT->lock is locked. */ + +_HURD_PORT_H_EXTERN_INLINE void +_hurd_port_locked_set (struct hurd_port *port, mach_port_t newport) +{ + mach_port_t old; + old = _hurd_userlink_clear (&port->users) ? port->port : MACH_PORT_NULL; + port->port = newport; + __spin_unlock (&port->lock); + if (old != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), old); +} + +/* Same, but locks PORT first. */ + +_HURD_PORT_H_EXTERN_INLINE void +_hurd_port_set (struct hurd_port *port, mach_port_t newport) +{ + HURD_CRITICAL_BEGIN; + __spin_lock (&port->lock); + _hurd_port_locked_set (port, newport); + HURD_CRITICAL_END; +} + + +#endif /* hurd/port.h */ diff --git a/REORG.TODO/hurd/hurd/resource.h b/REORG.TODO/hurd/hurd/resource.h new file mode 100644 index 0000000000..c550d04f07 --- /dev/null +++ b/REORG.TODO/hurd/hurd/resource.h @@ -0,0 +1,51 @@ +/* Resource limits for the Hurd. + Copyright (C) 1994-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_RESOURCE_H +#define _HURD_RESOURCE_H + +#include <sys/types.h> +#include <sys/resource.h> +#include <errno.h> +#include <hurd/process.h> + +/* This array contains the current resource limits for the process. */ +extern struct rlimit _hurd_rlimits[RLIM_NLIMITS]; +extern struct mutex _hurd_rlimit_lock; /* Locks _hurd_rlimits. */ + + +/* Helper function for getpriority and setpriority. Maps FN over all the + processes specified by WHICH and WHO. PI is non-null if a + proc_getprocinfo was already done; FN may use *PI arbitrarily, it is + reset on the next call; PI_FLAGS is passed to proc_getprocinfo. Returns + FN's result the first time it returns nonzero. If FN never returns + nonzero, this returns zero. */ +extern error_t _hurd_priority_which_map (enum __priority_which which, int who, + error_t (*fn) (pid_t pid, + struct procinfo *pi), + int pi_flags); + +/* Convert between Mach priority values and the priority + values used by getpriority, setpriority, and nice. */ +#define MACH_PRIORITY_TO_NICE(prio) ((prio) - 25) +#define NICE_TO_MACH_PRIORITY(nice) ((nice) + 25) + + + + +#endif diff --git a/REORG.TODO/hurd/hurd/signal.h b/REORG.TODO/hurd/hurd/signal.h new file mode 100644 index 0000000000..e03d53e6d7 --- /dev/null +++ b/REORG.TODO/hurd/hurd/signal.h @@ -0,0 +1,364 @@ +/* Implementing POSIX.1 signals under the Hurd. + Copyright (C) 1993-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_SIGNAL_H + +#define _HURD_SIGNAL_H 1 +#include <features.h> +/* Make sure <signal.h> is going to define NSIG. */ +#ifndef __USE_GNU +#error "Must have `_GNU_SOURCE' feature test macro to use this file" +#endif + +#define __need_size_t +#define __need_NULL +#include <stddef.h> + +#include <mach/mach_types.h> +#include <mach/port.h> +#include <mach/message.h> +#include <hurd/hurd_types.h> +#include <signal.h> +#include <errno.h> +#include <hurd/msg.h> + +#include <cthreads.h> /* For `struct mutex'. */ +#include <setjmp.h> /* For `jmp_buf'. */ +#include <spin-lock.h> +#include <hurd/threadvar.h> /* We cache sigstate in a threadvar. */ +struct hurd_signal_preemptor; /* <hurd/sigpreempt.h> */ + + +/* Full details of a signal. */ +struct hurd_signal_detail + { + /* Codes from origination Mach exception_raise message. */ + integer_t exc, exc_code, exc_subcode; + /* Sigcode as passed or computed from exception codes. */ + integer_t code; + /* Error code as passed or extracted from exception codes. */ + error_t error; + }; + + +/* Per-thread signal state. */ + +struct hurd_sigstate + { + spin_lock_t critical_section_lock; /* Held if in critical section. */ + + spin_lock_t lock; /* Locks most of the rest of the structure. */ + + thread_t thread; + struct hurd_sigstate *next; /* Linked-list of thread sigstates. */ + + sigset_t blocked; /* What signals are blocked. */ + sigset_t pending; /* Pending signals, possibly blocked. */ + struct sigaction actions[NSIG]; + stack_t sigaltstack; + + /* Chain of thread-local signal preemptors; see <hurd/sigpreempt.h>. + Each element of this chain is in local stack storage, and the chain + parallels the stack: the head of this chain is in the innermost + stack frame, and each next element in an outermore frame. */ + struct hurd_signal_preemptor *preemptors; + + /* For each signal that may be pending, the details to deliver it with. */ + struct hurd_signal_detail pending_data[NSIG]; + + /* If `suspended' is set when this thread gets a signal, + the signal thread sends an empty message to it. */ + mach_port_t suspended; + + /* The following members are not locked. They are used only by this + thread, or by the signal thread with this thread suspended. */ + + volatile mach_port_t intr_port; /* Port interruptible RPC was sent on. */ + + /* If this is not null, the thread is in sigreturn awaiting delivery of + pending signals. This context (the machine-dependent portions only) + will be passed to sigreturn after running the handler for a pending + signal, instead of examining the thread state. */ + struct sigcontext *context; + + /* This is the head of the thread's list of active resources; see + <hurd/userlink.h> for details. This member is only used by the + thread itself, and always inside a critical section. */ + struct hurd_userlink *active_resources; + + /* These are locked normally. */ + int cancel; /* Flag set by hurd_thread_cancel. */ + void (*cancel_hook) (void); /* Called on cancellation. */ + }; + +/* Linked list of states of all threads whose state has been asked for. */ + +extern struct hurd_sigstate *_hurd_sigstates; + +extern struct mutex _hurd_siglock; /* Locks _hurd_sigstates. */ + +/* Get the sigstate of a given thread, taking its lock. */ + +extern struct hurd_sigstate *_hurd_thread_sigstate (thread_t); + +/* Get the sigstate of the current thread. + This uses a per-thread variable to optimize the lookup. */ + +extern struct hurd_sigstate *_hurd_self_sigstate (void) + /* This declaration tells the compiler that the value is constant. + We assume this won't be called twice from the same stack frame + by different threads. */ + __attribute__ ((__const__)); + +#ifndef _HURD_SIGNAL_H_EXTERN_INLINE +#define _HURD_SIGNAL_H_EXTERN_INLINE __extern_inline +#endif + +_HURD_SIGNAL_H_EXTERN_INLINE struct hurd_sigstate * +_hurd_self_sigstate (void) +{ + struct hurd_sigstate **location = (struct hurd_sigstate **) + (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE); + if (*location == NULL) + *location = _hurd_thread_sigstate (__mach_thread_self ()); + return *location; +} + +/* Thread listening on our message port; also called the "signal thread". */ + +extern thread_t _hurd_msgport_thread; + +/* Our message port. We hold the receive right and _hurd_msgport_thread + listens for messages on it. We also hold a send right, for convenience. */ + +extern mach_port_t _hurd_msgport; + + +/* Thread to receive process-global signals. */ + +extern thread_t _hurd_sigthread; + + +/* Resource limit on core file size. Enforced by hurdsig.c. */ +extern int _hurd_core_limit; + +/* Critical sections. + + A critical section is a section of code which cannot safely be interrupted + to run a signal handler; for example, code that holds any lock cannot be + interrupted lest the signal handler try to take the same lock and + deadlock result. */ + +_HURD_SIGNAL_H_EXTERN_INLINE void * +_hurd_critical_section_lock (void) +{ + struct hurd_sigstate **location = (struct hurd_sigstate **) + (void *) __hurd_threadvar_location (_HURD_THREADVAR_SIGSTATE); + struct hurd_sigstate *ss = *location; + if (ss == NULL) + { + /* The thread variable is unset; this must be the first time we've + asked for it. In this case, the critical section flag cannot + possible already be set. Look up our sigstate structure the slow + way. */ + ss = *location = _hurd_thread_sigstate (__mach_thread_self ()); + } + + if (! __spin_try_lock (&ss->critical_section_lock)) + /* We are already in a critical section, so do nothing. */ + return NULL; + + /* With the critical section lock held no signal handler will run. + Return our sigstate pointer; this will be passed to + _hurd_critical_section_unlock to unlock it. */ + return ss; +} + +_HURD_SIGNAL_H_EXTERN_INLINE void +_hurd_critical_section_unlock (void *our_lock) +{ + if (our_lock == NULL) + /* The critical section lock was held when we began. Do nothing. */ + return; + else + { + /* It was us who acquired the critical section lock. Unlock it. */ + struct hurd_sigstate *ss = (struct hurd_sigstate *) our_lock; + sigset_t pending; + __spin_lock (&ss->lock); + __spin_unlock (&ss->critical_section_lock); + pending = ss->pending & ~ss->blocked; + __spin_unlock (&ss->lock); + if (! __sigisemptyset (&pending)) + /* There are unblocked signals pending, which weren't + delivered because we were in the critical section. + Tell the signal thread to deliver them now. */ + __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ()); + } +} + +/* Convenient macros for simple uses of critical sections. + These two must be used as a pair at the same C scoping level. */ + +#define HURD_CRITICAL_BEGIN \ + { void *__hurd_critical__ = _hurd_critical_section_lock () +#define HURD_CRITICAL_END \ + _hurd_critical_section_unlock (__hurd_critical__); } while (0) + +/* Initialize the signal code, and start the signal thread. + Arguments give the "init ints" from exec_startup. */ + +extern void _hurdsig_init (const int *intarray, size_t intarraysize); + +/* Initialize proc server-assisted fault recovery for the signal thread. */ + +extern void _hurdsig_fault_init (void); + +/* Raise a signal as described by SIGNO an DETAIL, on the thread whose + sigstate SS points to. If SS is a null pointer, this instead affects + the calling thread. */ + +extern int _hurd_raise_signal (struct hurd_sigstate *ss, int signo, + const struct hurd_signal_detail *detail); + +/* Translate a Mach exception into a signal (machine-dependent). */ + +extern void _hurd_exception2signal (struct hurd_signal_detail *detail, + int *signo); + + +/* Make the thread described by SS take the signal described by SIGNO and + DETAIL. If the process is traced, this will in fact stop with a SIGNO + as the stop signal unless UNTRACED is nonzero. When the signal can be + considered delivered, sends a sig_post reply message on REPLY_PORT + indicating success. SS is not locked. */ + +extern void _hurd_internal_post_signal (struct hurd_sigstate *ss, + int signo, + struct hurd_signal_detail *detail, + mach_port_t reply_port, + mach_msg_type_name_t reply_port_type, + int untraced); + +/* Set up STATE and SS to handle signal SIGNO by running HANDLER. If + RPC_WAIT is nonzero, the thread needs to wait for a pending RPC to + finish before running the signal handler. The handler is passed SIGNO, + SIGCODE, and the returned `struct sigcontext' (which resides on the + stack the handler will use, and which describes the state of the thread + encoded in STATE before running the handler). */ + +struct machine_thread_all_state; +extern struct sigcontext * +_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler, + int signo, struct hurd_signal_detail *detail, + int rpc_wait, struct machine_thread_all_state *state); + +/* Function run by the signal thread to receive from the signal port. */ + +extern void _hurd_msgport_receive (void); + +/* Set up STATE with a thread state that, when resumed, is + like `longjmp (_hurd_sigthread_fault_env, 1)'. */ + +extern void _hurd_initialize_fault_recovery_state (void *state); + +/* Set up STATE to do the equivalent of `longjmp (ENV, VAL);'. */ + +extern void _hurd_longjmp_thread_state (void *state, jmp_buf env, int value); + +/* Function run for SIGINFO when its action is SIG_DFL and the current + process is the session leader. */ + +extern void _hurd_siginfo_handler (int); + +/* Replacement for mach_msg used in RPCs to provide Hurd interruption + semantics. Args are all the same as for mach_msg. intr-rpc.h arranges + for this version to be used automatically by the RPC stubs the library + builds in place of the normal mach_msg. */ +error_t _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg, + mach_msg_option_t option, + mach_msg_size_t send_size, + mach_msg_size_t rcv_size, + mach_port_t rcv_name, + mach_msg_timeout_t timeout, + mach_port_t notify); + + +/* Milliseconds to wait for an interruptible RPC to return after + `interrupt_operation'. */ + +extern mach_msg_timeout_t _hurd_interrupted_rpc_timeout; + + +/* Mask of signals that cannot be caught, blocked, or ignored. */ +#define _SIG_CANT_MASK (__sigmask (SIGSTOP) | __sigmask (SIGKILL)) + +/* Do an RPC to a process's message port. + + Each argument is an expression which returns an error code; each + expression may be evaluated several times. FETCH_MSGPORT_EXPR should + fetch the appropriate message port and store it in the local variable + `msgport'; it will be deallocated after use. FETCH_REFPORT_EXPR should + fetch the appropriate message port and store it in the local variable + `refport' (if no reference port is needed in the call, then + FETCH_REFPORT_EXPR should be simply KERN_SUCCESS or 0); if + DEALLOC_REFPORT evaluates to nonzero it will be deallocated after use, + otherwise the FETCH_REFPORT_EXPR must take care of user references to + `refport'. RPC_EXPR should perform the desired RPC operation using + `msgport' and `refport'. + + The reason for the complexity is that a process's message port and + reference port may change between fetching those ports and completing an + RPC using them (usually they change only when a process execs). The RPC + will fail with MACH_SEND_INVALID_DEST if the msgport dies before we can + send the RPC request; or with MIG_SERVER_DIED if the msgport was + destroyed after we sent the RPC request but before it was serviced. In + either of these cases, we retry the entire operation, discarding the old + message and reference ports and fetch them anew. */ + +#define HURD_MSGPORT_RPC(fetch_msgport_expr, \ + fetch_refport_expr, dealloc_refport, \ + rpc_expr) \ +({ \ + error_t __err; \ + mach_port_t msgport, refport = MACH_PORT_NULL; \ + do \ + { \ + /* Get the message port. */ \ + __err = (error_t) (fetch_msgport_expr); \ + if (__err) \ + break; \ + /* Get the reference port. */ \ + __err = (error_t) (fetch_refport_expr); \ + if (__err) \ + { \ + /* Couldn't get it; deallocate MSGPORT and fail. */ \ + __mach_port_deallocate (__mach_task_self (), msgport); \ + break; \ + } \ + __err = (error_t) (rpc_expr); \ + __mach_port_deallocate (__mach_task_self (), msgport); \ + if ((dealloc_refport) && refport != MACH_PORT_NULL) \ + __mach_port_deallocate (__mach_task_self (), refport); \ + } while (__err == MACH_SEND_INVALID_DEST || \ + __err == MIG_SERVER_DIED); \ + __err; \ +}) + + +#endif /* hurd/signal.h */ diff --git a/REORG.TODO/hurd/hurd/sigpreempt.h b/REORG.TODO/hurd/hurd/sigpreempt.h new file mode 100644 index 0000000000..406f0f58fa --- /dev/null +++ b/REORG.TODO/hurd/hurd/sigpreempt.h @@ -0,0 +1,102 @@ +/* Preemption of Hurd signals before POSIX.1 semantics take over. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_SIGPREEMPT_H + +#define _HURD_SIGPREEMPT_H 1 +#include <errno.h> +#include <signal.h> /* For sigset_t, sighandler_t, SIG_ERR. */ +struct hurd_sigstate; /* <hurd/signal.h> */ +struct hurd_signal_detail; /* <hurd/signal.h> */ + +struct hurd_signal_preemptor + { + /* These members select which signals this structure will apply to. + The rest of the structure is only consulted if these match. */ + sigset_t signals; /* Signals preempted. */ + unsigned long int first, last; /* Range of sigcode values preempted. */ + + /* This function will be called (with SS->lock held) to decide what to + do with the signal described. It may modify the codes of the signal + passed. If the return value is SIG_ERR, the next matching preemptor + is tried, or the normal handling is done for the signal (which may + have been changed by the preemptor function). Otherwise, the signal + is processed as if the return value were its handler setting. */ + sighandler_t (*preemptor) (struct hurd_signal_preemptor *preemptor, + struct hurd_sigstate *ss, + int *signo, struct hurd_signal_detail *detail); + /* If PREEMPTOR is null, act as if it returned HANDLER. */ + sighandler_t handler; + + struct hurd_signal_preemptor *next; /* List structure. */ + }; + +#define HURD_PREEMPT_SIGNAL_P(preemptor, signo, sigcode) \ + (((preemptor)->signals & sigmask (signo)) && \ + (sigcode) >= (preemptor)->first && (sigcode) <= (preemptor)->last) + + +/* Signal preemptors applying to all threads; locked by _hurd_siglock. */ +extern struct hurd_signal_preemptor *_hurdsig_preemptors; +extern sigset_t _hurdsig_preempted_set; + + +/* The caller must initialize all members of *PREEMPTOR except `next'. + The preemptor is registered on the global list. */ +void hurd_preempt_signals (struct hurd_signal_preemptor *preemptor); + +/* Remove a preemptor registered with hurd_preempt_signals. */ +void hurd_unpreempt_signals (struct hurd_signal_preemptor *preemptor); + + +/* Call *OPERATE and return its value. If a signal in SIGSET with a sigcode + in the range [FIRST,LAST] arrives during the call, catch it. If HANDLER + is a function, it handles the signal in the normal way (i.e. it should + longjmp unless it can restart the insn on return). If it is SIG_ERR, + hurd_catch_signal returns the sc_error value from the signal (or + EGRATUITOUS if that is zero). + + The preemptor structure is passed to *OPERATE, which may modify its + sigcode range or functions at any time during which it is guaranteed no + signal in SIGSET will arrive. */ + +error_t hurd_catch_signal (sigset_t sigset, + unsigned long int first, unsigned long int last, + error_t (*operate) (struct hurd_signal_preemptor *), + sighandler_t handler); + + +/* Convenience functions using `hurd_catch_signal'. */ + + +/* Like `memset', but catch faults in DEST. */ +error_t hurd_safe_memset (void *dest, int byte, size_t nbytes); + +/* Like `memcpy', but catch faults in SRC. */ +error_t hurd_safe_copyin (void *dest, const void *src, size_t nbytes); + +/* Like `memcpy', but catch faults in DEST. */ +error_t hurd_safe_copyout (void *dest, const void *src, size_t nbytes); + +/* Like `memmove', but catch faults in SRC or DEST. + If only one region is expected to fault, it is more efficient + to use `hurd_safe_copyin' or `hurd_safe_copyout' as appropriate. */ +error_t hurd_safe_memmove (void *dest, const void *src, size_t nbytes); + + +#endif /* hurd/sigpreempt.h */ diff --git a/REORG.TODO/hurd/hurd/threadvar.h b/REORG.TODO/hurd/hurd/threadvar.h new file mode 100644 index 0000000000..72982e1744 --- /dev/null +++ b/REORG.TODO/hurd/hurd/threadvar.h @@ -0,0 +1,116 @@ +/* Internal per-thread variables for the Hurd. + Copyright (C) 1994-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_THREADVAR_H +#define _HURD_THREADVAR_H + +#include <features.h> + +/* The per-thread variables are found by ANDing this mask + with the value of the stack pointer and then adding this offset. + + In the multi-threaded case, cthreads initialization sets + __hurd_threadvar_stack_mask to ~(cthread_stack_size - 1), a mask which + finds the base of the fixed-size cthreads stack; and + __hurd_threadvar_stack_offset to a small offset that skips the data + cthreads itself maintains at the base of each thread's stack. + + In the single-threaded case, __hurd_threadvar_stack_mask is zero, so the + stack pointer is ignored; and __hurd_threadvar_stack_offset gives the + address of a small allocated region which contains the variables for the + single thread. */ + +extern unsigned long int __hurd_threadvar_stack_mask; +extern unsigned long int __hurd_threadvar_stack_offset; + +/* A special case must always be made for the signal thread. Even when there + is only one user thread and an allocated region can be used for the user + thread's variables, the signal thread needs to have its own location for + per-thread variables. The variables __hurd_sigthread_stack_base and + __hurd_sigthread_stack_end define the bounds of the stack used by the + signal thread, so that thread can always be specifically identified. */ + +extern unsigned long int __hurd_sigthread_stack_base; +extern unsigned long int __hurd_sigthread_stack_end; +extern unsigned long int *__hurd_sigthread_variables; + + +/* At the location described by the two variables above, + there are __hurd_threadvar_max `unsigned long int's of per-thread data. */ +extern unsigned int __hurd_threadvar_max; + +/* These values are the indices for the standard per-thread variables. */ +enum __hurd_threadvar_index + { + _HURD_THREADVAR_MIG_REPLY, /* Reply port for MiG user stub functions. */ + _HURD_THREADVAR_ERRNO, /* `errno' value for this thread. */ + _HURD_THREADVAR_SIGSTATE, /* This thread's `struct hurd_sigstate'. */ + _HURD_THREADVAR_DYNAMIC_USER, /* Dynamically-assigned user variables. */ + _HURD_THREADVAR_MALLOC, /* For use of malloc. */ + _HURD_THREADVAR_DL_ERROR, /* For use of -ldl and dynamic linker. */ + _HURD_THREADVAR_RPC_VARS, /* For state of RPC functions. */ + _HURD_THREADVAR_LOCALE, /* For thread-local locale setting. */ + _HURD_THREADVAR_CTYPE_B, /* Cache of thread-local locale data. */ + _HURD_THREADVAR_CTYPE_TOLOWER, /* Cache of thread-local locale data. */ + _HURD_THREADVAR_CTYPE_TOUPPER, /* Cache of thread-local locale data. */ + _HURD_THREADVAR_MAX /* Default value for __hurd_threadvar_max. */ + }; + + +#ifndef _HURD_THREADVAR_H_EXTERN_INLINE +#define _HURD_THREADVAR_H_EXTERN_INLINE __extern_inline +#endif + +/* Return the location of the value for the per-thread variable with index + INDEX used by the thread whose stack pointer is SP. */ + +extern unsigned long int *__hurd_threadvar_location_from_sp + (enum __hurd_threadvar_index __index, void *__sp); +_HURD_THREADVAR_H_EXTERN_INLINE unsigned long int * +__hurd_threadvar_location_from_sp (enum __hurd_threadvar_index __index, + void *__sp) +{ + unsigned long int __stack = (unsigned long int) __sp; + return &((__stack >= __hurd_sigthread_stack_base && + __stack < __hurd_sigthread_stack_end) + ? __hurd_sigthread_variables + : (unsigned long int *) ((__stack & __hurd_threadvar_stack_mask) + + __hurd_threadvar_stack_offset))[__index]; +} + +#include <machine-sp.h> /* Define __thread_stack_pointer. */ + +/* Return the location of the current thread's value for the + per-thread variable with index INDEX. */ + +extern unsigned long int * +__hurd_threadvar_location (enum __hurd_threadvar_index __index) __THROW + /* This declaration tells the compiler that the value is constant + given the same argument. We assume this won't be called twice from + the same stack frame by different threads. */ + __attribute__ ((__const__)); + +_HURD_THREADVAR_H_EXTERN_INLINE unsigned long int * +__hurd_threadvar_location (enum __hurd_threadvar_index __index) +{ + return __hurd_threadvar_location_from_sp (__index, + __thread_stack_pointer ()); +} + + +#endif /* hurd/threadvar.h */ diff --git a/REORG.TODO/hurd/hurd/userlink.h b/REORG.TODO/hurd/hurd/userlink.h new file mode 100644 index 0000000000..4946402df5 --- /dev/null +++ b/REORG.TODO/hurd/hurd/userlink.h @@ -0,0 +1,147 @@ +/* Support for chains recording users of a resource; `struct hurd_userlink'. + Copyright (C) 1994-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_USERLINK_H + +#define _HURD_USERLINK_H 1 +#include <features.h> + +#define __need_NULL +#include <stddef.h> + +#include <hurd/signal.h> +#include <setjmp.h> + + +/* This structure records a link in two doubly-linked lists. + We call these the per-resource user list and the per-thread + active-resource list. + + Users of a given resource are recorded by their presence in a list + associated with that resource. A user attaches his own link (in local + storage on his stack) to a shared chain at the time he begins using some + resource. When finished with that resource, the user removes his link + from the chain. If his link is the last (there are no other users of + the resource), and his chain has been detached from the shared cell (the + resource in the cell has been replaced), then the user deallocates the + resource that he used. + + All uses of shared resources by a single thread are linked together by + its `active-resource' list; the head of this list is stored in the + per-thread sigstate structure. When the thread makes a non-local exit + (i.e. longjmp), it will examine its active-resource list, and each link + residing in a stack frame being jumped out of will be unlinked from both + the resource's user list and the thread's active-resource list, and + deallocate the resource if that was the last user link for that resource. + + NOTE: Access to a thread's active-resource list must always be done + inside a signal-proof critical section; the functions in this file + assume they are called inside a critical section, and do no locking of + their own. Also important: the longjmp cleanup relies on all userlink + structures residing on the stack of the using thread. */ + +struct hurd_userlink + { + struct + { + struct hurd_userlink *next, **prevp; + } resource, thread; + + /* This function is called when a non-local exit + unwinds the frame containing this link. */ + void (*cleanup) (void *cleanup_data, jmp_buf env, int val); + void *cleanup_data; + }; + + +#ifndef _HURD_USERLINK_H_EXTERN_INLINE +#define _HURD_USERLINK_H_EXTERN_INLINE __extern_inline +#endif + + +/* Attach LINK to the chain of users at *CHAINP. */ + +_HURD_USERLINK_H_EXTERN_INLINE void +_hurd_userlink_link (struct hurd_userlink **chainp, + struct hurd_userlink *link) +{ + struct hurd_userlink **thread_chainp; + + link->resource.next = *chainp; + if (link->resource.next) + link->resource.next->resource.prevp = &link->resource.next; + link->resource.prevp = chainp; + *chainp = link; + + /* Also chain it on the current thread's list of active resources. */ + thread_chainp = &_hurd_self_sigstate ()->active_resources; + link->thread.next = *thread_chainp; + if (link->thread.next) + link->thread.next->thread.prevp = &link->thread.next; + link->thread.prevp = thread_chainp; + *thread_chainp = link; +} + + +/* Detach LINK from its chain. Returns nonzero iff this was the + last user of the resource and it should be deallocated. */ + +_HURD_USERLINK_H_EXTERN_INLINE int +_hurd_userlink_unlink (struct hurd_userlink *link) +{ + /* We should deallocate the resource used if this chain has been detached + from the cell (and thus has a nil `prevp'), and there is no next link + representing another user reference to the same resource. */ + int dealloc = ! link->resource.next && ! link->resource.prevp; + + /* Remove our link from the chain of current users. */ + if (link->resource.prevp) + *link->resource.prevp = link->resource.next; + if (link->resource.next) + link->resource.next->resource.prevp = link->resource.prevp; + + /* Remove our link from the chain of currently active resources + for this thread. */ + *link->thread.prevp = link->thread.next; + if (link->thread.next) + link->thread.next->thread.prevp = link->thread.prevp; + + return dealloc; +} + + +/* Clear all users from *CHAINP. Call this when the resource *CHAINP + protects is changing. If the return value is nonzero, no users are on + the chain and the caller should deallocate the resource. If the return + value is zero, someone is still using the resource and they will + deallocate it when they are finished. */ + +_HURD_USERLINK_H_EXTERN_INLINE int +_hurd_userlink_clear (struct hurd_userlink **chainp) +{ + if (*chainp == NULL) + return 1; + + /* Detach the chain of current users from the cell. The last user to + remove his link from that chain will deallocate the old resource. */ + (*chainp)->resource.prevp = NULL; + *chainp = NULL; + return 0; +} + +#endif /* hurd/userlink.h */ diff --git a/REORG.TODO/hurd/hurd/xattr.h b/REORG.TODO/hurd/hurd/xattr.h new file mode 100644 index 0000000000..bc4c2ce451 --- /dev/null +++ b/REORG.TODO/hurd/hurd/xattr.h @@ -0,0 +1,34 @@ +/* Access to extended attributes on files for GNU/Hurd. + Copyright (C) 2005-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _HURD_XATTR_H +#define _HURD_XATTR_H 1 + +#include <sys/xattr.h> /* This defines the XATTR_* flags. */ + +/* These are the internal versions of getxattr/setxattr/listxattr. */ +extern error_t _hurd_xattr_get (io_t port, const char *name, + void *value, size_t *size); +extern error_t _hurd_xattr_set (io_t port, const char *name, + const void *value, size_t size, int flags); +extern error_t _hurd_xattr_remove (io_t port, const char *name); +extern error_t _hurd_xattr_list (io_t port, void *buffer, size_t *size); + + + +#endif /* hurd/xattr.h */ |