- /* 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);
-
- IF_DEBUG(scheduler, sched_belch("raising exception in thread %ld.", tso->id));
- /* 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_)&stg_dummy_ret_closure;
- }
-
- while (1) {
- nat 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 the THUNK raise(exception), and leave it on
- * top of the CATCH_FRAME ready to enter.
- */
- if (get_itbl(su)->type == CATCH_FRAME && exception != NULL) {
-#ifdef PROFILING
- StgCatchFrame *cf = (StgCatchFrame *)su;
-#endif
- StgClosure *raise;
-
- /* we've got an exception to raise, so let's pass it to the
- * handler in this frame.
- */
- raise = (StgClosure *)allocate(sizeofW(StgClosure)+1);
- TICK_ALLOC_SE_THK(1,0);
- SET_HDR(raise,&stg_raise_info,cf->header.prof.ccs);
- raise->payload[0] = exception;
-
- /* throw away the stack from Sp up to the CATCH_FRAME.
- */
- sp = (P_)su - 1;
-
- /* Ensure that async excpetions are blocked now, so we don't get
- * a surprise exception before we get around to executing the
- * handler.
- */
- if (tso->blocked_exceptions == NULL) {
- tso->blocked_exceptions = END_TSO_QUEUE;
- }
-
- /* Put the newly-built THUNK on top of the stack, ready to execute
- * when the thread restarts.
- */
- sp[0] = (W_)raise;
- tso->sp = sp;
- tso->su = su;
- tso->what_next = ThreadEnterGHC;
- IF_DEBUG(sanity, checkTSO(tso));
- return;