- /* Thread already dead? */
- if (tso->what_next == ThreadComplete || tso->what_next == ThreadKilled) {
- return;
- }
-
- IF_DEBUG(scheduler, sched_belch("raising exception in thread %ld.", tso->id));
-
- /* Remove it from any blocking queues */
- unblockThread(tso);
-
- /* The stack freezing code assumes there's a closure pointer on
- * the top of the stack. This isn't always the case with compiled
- * code, so we have to push a dummy closure on the top which just
- * returns to the next return address on the stack.
- */
- if ( LOOKS_LIKE_GHC_INFO((void*)*sp) ) {
- *(--sp) = (W_)&dummy_ret_closure;
- }
-
- while (1) {
- int words = ((P_)su - (P_)sp) - 1;
- nat i;
- StgAP_UPD * ap;
-
- /* If we find a CATCH_FRAME, and we've got an exception to raise,
- * then build PAP(handler,exception,realworld#), and leave it on
- * top of the stack ready to enter.
- */
- if (get_itbl(su)->type == CATCH_FRAME && exception != NULL) {
- StgCatchFrame *cf = (StgCatchFrame *)su;
- /* we've got an exception to raise, so let's pass it to the
- * handler in this frame.
- */
- ap = (StgAP_UPD *)allocate(sizeofW(StgPAP) + 2);
- TICK_ALLOC_UPD_PAP(3,0);
- SET_HDR(ap,&PAP_info,cf->header.prof.ccs);
-
- ap->n_args = 2;
- ap->fun = cf->handler; /* :: Exception -> IO a */
- ap->payload[0] = (P_)exception;
- ap->payload[1] = ARG_TAG(0); /* realworld token */
-
- /* throw away the stack from Sp up to and including the
- * CATCH_FRAME.
- */
- sp = (P_)su + sizeofW(StgCatchFrame) - 1;
- tso->su = cf->link;
-
- /* Restore the blocked/unblocked state for asynchronous exceptions
- * at the CATCH_FRAME.
- *
- * If exceptions were unblocked at the catch, arrange that they
- * are unblocked again after executing the handler by pushing an
- * unblockAsyncExceptions_ret stack frame.
- */
- if (!cf->exceptions_blocked) {
- *(sp--) = (W_)&unblockAsyncExceptionszh_ret_info;
- }
-
- /* Ensure that async exceptions are blocked when running the handler.
- */
- if (tso->blocked_exceptions == NULL) {
- tso->blocked_exceptions = END_TSO_QUEUE;
- }
-
- /* Put the newly-built PAP on top of the stack, ready to execute
- * when the thread restarts.
- */
- sp[0] = (W_)ap;
- tso->sp = sp;
- tso->what_next = ThreadEnterGHC;
- IF_DEBUG(sanity, checkTSO(tso));
- return;