| 602 | |
| 603 | |
| 604 | static int pthread_cancel(pthread_t t) |
| 605 | { |
| 606 | if (t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS) |
| 607 | { |
| 608 | /* Dangerous asynchronous cancelling */ |
| 609 | CONTEXT ctxt; |
| 610 | |
| 611 | /* Already done? */ |
| 612 | if (t->cancelled) return ESRCH; |
| 613 | |
| 614 | ctxt.ContextFlags = CONTEXT_CONTROL; |
| 615 | |
| 616 | SuspendThread(t->h); |
| 617 | GetThreadContext(t->h, &ctxt); |
| 618 | #ifdef _M_X64 |
| 619 | ctxt.Rip = (uintptr_t) _pthread_invoke_cancel; |
| 620 | #else |
| 621 | ctxt.Eip = (uintptr_t) _pthread_invoke_cancel; |
| 622 | #endif |
| 623 | SetThreadContext(t->h, &ctxt); |
| 624 | |
| 625 | /* Also try deferred Cancelling */ |
| 626 | t->cancelled = 1; |
| 627 | |
| 628 | /* Notify everyone to look */ |
| 629 | _InterlockedIncrement(&_pthread_cancelling); |
| 630 | |
| 631 | ResumeThread(t->h); |
| 632 | } |
| 633 | else |
| 634 | { |
| 635 | /* Safe deferred Cancelling */ |
| 636 | t->cancelled = 1; |
| 637 | |
| 638 | /* Notify everyone to look */ |
| 639 | _InterlockedIncrement(&_pthread_cancelling); |
| 640 | } |
| 641 | |
| 642 | return 0; |
| 643 | } |
| 644 | |
| 645 | static unsigned _pthread_get_state(pthread_attr_t *attr, unsigned flag) |
| 646 | { |
no outgoing calls
no test coverage detected