diff options
-rw-r--r-- | debian/patches/0001-ipc-rework-the-ikm-cache-XXX.patch | 302 | ||||
-rw-r--r-- | debian/patches/0002-ipc-use-ikm-cache-for-kernel-messages.patch | 37 | ||||
-rw-r--r-- | debian/patches/series | 2 |
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 |