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

📄 break.c

📁 一个简单的操作系统minix的核心代码
💻 C
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
				src/mm/break.c	 	 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

17600	/* The MINIX model of memory allocation reserves a fixed amount of memory for
17601	 * the combined text, data, and stack segments.  The amount used for a child
17602	 * process created by FORK is the same as the parent had.  If the child does
17603	 * an EXEC later, the new size is taken from the header of the file EXEC'ed.
17604	 *
17605	 * The layout in memory consists of the text segment, followed by the data
17606	 * segment, followed by a gap (unused memory), followed by the stack segment.
17607	 * The data segment grows upward and the stack grows downward, so each can
17608	 * take memory from the gap.  If they meet, the process must be killed.  The
17609	 * procedures in this file deal with the growth of the data and stack segments.
17610	 *
17611	 * The entry points into this file are:
17612	 *   do_brk:      BRK/SBRK system calls to grow or shrink the data segment
17613	 *   adjust:      see if a proposed segment adjustment is allowed
17614	 *   size_ok:     see if the segment sizes are feasible
17615	 */
17616	
17617	#include "mm.h"
17618	#include <signal.h>
17619	#include "mproc.h"
17620	#include "param.h"
17621	
17622	#define DATA_CHANGED       1    /* flag value when data segment size changed */
17623	#define STACK_CHANGED      2    /* flag value when stack size changed */
17624	
17625	/*===========================================================================*
17626	 *                              do_brk                                       *
17627	 *===========================================================================*/
17628	PUBLIC int do_brk()
17629	{
17630	/* Perform the brk(addr) system call.
17631	 *
17632	 * The call is complicated by the fact that on some machines (e.g., 8088),
17633	 * the stack pointer can grow beyond the base of the stack segment without
17634	 * anybody noticing it.
17635	 * The parameter, 'addr' is the new virtual address in D space.
17636	 */
17637	
17638	  register struct mproc *rmp;
17639	  int r;
17640	  vir_bytes v, new_sp;
17641	  vir_clicks new_clicks;
17642	
17643	  rmp = mp;
17644	  v = (vir_bytes) addr;
17645	  new_clicks = (vir_clicks) ( ((long) v + CLICK_SIZE - 1) >> CLICK_SHIFT);
17646	  if (new_clicks < rmp->mp_seg[D].mem_vir) {
17647	        res_ptr = (char *) -1;
17648	        return(ENOMEM);
17649	  }
17650	  new_clicks -= rmp->mp_seg[D].mem_vir;
17651	  sys_getsp(who, &new_sp);      /* ask kernel for current sp value */
17652	  r = adjust(rmp, new_clicks, new_sp);
17653	  res_ptr = (r == OK ? addr : (char *) -1);
17654	  return(r);                    /* return new address or -1 */
17655	}
	
	
17658	/*===========================================================================*
17659	 *                              adjust                                       *
17660	 *===========================================================================*/
17661	PUBLIC int adjust(rmp, data_clicks, sp)
17662	register struct mproc *rmp;     /* whose memory is being adjusted? */
17663	vir_clicks data_clicks;         /* how big is data segment to become? */
17664	vir_bytes sp;                   /* new value of sp */
17665	{
17666	/* See if data and stack segments can coexist, adjusting them if need be.
17667	 * Memory is never allocated or freed.  Instead it is added or removed from the
17668	 * gap between data segment and stack segment.  If the gap size becomes
17669	 * negative, the adjustment of data or stack fails and ENOMEM is returned.
17670	 */
17671	
17672	  register struct mem_map *mem_sp, *mem_dp;
17673	  vir_clicks sp_click, gap_base, lower, old_clicks;
17674	  int changed, r, ft;
17675	  long base_of_stack, delta;    /* longs avoid certain problems */
17676	
17677	  mem_dp = &rmp->mp_seg[D];     /* pointer to data segment map */
17678	  mem_sp = &rmp->mp_seg[S];     /* pointer to stack segment map */
17679	  changed = 0;                  /* set when either segment changed */
17680	
17681	  if (mem_sp->mem_len == 0) return(OK); /* don't bother init */
17682	
17683	  /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */
17684	  base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
17685	  sp_click = sp >> CLICK_SHIFT; /* click containing sp */
17686	  if (sp_click >= base_of_stack) return(ENOMEM);        /* sp too high */
17687	
17688	  /* Compute size of gap between stack and data segments. */
17689	  delta = (long) mem_sp->mem_vir - (long) sp_click;
17690	  lower = (delta > 0 ? sp_click : mem_sp->mem_vir);
17691	
17692	  /* Add a safety margin for future stack growth. Impossible to do right. */
17693	#define SAFETY_BYTES  (384 * sizeof(char *))
17694	#define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE)
17695	  gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS;
17696	  if (lower < gap_base) return(ENOMEM); /* data and stack collided */
17697	
17698	  /* Update data length (but not data orgin) on behalf of brk() system call. */
17699	  old_clicks = mem_dp->mem_len;
17700	  if (data_clicks != mem_dp->mem_len) {
17701	        mem_dp->mem_len = data_clicks;
17702	        changed |= DATA_CHANGED;
17703	  }
17704	
17705	  /* Update stack length and origin due to change in stack pointer. */
17706	  if (delta > 0) {
17707	        mem_sp->mem_vir -= delta;
17708	        mem_sp->mem_phys -= delta;
17709	        mem_sp->mem_len += delta;
17710	        changed |= STACK_CHANGED;
17711	  }
17712	
17713	  /* Do the new data and stack segment sizes fit in the address space? */
17714	  ft = (rmp->mp_flags & SEPARATE);
17715	  r = size_ok(ft, rmp->mp_seg[T].mem_len, rmp->mp_seg[D].mem_len, 
17716	       rmp->mp_seg[S].mem_len, rmp->mp_seg[D].mem_vir, rmp->mp_seg[S].mem_vir);
17717	  if (r == OK) {
17718	        if (changed) sys_newmap((int)(rmp - mproc), rmp->mp_seg);
17719	        return(OK);
17720	  }
17721	
17722	  /* New sizes don't fit or require too many page/segment registers. Restore.*/
17723	  if (changed & DATA_CHANGED) mem_dp->mem_len = old_clicks;
17724	  if (changed & STACK_CHANGED) {
17725	        mem_sp->mem_vir += delta;
17726	        mem_sp->mem_phys += delta;
17727	        mem_sp->mem_len -= delta;
17728	  }
17729	  return(ENOMEM);
17730	}
	
	
17733	/*===========================================================================*
17734	 *                              size_ok                                      *
17735	 *===========================================================================*/
17736	PUBLIC int size_ok(file_type, tc, dc, sc, dvir, s_vir)
17737	int file_type;                  /* SEPARATE or 0 */
17738	vir_clicks tc;                  /* text size in clicks */
17739	vir_clicks dc;                  /* data size in clicks */
17740	vir_clicks sc;                  /* stack size in clicks */
17741	vir_clicks dvir;                /* virtual address for start of data seg */
17742	vir_clicks s_vir;               /* virtual address for start of stack seg */
17743	{
17744	/* Check to see if the sizes are feasible and enough segmentation registers
17745	 * exist.  On a machine with eight 8K pages, text, data, stack sizes of
17746	 * (32K, 16K, 16K) will fit, but (33K, 17K, 13K) will not, even though the
17747	 * former is bigger (64K) than the latter (63K).  Even on the 8088 this test
17748	 * is needed, since the data and stack may not exceed 4096 clicks.
17749	 */
17750	
17751	#if (CHIP == INTEL && _WORD_SIZE == 2)
17752	  int pt, pd, ps;               /* segment sizes in pages */
17753	
17754	  pt = ( (tc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
17755	  pd = ( (dc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
17756	  ps = ( (sc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
17757	
17758	  if (file_type == SEPARATE) {
17759	        if (pt > MAX_PAGES || pd + ps > MAX_PAGES) return(ENOMEM);
17760	  } else {
17761	        if (pt + pd + ps > MAX_PAGES) return(ENOMEM);
17762	  }
17763	#endif
17764	
17765	  if (dvir + dc > s_vir) return(ENOMEM);
17766	
17767	  return(OK);
17768	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -