[rtems commit] libnetworking: Avoid deadlock during starvation

Sebastian Huber sebh at rtems.org
Fri Nov 2 15:03:29 UTC 2012


Module:    rtems
Branch:    master
Commit:    b3cee28a519e96082d4309447d268dd4740a187c
Changeset: http://git.rtems.org/rtems/commit/?id=b3cee28a519e96082d4309447d268dd4740a187c

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Fri Nov  2 11:46:08 2012 +0100

libnetworking: Avoid deadlock during starvation

---

 cpukit/libnetworking/rtems/rtems_glue.c |   43 ++++++++++++++++++++++++++-----
 1 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/cpukit/libnetworking/rtems/rtems_glue.c b/cpukit/libnetworking/rtems/rtems_glue.c
index 09240a4..ab7f7c9 100644
--- a/cpukit/libnetworking/rtems/rtems_glue.c
+++ b/cpukit/libnetworking/rtems/rtems_glue.c
@@ -111,6 +111,33 @@ rtems_bsdnet_initialize_sockaddr_in(struct sockaddr_in *addr)
 	memcpy(addr, &address_template, sizeof(*addr));
 }
 
+static uint32_t
+rtems_bsdnet_semaphore_release_recursive(void)
+{
+#ifdef RTEMS_FAST_MUTEX
+	uint32_t nest_count = the_networkSemaphore->Core_control.mutex.nest_count;
+	uint32_t i;
+
+	for (i = 0; i < nest_count; ++i) {
+		rtems_bsdnet_semaphore_release();
+	}
+
+	return nest_count;
+#else
+	#error "not implemented"
+#endif
+}
+
+static void
+rtems_bsdnet_semaphore_obtain_recursive(uint32_t nest_count)
+{
+	uint32_t i;
+
+	for (i = 0; i < nest_count; ++i) {
+		rtems_bsdnet_semaphore_obtain();
+	}
+}
+
 /*
  * Perform FreeBSD memory allocation.
  * FIXME: This should be modified to keep memory allocation statistics.
@@ -126,16 +153,18 @@ rtems_bsdnet_malloc (size_t size, int type, int flags)
 	int try = 0;
 
 	for (;;) {
+		uint32_t nest_count;
+
 		p = malloc (size);
 		if (p || (flags & M_NOWAIT))
 			return p;
-		rtems_bsdnet_semaphore_release ();
+		nest_count = rtems_bsdnet_semaphore_release_recursive ();
 		if (++try >= 30) {
 			rtems_bsdnet_malloc_starvation();
 			try = 0;
 		}
-        rtems_task_wake_after (rtems_bsdnet_ticks_per_second);
-		rtems_bsdnet_semaphore_obtain ();
+		rtems_task_wake_after (rtems_bsdnet_ticks_per_second);
+		rtems_bsdnet_semaphore_obtain_recursive (nest_count);
 	}
 }
 
@@ -1259,9 +1288,9 @@ m_mballoc(int nmb, int nowait)
 
 		mbstat.m_wait++;
 		for (;;) {
-			rtems_bsdnet_semaphore_release ();
+			uint32_t nest_count = rtems_bsdnet_semaphore_release_recursive ();
 			rtems_task_wake_after (1);
-			rtems_bsdnet_semaphore_obtain ();
+			rtems_bsdnet_semaphore_obtain_recursive (nest_count);
 			if (mmbfree)
 				break;
 			if (++try >= print_limit) {
@@ -1288,9 +1317,9 @@ m_clalloc(int ncl, int nowait)
 
 		mbstat.m_wait++;
 		for (;;) {
-			rtems_bsdnet_semaphore_release ();
+			uint32_t nest_count = rtems_bsdnet_semaphore_release_recursive ();
 			rtems_task_wake_after (1);
-			rtems_bsdnet_semaphore_obtain ();
+			rtems_bsdnet_semaphore_obtain_recursive (nest_count);
 			if (mclfree)
 				break;
 			if (++try >= print_limit) {




More information about the vc mailing list