?? jobc.c
字號:
xprintf("PhyAdd : %08x\r\n", PhyAdd);
ReadKbd(&KeyCodeE, 1);
*/
/* Now we can allocate User Job Memory */
/* Allocate user memory for Stack Code and Data */
/* This is done in the OS PD */
nPages = sStack/4096;
if (sStack%4096) nPages++;
erc = AllocPage(nPages, &pStack);
sStack = nPages * 4096; /* set to whole pages */
nPages = sCode/4096;
if (sCode%4096) nPages++;
if (!erc)
erc = AllocPage(nPages, &pCode);
nPages = sData/4096;
if (sData%4096) nPages++;
if (!erc)
erc = AllocPage(nPages, &pData);
/* Right now, the OS PD looks exacly like we want
the User PD to look. We will now copy the entire
OS PD into the User's New PD.
*/
CopyData(pOSPD, pPD, 4096); /* Copy OS PD to User PD */
/* All Job memory is now allocated, so let's LOAD IT! */
if (!erc)
erc = SetFileLFA(fh, oCode);
if (!erc)
erc = ReadBytes (fh, pCode, sCode, &dret);
if (!erc)
erc = SetFileLFA(fh, oData);
if (!erc)
erc = ReadBytes (fh, pData, sData, &dret);
/* Now that we have read in the code and data we
apply fixups to these segments from the runfile
*/
if (!erc) {
if (nCDFIX) {
erc = SetFileLFA(fh, oCDFIX); /* back to fixups */
while ((nCDFIX--) && (!erc)) {
erc = ReadBytes (fh, &i, 4, &dret);
pFix = pCode + i; /* Where in CSeg */
*pFix = *pFix - offData + pData;
}
}
if (nCCFIX) {
erc = SetFileLFA(fh, oCCFIX); /* back to fixups */
while ((nCCFIX--) && (!erc)) {
erc = ReadBytes (fh, &i, 4, &dret);
pFix = pCode + i; /* Where in CSeg */
*pFix = *pFix - offCode + pCode;
}
}
if (nDCFIX) {
erc = SetFileLFA(fh, oDCFIX); /* back to fixups */
while ((nDCFIX--) && (!erc)) {
erc = ReadBytes (fh, &i, 4, &dret);
pFix = pData + i; /* Where in DSeg */
*pFix = *pFix - offCode + pCode;
}
}
if (nDDFIX) {
erc = SetFileLFA(fh, oDDFIX); /* back to fixups */
while ((nDDFIX--) && (!erc)) {
erc = ReadBytes (fh, &i, 4, &dret);
pFix = pData + i; /* Where in DSeg */
*pFix = *pFix - offData + pData;
}
}
}
/* Clean the OS PD of User memory */
FillData(&pOSPD[256], 1024, 0); /* Clean OS PD of User PDEs */
FillData(&pOSPD[768], 1024, 0); /* Clean OS PD of User Shadow */
/* Now we fill in the rest of the User's JCB */
pNewJCB->pJcbPD = pPD; /* Lin Add of PD */
pNewJCB->pJcbStack = pStack; /* Add of Stack */
pNewJCB->sJcbStack = sStack; /* Size of Code */
pNewJCB->pJcbCode = pCode; /* Add of Code */
pNewJCB->sJcbCode = sCode; /* Size of Code */
pNewJCB->pJcbData = pData; /* Add of Code */
pNewJCB->sJcbData = sData; /* Size of Code */
pNewJCB->sbUserName[0] = 0; /* Zero UserName */
pNewJCB->sbPath[0] = 0; /* No Default path */
pNewJCB->JcbExitRF[0] = 0; /* No Exit Run File */
pNewJCB->JcbCmdLine[0] = 0; /* No Cmd Line */
CopyData("KBD", &pNewJCB->JcbSysIn[1], 3);
pNewJCB->JcbSysIn[0] = 3; /* Size */
CopyData("VID", &pNewJCB->JcbSysOut[1], 3);
pNewJCB->JcbSysOut[0] = 3; /* Size */
pNewJCB->pVidMem = pVid; /* Default to Virt Vid */
pNewJCB->pVirtVid = pVid; /* Virtual Video memory */
pNewJCB->CrntX = 0; /* Vid X Position */
pNewJCB->CrntY = 0; /* Vid Y Position */
pNewJCB->nCols = 80; /* Columns */
pNewJCB->nLines = 25; /* Lines */
pNewJCB->VidMode = 0; /* 80x25 VGA Color Text */
pNewJCB->fCursOn = 1; /* Cursor On */
pNewJCB->fCursType = 0; /* UnderLine */
/* Finally, we crank up the new task and schedule it for
execution!
*/
if (!erc)
erc = AllocExch(&i);
if (!erc)
erc = NewTask(JobNum, 0x18, 25, 0, i,
pStack+sStack-4,
pStart+pCode-offCode);
if (!erc)
SetExchOwner(i, pNewJCB); /* Exch now belongs to new JCB */
}
CloseFile(fh);
} /* read run file OK */
if (!erc)
*pJobNumRet = JobNum;
return(erc);
}
/*********************************************************
This loads a job into an existing PD and JCB. This is
called by Chain() and may also be called by ExitJob()
if an ExitJob was specified in the current JCB.
The PD, pVid & first PT still exist in OS memory.
(CleanPD left the first PT for us). ExitJob and Chain
are responsible for opening and validating the runfile
and setting up the run file variables.
*********************************************************/
long LoadJob(char *pJCB, long fh)
{
long erc, i, dret, nPages;
long *pFix;
pNewJCB = pJCB;
/* Allocate user memory for Stack, Code and Data */
/* This is done in the USER PD */
nPages = sStack/4096;
if (sStack%4096) nPages++;
erc = AllocPage(nPages, &pStack);
sStack = nPages * 4096; /* set to whole pages */
nPages = sCode/4096;
if (sCode%4096) nPages++;
if (!erc)
erc = AllocPage(nPages, &pCode);
nPages = sData/4096;
if (sData%4096) nPages++;
erc = AllocPage(nPages, &pData);
/* All Job memory is now allocated, so let's LOAD IT! */
if (!erc)
erc = SetFileLFA(fh, oCode);
if (!erc)
erc = ReadBytes (fh, pCode, sCode, &dret);
if (!erc)
erc = SetFileLFA(fh, oData);
if (!erc)
erc = ReadBytes (fh, pData, sData, &dret);
/* Now that we have read in the code and data we
apply fixups to these segments from the runfile
*/
if (!erc) {
if (nCDFIX) {
erc = SetFileLFA(fh, oCDFIX); /* back to fixups */
while ((nCDFIX--) && (!erc)) {
erc = ReadBytes (fh, &i, 4, &dret);
pFix = pCode + i; /* Where in CSeg */
*pFix = *pFix - offData + pData;
}
}
if (nCCFIX) {
erc = SetFileLFA(fh, oCCFIX); /* back to fixups */
while ((nCCFIX--) && (!erc)) {
erc = ReadBytes (fh, &i, 4, &dret);
pFix = pCode + i; /* Where in CSeg */
*pFix = *pFix - offCode + pCode;
}
}
if (nDCFIX) {
erc = SetFileLFA(fh, oDCFIX); /* back to fixups */
while ((nDCFIX--) && (!erc)) {
erc = ReadBytes (fh, &i, 4, &dret);
pFix = pData + i; /* Where in DSeg */
*pFix = *pFix - offCode + pCode;
}
}
if (nDDFIX) {
erc = SetFileLFA(fh, oDDFIX); /* back to fixups */
while ((nDDFIX--) && (!erc)) {
erc = ReadBytes (fh, &i, 4, &dret);
pFix = pData + i; /* Where in DSeg */
*pFix = *pFix - offData + pData;
}
}
/* Now we fill in the rest of the User's JCB */
pNewJCB->pJcbStack = pStack; /* Add of Stack */
pNewJCB->sJcbStack = sStack; /* Size of Code */
pNewJCB->pJcbCode = pCode; /* Add of Code */
pNewJCB->sJcbCode = sCode; /* Size of Code */
pNewJCB->pJcbData = pData; /* Add of Code */
pNewJCB->sJcbData = sData; /* Size of Code */
}
CloseFile(fh);
return(erc);
}
/******************************************************
This called from Exit() in C or directly from a user
job or service. This cleans up ALL resources that the
job had allocated.
This also checks for an exit run file to load if
one is specified. If no exit run file is specified
we just kill the JCB entirely and if video and
keyboard are assigned we assign them to the Monitor.
******************************************************/
void far ExitJob(long dError)
{
/* NO LOCAL VARIABLES BECAUSE WE SWITCH STACKS!! */
GetJobNum(&JobNumE);
GetpJCB(JobNumE, &pCrntJCB); /* Get pJCB to current Job */
pCrntJCB->ExitError = dError;
/* Remove ALL tasks for this job that are at the ReadyQue.
The task we are in won't be removed because its RUNNING!
*/
RemoveRdyJob(pCrntJCB); /* It always returns ErcOk */
/* Deallocate all exchanges for this job except the one belonging
to current TSS! The Dealloc Exchange call will invalidate
all TSSs found at exchanges belonging to this user, and
will also free up RQBs and Link Blocks. The job will not be
able to initiate requests or send messages after this unless
it is done with the TSSExchange because it will get a kernel
error (invalid exchange).
*/
/* Find out what our TSS exchange is so
we don't deallocate it to! */
GetTSSExch(&ExchE);
ercE = 0;
iE = 0;
while (ercE != ErcOutOfRange) {
ercE = GetExchOwner(iE, &pExchJCBE);
if ((!ercE) && (iE != ExchE) && (pExchJCBE == pCrntJCB))
DeAllocExch(iE);
iE++;
}
ercE = 0; /* Clear the error */
/* Now that the user can't make anymore requests,
Send Abort messages to all services.
This closes all files that were opened by the Job
and frees up any other resources held for this
job by any service.
*/
/* SendAbort(JobNumE, ExchE); */
/* We must now switch to a temporary stack so we can
clean out the user PD (we are on his stack right now!).
*/
#asm
MOV EAX, OFFSET _TmpStack
ADD EAX, 508
MOV ESP, EAX
MOV EBP, EAX
#endasm
/* Clean the PD of all user memory leaving OS memory for next
job if there is one.
*/
pPDE = pCrntJCB->pJcbPD;
CleanUserPD(pPDE);
/* Look for Exit Run file to load if any exists. If no exit run
file, we deallocate the PD and JCB then return to JOB 1. */
GetExitJob(FileE, &cbFileE); /* Exit Run File!! */
if (!cbFileE)
ercE = ErcNoExitJob;
if (!ercE)
ercE = GetRunFile(FileE, cbFileE, &job_fhE);
if (!ercE)
ercE = LoadJob(pCrntJCB, job_fhE);
if (!ercE) {
pStart = pStart+pCode-offCode;
/* Now we RETURN to new job's address after we put him
on his new stack. */
#asm
MOV EAX, _pStack
MOV EBX, _sStack
ADD EAX, EBX
SUB EAX, 4
MOV ESP, EAX
MOV EBP, EAX
PUSH 18h
MOV EAX, _pStart
PUSH EAX
RETF ;We are history!
#endasm
}
if (ercE) { /* something failed or we don't have an ExitRF */
/* In case there is no job to run or a fatal error has happened
we send a message (ISendMsg) to the monitor status
task with our TSSExch and the Error. Then he will WIPE US OUT!
We use ISend (vice send) so he can't run before we get to
the exchange otherwise we will be placed back on the readyQueue!
*/
ISendMsg(KillExch, ExchE, ercE);
WaitMsg(ExchE, BogusMsg);
/* We are NO MORE */
}
}
/******************************************************
This is called to execute a program without changing
the ExitJob. This is so you can run program B from
program A and return to program A when program B is
done. This runs Job B in the "context" of Job A
which means Job B inherits the JCB and PD of job A
so it can use things like the command line and
path that were set up by A.
Information can be passed to Job B by calling
SetCmdLine (if Job B reads it), and also by
setting the ExitError value in the parameter.
Chain will only return to you if there was an
error loading the Job. In other words, if Chain
fails in a critial section we try to load the
ExitJob and pass it the error.
******************************************************/
long far Chain(char *pFileName, long cbFileName, long dExitError)
{
/* NO LOCAL VARIABLES BECAUSE WE SWITCH STACKS!! */
ercE = GetRunFile(pFileName, cbFileName, &job_fhE);
if (ercE)
return(ercE);
GetJobNum(&JobNumE);
GetpJCB(JobNumE, &pCrntJCB); /* Get pJCB to current Job */
pCrntJCB->ExitError = dExitError;
/* Remove ALL tasks for this job that are at the ReadyQue.
The task we are in won't be removed because its RUNNING!
*/
RemoveRdyJob(pCrntJCB); /* It always returns ErcOk */
/* Deallocate all exchanges for this job except the one belonging
to current TSS! The Dealloc Exchange call will invalidate
all TSSs found at exchanges belonging to this user, and
will also free up RQBs and Link Blocks. The job will not be
able to initiate requests or send messages after this unless
it is done with the TSSExchange because it will get a kernel
error (invalid exchange).
*/
/* Find out what our TSS exchange is so
we don't deallocate it to! */
GetTSSExch(&ExchE);
ercE = 0;
iE = 0;
while (ercE != ErcOutOfRange) {
ercE = GetExchOwner(iE, &pExchJCBE);
if ((!ercE) && (iE != ExchE) && (pExchJCBE == pCrntJCB))
DeAllocExch(iE);
iE++;
}
/* Now that the user can't make anymore requests,
Send Abort messages to all services.
This closes all files that were opened by the Job
and frees up any other resources held for this
job by any services.
*/
/* SendAbort(JobNumE, ExchE); */
/* We must now switch to a temporary stack so we can
clean out the user PD (we are on his stack right now!).
*/
#asm
MOV EAX, OFFSET _TmpStack
ADD EAX, 508
MOV ESP, EAX
MOV EBP, EAX
#endasm
/* Clean the PD of all user memory leaving OS memory for next
job if there is one.
*/
pPDE = pCrntJCB->pJcbPD;
CleanUserPD(pPDE);
/* Look for Exit Run file to load if any exists. If no exit run
file, we deallocate the PD and JCB then return to the JOB 1. */
ercE = LoadJob(pCrntJCB, job_fhE);
if (ercE) {
/* We have errored in a critical part of Chain (LoadJob).
The original user's job is destroyed, and we can run the
chain file (bummer).
The only thing left to do is Look for Exit Run file to load
if any exists. If no exit run file, we kill this guy
and return to the monitor if he had the screen. */
GetExitJob(FileE, &cbFileE); /* Exit Run File!! */
if (!cbFileE)
ercE = ErcNoExitJob;
if (!ercE)
ercE = GetRunFile(FileE, cbFileE, &job_fhE);
if (!ercE)
ercE = LoadJob(pCrntJCB, job_fhE);
}
if (!ercE) { /* No error */
pStart = pStart+pCode-offCode;
/* Now we RETURN to new job's address after we put him
on his new stack. */
#asm
MOV EAX, _pStack
MOV EBX, _sStack
ADD EAX, EBX
SUB EAX, 4
MOV ESP, EAX
MOV EBP, EAX
PUSH 18h
MOV EAX, _pStart
PUSH EAX
RETF ;We are history!
#endasm
}
if (ercE) { /* Something failed loading the job (Chain or Exit) */
/* In case there is no job to run or a fatal error has happened
we send a message (ISendMsg) to the monitor status
task with our TSSExch and the Error. Then he will WIPE US OUT!
We use ISend (vice send) so he can't run before we get to
the exchange otherwise we will be placed back on the readyQueue!
*/
ISendMsg(KillExch, ExchE, ercE); /* ISend clears ints! */
#asm
STI
#endasm
WaitMsg(ExchE, BogusMsg);
/* We are NO MORE */
}
}
/*********************** End of Module *****************/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -