Trivial Solutions
                    The LoseThos 64-bit PC Operating System
File:/LT/OSMain/Except.CPZ
This, and all LoseThos files, are public domain.  Do whatever you like.
God is watching; God is just; God is never out-done in generosity.  He talks!

LoseThos code compiles with the 64-bit LoseThos compiler/assembler I wrote.
Boot the LoseThos CD and you can compile it.  Not in Kansas anymore!

Click here for preliminary compiler information you need.

Project: OSMain
U64 ExceptDepth(TaskStruct *task=NULL)
{
  U64 result=0;
  ExceptStruct *tempt;
  if (!task) task=Fs;
  tempt=task->next_except;
  while (tempt!=&task->next_except) {
    result++;
    tempt=tempt->next;
  }
  return result;
}

asm {
USE64
#assert !((CREG_NON_PTR_MASK|CREG_VARS_MASK)&~0xFCC0)
_TEST_EXCEPT::
        XOR     RAX,RAX
        MOV     RAX,FS:U64 TASK_LAST_EXCEPT[RAX]
        MOV     RBP,U64 EXCEPT_RBP[RAX]
        MOV     RSI,U64 EXCEPT_RSI[RAX]
        MOV     RDI,U64 EXCEPT_RDI[RAX]
        MOV     R10,U64 EXCEPT_R10[RAX]
        MOV     R11,U64 EXCEPT_R11[RAX]
        MOV     R12,U64 EXCEPT_R12[RAX]
        MOV     R13,U64 EXCEPT_R13[RAX]
        MOV     R14,U64 EXCEPT_R14[RAX]
        MOV     R15,U64 EXCEPT_R15[RAX]
        PUSH    U64 EXCEPT_RFLAGS[RAX]
        POPFD
        JMP     U64 EXCEPT_HANDLER_START[RAX]

_TAKE_EXCEPT::
        XOR     RAX,RAX
        MOV     RAX,FS:U64 TASK_LAST_EXCEPT[RAX]
        MOV     RSP,U64 EXCEPT_RSP[RAX]
        JMP     U64 EXCEPT_HANDLER_SKIP[RAX]

_SAVE_EXCEPT_REGS::
        ENTER   0
        MOV     RAX,U64 SF_ARG1[RBP]
        MOV     U64 EXCEPT_RSI[RAX],RSI
        MOV     U64 EXCEPT_RDI[RAX],RDI
        MOV     U64 EXCEPT_R10[RAX],R10
        MOV     U64 EXCEPT_R11[RAX],R11
        MOV     U64 EXCEPT_R12[RAX],R12
        MOV     U64 EXCEPT_R13[RAX],R13
        MOV     U64 EXCEPT_R14[RAX],R14
        MOV     U64 EXCEPT_R15[RAX],R15
        LEAVE
        RET1    8
}

LTextern _TEST_EXCEPT U0 TestExcept();
LTextern _TAKE_EXCEPT U0 TakeExcept();
LTextern _SAVE_EXCEPT_REGS U0 SaveExceptRegs(ExceptStruct *t);

#exe {NoRegVar(ON);};

class SysTryStk
{
  U64 var_tempt;
  U64 var_old_flags;
  U64 var_rbp;
  U64 var_rsp;
  U64 rbp;
  U64 ret_rip;
  U64 arg1;
  U64 arg2;
};

U0 SysTry(U8 *catch_start,U8 *untry_start)
{
  U64 *rsp=GetStkPtr,*rbp=GetBasePtr,old_flags=GetFlags;
  ExceptStruct *tempt=MAlloc(sizeof(ExceptStruct));
  tempt->handler_catch=catch_start;
  tempt->handler_untry=untry_start;
  tempt->rsp=rsp><(U8 *)+sizeof(SysTryStk);
  tempt->rbp=*rbp;
  tempt->rflags=old_flags;
  SaveExceptRegs(tempt);
  Cli;
  InsQue(tempt,Fs->last_except);
  SetFlags(old_flags);
}

U0 SysUntry()
{
  ExceptStruct *tempt=Fs->last_except;
  PushFD;
//The adam task sometimes probes except depth,
//so we lock it out.  A probe from a multicore
//would fail, but who'd want to do that?
  Cli;
  RemQue(tempt);
  PopFD;
  Free(tempt);
}

