diff options
Diffstat (limited to 'libports/introspection.c')
-rw-r--r-- | libports/introspection.c | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/libports/introspection.c b/libports/introspection.c new file mode 100644 index 00000000..05aee92f --- /dev/null +++ b/libports/introspection.c @@ -0,0 +1,189 @@ +/* Hurd server introspection. + + Copyright (C) 2014 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd 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. + + 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. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */ + +#include <error.h> +#include <hurd/introspection.h> +#include <pthread.h> +#include <stdio.h> +#include <string.h> + +#include "ports.h" +#include "hurd_port_U.h" + +/* We service introspection requests on this port. */ +static mach_port_t introspection_port; + +/* We use a separate thread to service the introspection requests. It + is a straight forward Mach server for the hurd_port protocol. */ +static void * +service_introspection_requests (void *arg) +{ + error_t err; + + err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, + &introspection_port); + if (err) + { + error (0, err, "mach_port_allocate"); + return NULL; + } + + err = mach_port_insert_right (mach_task_self (), + introspection_port, introspection_port, + MACH_MSG_TYPE_MAKE_SEND); + if (err) + { + error (0, err, "mach_port_insert_right"); + return NULL; + } + + err = introspection_set_port (mach_task_self (), introspection_port); + if (err) + { + error (0, err, "introspection_set_port"); + return NULL; + } + + /* XXX mig should emit this declaration. */ + boolean_t ports_hurd_port_server (mach_msg_header_t *InHeadP, + mach_msg_header_t *OutHeadP); + + while (1) + mach_msg_server (ports_hurd_port_server, 0, introspection_port); + + /* Not reached. */ + return NULL; +} + +/* Start the introspection server before main is called. */ +static void __attribute__ ((constructor)) +init (void) +{ + error_t err; + + pthread_t thread; + pthread_attr_t attr; +#define STACK_SIZE (64 * 1024) + pthread_attr_init (&attr); + pthread_attr_setstacksize (&attr, STACK_SIZE); +#undef STACK_SIZE + + err = pthread_create (&thread, &attr, + service_introspection_requests, NULL); + if (err) + error (1, err, "pthread_create"); + pthread_detach (thread); +} + +/* Return the number of hard and weak references of the object + directly associated with the receive right NAME. + + Return EINVAL if NAME does not denote a receive right managed by + the port-to-object mapper, or if the concept of reference counting + simply does not apply. */ +error_t +ports_S_hurd_port_get_refcounts (mach_port_t port, + mach_port_t name, + natural_t *hard, + natural_t *weak) +{ + struct references result; + struct port_info *pi; + + if (port != introspection_port) + return EOPNOTSUPP; + + pi = ports_lookup_port (0, name, 0); + if (pi == NULL) + return EINVAL; + + refcounts_references (&pi->refcounts, &result); + + *hard = result.hard - 1; + *weak = result.weak; + ports_port_deref (pi); + return 0; +} + +static error_t +default_debug_info (const void *port, char *buffer, size_t size) +{ + const struct port_info *pi = port; + snprintf (buffer, size, + "bucket: %s, class: %s", + pi->bucket->label, pi->class->label); + return 0; +} + +/* Return a compact, human-readable description of the object related + with the receive right NAME. + + This description is meant for debugging purposes and should include + relevant internal state. If possible, it should include + information that is meaningful in other contexts (like a file name, + or the inode number). + + Return EINVAL if NAME does not denote a receive right managed by + the port-to-object mapper. */ +error_t +ports_S_hurd_port_debug_info (mach_port_t port, + mach_port_t name, + char *info) +{ + error_t err; + struct port_info *pi; + + if (port != introspection_port) + return EOPNOTSUPP; + + pi = ports_lookup_port (0, name, 0); + if (pi == NULL) + return EINVAL; + + if (pi->class->debug_info) + err = pi->class->debug_info (pi, info, 1024 /* XXX */); + else + err = default_debug_info (pi, info, 1024 /* XXX */); + info[1023] = 0; + + ports_port_deref (pi); + return err; +} + +error_t +ports_S_hurd_port_trace_class_rpcs (mach_port_t port, + mach_port_t name, + mach_port_t trace_port) +{ + struct port_info *pi; + + if (port != introspection_port) + return EOPNOTSUPP; + + pi = ports_lookup_port (0, name, 0); + if (pi == NULL) + return EINVAL; + + if (MACH_PORT_VALID (pi->class->trace_port)) + mach_port_deallocate (mach_task_self (), pi->class->trace_port); + + pi->class->trace_port = trace_port; + + return 0; +} |