Add support for enabling/disbaling interrupts

RESOLVED FIXED

Status

defect
P3
normal
RESOLVED FIXED
20 years ago
20 years ago

People

(Reporter: srinivas, Assigned: srinivas)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

Assignee

Description

20 years ago
It will be useful to functions to enable and disable interrupts.
Assignee

Updated

20 years ago
Status: NEW → ASSIGNED
Assignee

Comment 1

20 years ago
Two new interfaces, PR_BlockInterrupt and PR_UnblockInterrupt are added to NSPR.
When a thread blocks interrupt, the interrupt is kept pending until it is
unblocked.

Files modified:

include/prthread.h, rev 3.5
include/private/primpl.h, rev 3.25
src/pthreads/ptio.c, rev 3.33
src/pthreads/ptsynch.c, rev 3.10
src/pthreads/ptthread.c, rev 3.27
src/threads/prcthr.c, rev 3.8
tests/intrupt.c, rev 3.4

Comment 2

20 years ago
The current implementation will generate a spurious
wakeup if a thread in PR_WaitCondVar is interrupted
while interrupt is blocked, because PR_Interrupt
does not check whether interrupt is being blocked.

For example, in ptthread.c, PR_Interrupt, we have:
    PRCondVar *cv;
    PR_ASSERT(NULL != thred);
    if (NULL == thred) return PR_FAILURE;

    thred->state |= PT_THREAD_ABORTED;

    cv = thred->waiting;
    if (NULL != cv)
    {
        PRIntn rv = pthread_cond_broadcast(&cv->cv);
        PR_ASSERT(0 == rv);
    }
    return PR_SUCCESS;

So pthread_cond_broadcast is always called
regardless of the value of thred->interrupt_blocked.
PR_WaitCondVar does check thred->interrupt_blocked
and would return PR_SUCCESS (as opposed to PR_FAILURE
with PR_PENDING_INTERRUPT_ERROR), resulting in a
spurious wakeup.

Since our clients are supposed to deal with spurious
wakeups, this won't break any correct code.  But ideally
PR_Interrupt should check thred->interrupt_blocked
to avoid generating a spurious wakeup. However, to
do that check safely would require a lock on 'thred',
right?
Assignee

Comment 3

20 years ago
Yes, a lock on thred is required. But, if thred->interrupt_blocked is checked
without a lock, most spurious interrupts are likely to be avoided because a
thread can block/unblock it's own interrupts. Simultaneous thread interrupts and
interrupt blocks don't happen frequently.
Assignee

Comment 4

20 years ago
The following patch for reducing spurious notifications needs to be reviewed:

RCS file: /cvsroot/mozilla/nsprpub/pr/src/pthreads/ptthread.c,v
retrieving revision 3.28
diff -u -r3.28 ptthread.c
--- ptthread.c  1999/11/16 23:44:34     3.28
+++ ptthread.c  1999/12/22 22:34:59
@@ -657,7 +657,7 @@
     thred->state |= PT_THREAD_ABORTED;

     cv = thred->waiting;
