summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTill Straumann <strauman@slac.stanford.edu>2009-04-23 04:26:07 +0000
committerTill Straumann <strauman@slac.stanford.edu>2009-04-23 04:26:07 +0000
commitacc2a645a748497ba85d7d1763a84006b93dac3c (patch)
treedb78372d5f7a3cd8469392167c6fe452719d2d98
parent86beed821051e3741c8d54a56860a9b9e714a30c (diff)
downloadlibbsdport-acc2a645a748497ba85d7d1763a84006b93dac3c.tar.bz2
- callout_stop() and callout_reset() actually must return an 'int' value
indicating whether a callout was pending. - added callout_active(), callout_pending(), callout_deactivate().
-rw-r--r--bsd_eth_drivers/libbsdport/callout.h44
-rw-r--r--bsd_eth_drivers/libbsdport/rtems_callout.c26
2 files changed, 63 insertions, 7 deletions
diff --git a/bsd_eth_drivers/libbsdport/callout.h b/bsd_eth_drivers/libbsdport/callout.h
index 3f586bf..acc9de0 100644
--- a/bsd_eth_drivers/libbsdport/callout.h
+++ b/bsd_eth_drivers/libbsdport/callout.h
@@ -18,16 +18,56 @@ struct callout {
void *c_arg;
struct mtx *c_mtx;
callout_time_t c_time;
+ unsigned c_flags;
};
+#define CALLOUT_PENDING (1<<0)
+#define CALLOUT_ACTIVE (1<<1)
+
+/*
+ * Strictly, we don't need any protection
+ * because the global network semaphore
+ * takes care; however we want to
+ */
+static inline int
+callout_active(struct callout *p_c)
+{
+int rval;
+rtems_interrupt_level l;
+ rtems_interrupt_disable(l);
+ rval = p_c->c_flags & CALLOUT_ACTIVE;
+ rtems_interrupt_enable(l);
+ return rval;
+}
+
+static inline int
+callout_pending(struct callout *p_c)
+{
+int rval;
+rtems_interrupt_level l;
+ rtems_interrupt_disable(l);
+ rval = p_c->c_flags & CALLOUT_PENDING;
+ rtems_interrupt_enable(l);
+ return rval;
+}
+
+static inline void
+callout_decativate(struct callout *p_c)
+{
+rtems_interrupt_level l;
+ rtems_interrupt_disable(l);
+ p_c->c_flags &= ~CALLOUT_ACTIVE;
+ rtems_interrupt_enable(l);
+}
+
/* We cannot stop a callout that's in progress */
-void
+int
callout_stop(struct callout *c);
#define callout_drain callout_stop
-void
+int
callout_reset(struct callout *c, int ticks, void (*fn)(void*), void *arg);
void
diff --git a/bsd_eth_drivers/libbsdport/rtems_callout.c b/bsd_eth_drivers/libbsdport/rtems_callout.c
index ce9a477..de1df83 100644
--- a/bsd_eth_drivers/libbsdport/rtems_callout.c
+++ b/bsd_eth_drivers/libbsdport/rtems_callout.c
@@ -100,6 +100,9 @@ LIST_KEY_DECL(k);
n = c->c_next;
if ( c->c_time <= 0 ) {
/* this one expired */
+ rtems_interrupt_disable(k1);
+ c->c_flags &= ~ CALLOUT_PENDING;
+ rtems_interrupt_enable(k1);
c_deq(c);
if ( c->c_func )
c->c_func(c->c_arg);
@@ -173,31 +176,38 @@ bail:
/* We cannot stop a callout that's in progress */
-void
+int
callout_stop(struct callout *c)
{
+rtems_interrupt_level l;
LIST_KEY_DECL(k);
if ( !c->c_pprev )
- return; /* not currently on a list */
+ return 0; /* not currently on a list */
LIST_LOCK(k);
/* remove from list */
c_deq(c);
+ rtems_interrupt_disable(l);
+ c->c_flags &= ~(CALLOUT_ACTIVE | CALLOUT_PENDING);
+ rtems_interrupt_enable(l);
LIST_UNLOCK(k);
+
+ return 1;
}
-void
+int
callout_reset(struct callout *c, int ticks, timeout_t fn, void *arg)
{
+rtems_interrupt_level l;
LIST_KEY_DECL(k);
-int i;
+int i, rval;
if ( ticks <= 0 )
ticks = 1;
- callout_stop(c);
+ rval = callout_stop(c);
c->c_func = fn;
c->c_arg = arg;
@@ -209,7 +219,13 @@ int i;
/* enqueue */
c_enq(&c_wheel[i], c);
+ rtems_interrupt_disable(l);
+ c->c_flags |= (CALLOUT_ACTIVE | CALLOUT_PENDING);
+ rtems_interrupt_enable(l);
+
LIST_UNLOCK(k);
+
+ return rval;
}
static rtems_id callout_tid = 0;