diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2012-11-02 11:46:08 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2012-11-02 16:06:57 +0100 |
commit | b3cee28a519e96082d4309447d268dd4740a187c (patch) | |
tree | 9b71bcb2df5719a24bb1c6d036a2313a9e2f8ed4 /cpukit/libnetworking | |
parent | monitor: Support for system events (diff) | |
download | rtems-b3cee28a519e96082d4309447d268dd4740a187c.tar.bz2 |
libnetworking: Avoid deadlock during starvation
Diffstat (limited to 'cpukit/libnetworking')
-rw-r--r-- | 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 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) { |