summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pfinet/glue-include/linux/interrupt.h2
-rw-r--r--pfinet/loopback.c7
-rw-r--r--pfinet/sched.c7
3 files changed, 15 insertions, 1 deletions
diff --git a/pfinet/glue-include/linux/interrupt.h b/pfinet/glue-include/linux/interrupt.h
index df58d2f4..22312ba4 100644
--- a/pfinet/glue-include/linux/interrupt.h
+++ b/pfinet/glue-include/linux/interrupt.h
@@ -21,6 +21,7 @@ extern pthread_mutex_t net_bh_lock;
/* See sched.c::net_bh_worker comments. */
extern pthread_cond_t net_bh_wakeup;
+extern int net_bh_raised;
#define NET_BH 0xb00bee51
@@ -30,6 +31,7 @@ static inline void
mark_bh (int bh)
{
assert (bh == NET_BH);
+ net_bh_raised = 1;
pthread_cond_broadcast (&net_bh_wakeup);
}
diff --git a/pfinet/loopback.c b/pfinet/loopback.c
index 068cf3c8..e15e4265 100644
--- a/pfinet/loopback.c
+++ b/pfinet/loopback.c
@@ -71,6 +71,13 @@ static int loopback_xmit(struct sk_buff *skb, struct device *dev)
#ifndef LOOPBACK_MUST_CHECKSUM
skb->ip_summed = CHECKSUM_UNNECESSARY;
#endif
+
+ /*
+ * Calling netif_rx() requires locking net_bh_lock, which
+ * has already been done since this function is called by
+ * the net_bh worker thread.
+ */
+
netif_rx(skb);
stats->rx_bytes+=skb->len;
diff --git a/pfinet/sched.c b/pfinet/sched.c
index 89927741..af03ab49 100644
--- a/pfinet/sched.c
+++ b/pfinet/sched.c
@@ -26,6 +26,7 @@
pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t net_bh_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t net_bh_wakeup = PTHREAD_COND_INITIALIZER;
+int net_bh_raised = 0;
struct task_struct current_contents; /* zeros are right default values */
@@ -61,7 +62,11 @@ net_bh_worker (void *arg)
pthread_mutex_lock (&net_bh_lock);
while (1)
{
- pthread_cond_wait (&net_bh_wakeup, &net_bh_lock);
+ while (!net_bh_raised)
+ pthread_cond_wait (&net_bh_wakeup, &net_bh_lock);
+
+ net_bh_raised = 0;
+
pthread_mutex_lock (&global_lock);
net_bh ();
pthread_mutex_unlock (&global_lock);