summaryrefslogtreecommitdiffstats
path: root/cpukit/libnetworking
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2012-11-02 11:46:08 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2012-11-02 16:06:57 +0100
commitb3cee28a519e96082d4309447d268dd4740a187c (patch)
tree9b71bcb2df5719a24bb1c6d036a2313a9e2f8ed4 /cpukit/libnetworking
parentmonitor: Support for system events (diff)
downloadrtems-b3cee28a519e96082d4309447d268dd4740a187c.tar.bz2
libnetworking: Avoid deadlock during starvation
Diffstat (limited to 'cpukit/libnetworking')
-rw-r--r--cpukit/libnetworking/rtems/rtems_glue.c43
1 files changed, 36 insertions, 7 deletions
diff --git a/cpukit/libnetworking/rtems/rtems_glue.c b/cpukit/libnetworking/rtems/rtems_glue.c
index 09240a4534..ab7f7c9e18 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) {