diff options
author | Gregory Nutt <gnutt@nuttx.org> | 2014-06-22 11:27:57 -0600 |
---|---|---|
committer | Gregory Nutt <gnutt@nuttx.org> | 2014-06-22 11:27:57 -0600 |
commit | 0c72d9900e00e06e9c9b1008e795766011a9c46f (patch) | |
tree | 0a7b6144118d955836693cd0d31b2d9127418de7 /nuttx/net/tcp/tcp_wrbuffer.c | |
parent | 8cf46d1f34452aca50d6aabe3d13bd12f54d5906 (diff) | |
download | px4-nuttx-0c72d9900e00e06e9c9b1008e795766011a9c46f.tar.gz px4-nuttx-0c72d9900e00e06e9c9b1008e795766011a9c46f.tar.bz2 px4-nuttx-0c72d9900e00e06e9c9b1008e795766011a9c46f.zip |
First cut at conversion of write-buffering to use I/O buffer chaings (IOBs)
Diffstat (limited to 'nuttx/net/tcp/tcp_wrbuffer.c')
-rw-r--r-- | nuttx/net/tcp/tcp_wrbuffer.c | 65 |
1 files changed, 46 insertions, 19 deletions
diff --git a/nuttx/net/tcp/tcp_wrbuffer.c b/nuttx/net/tcp/tcp_wrbuffer.c index cba5f5d23..929b2f3a2 100644 --- a/nuttx/net/tcp/tcp_wrbuffer.c +++ b/nuttx/net/tcp/tcp_wrbuffer.c @@ -50,9 +50,13 @@ #include <queue.h> #include <semaphore.h> +#include <string.h> +#include <assert.h> #include <debug.h> -#include "uip/uip_internal.h" +#include "tcp/tcp.h" +#include "nuttx/net/iob.h" +#include "nuttx/net/uip/uip-tcp.h" /**************************************************************************** * Private Types @@ -72,7 +76,7 @@ struct wrbuffer_s /* These are the pre-allocated write buffers */ - struct tcp_wrbuffer_s buffers[CONFIG_NET_NTCP_WRITE_BUFFERS]; + struct tcp_wrbuffer_s buffers[CONFIG_NET_TCP_NWRBCHAINS]; }; /**************************************************************************** @@ -108,12 +112,12 @@ void tcp_wrbuffer_initialize(void) sq_init(&g_wrbuffer.freebuffers); - for (i = 0; i < CONFIG_NET_NTCP_WRITE_BUFFERS; i++) + for (i = 0; i < CONFIG_NET_TCP_NWRBCHAINS; i++) { sq_addfirst(&g_wrbuffer.buffers[i].wb_node, &g_wrbuffer.freebuffers); } - sem_init(&g_wrbuffer.sem, 0, CONFIG_NET_NTCP_WRITE_BUFFERS); + sem_init(&g_wrbuffer.sem, 0, CONFIG_NET_TCP_NWRBCHAINS); } /**************************************************************************** @@ -129,26 +133,39 @@ void tcp_wrbuffer_initialize(void) * ****************************************************************************/ -FAR struct tcp_wrbuffer_s * -tcp_wrbuffer_alloc(FAR const struct timespec *abstime) +FAR struct tcp_wrbuffer_s *tcp_wrbuffer_alloc(void) { - int ret; + FAR struct tcp_wrbuffer_s *wrb; - if (abstime) - { - ret = sem_timedwait(&g_wrbuffer.sem, abstime); - } - else - { - ret = sem_wait(&g_wrbuffer.sem); - } + /* We need to allocate two things: (1) A write buffer structure and (2) + * at least one I/O buffer to start the chain. + * + * Allocate the write buffer structure first then the IOBG. In order to + * avoid deadlocks, we will need to free the IOB first, then the write + * buffer + */ + + DEBUGVERIFY(sem_wait(&g_wrbuffer.sem)); + + /* Now, we are guaranteed to have a write buffer structure reserved + * for us in the free list. + */ - if (ret != 0) + wrb = (FAR struct tcp_wrbuffer_s *)sq_remfirst(&g_wrbuffer.freebuffers); + DEBUGASSERT(wrb); + memset(wrb, 0, sizeof(struct tcp_wrbuffer_s)); + + /* Now get the first I/O buffer for the write buffer structure */ + + wrb->wb_iob = iob_alloc(); + if (!wrb->wb_iob) { + ndbg("ERROR: Failed to allocate I/O buffer\n"); + tcp_wrbuffer_release(wrb); return NULL; } - return (FAR struct tcp_wrbuffer_s*)sq_remfirst(&g_wrbuffer.freebuffers); + return wrb; } /**************************************************************************** @@ -164,9 +181,19 @@ tcp_wrbuffer_alloc(FAR const struct timespec *abstime) * ****************************************************************************/ -void tcp_wrbuffer_release(FAR struct tcp_wrbuffer_s *wrbuffer) +void tcp_wrbuffer_release(FAR struct tcp_wrbuffer_s *wrb) { - sq_addlast(&wrbuffer->wb_node, &g_wrbuffer.freebuffers); + DEBUGASSERT(wrb && wrb->wb_iob); + + /* To avoid deadlocks, we must following this ordering: Release the I/O + * buffer chain first, then the write buffer structure. + */ + + iob_free_chain(wrb->wb_iob); + + /* Then free the write buffer structure */ + + sq_addlast(&wrb->wb_node, &g_wrbuffer.freebuffers); sem_post(&g_wrbuffer.sem); } |