summaryrefslogtreecommitdiff
path: root/libports/introspection.c
diff options
context:
space:
mode:
Diffstat (limited to 'libports/introspection.c')
-rw-r--r--libports/introspection.c189
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;
+}