summaryrefslogtreecommitdiff
path: root/debian/patches/introspection0003-libports-implement-the-Hurd-server-introspection-pro.patch
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/introspection0003-libports-implement-the-Hurd-server-introspection-pro.patch')
-rw-r--r--debian/patches/introspection0003-libports-implement-the-Hurd-server-introspection-pro.patch481
1 files changed, 481 insertions, 0 deletions
diff --git a/debian/patches/introspection0003-libports-implement-the-Hurd-server-introspection-pro.patch b/debian/patches/introspection0003-libports-implement-the-Hurd-server-introspection-pro.patch
new file mode 100644
index 00000000..43d8f846
--- /dev/null
+++ b/debian/patches/introspection0003-libports-implement-the-Hurd-server-introspection-pro.patch
@@ -0,0 +1,481 @@
+From 798eae80f9de731d0dc3ff5bb8172cef99cad207 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 hurd 03/10] 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/manage-multithread.c (internal_demuxer): Trace messages if
+desired.
+* libports/manage-one-thread.c (internal_demuxer): 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.
+---
+ ext2fs/Makefile | 3 +-
+ fatfs/Makefile | 3 +-
+ isofs/Makefile | 3 +-
+ libports/Makefile | 6 +-
+ libports/create-bucket.c | 7 ++
+ libports/create-class.c | 16 ++++
+ libports/introspection.c | 189 ++++++++++++++++++++++++++++++++++++++++++
+ libports/manage-multithread.c | 10 +++
+ libports/manage-one-thread.c | 11 +++
+ libports/ports.h | 14 ++++
+ tmpfs/Makefile | 3 +-
+ 11 files changed, 258 insertions(+), 7 deletions(-)
+ create mode 100644 libports/introspection.c
+
+diff --git a/ext2fs/Makefile b/ext2fs/Makefile
+index 8d2e68c..9d72fda 100644
+--- a/ext2fs/Makefile
++++ b/ext2fs/Makefile
+@@ -23,7 +23,8 @@ target = ext2fs
+ SRCS = balloc.c dir.c ext2fs.c getblk.c hyper.c ialloc.c \
+ inode.c pager.c pokel.c truncate.c storeinfo.c msg.c xinl.c
+ OBJS = $(SRCS:.c=.o)
+-HURDLIBS = diskfs pager iohelp fshelp store ports ihash shouldbeinlibc
++HURDLIBS = diskfs pager iohelp fshelp store ports ihash introspection \
++ shouldbeinlibc
+ OTHERLIBS = -lpthread $(and $(HAVE_LIBBZ2),-lbz2) $(and $(HAVE_LIBZ),-lz)
+
+ include ../Makeconf
+diff --git a/fatfs/Makefile b/fatfs/Makefile
+index 6224b64..e4f01ec 100644
+--- a/fatfs/Makefile
++++ b/fatfs/Makefile
+@@ -22,7 +22,8 @@ target = fatfs
+ SRCS = inode.c main.c dir.c pager.c fat.c virt-inode.c node-create.c
+
+ OBJS = $(SRCS:.c=.o)
+-HURDLIBS = diskfs iohelp fshelp store pager ports ihash shouldbeinlibc
++HURDLIBS = diskfs iohelp fshelp store pager ports ihash introspection \
++ shouldbeinlibc
+ OTHERLIBS = -lpthread $(and $(HAVE_LIBBZ2),-lbz2) $(and $(HAVE_LIBZ),-lz)
+
+ include ../Makeconf
+diff --git a/isofs/Makefile b/isofs/Makefile
+index 6475c52..9e399bf 100644
+--- a/isofs/Makefile
++++ b/isofs/Makefile
+@@ -21,7 +21,8 @@ target = iso9660fs
+ SRCS = inode.c main.c lookup.c pager.c rr.c
+
+ OBJS = $(SRCS:.c=.o)
+-HURDLIBS = diskfs iohelp fshelp store pager ports ihash shouldbeinlibc
++HURDLIBS = diskfs iohelp fshelp store pager ports ihash introspection \
++ shouldbeinlibc
+ OTHERLIBS = -lpthread $(and $(HAVE_LIBBZ2),-lbz2) $(and $(HAVE_LIBZ),-lz)
+
+ include ../Makeconf
+diff --git a/libports/Makefile b/libports/Makefile
+index af881f8..ec98bad 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 extern-inline.c port-deref-deferred.c
++ interrupted.c extern-inline.c port-deref-deferred.c introspection.c
+
+ installhdrs = ports.h port-deref-deferred.h
+
+-HURDLIBS= ihash
++HURDLIBS= ihash introspection
+ 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 82c00a4..34559f5 100644
+--- a/libports/create-bucket.c
++++ b/libports/create-bucket.c
+@@ -49,5 +49,12 @@ ports_create_bucket ()
+ hurd_ihash_init (&ret->htable, offsetof (struct port_info, hentry));
+ ret->rpcs = ret->flags = ret->count = 0;
+ _ports_threadpool_init (&ret->threadpool);
++ 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..8abf643 100644
+--- a/libports/create-class.c
++++ b/libports/create-class.c
+@@ -41,6 +41,22 @@ 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";
++ cl->trace_port = MACH_PORT_NULL;
+
+ return cl;
+ }
++
++/* Label CLASS 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_label_class (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..912c768
+--- /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 /* XXX */] = 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;
++ ports_port_deref (pi);
++ return 0;
++}
+diff --git a/libports/manage-multithread.c b/libports/manage-multithread.c
+index 60743d9..8707d98 100644
+--- a/libports/manage-multithread.c
++++ b/libports/manage-multithread.c
+@@ -21,6 +21,7 @@
+ #include "ports.h"
+ #include <assert.h>
+ #include <error.h>
++#include <hurd/introspection.h>
+ #include <stdio.h>
+ #include <mach/message.h>
+ #include <mach/thread_info.h>
+@@ -189,6 +190,11 @@ ports_manage_port_operations_multithread (struct port_bucket *bucket,
+
+ if (pi)
+ {
++ mach_port_t trace_port = pi->class->trace_port;
++ mach_port_t trace_id;
++ if (__builtin_expect (MACH_PORT_VALID (trace_port), 0))
++ introspection_trace_request (trace_port, inp, &trace_id);
++
+ error_t err = ports_begin_rpc (pi, inp->msgh_id, &link);
+ if (err)
+ {
+@@ -207,6 +213,10 @@ ports_manage_port_operations_multithread (struct port_bucket *bucket,
+ ports_end_rpc (pi, &link);
+ }
+ ports_port_deref (pi);
++
++ if (__builtin_expect (MACH_PORT_VALID (trace_port), 0)
++ && outp->RetCode != MIG_NO_REPLY)
++ introspection_trace_message (trace_port, outp, trace_id);
+ }
+ else
+ {
+diff --git a/libports/manage-one-thread.c b/libports/manage-one-thread.c
+index b920338..55aa378 100644
+--- a/libports/manage-one-thread.c
++++ b/libports/manage-one-thread.c
+@@ -18,6 +18,8 @@
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
++#include <hurd/introspection.h>
++
+ #include "ports.h"
+
+ void
+@@ -80,6 +82,11 @@ ports_manage_port_operations_one_thread (struct port_bucket *bucket,
+
+ if (pi)
+ {
++ mach_port_t trace_port = pi->class->trace_port;
++ mach_port_t trace_id;
++ if (__builtin_expect (MACH_PORT_VALID (trace_port), 0))
++ introspection_trace_request (trace_port, inp, &trace_id);
++
+ err = ports_begin_rpc (pi, inp->msgh_id, &link);
+ if (err)
+ {
+@@ -96,6 +103,10 @@ ports_manage_port_operations_one_thread (struct port_bucket *bucket,
+ ports_end_rpc (pi, &link);
+ }
+ ports_port_deref (pi);
++
++ if (__builtin_expect (MACH_PORT_VALID (trace_port), 0)
++ && outp->RetCode != MIG_NO_REPLY)
++ introspection_trace_message (trace_port, outp, trace_id);
+ }
+ else
+ {
+diff --git a/libports/ports.h b/libports/ports.h
+index 9299bc4..a31b894 100644
+--- a/libports/ports.h
++++ b/libports/ports.h
+@@ -76,6 +76,7 @@ struct port_bucket
+ int flags;
+ int count;
+ struct ports_threadpool threadpool;
++ const char *label;
+ };
+ /* FLAGS above are the following: */
+ #define PORT_BUCKET_INHIBITED PORTS_INHIBITED
+@@ -91,7 +92,10 @@ 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;
++ mach_port_t trace_port;
+ };
+ /* FLAGS are the following: */
+ #define PORT_CLASS_INHIBITED PORTS_INHIBITED
+@@ -160,6 +164,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
+@@ -169,6 +176,12 @@ struct port_bucket *ports_create_bucket (void);
+ struct port_class *ports_create_class (void (*clean_routine)(void *),
+ void (*dropweak_routine)(void *));
+
++/* Label CLASS 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_label_class (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. */
+@@ -482,5 +495,6 @@ extern int _ports_flags;
+ void _ports_complete_deallocate (struct port_info *);
+ error_t _ports_create_port_internal (struct port_class *, struct port_bucket *,
+ size_t, void *, int);
++error_t _ports_trace_message (mach_port_t, const mach_msg_header_t *);
+
+ #endif
+diff --git a/tmpfs/Makefile b/tmpfs/Makefile
+index fdcae34..fc27909 100644
+--- a/tmpfs/Makefile
++++ b/tmpfs/Makefile
+@@ -23,7 +23,8 @@ target = tmpfs
+ SRCS = tmpfs.c node.c dir.c pager-stubs.c
+ OBJS = $(SRCS:.c=.o) default_pagerUser.o
+ # XXX The shared libdiskfs requires libstore even though we don't use it here.
+-HURDLIBS = diskfs pager iohelp fshelp store ports ihash shouldbeinlibc
++HURDLIBS = diskfs pager iohelp fshelp store ports ihash introspection \
++ shouldbeinlibc
+ OTHERLIBS = -lpthread
+
+ include ../Makeconf
+--
+2.1.4
+