U0 AdamLogExcept(I64 argc,I64 *argv)
{
  U64 i;
  if (!Gs->num) { //TODO: Other cores
    AdamLog("Depth:%02X Task:%08X throw(",
      ExceptDepth(Fs),Fs);
    for (i=0;i<argc;i++) {
      AdamLog("%X",argv[i]);
      if (i<argc-1)
        AdamLog(",");
    }
    AdamLog(");\n");
  }
}

U0 PutExcept()
{
  I64 i;
  if (Fs->except_argc>0) {
    if (Fs->except_argv[0]<DefineSubCnt("ST_EXCEPT_TYPES")) {
      "Exception Type :%Z\n",Fs->except_argv[0],"ST_EXCEPT_TYPES";
      if (Fs->except_argv[0]==EXCEPT_UNDEF_DEFINE)
        "Name:'%s'\n",Fs->except_argv[1];
      else if (Fs->except_argv[0]==EXCEPT_DIVIDE_BY_ZERO)
        "Addr:%P\n",Fs->except_argv[1];
      else {
        for (i=1;i<Fs->except_argc;i++)
          "%016X ",Fs->except_argv[i];
        NewLine;
      }
    } else {
      "Exception:";
      for (i=0;i<Fs->except_argc;i++)
        "%016X ",Fs->except_argv[i];
      NewLine;
    }
  } else
    "Generic Exception\n";
}

U0 throw_join(I64 argc,I64 *argv)
{
  ExceptStruct *tempt=Fs->last_except;
  BoolI8 was_raw;

  Fs->except_argc=argc;
  Fs->except_argv=argv;
  Fs->except_rbp=GetBasePtr;
  Fs->catch_except=FALSE;
  Fs->ignore_except=FALSE;
  while (Fs->next_except!=&Fs->next_except) {
    TestExcept;
    if (Fs->catch_except)
      TakeExcept;
    if (Fs->ignore_except)
      return;
    SetBasePtr(Fs->except_rbp);
    tempt=Fs->last_except;
    RemQue(tempt);
    Free(tempt);
  }
  was_raw=Raw(ON);
  PutExcept;
  if (!Gs->num)
    Dbg("Unhandled Exception");
  else {
    DbgStr("Unhandled MP Exception",5000);
    while (TRUE)
      Beep;
  }
  Raw(was_raw);
}

U0 throw_no_log(...)
{
  throw_join(argc,argv);
}

U0 throw(...)
{
  AdamLogExcept(argc,argv);
  throw_join(argc,argv);
}

#exe {NoRegVar(OFF);};

U0 SysThrowBreak()
{
  if (Bt(&Fs->task_flags,TASKf_BREAK_TO_SHIFT_ESC))
    Msg(MSG_KEY_DOWN,CH_SHIFT_ESC,0x20100000201);
  else { //TODO: Might want lock
    Fs->wake_jiffy=0;
    TaskRstAwaitingMsg;
    PrtsRelease();
    BlkDevsRelease();
    FlushMsgs;
    throw(EXCEPT_BREAK);
  }
}

//This can be used to exit an app, but not a task.
U0 ThrowBreak(TaskStruct *task=NULL)
{
  if (task && task!=Fs) {
    if (!TaskValidate(task)) return;
    //TODO: Might want lock
    sys_focus_task=task;
    LBts(sys_ctrl_alt_flags,SYSf_CTRL_ALT_C);
  } else
    SysThrowBreak;
}

BoolI64 BreakLock(TaskStruct *task=NULL)
{
  if (!task) task=Fs;
  return !LBts(&task->task_flags,TASKf_BREAK_LOCKED);
}

BoolI64 BreakUnlock(TaskStruct *task=NULL)
{
  BoolI8 result;
  if (!task) task=Fs;
  result=LBtr(&task->task_flags,TASKf_BREAK_LOCKED);
  if (LBtr(&task->task_flags,TASKf_PENDING_BREAK)) {
    if (task==Fs)
      ThrowBreak;
    else
      task->rip=&ThrowBreak;
  }
  return result;
}

U0 CatchAll()
{
  PutExcept;
  Fs->catch_except=TRUE;
}
Historical capture: 2012-03-09. Home | Power on LoseThos | Sources and changes