-    if (NULL != cv)
+    if ((NULL != cv) && !thred->interrupt_blocked)
     {
         PRIntn rv = pthread_cond_broadcast(&cv->cv);
         PR_ASSERT(0 == rv);
Index: src/threads/prcthr.c
===================================================================
RCS file: /cvsroot/mozilla/nsprpub/pr/src/threads/prcthr.c,v
retrieving revision 3.11
diff -u -r3.11 prcthr.c
--- prcthr.c    1999/12/22 20:51:26     3.11
+++ prcthr.c    1999/12/22 22:34:59
@@ -171,7 +171,7 @@
     thread->flags |= _PR_INTERRUPT;
     victim = thread->wait.cvar;
     _PR_THREAD_UNLOCK(thread);
-    if (NULL != victim) {
+    if ((NULL != victim) && !thread->interrupt_blocked) {
         int haveLock = (victim->lock->owner == _PR_MD_CURRENT_THREAD());

         if (!haveLock) PR_Lock(victim->lock);
@@ -194,7 +194,8 @@
                          * call is made with thread locked;
                          * on return lock is released
                          */
-                        _PR_NotifyLockedThread(thread);
+                                               if (!thread->interrupt_blocked)
+                               _PR_NotifyLockedThread(thread);
                         break;
                 case _PR_IO_WAIT:
                         /*
@@ -203,7 +204,8 @@
                          * released.
                          */
 #if defined(XP_UNIX) || defined(WINNT) || defined(WIN16)
-                        _PR_Unblock_IO_Wait(thread);
+                                               if (!thread->interrupt_blocked)
+                               _PR_Unblock_IO_Wait(thread);
 #else
                         _PR_THREAD_UNLOCK(thread);
 #endif

Comment 5

20 years ago
I reviewed the patch for reducing spurious notifications.
The patch itself is good, although our thread interrupt
code still has race conditions (not introduced by this
patch).

The problem is that we are notifying the cv (thred->waiting
in the pthreads version or thread->wait.cvar in the global
threads only version) without locking the thread.  It is
possible for the target thread to finish waiting on that
cv at that instant of time.  Then, the cv could be deleted,
and we would be notifying a destroyed cv.  Or the
target thread could go on to wait on a different cv, and
notifying the old cv would not wake up the thread.

It seems that solving this problem requires that we
notify the cv while locking the thread.  Since this
problem has always been there and is not introduced
or made worse by this patch, I think it is okay to
check in this patch while we think about how to completely
solve the race condition problem.
Assignee

Updated

20 years ago
Status: ASSIGNED → RESOLVED
Last Resolved: 20 years ago
Resolution: --- → FIXED
Assignee

Comment 6

20 years ago
Files modified:

/cvsroot/mozilla/nsprpub/pr/src/pthreads/ptthread.c,v  <--  ptthread.c
new revision: 3.29; previous revision: 3.28
/cvsroot/mozilla/nsprpub/pr/src/threads/prcthr.c,v  <--  prcthr.c
new revision: 3.12; previous revision: 3.11
Assignee

Comment 7

20 years ago
The patch to prcthr.c was incorrect; the _PR_INTERRUPT_BLOCKED field of
thread->flags should be used for classic version of NSPR and the
thread->interrupt_blocked field should be used for the pthreads version.

===================================================================
RCS file: /cvsroot/mozilla/nsprpub/pr/src/threads/prcthr.c,v
retrieving revision 3.13
diff -u -r3.13 prcthr.c
--- prcthr.c    1999/12/24 02:07:15     3.13
+++ prcthr.c    1999/12/29 16:49:19
@@ -171,7 +171,7 @@
     thread->flags |= _PR_INTERRUPT;
     victim = thread->wait.cvar;
     _PR_THREAD_UNLOCK(thread);
-    if (NULL != victim) {
+    if ((NULL != victim) && (!(thread->flags & _PR_INTERRUPT_BLOCKED))) {
         int haveLock = (victim->lock->owner == _PR_MD_CURRENT_THREAD());

         if (!haveLock) PR_Lock(victim->lock);
@@ -194,7 +194,8 @@
                          * call is made with thread locked;
                          * on return lock is released
                          */
-                        _PR_NotifyLockedThread(thread);
+                                               if (!(thread->flags & _PR_INTERR
UPT_BLOCKED))
+                               _PR_NotifyLockedThread(thread);
                         break;
                 case _PR_IO_WAIT:
                         /*
@@ -203,7 +204,8 @@
                          * released.
                          */
 #if defined(XP_UNIX) || defined(WINNT) || defined(WIN16)
-                        _PR_Unblock_IO_Wait(thread);
+                                               if (!(thread->flags & _PR_INTERR
UPT_BLOCKED))
+                               _PR_Unblock_IO_Wait(thread);
 #else
                         _PR_THREAD_UNLOCK(thread);
 #endif
You need to log in before you can comment on or make changes to this bug.