summaryrefslogtreecommitdiff
path: root/debian/patches/0023-libports-implement-the-Hurd-server-introspection-pro.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/0023-libports-implement-the-Hurd-server-introspection-pro.patch')
-rw-r--r--debian/patches/0023-libports-implement-the-Hurd-server-introspection-pro.patch328
1 files changed, 328 insertions, 0 deletions
diff --git a/debian/patches/0023-libports-implement-the-Hurd-server-introspection-pro.patch b/debian/patches/0023-libports-implement-the-Hurd-server-introspection-pro.patch
new file mode 100644
index 00000000..243f5a96
--- /dev/null
+++ b/debian/patches/0023-libports-implement-the-Hurd-server-introspection-pro.patch
@@ -0,0 +1,328 @@
+From d494a068b98f79a7c454802a52eddbff3350acbc Mon Sep 17 00:00:00 2001
+From: Justus Winter <4winter@informatik.uni-hamburg.de>
+Date: Wed, 21 May 2014 16:47:14 +0200
+Subject: [PATCH 23/27] libports: implement the Hurd server introspection
+ protocol
+
+Add a compact and self-contained introspection server to libports.
+Add functions to to label port buckets and classes. Make it possible
+to provide a function that given an object of a class, returns a
+human-readable representation for it.
+
+* libports/introspection.c: New file.
+* libports/create-bucket.c (ports_label_bucket): New function.
+* libports/create-class.c (ports_set_debug_info): Likewise.
+* libports/ports.h (struct port_bucket): Add label.
+(struct port_class): Add debug_info and label.
+(ports_label_bucket): New declaration.
+(ports_set_debug_info): Likewise.
+* libports/Makefile (SRCS): Add introspection.c.
+(OBJS): Add hurd_portServer.o.
+---
+ libports/Makefile | 4 +-
+ libports/create-bucket.c | 7 ++
+ libports/create-class.c | 15 ++++
+ libports/introspection.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++
+ libports/ports.h | 12 ++++
+ 5 files changed, 218 insertions(+), 2 deletions(-)
+ create mode 100644 libports/introspection.c
+
+diff --git a/libports/Makefile b/libports/Makefile
+index 30da1c1..6c7f5df 100644
+--- a/libports/Makefile
++++ b/libports/Makefile
+@@ -36,13 +36,13 @@ SRCS = create-bucket.c create-class.c \
+ interrupt-operation.c interrupt-on-notify.c interrupt-notified-rpcs.c \
+ dead-name.c create-port.c import-port.c default-uninhibitable-rpcs.c \
+ claim-right.c transfer-right.c create-port-noinstall.c create-internal.c \
+- interrupted.c
++ interrupted.c introspection.c
+
+ installhdrs = ports.h
+
+ HURDLIBS= ihash
+ LDLIBS += -lpthread
+-OBJS = $(SRCS:.c=.o) notifyServer.o interruptServer.o
++OBJS = $(SRCS:.c=.o) notifyServer.o interruptServer.o hurd_portServer.o
+
+ MIGCOMSFLAGS = -prefix ports_
+ MIGSFLAGS = -imacros $(srcdir)/mig-mutate.h
+diff --git a/libports/create-bucket.c b/libports/create-bucket.c
+index 2c5f1b6..51168cb 100644
+--- a/libports/create-bucket.c
++++ b/libports/create-bucket.c
+@@ -48,5 +48,12 @@ ports_create_bucket ()
+
+ hurd_ihash_init (&ret->htable, offsetof (struct port_info, hentry));
+ ret->rpcs = ret->flags = ret->count = 0;
++ ret->label = "unlabeled bucket";
+ return ret;
+ }
++
++/* Label BUCKET with LABEL. */
++void ports_label_bucket (struct port_bucket *bucket, const char *label)
++{
++ bucket->label = label;
++}
+diff --git a/libports/create-class.c b/libports/create-class.c
+index 782f52b..fbce9d9 100644
+--- a/libports/create-class.c
++++ b/libports/create-class.c
+@@ -41,6 +41,21 @@ ports_create_class (void (*clean_routine)(void *),
+ cl->rpcs = 0;
+ cl->count = 0;
+ cl->uninhibitable_rpcs = ports_default_uninhibitable_rpcs;
++ cl->debug_info = NULL;
++ cl->label = "unlabeled class";
+
+ return cl;
+ }
++
++/* Label BUCKET with LABEL. Use DEBUG_INFO to format human-readable
++ information about a given object belonging to CLASS into an buffer,
++ or the default formatting function if DEBUG_INFO is NULL. */
++void
++ports_set_debug_info (struct port_class *class,
++ const char *label,
++ error_t (*debug_info) (const void *, char *, size_t))
++{
++ class->label = label;
++ if (debug_info)
++ class->debug_info = debug_info;
++}
+diff --git a/libports/introspection.c b/libports/introspection.c
+new file mode 100644
+index 0000000..dcebd6b
+--- /dev/null
++++ b/libports/introspection.c
+@@ -0,0 +1,182 @@
++/* 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 <mach/mach_param.h>
++#include <pthread.h>
++#include <stdio.h>
++#include <string.h>
++
++#include "ports.h"
++#include "hurd_port_S.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;
++ mach_port_t *ports;
++ size_t ports_len;
++
++ 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 = mach_ports_lookup (mach_task_self (),
++ &ports, &ports_len);
++ if (err)
++ {
++ error (0, err, "mach_ports_lookup");
++ return NULL;
++ }
++
++ ports[HURD_PORT_REGISTER_INTROSPECTION] = introspection_port;
++
++ err = mach_ports_register (mach_task_self (),
++ ports,
++ HURD_PORT_REGISTER_MAX);
++ if (err)
++ {
++ error (0, err, "mach_ports_register");
++ 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;
++}
+diff --git a/libports/ports.h b/libports/ports.h
+index 3439443..18eb5cb 100644
+--- a/libports/ports.h
++++ b/libports/ports.h
+@@ -65,6 +65,7 @@ struct port_bucket
+ int rpcs;
+ int flags;
+ int count;
++ const char *label;
+ };
+ /* FLAGS above are the following: */
+ #define PORT_BUCKET_INHIBITED PORTS_INHIBITED
+@@ -80,7 +81,9 @@ struct port_class
+ int count;
+ void (*clean_routine) (void *);
+ void (*dropweak_routine) (void *);
++ error_t (*debug_info) (const void *, char *, size_t);
+ struct ports_msg_id_range *uninhibitable_rpcs;
++ const char *label;
+ };
+ /* FLAGS are the following: */
+ #define PORT_CLASS_INHIBITED PORTS_INHIBITED
+@@ -149,6 +152,9 @@ extern struct ports_msg_id_range *ports_default_uninhibitable_rpcs;
+ /* Create and return a new bucket. */
+ struct port_bucket *ports_create_bucket (void);
+
++/* Label BUCKET with LABEL. */
++void ports_label_bucket (struct port_bucket *bucket, const char *label);
++
+ /* Create and return a new port class. If nonzero, CLEAN_ROUTINE will
+ be called for each allocated port object in this class when it is
+ being destroyed. If nonzero, DROPWEAK_ROUTINE will be called
+@@ -158,6 +164,12 @@ struct port_bucket *ports_create_bucket (void);
+ struct port_class *ports_create_class (void (*clean_routine)(void *),
+ void (*dropweak_routine)(void *));
+
++/* Label BUCKET with LABEL. Use DEBUG_INFO to format human-readable
++ information about a given object belonging to CLASS into an buffer,
++ or the default formatting function if DEBUG_INFO is NULL. */
++void ports_set_debug_info (struct port_class *class, const char *label,
++ error_t (*debug_info) (const void *, char *, size_t));
++
+ /* Create and return in RESULT a new port in CLASS and BUCKET; SIZE bytes
+ will be allocated to hold the port structure and whatever private data the
+ user desires. */
+--
+2.0.0.rc2
+