LwIP binary semaphore usage issue
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 1.2k
- Forks
- 1.1k
- PR merge metrics
- No merged PRs in 30d
Description
Hi to all,
I have been working on MicroBlaze with FreeRTOS Lwip Echo Server example. I use lwip in "Socket API" mode. But default project settings and configurations do not work properly. I start ping to FPGA and pings stop for a while. I started debug to code. I realized that this problem is derived from "Binary Semaphore" usage in "xemacif_recv_handler" function.
Let me explain problem step by step:
-
A packet is received from Emaclite within "xemacif_recv_handler()" interrupt funtion.
-
Packet is written to receive queue.
-
Binary Semaphore is given
After scheduler works , xemacif_input_thread takes the Binary Semaphore and read only one incoming packet from queue. Packet processing stuff goes on... and then xemacif_input_thread starts waiting the binary semaphore again.
But, if two packets are received from Emaclite before scheduler works(it means two packets arrived nearly at same time and xemacif_input_thread did not work yet), then the above steps are repeated except 3rd step. Because binary semaphore is already given when first packet received. But length of receive queue became 2. So it will cause an event lost.
After scheduler works xemac_input_thread takes the binary semaphore which is given by interrupt handler. And only one incoming packet is processed due to one binary semaphore. But now one packet is still waiting in receive queue. Because binary semaphore is given once however incoming packets keep writting to receive queue all time. So, counting of coming packets accumulating slowly.
I think that it would be better to use counting semaphore instead of binary semaphore in xemacif_recv_handler().
How can I solve this problem? Using counting semaphore enough? Do you have any idea?
Thanks...
-------------- Packet Processing Thread--------------------
#if !NO_SYS
/*
- The input thread calls lwIP to process any received packets.
- This thread waits until a packet is received (sem_rx_data_available),
- and then calls xemacif_input which processes 1 packet at a time.
*/
void
xemacif_input_thread(struct netif *netif)
{
struct xemac_s *emac = (struct xemac_s )netif->state;
while (1) {
/ sleep until there are packets to process - This semaphore is set by the packet receive interrupt
- routine.
*/
sys_sem_wait(&emac->sem_rx_data_available); //Semaphore is waiting...
/* move all received packets to lwIP */
xemacif_input(netif); // Only one Packet is read from queue
}
}
#endif
-------------- Packet Received Interrupt--------------------
static void
xemacif_recv_handler(void *arg) {
struct xemac_s *xemac = (struct xemac_s *)(arg);
xemacliteif_s *xemacliteif = (xemacliteif_s *)(xemac->state);
XEmacLite *instance = xemacliteif->instance;
struct pbuf *p;
int len = 0;
struct xtopology_t *xtopologyp = &xtopology[xemac->topology_index];
#ifdef OS_IS_FREERTOS
xInsideISR++;
#endif
#if XLWIP_CONFIG_INCLUDE_EMACLITE_ON_ZYNQ == 1
#else
XIntc_AckIntr(xtopologyp->intc_baseaddr, 1 << xtopologyp->intc_emac_intr);
#endif
p = pbuf_alloc(PBUF_RAW, XEL_MAX_FRAME_SIZE, PBUF_POOL);
if (!p)
{
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif
/* receive and just ignore the frame.
- we need to receive the frame because otherwise emaclite will
- not generate any other interrupts since it cannot receive,
- and we do not actively poll the emaclite
*/
XEmacLite_Recv(instance, xemac_tx_frame);
#ifdef OS_IS_FREERTOS
xInsideISR--;
#endif
return;
}
/* receive the packet */
len = XEmacLite_Recv(instance, p->payload); // receive the packet from EmacLite
if (len == 0)
{
#if LINK_STATS
lwip_stats.link.drop++;
#endif
pbuf_free(p);
#ifdef OS_IS_FREERTOS
xInsideISR--;
#endif
return;
}
/* store it in the receive queue, where it'll be processed by xemacif input thread /
if (pq_enqueue(xemacliteif->recv_q, (void)p) < 0) //Write packet to queue
{
#if LINK_STATS
lwip_stats.link.memerr++;
lwip_stats.link.drop++;
#endif
pbuf_free(p);
#ifdef OS_IS_FREERTOS
xInsideISR--;
#endif
return;
}
#if !NO_SYS
sys_sem_signal(&xemac->sem_rx_data_available); // Semaphore is given
#endif
#ifdef OS_IS_FREERTOS
xInsideISR--;
#endif
}
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with xemacif_recv_handler and xemacif_input_thread in the LwIP Socket API Echo Server path, then inspect how recv_q and sem_rx_data_available interact. Reproduce the issue with multiple packets arriving before the input thread runs, and verify that every queued packet is eventually processed without stalled pings.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- embedded-iot, networking
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100