⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 system.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 4 页
字号:
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 + -