static ULONG vlc_DosWaitEventSemEx( HEV hev, ULONG ulTimeout, BOOL fCancelable ) { HMUX hmux; SEMRECORD asr[ 2 ]; ULONG ulUser; int n; ULONG rc; struct vlc_thread *th = vlc_threadvar_get( thread_key ); if( th == NULL || !fCancelable ) { /* Main thread - cannot be cancelled anyway * Alien thread - out of our control */ if( hev != NULLHANDLE ) return DosWaitEventSem( hev, ulTimeout ); return DosSleep( ulTimeout ); } n = 0; if( hev != NULLHANDLE ) { asr[ n ].hsemCur = ( HSEM )hev; asr[ n ].ulUser = 0; n++; } asr[ n ].hsemCur = ( HSEM )th->cancel_event; asr[ n ].ulUser = 0xFFFF; n++; DosCreateMuxWaitSem( NULL, &hmux, n, asr, DCMW_WAIT_ANY ); rc = DosWaitMuxWaitSem( hmux, ulTimeout, &ulUser ); DosCloseMuxWaitSem( hmux ); if( rc ) return rc; if( ulUser == 0xFFFF ) { vlc_cancel_self( th ); return ERROR_INTERRUPT; } return NO_ERROR; }
static DWORD vlc_WaitForMultipleObjects (DWORD count, const HANDLE *handles, DWORD delay) { DWORD ret; #ifdef UNDER_CE HANDLE buf[count + 1]; struct vlc_thread *th = vlc_threadvar_get (thread_key); if (th != NULL) { memcpy (buf, handles, count * sizeof(HANDLE)); buf[count++] = th->cancel_event; handles = buf; } if (count == 0) { Sleep (delay); ret = WAIT_TIMEOUT; } else ret = WaitForMultipleObjects (count, handles, FALSE, delay); if ((th != NULL) && (ret == WAIT_OBJECT_0 + count - 1)) { vlc_cancel_self ((uintptr_t)th); ret = WAIT_IO_COMPLETION; } #else if (count == 0) { ret = SleepEx (delay, TRUE); if (ret == 0) ret = WAIT_TIMEOUT; } else ret = WaitForMultipleObjectsEx (count, handles, FALSE, delay, TRUE); #endif /* We do not abandon objects... this would be a bug */ assert (ret < WAIT_ABANDONED_0 || WAIT_ABANDONED_0 + count - 1 < ret); if (unlikely(ret == WAIT_FAILED)) abort (); /* We are screwed! */ return ret; }
void vlc_testcancel (void) { struct vlc_thread *th = vlc_threadvar_get (thread_key); if (th == NULL) return; /* Main thread - cannot be cancelled anyway */ /* This check is needed for the case that vlc_cancel() is followed by * vlc_testcancel() without any cancellation point */ if( DosWaitEventSem( th->cancel_event, 0 ) == NO_ERROR ) vlc_cancel_self( NULL ); if (th->killable && th->killed) { for (vlc_cleanup_t *p = th->cleaners; p != NULL; p = p->next) p->proc (p->data); DosPostEventSem( th->done_event ); th->data = NULL; /* TODO: special value? */ vlc_thread_cleanup (th); _endthread(); } }
static DWORD vlc_cancelable_wait (DWORD count, const HANDLE *handles, DWORD delay) { vlc_cancel_t *nfo = vlc_threadvar_get (cancel_key); if (nfo == NULL) { /* Main thread - cannot be cancelled anyway */ return WaitForMultipleObjects (count, handles, FALSE, delay); } HANDLE new_handles[count + 1]; memcpy(new_handles, handles, count * sizeof(HANDLE)); new_handles[count] = nfo->cancel_event; DWORD result = WaitForMultipleObjects (count + 1, new_handles, FALSE, delay); if (result == WAIT_OBJECT_0 + count) { vlc_cancel_self (NULL); return WAIT_IO_COMPLETION; } else { return result; } }