system.c
来自「MINIX2.0操作系统源码 MINIX2.0操作系统源码」· C语言 代码 · 共 1,159 行 · 第 1/3 页
C
1,159 行
return(OK);
}
/*==========================================================================*
* do_gboot *
*==========================================================================*/
PUBLIC struct bparam_s boot_parameters;
PRIVATE int do_gboot(m_ptr)
message *m_ptr; /* pointer to request message */
{
/* Copy the boot parameters. Normally only called during fs init. */
phys_bytes dst_phys;
dst_phys = umap(proc_addr(m_ptr->PROC1), D, (vir_bytes) m_ptr->MEM_PTR,
(vir_bytes) sizeof(boot_parameters));
if (dst_phys == 0) panic("bad call to SYS_GBOOT", NO_NUM);
phys_copy(vir2phys(&boot_parameters), dst_phys,
(phys_bytes) sizeof(boot_parameters));
return(OK);
}
/*===========================================================================*
* do_mem *
*===========================================================================*/
PRIVATE int do_mem(m_ptr)
register message *m_ptr; /* pointer to request message */
{
/* Return the base and size of the next chunk of memory. */
struct memory *memp;
for (memp = mem; memp < &mem[NR_MEMS]; ++memp) {
m_ptr->m1_i1 = memp->base;
m_ptr->m1_i2 = memp->size;
m_ptr->m1_i3 = tot_mem_size;
memp->size = 0;
if (m_ptr->m1_i2 != 0) break; /* found a chunk */
}
return(OK);
}
/*==========================================================================*
* do_umap *
*==========================================================================*/
PRIVATE int do_umap(m_ptr)
register message *m_ptr; /* pointer to request message */
{
/* Same as umap(), for non-kernel processes. */
m_ptr->SRC_BUFFER = umap(proc_addr((int) m_ptr->SRC_PROC_NR),
(int) m_ptr->SRC_SPACE,
(vir_bytes) m_ptr->SRC_BUFFER,
(vir_bytes) m_ptr->COPY_BYTES);
return(OK);
}
/*==========================================================================*
* do_trace *
*==========================================================================*/
#define TR_PROCNR (m_ptr->m2_i1)
#define TR_REQUEST (m_ptr->m2_i2)
#define TR_ADDR ((vir_bytes) m_ptr->m2_l1)
#define TR_DATA (m_ptr->m2_l2)
#define TR_VLSIZE ((vir_bytes) sizeof(long))
PRIVATE int do_trace(m_ptr)
register message *m_ptr;
{
/* Handle the debugging commands supported by the ptrace system call
* The commands are:
* T_STOP stop the process
* T_OK enable tracing by parent for this process
* T_GETINS return value from instruction space
* T_GETDATA return value from data space
* T_GETUSER return value from user process table
* T_SETINS set value from instruction space
* T_SETDATA set value from data space
* T_SETUSER set value in user process table
* T_RESUME resume execution
* T_EXIT exit
* T_STEP set trace bit
*
* The T_OK and T_EXIT commands are handled completely by the memory manager,
* all others come here.
*/
register struct proc *rp;
phys_bytes src, dst;
int i;
rp = proc_addr(TR_PROCNR);
if (rp->p_flags & P_SLOT_FREE) return(EIO);
switch (TR_REQUEST) {
case T_STOP: /* stop process */
if (rp->p_flags == 0) lock_unready(rp);
rp->p_flags |= P_STOP;
rp->p_reg.psw &= ~TRACEBIT; /* clear trace bit */
return(OK);
case T_GETINS: /* return value from instruction space */
if (rp->p_map[T].mem_len != 0) {
if ((src = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
break;
}
/* Text space is actually data space - fall through. */
case T_GETDATA: /* return value from data space */
if ((src = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
break;
case T_GETUSER: /* return value from process table */
if ((TR_ADDR & (sizeof(long) - 1)) != 0 ||
TR_ADDR > sizeof(struct proc) - sizeof(long))
return(EIO);
TR_DATA = *(long *) ((char *) rp + (int) TR_ADDR);
break;
case T_SETINS: /* set value in instruction space */
if (rp->p_map[T].mem_len != 0) {
if ((dst = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
TR_DATA = 0;
break;
}
/* Text space is actually data space - fall through. */
case T_SETDATA: /* set value in data space */
if ((dst = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
TR_DATA = 0;
break;
case T_SETUSER: /* set value in process table */
if ((TR_ADDR & (sizeof(reg_t) - 1)) != 0 ||
TR_ADDR > sizeof(struct stackframe_s) - sizeof(reg_t))
return(EIO);
i = (int) TR_ADDR;
#if (CHIP == INTEL)
/* Altering segment registers might crash the kernel when it
* tries to load them prior to restarting a process, so do
* not allow it.
*/
if (i == (int) &((struct proc *) 0)->p_reg.cs ||
i == (int) &((struct proc *) 0)->p_reg.ds ||
i == (int) &((struct proc *) 0)->p_reg.es ||
#if _WORD_SIZE == 4
i == (int) &((struct proc *) 0)->p_reg.gs ||
i == (int) &((struct proc *) 0)->p_reg.fs ||
#endif
i == (int) &((struct proc *) 0)->p_reg.ss)
return(EIO);
#endif
if (i == (int) &((struct proc *) 0)->p_reg.psw)
/* only selected bits are changeable */
SETPSW(rp, TR_DATA);
else
*(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) TR_DATA;
TR_DATA = 0;
break;
case T_RESUME: /* resume execution */
rp->p_flags &= ~P_STOP;
if (rp->p_flags == 0) lock_ready(rp);
TR_DATA = 0;
break;
case T_STEP: /* set trace bit */
rp->p_reg.psw |= TRACEBIT;
rp->p_flags &= ~P_STOP;
if (rp->p_flags == 0) lock_ready(rp);
TR_DATA = 0;
break;
default:
return(EIO);
}
return(OK);
}
/*===========================================================================*
* cause_sig *
*===========================================================================*/
PUBLIC void cause_sig(proc_nr, sig_nr)
int proc_nr; /* process to be signalled */
int sig_nr; /* signal to be sent, 1 to _NSIG */
{
/* A task wants to send a signal to a process. Examples of such tasks are:
* TTY wanting to cause SIGINT upon getting a DEL
* CLOCK wanting to cause SIGALRM when timer expires
* FS also uses this to send a signal, via the SYS_KILL message.
* Signals are handled by sending a message to MM. The tasks don't dare do
* that directly, for fear of what would happen if MM were busy. Instead they
* call cause_sig, which sets bits in p_pending, and then carefully checks to
* see if MM is free. If so, a message is sent to it. If not, when it becomes
* free, a message is sent. The process being signaled is blocked while MM
* has not seen or finished with all signals for it. These signals are
* counted in p_pendcount, and the SIG_PENDING flag is kept nonzero while
* there are some. It is not sufficient to ready the process when MM is
* informed, because MM can block waiting for FS to do a core dump.
*/
register struct proc *rp, *mmp;
rp = proc_addr(proc_nr);
if (sigismember(&rp->p_pending, sig_nr))
return; /* this signal already pending */
sigaddset(&rp->p_pending, sig_nr);
++rp->p_pendcount; /* count new signal pending */
if (rp->p_flags & PENDING)
return; /* another signal already pending */
if (rp->p_flags == 0) lock_unready(rp);
rp->p_flags |= PENDING | SIG_PENDING;
++sig_procs; /* count new process pending */
mmp = proc_addr(MM_PROC_NR);
if ( ((mmp->p_flags & RECEIVING) == 0) || mmp->p_getfrom != ANY) return;
inform();
}
/*===========================================================================*
* inform *
*===========================================================================*/
PUBLIC void inform()
{
/* When a signal is detected by the kernel (e.g., DEL), or generated by a task
* (e.g. clock task for SIGALRM), cause_sig() is called to set a bit in the
* p_pending field of the process to signal. Then inform() is called to see
* if MM is idle and can be told about it. Whenever MM blocks, a check is
* made to see if 'sig_procs' is nonzero; if so, inform() is called.
*/
register struct proc *rp;
/* MM is waiting for new input. Find a process with pending signals. */
for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++)
if (rp->p_flags & PENDING) {
m.m_type = KSIG;
m.SIG_PROC = proc_number(rp);
m.SIG_MAP = rp->p_pending;
sig_procs--;
if (lock_mini_send(proc_addr(HARDWARE), MM_PROC_NR, &m) != OK)
panic("can't inform MM", NO_NUM);
sigemptyset(&rp->p_pending); /* the ball is now in MM's court */
rp->p_flags &= ~PENDING;/* remains inhibited by SIG_PENDING */
lock_pick_proc(); /* avoid delay in scheduling MM */
return;
}
}
/*===========================================================================*
* umap *
*===========================================================================*/
PUBLIC phys_bytes umap(rp, seg, vir_addr, bytes)
register struct proc *rp; /* pointer to proc table entry for process */
int seg; /* T, D, or S segment */
vir_bytes vir_addr; /* virtual address in bytes within the seg */
vir_bytes bytes; /* # of bytes to be copied */
{
/* Calculate the physical memory address for a given virtual address. */
vir_clicks vc; /* the virtual address in clicks */
phys_bytes pa; /* intermediate variables as phys_bytes */
#if (CHIP == INTEL)
phys_bytes seg_base;
#endif
/* If 'seg' is D it could really be S and vice versa. T really means T.
* If the virtual address falls in the gap, it causes a problem. On the
* 8088 it is probably a legal stack reference, since "stackfaults" are
* not detected by the hardware. On 8088s, the gap is called S and
* accepted, but on other machines it is called D and rejected.
* The Atari ST behaves like the 8088 in this respect.
*/
if (bytes <= 0) return( (phys_bytes) 0);
vc = (vir_addr + bytes - 1) >> CLICK_SHIFT; /* last click of data */
#if (CHIP == INTEL) || (CHIP == M68000)
if (seg != T)
seg = (vc < rp->p_map[D].mem_vir + rp->p_map[D].mem_len ? D : S);
#else
if (seg != T)
seg = (vc < rp->p_map[S].mem_vir ? D : S);
#endif
if((vir_addr>>CLICK_SHIFT) >= rp->p_map[seg].mem_vir+ rp->p_map[seg].mem_len)
return( (phys_bytes) 0 );
#if (CHIP == INTEL)
seg_base = (phys_bytes) rp->p_map[seg].mem_phys;
seg_base = seg_base << CLICK_SHIFT; /* segment origin in bytes */
#endif
pa = (phys_bytes) vir_addr;
#if (CHIP != M68000)
pa -= rp->p_map[seg].mem_vir << CLICK_SHIFT;
return(seg_base + pa);
#endif
#if (CHIP == M68000)
#if (SHADOWING == 0)
pa -= (phys_bytes)rp->p_map[seg].mem_vir << CLICK_SHIFT;
pa += (phys_bytes)rp->p_map[seg].mem_phys << CLICK_SHIFT;
#else
if (rp->p_shadow && seg != T) {
pa -= (phys_bytes)rp->p_map[D].mem_phys << CLICK_SHIFT;
pa += (phys_bytes)rp->p_shadow << CLICK_SHIFT;
}
#endif
return(pa);
#endif
}
/*==========================================================================*
* numap *
*==========================================================================*/
PUBLIC phys_bytes numap(proc_nr, vir_addr, bytes)
int proc_nr; /* process number to be mapped */
vir_bytes vir_addr; /* virtual address in bytes within D seg */
vir_bytes bytes; /* # of bytes required in segment */
{
/* Do umap() starting from a process number instead of a pointer. This
* function is used by device drivers, so they need not know about the
* process table. To save time, there is no 'seg' parameter. The segment
* is always D.
*/
return(umap(proc_addr(proc_nr), D, vir_addr, bytes));
}
#if (CHIP == INTEL)
/*==========================================================================*
* alloc_segments *
*==========================================================================*/
PUBLIC void alloc_segments(rp)
register struct proc *rp;
{
/* This is called only by do_newmap, but is broken out as a separate function
* because so much is hardware-dependent.
*/
phys_bytes code_bytes;
phys_bytes data_bytes;
int privilege;
if (protected_mode) {
data_bytes = (phys_bytes) (rp->p_map[S].mem_vir + rp->p_map[S].mem_len)
<< CLICK_SHIFT;
if (rp->p_map[T].mem_len == 0)
code_bytes = data_bytes; /* common I&D, poor protect */
else
code_bytes = (phys_bytes) rp->p_map[T].mem_len << CLICK_SHIFT;
privilege = istaskp(rp) ? TASK_PRIVILEGE : USER_PRIVILEGE;
init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
(phys_bytes) rp->p_map[T].mem_phys << CLICK_SHIFT,
code_bytes, privilege);
init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
(phys_bytes) rp->p_map[D].mem_phys << CLICK_SHIFT,
data_bytes, privilege);
rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
#if _WORD_SIZE == 4
rp->p_reg.gs =
rp->p_reg.fs =
#endif
rp->p_reg.ss =
rp->p_reg.es =
rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
} else {
rp->p_reg.cs = click_to_hclick(rp->p_map[T].mem_phys);
rp->p_reg.ss =
rp->p_reg.es =
rp->p_reg.ds = click_to_hclick(rp->p_map[D].mem_phys);
}
}
#endif /* (CHIP == INTEL) */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?