summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/patches/0001-ipc-rework-the-ikm-cache-XXX.patch302
-rw-r--r--debian/patches/0002-ipc-use-ikm-cache-for-kernel-messages.patch37
-rw-r--r--debian/patches/series2
3 files changed, 341 insertions, 0 deletions
diff --git a/debian/patches/0001-ipc-rework-the-ikm-cache-XXX.patch b/debian/patches/0001-ipc-rework-the-ikm-cache-XXX.patch
new file mode 100644
index 0000000..2d56474
--- /dev/null
+++ b/debian/patches/0001-ipc-rework-the-ikm-cache-XXX.patch
@@ -0,0 +1,302 @@
+From 613e532f48474ff4be6948fe635fb0642e522f48 Mon Sep 17 00:00:00 2001
+From: Justus Winter <4winter@informatik.uni-hamburg.de>
+Date: Wed, 17 Dec 2014 14:21:15 +0100
+Subject: [PATCH gnumach 1/2] ipc: rework the ikm cache XXX
+
+---
+ ipc/ipc_kmsg.c | 29 ++++------------------
+ ipc/ipc_kmsg.h | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++---
+ ipc/mach_msg.c | 18 ++++++--------
+ kern/exception.c | 28 +++++----------------
+ kern/ipc_kobject.c | 6 +----
+ 5 files changed, 89 insertions(+), 65 deletions(-)
+
+diff --git a/ipc/ipc_kmsg.c b/ipc/ipc_kmsg.c
+index 66643fd..04cdbc9 100644
+--- a/ipc/ipc_kmsg.c
++++ b/ipc/ipc_kmsg.c
+@@ -73,7 +73,7 @@
+ #define ptr_align(x) \
+ ( ( ((vm_offset_t)(x)) + (sizeof(vm_offset_t)-1) ) & ~(sizeof(vm_offset_t)-1) )
+
+-ipc_kmsg_t ipc_kmsg_cache[NCPUS];
++struct ipc_kmsg_cpu_cache ipc_kmsg_cache[NCPUS];
+
+ /*
+ * Routine: ipc_kmsg_enqueue
+@@ -506,23 +506,9 @@ ipc_kmsg_get(
+ if ((size < sizeof(mach_msg_header_t)) || (size & 3))
+ return MACH_SEND_MSG_TOO_SMALL;
+
+- if (size <= IKM_SAVED_MSG_SIZE) {
+- kmsg = ikm_cache();
+- if (kmsg != IKM_NULL) {
+- ikm_cache() = IKM_NULL;
+- ikm_check_initialized(kmsg, IKM_SAVED_KMSG_SIZE);
+- } else {
+- kmsg = ikm_alloc(IKM_SAVED_MSG_SIZE);
+- if (kmsg == IKM_NULL)
+- return MACH_SEND_NO_BUFFER;
+- ikm_init(kmsg, IKM_SAVED_MSG_SIZE);
+- }
+- } else {
+- kmsg = ikm_alloc(size);
+- if (kmsg == IKM_NULL)
+- return MACH_SEND_NO_BUFFER;
+- ikm_init(kmsg, size);
+- }
++ kmsg = ikm_cache_get (size);
++ if (kmsg == IKM_NULL)
++ return MACH_SEND_NO_BUFFER;
+
+ if (copyinmsg(msg, &kmsg->ikm_header, size)) {
+ ikm_free(kmsg);
+@@ -599,12 +585,7 @@ ipc_kmsg_put(
+ else
+ mr = MACH_MSG_SUCCESS;
+
+- if ((kmsg->ikm_size == IKM_SAVED_KMSG_SIZE) &&
+- (ikm_cache() == IKM_NULL))
+- ikm_cache() = kmsg;
+- else
+- ikm_free(kmsg);
+-
++ ikm_cache_put (kmsg);
+ return mr;
+ }
+
+diff --git a/ipc/ipc_kmsg.h b/ipc/ipc_kmsg.h
+index 620785b..231fcaf 100644
+--- a/ipc/ipc_kmsg.h
++++ b/ipc/ipc_kmsg.h
+@@ -96,11 +96,30 @@ MACRO_END
+ * The per-processor cache seems to miss less than a per-thread cache,
+ * and it also uses less memory. Access to the cache doesn't
+ * require locking.
++ *
++ * The per-processor cache is a stack containing unused kernel
++ * message buffers. We choose IKM_CACHE_SIZE so that the size of
++ * the struct ipc_kmsg_cpu_cache is a multiple of a cache line,
++ * to prevent it bouncing between per-cpu caches.
++ *
++ * A kernel message buffer can be allocated using
++ * `ikm_cache_get', and returned using `ikm_cache_put'.
+ */
+
+-extern ipc_kmsg_t ipc_kmsg_cache[NCPUS];
++#define IKM_CACHE_SIZE (((1 << CPU_L1_SHIFT) - sizeof (size_t)) \
++ / sizeof (ipc_kmsg_t))
++
++struct ipc_kmsg_cpu_cache
++{
++ size_t count;
++ ipc_kmsg_t buffers[IKM_CACHE_SIZE];
++};
++
++extern struct ipc_kmsg_cpu_cache ipc_kmsg_cache[NCPUS];
+
+-#define ikm_cache() ipc_kmsg_cache[cpu_number()]
++/* These functions are defined at the end of this file. */
++static inline ipc_kmsg_t ikm_cache_get (mach_msg_size_t size);
++static inline void ikm_cache_put (ipc_kmsg_t kmsg);
+
+ /*
+ * The size of the kernel message buffers that will be cached.
+@@ -150,11 +169,18 @@ MACRO_BEGIN \
+ register vm_size_t _size = (kmsg)->ikm_size; \
+ \
+ if ((integer_t)_size > 0) \
+- kfree((vm_offset_t) (kmsg), _size); \
++ ikm_cache_put (kmsg); \
+ else \
+ ipc_kmsg_free(kmsg); \
+ MACRO_END
+
++#define _ikm_free(kmsg) \
++MACRO_BEGIN \
++ vm_size_t _size = (kmsg)->ikm_size; \
++ assert (_size != IKM_SIZE_NETWORK); \
++ kfree((vm_offset_t) (kmsg), _size); \
++MACRO_END
++
+ /*
+ * struct ipc_kmsg_queue is defined in ipc/ipc_kmsg_queue.h
+ */
+@@ -280,5 +306,46 @@ ipc_kmsg_copyout_pseudo(ipc_kmsg_t, ipc_space_t, vm_map_t);
+
+ extern void
+ ipc_kmsg_copyout_dest(ipc_kmsg_t, ipc_space_t);
++
++static inline ipc_kmsg_t
++ikm_cache_get (mach_msg_size_t size)
++{
++ ipc_kmsg_t kmsg;
++ struct ipc_kmsg_cpu_cache *c = &ipc_kmsg_cache[cpu_number ()];
++
++ if (size < IKM_SAVED_MSG_SIZE)
++ size = IKM_SAVED_MSG_SIZE;
++
++ if (size > IKM_SAVED_MSG_SIZE
++ || c->count == 0) {
++ kmsg = ikm_alloc (size);
++ if (kmsg)
++ ikm_init (kmsg, size);
++ return kmsg;
++ }
++
++ c->count -= 1;
++ kmsg = c->buffers[c->count];
++
++ ikm_check_initialized (kmsg, IKM_SAVED_KMSG_SIZE);
++ return kmsg;
++}
++
++static inline void
++ikm_cache_put (ipc_kmsg_t kmsg)
++{
++ struct ipc_kmsg_cpu_cache *c = &ipc_kmsg_cache[cpu_number ()];
++
++ if (kmsg->ikm_size != IKM_SAVED_KMSG_SIZE
++ || c->count == IKM_CACHE_SIZE) {
++ _ikm_free (kmsg);
++ return;
++ }
++
++ c->buffers[c->count] = kmsg;
++ c->count += 1;
++
++ ikm_check_initialized (kmsg, IKM_SAVED_KMSG_SIZE);
++}
+
+ #endif /* _IPC_IPC_KMSG_H_ */
+diff --git a/ipc/mach_msg.c b/ipc/mach_msg.c
+index 1e122c7..71a3c95 100644
+--- a/ipc/mach_msg.c
++++ b/ipc/mach_msg.c
+@@ -451,16 +451,14 @@ mach_msg_trap(
+
+ if ((send_size > IKM_SAVED_MSG_SIZE) ||
+ (send_size < sizeof(mach_msg_header_t)) ||
+- (send_size & 3) ||
+- ((kmsg = ikm_cache()) == IKM_NULL))
+- goto slow_get;
++ (send_size & 3))
++ goto slow_get; //XXX
+
+- ikm_cache() = IKM_NULL;
+- ikm_check_initialized(kmsg, IKM_SAVED_KMSG_SIZE);
++ kmsg = ikm_cache_get (IKM_SAVED_MSG_SIZE);
+
+ if (copyinmsg(msg, &kmsg->ikm_header,
+ send_size)) {
+- ikm_free(kmsg);
++ ikm_cache_put (kmsg);
+ goto slow_get;
+ }
+
+@@ -1263,18 +1261,16 @@ mach_msg_trap(
+ * We have the reply message data in kmsg,
+ * and the reply message size in reply_size.
+ * Just need to copy it out to the user and free kmsg.
+- * We must check ikm_cache after copyoutmsg.
+ */
+
+ ikm_check_initialized(kmsg, kmsg->ikm_size);
+
+ if ((kmsg->ikm_size != IKM_SAVED_KMSG_SIZE) ||
+ copyoutmsg(&kmsg->ikm_header, msg,
+- reply_size) ||
+- (ikm_cache() != IKM_NULL))
+- goto slow_put;
++ reply_size))
++ goto slow_put; //XXX
+
+- ikm_cache() = kmsg;
++ ikm_cache_put (kmsg);
+ thread_syscall_return(MACH_MSG_SUCCESS);
+ /*NOTREACHED*/
+ return MACH_MSG_SUCCESS; /* help for the compiler */
+diff --git a/kern/exception.c b/kern/exception.c
+index 7954fba..ffe701b 100644
+--- a/kern/exception.c
++++ b/kern/exception.c
+@@ -348,16 +348,9 @@ exception_raise(
+ * and it will give the buffer back with its reply.
+ */
+
+- kmsg = ikm_cache();
+- if (kmsg != IKM_NULL) {
+- ikm_cache() = IKM_NULL;
+- ikm_check_initialized(kmsg, IKM_SAVED_KMSG_SIZE);
+- } else {
+- kmsg = ikm_alloc(IKM_SAVED_MSG_SIZE);
+- if (kmsg == IKM_NULL)
+- panic("exception_raise");
+- ikm_init(kmsg, IKM_SAVED_MSG_SIZE);
+- }
++ kmsg = ikm_cache_get (IKM_SAVED_MSG_SIZE);
++ if (kmsg == IKM_NULL)
++ panic("exception_raise");
+
+ /*
+ * We need a reply port for the RPC.
+@@ -681,22 +674,19 @@ exception_raise(
+
+ /*
+ * Optimized version of ipc_kmsg_put.
+- * We must check ikm_cache after copyoutmsg.
+ */
+-
+ ikm_check_initialized(kmsg, kmsg->ikm_size);
+ assert(kmsg->ikm_size == IKM_SAVED_KMSG_SIZE);
+
+ if (copyoutmsg(&kmsg->ikm_header, receiver->ith_msg,
+- sizeof(struct mach_exception)) ||
+- (ikm_cache() != IKM_NULL)) {
++ sizeof(struct mach_exception))) { //XXX
+ mr = ipc_kmsg_put(receiver->ith_msg, kmsg,
+ kmsg->ikm_header.msgh_size);
+ thread_syscall_return(mr);
+ /*NOTREACHED*/
+ }
+
+- ikm_cache() = kmsg;
++ ikm_cache_put (kmsg);
+ thread_syscall_return(MACH_MSG_SUCCESS);
+ /*NOTREACHED*/
+ #ifndef __GNUC__
+@@ -809,13 +799,7 @@ exception_parse_reply(ipc_kmsg_t kmsg)
+ }
+
+ kr = msg->RetCode;
+-
+- if ((kmsg->ikm_size == IKM_SAVED_KMSG_SIZE) &&
+- (ikm_cache() == IKM_NULL))
+- ikm_cache() = kmsg;
+- else
+- ikm_free(kmsg);
+-
++ ikm_cache_put (kmsg);
+ return kr;
+ }
+
+diff --git a/kern/ipc_kobject.c b/kern/ipc_kobject.c
+index bf22028..27535b0 100644
+--- a/kern/ipc_kobject.c
++++ b/kern/ipc_kobject.c
+@@ -236,11 +236,7 @@ ipc_kobject_server(request)
+ /* like ipc_kmsg_put, but without the copyout */
+
+ ikm_check_initialized(request, request->ikm_size);
+- if ((request->ikm_size == IKM_SAVED_KMSG_SIZE) &&
+- (ikm_cache() == IKM_NULL))
+- ikm_cache() = request;
+- else
+- ikm_free(request);
++ ikm_cache_put (request);
+ } else {
+ /*
+ * The message contents of the request are intact.
+--
+2.1.3
+
diff --git a/debian/patches/0002-ipc-use-ikm-cache-for-kernel-messages.patch b/debian/patches/0002-ipc-use-ikm-cache-for-kernel-messages.patch
new file mode 100644
index 0000000..3c289ff
--- /dev/null
+++ b/debian/patches/0002-ipc-use-ikm-cache-for-kernel-messages.patch
@@ -0,0 +1,37 @@
+From 286be1ce09a0c74bc6c1519005ba7d08b5138a25 Mon Sep 17 00:00:00 2001
+From: Justus Winter <4winter@informatik.uni-hamburg.de>
+Date: Wed, 17 Dec 2014 14:47:19 +0100
+Subject: [PATCH gnumach 2/2] ipc: use ikm cache for kernel messages
+
+---
+ ipc/ipc_kmsg.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/ipc/ipc_kmsg.c b/ipc/ipc_kmsg.c
+index 04cdbc9..c26569b 100644
+--- a/ipc/ipc_kmsg.c
++++ b/ipc/ipc_kmsg.c
+@@ -544,10 +544,9 @@ ipc_kmsg_get_from_kernel(
+ assert(size >= sizeof(mach_msg_header_t));
+ assert((size & 3) == 0);
+
+- kmsg = ikm_alloc(size);
++ kmsg = ikm_cache_get (size);
+ if (kmsg == IKM_NULL)
+ return MACH_SEND_NO_BUFFER;
+- ikm_init(kmsg, size);
+
+ memcpy(&kmsg->ikm_header, msg, size);
+
+@@ -611,7 +610,7 @@ ipc_kmsg_put_to_kernel(
+
+ memcpy(msg, &kmsg->ikm_header, size);
+
+- ikm_free(kmsg);
++ ikm_cache_put (kmsg);
+ }
+
+ /*
+--
+2.1.3
+
diff --git a/debian/patches/series b/debian/patches/series
index 52021c2..920703e 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -6,3 +6,5 @@
Add-some-padding-to-make-objects-fit-a-single-cache-.patch
vm_cache_policy.patch
+0001-ipc-rework-the-ikm-cache-XXX.patch
+0002-ipc-use-ikm-cache-for-kernel-messages.patch