Scope callout_stop drain case properly
A deadlock condition was introduced with commit 164ca60.
Essentially callout_stop was incorrectly always running the "drain"
code where it is allowed to block if curently executing. Constrain
the behavior properly (via the CS_DRAIN flag), and cleanup one use
case.
Note: this likely restores the original race condition for which the
original set of changes were added to guard against.
diff --git a/usrsctplib/netinet/sctp_callout.c b/usrsctplib/netinet/sctp_callout.c
index f864ece..70ebbfa 100755
--- a/usrsctplib/netinet/sctp_callout.c
+++ b/usrsctplib/netinet/sctp_callout.c
@@ -159,7 +159,7 @@
}
int
-sctp_os_timer_stop(sctp_os_timer_t *c)
+sctp_os_timer_stop(sctp_os_timer_t *c, int flags)
{
int wakeup_cookie;
@@ -169,10 +169,19 @@
*/
if (!(c->c_flags & SCTP_CALLOUT_PENDING)) {
c->c_flags &= ~SCTP_CALLOUT_ACTIVE;
+
+ /* is the callout currently being run? */
if (sctp_os_timer_current != c) {
SCTP_TIMERQ_UNLOCK();
return (0);
} else {
+ /* the callout is currently running */
+ if (!(flags & SCTP_CS_DRAIN)) {
+ /* if no drain is requested, so just return */
+ SCTP_TIMERQ_UNLOCK();
+ return (0);
+ }
+
/*
* Deleting the callout from the currently running
* callout from the same thread, so just return
diff --git a/usrsctplib/netinet/sctp_callout.h b/usrsctplib/netinet/sctp_callout.h
index 5acf9dd..c43d5e9 100755
--- a/usrsctplib/netinet/sctp_callout.h
+++ b/usrsctplib/netinet/sctp_callout.h
@@ -100,16 +100,17 @@
#define SCTP_CALLOUT_ACTIVE 0x0002 /* callout is currently active */
#define SCTP_CALLOUT_PENDING 0x0004 /* callout is waiting for timeout */
+#define SCTP_CS_DRAIN 0x0001 /* callout drain, wait allowed */
+
void sctp_os_timer_init(sctp_os_timer_t *tmr);
void sctp_os_timer_start(sctp_os_timer_t *, int, void (*)(void *), void *);
-int sctp_os_timer_stop(sctp_os_timer_t *);
+int sctp_os_timer_stop(sctp_os_timer_t *, int);
void sctp_handle_tick(int);
#define SCTP_OS_TIMER_INIT sctp_os_timer_init
#define SCTP_OS_TIMER_START sctp_os_timer_start
-#define SCTP_OS_TIMER_STOP sctp_os_timer_stop
-/* MT FIXME: Is the following correct? */
-#define SCTP_OS_TIMER_STOP_DRAIN SCTP_OS_TIMER_STOP
+#define SCTP_OS_TIMER_STOP(tmr) sctp_os_timer_stop((tmr), 0)
+#define SCTP_OS_TIMER_STOP_DRAIN(tmr) sctp_os_timer_stop((tmr), SCTP_CS_DRAIN)
#define SCTP_OS_TIMER_PENDING(tmr) ((tmr)->c_flags & SCTP_CALLOUT_PENDING)
#define SCTP_OS_TIMER_ACTIVE(tmr) ((tmr)->c_flags & SCTP_CALLOUT_ACTIVE)
#define SCTP_OS_TIMER_DEACTIVATE(tmr) ((tmr)->c_flags &= ~SCTP_CALLOUT_ACTIVE)