📄 system.c
字号:
15491
15492 rp = proc_addr(TR_PROCNR);
15493 if (rp->p_flags & P_SLOT_FREE) return(EIO);
15494 switch (TR_REQUEST) {
15495 case T_STOP: /* stop process */
15496 if (rp->p_flags == 0) lock_unready(rp);
15497 rp->p_flags |= P_STOP;
15498 rp->p_reg.psw &= ~TRACEBIT; /* clear trace bit */
15499 return(OK);
15500
15501 case T_GETINS: /* return value from instruction space */
15502 if (rp->p_map[T].mem_len != 0) {
15503 if ((src = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
15504 phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
15505 break;
15506 }
15507 /* Text space is actually data space - fall through. */
15508
15509 case T_GETDATA: /* return value from data space */
15510 if ((src = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
15511 phys_copy(src, vir2phys(&TR_DATA), (phys_bytes) sizeof(long));
15512 break;
15513
15514 case T_GETUSER: /* return value from process table */
15515 if ((TR_ADDR & (sizeof(long) - 1)) != 0 ||
15516 TR_ADDR > sizeof(struct proc) - sizeof(long))
15517 return(EIO);
15518 TR_DATA = *(long *) ((char *) rp + (int) TR_ADDR);
15519 break;
15520
15521 case T_SETINS: /* set value in instruction space */
15522 if (rp->p_map[T].mem_len != 0) {
15523 if ((dst = umap(rp, T, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
15524 phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
15525 TR_DATA = 0;
15526 break;
15527 }
15528 /* Text space is actually data space - fall through. */
15529
15530 case T_SETDATA: /* set value in data space */
15531 if ((dst = umap(rp, D, TR_ADDR, TR_VLSIZE)) == 0) return(EIO);
15532 phys_copy(vir2phys(&TR_DATA), dst, (phys_bytes) sizeof(long));
15533 TR_DATA = 0;
15534 break;
15535
15536 case T_SETUSER: /* set value in process table */
15537 if ((TR_ADDR & (sizeof(reg_t) - 1)) != 0 ||
15538 TR_ADDR > sizeof(struct stackframe_s) - sizeof(reg_t))
15539 return(EIO);
15540 i = (int) TR_ADDR;
15541 #if (CHIP == INTEL)
15542 /* Altering segment registers might crash the kernel when it
15543 * tries to load them prior to restarting a process, so do
15544 * not allow it.
15545 */
15546 if (i == (int) &((struct proc *) 0)->p_reg.cs ||
15547 i == (int) &((struct proc *) 0)->p_reg.ds ||
15548 i == (int) &((struct proc *) 0)->p_reg.es ||
15549 #if _WORD_SIZE == 4
15550 i == (int) &((struct proc *) 0)->p_reg.gs ||
15551 i == (int) &((struct proc *) 0)->p_reg.fs ||
15552 #endif
15553 i == (int) &((struct proc *) 0)->p_reg.ss)
15554 return(EIO);
15555 #endif
15556 if (i == (int) &((struct proc *) 0)->p_reg.psw)
15557 /* only selected bits are changeable */
15558 SETPSW(rp, TR_DATA);
15559 else
15560 *(reg_t *) ((char *) &rp->p_reg + i) = (reg_t) TR_DATA;
15561 TR_DATA = 0;
15562 break;
15563
15564 case T_RESUME: /* resume execution */
15565 rp->p_flags &= ~P_STOP;
15566 if (rp->p_flags == 0) lock_ready(rp);
15567 TR_DATA = 0;
15568 break;
15569
15570 case T_STEP: /* set trace bit */
15571 rp->p_reg.psw |= TRACEBIT;
15572 rp->p_flags &= ~P_STOP;
15573 if (rp->p_flags == 0) lock_ready(rp);
15574 TR_DATA = 0;
15575 break;
15576
15577 default:
15578 return(EIO);
15579 }
15580 return(OK);
15581 }
15583 /*===========================================================================*
15584 * cause_sig *
15585 *===========================================================================*/
15586 PUBLIC void cause_sig(proc_nr, sig_nr)
15587 int proc_nr; /* process to be signalled */
15588 int sig_nr; /* signal to be sent, 1 to _NSIG */
15589 {
15590 /* A task wants to send a signal to a process. Examples of such tasks are:
15591 * TTY wanting to cause SIGINT upon getting a DEL
15592 * CLOCK wanting to cause SIGALRM when timer expires
15593 * FS also uses this to send a signal, via the SYS_KILL message.
15594 * Signals are handled by sending a message to MM. The tasks don't dare do
15595 * that directly, for fear of what would happen if MM were busy. Instead they
15596 * call cause_sig, which sets bits in p_pending, and then carefully checks to
15597 * see if MM is free. If so, a message is sent to it. If not, when it becomes
15598 * free, a message is sent. The process being signaled is blocked while MM
15599 * has not seen or finished with all signals for it. These signals are
15600 * counted in p_pendcount, and the SIG_PENDING flag is kept nonzero while
15601 * there are some. It is not sufficient to ready the process when MM is
15602 * informed, because MM can block waiting for FS to do a core dump.
15603 */
15604
15605 register struct proc *rp, *mmp;
15606
15607 rp = proc_addr(proc_nr);
15608 if (sigismember(&rp->p_pending, sig_nr))
15609 return; /* this signal already pending */
15610 sigaddset(&rp->p_pending, sig_nr);
15611 ++rp->p_pendcount; /* count new signal pending */
15612 if (rp->p_flags & PENDING)
15613 return; /* another signal already pending */
15614 if (rp->p_flags == 0) lock_unready(rp);
15615 rp->p_flags |= PENDING | SIG_PENDING;
15616 ++sig_procs; /* count new process pending */
15617
15618 mmp = proc_addr(MM_PROC_NR);
15619 if ( ((mmp->p_flags & RECEIVING) == 0) || mmp->p_getfrom != ANY) return;
15620 inform();
15621 }
15624 /*===========================================================================*
15625 * inform *
15626 *===========================================================================*/
15627 PUBLIC void inform()
15628 {
15629 /* When a signal is detected by the kernel (e.g., DEL), or generated by a task
15630 * (e.g. clock task for SIGALRM), cause_sig() is called to set a bit in the
15631 * p_pending field of the process to signal. Then inform() is called to see
15632 * if MM is idle and can be told about it. Whenever MM blocks, a check is
15633 * made to see if 'sig_procs' is nonzero; if so, inform() is called.
15634 */
15635
15636 register struct proc *rp;
15637
15638 /* MM is waiting for new input. Find a process with pending signals. */
15639 for (rp = BEG_SERV_ADDR; rp < END_PROC_ADDR; rp++)
15640 if (rp->p_flags & PENDING) {
15641 m.m_type = KSIG;
15642 m.SIG_PROC = proc_number(rp);
15643 m.SIG_MAP = rp->p_pending;
15644 sig_procs--;
15645 if (lock_mini_send(proc_addr(HARDWARE), MM_PROC_NR, &m) != OK)
15646 panic("can't inform MM", NO_NUM);
15647 sigemptyset(&rp->p_pending); /* the ball is now in MM's court */
15648 rp->p_flags &= ~PENDING;/* remains inhibited by SIG_PENDING */
15649 lock_pick_proc(); /* avoid delay in scheduling MM */
15650 return;
15651 }
15652 }
15655 /*===========================================================================*
15656 * umap *
15657 *===========================================================================*/
15658 PUBLIC phys_bytes umap(rp, seg, vir_addr, bytes)
15659 register struct proc *rp; /* pointer to proc table entry for process */
15660 int seg; /* T, D, or S segment */
15661 vir_bytes vir_addr; /* virtual address in bytes within the seg */
15662 vir_bytes bytes; /* # of bytes to be copied */
15663 {
15664 /* Calculate the physical memory address for a given virtual address. */
15665
15666 vir_clicks vc; /* the virtual address in clicks */
15667 phys_bytes pa; /* intermediate variables as phys_bytes */
15668 phys_bytes seg_base;
15669
15670 /* If 'seg' is D it could really be S and vice versa. T really means T.
15671 * If the virtual address falls in the gap, it causes a problem. On the
15672 * 8088 it is probably a legal stack reference, since "stackfaults" are
15673 * not detected by the hardware. On 8088s, the gap is called S and
15674 * accepted, but on other machines it is called D and rejected.
15675 * The Atari ST behaves like the 8088 in this respect.
15676 */
15677
15678 if (bytes <= 0) return( (phys_bytes) 0);
15679 vc = (vir_addr + bytes - 1) >> CLICK_SHIFT; /* last click of data */
15680
15681 if (seg != T)
15682 seg = (vc < rp->p_map[D].mem_vir + rp->p_map[D].mem_len ? D : S);
15683
15684 if((vir_addr>>CLICK_SHIFT) >= rp->p_map[seg].mem_vir+ rp->p_map[seg].mem_len)
15685 return( (phys_bytes) 0 );
15686 seg_base = (phys_bytes) rp->p_map[seg].mem_phys;
15687 seg_base = seg_base << CLICK_SHIFT; /* segment origin in bytes */
15688 pa = (phys_bytes) vir_addr;
15689 pa -= rp->p_map[seg].mem_vir << CLICK_SHIFT;
15690 return(seg_base + pa);
15691 }
15694 /*==========================================================================*
15695 * numap *
15696 *==========================================================================*/
15697 PUBLIC phys_bytes numap(proc_nr, vir_addr, bytes)
15698 int proc_nr; /* process number to be mapped */
15699 vir_bytes vir_addr; /* virtual address in bytes within D seg */
15700 vir_bytes bytes; /* # of bytes required in segment */
15701 {
15702 /* Do umap() starting from a process number instead of a pointer. This
15703 * function is used by device drivers, so they need not know about the
15704 * process table. To save time, there is no 'seg' parameter. The segment
15705 * is always D.
15706 */
15707
15708 return(umap(proc_addr(proc_nr), D, vir_addr, bytes));
15709 }
15711 #if (CHIP == INTEL)
15712 /*==========================================================================*
15713 * alloc_segments *
15714 *==========================================================================*/
15715 PUBLIC void alloc_segments(rp)
15716 register struct proc *rp;
15717 {
15718 /* This is called only by do_newmap, but is broken out as a separate function
15719 * because so much is hardware-dependent.
15720 */
15721
15722 phys_bytes code_bytes;
15723 phys_bytes data_bytes;
15724 int privilege;
15725
15726 if (protected_mode) {
15727 data_bytes = (phys_bytes) (rp->p_map[S].mem_vir + rp->p_map[S].mem_len)
15728 << CLICK_SHIFT;
15729 if (rp->p_map[T].mem_len == 0)
15730 code_bytes = data_bytes; /* common I&D, poor protect */
15731 else
15732 code_bytes = (phys_bytes) rp->p_map[T].mem_len << CLICK_SHIFT;
15733 privilege = istaskp(rp) ? TASK_PRIVILEGE : USER_PRIVILEGE;
15734 init_codeseg(&rp->p_ldt[CS_LDT_INDEX],
15735 (phys_bytes) rp->p_map[T].mem_phys << CLICK_SHIFT,
15736 code_bytes, privilege);
15737 init_dataseg(&rp->p_ldt[DS_LDT_INDEX],
15738 (phys_bytes) rp->p_map[D].mem_phys << CLICK_SHIFT,
15739 data_bytes, privilege);
15740 rp->p_reg.cs = (CS_LDT_INDEX * DESC_SIZE) | TI | privilege;
15741 #if _WORD_SIZE == 4
15742 rp->p_reg.gs =
15743 rp->p_reg.fs =
15744 #endif
15745 rp->p_reg.ss =
15746 rp->p_reg.es =
15747 rp->p_reg.ds = (DS_LDT_INDEX*DESC_SIZE) | TI | privilege;
15748 } else {
15749 rp->p_reg.cs = click_to_hclick(rp->p_map[T].mem_phys);
15750 rp->p_reg.ss =
15751 rp->p_reg.es =
15752 rp->p_reg.ds = click_to_hclick(rp->p_map[D].mem_phys);
15753 }
15754 }
15755 #endif /* (CHIP == INTEL) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -