summaryrefslogtreecommitdiff
path: root/pfinet/sched.c
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2013-11-06 01:44:09 +0100
committerRichard Braun <rbraun@sceen.net>2013-11-06 01:44:09 +0100
commit218cae5a714342b5d82a5b004d58f0a9ebbbfe5e (patch)
tree620c7d730f94bf66e28b21a9a5d96b2426d2f05d /pfinet/sched.c
parent880dd56f468b57a198ab2136767d03ddaa586eef (diff)
pfinet: fix emission on the loopback device
Unlike other devices, sending packets on the loopback device causes the netif_rx() function to be called from the net_bh worker thread. Since the thread is already running, it can't wake itself up when calling mark_bh(). Use a new variable to indicate when net_bh work is pending. * glue-include/linux/interrupt.h (net_bh_raised): Declare new global variable. (mark_bh): Set net_bh_raised to 1 before waking up net_bh worker thread. * loopback.c (loopback_xmit): Add comment giving details about locking. * sched.c (net_bh_raised): Define new global variable. (net_bh_worker): Wait for net_bh_raised to become true and reset it before processing net_bh work.
Diffstat (limited to 'pfinet/sched.c')
-rw-r--r--pfinet/sched.c7
1 files changed, 6 insertions, 1 deletions
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);