Minix1.5/mm/main.c

Compare this file to the similar file:
Show the results in this format:

/* This file contains the main program of the memory manager and some related
 * procedures.  When MINIX starts up, the kernel runs for a little while,
 * initializing itself and its tasks, and then it runs MM.  MM at this point
 * does not know where FS is in memory and how big it is.  By convention, FS
 * must start at the click following MM, so MM can deduce where it starts at
 * least.  Later, when FS runs for the first time, FS makes a pseudo-call,
 * BRK2, to tell MM how big it is.  This allows MM to figure out where INIT
 * is.
 *
 * The entry points into this file are:
 *   main:	starts MM running
 *   reply:	reply to a process making an MM system call
 *   do_brk2:	pseudo-call for FS to report its size
 */

#include "mm.h"
#include <minix/callnr.h>
#include <minix/com.h>
#include "mproc.h"
#include "param.h"

FORWARD void get_work();
FORWARD void mm_init();

/*===========================================================================*
 *				main					     *
 *===========================================================================*/
PUBLIC void main()
{
/* Main routine of the memory manager. */

  int error;

  mm_init();			/* initialize memory manager tables */

  /* This is MM's main loop-  get work and do it, forever and forever. */
  while (TRUE) {
	/* Wait for message. */
	get_work();		/* wait for an MM system call */
	mp = &mproc[who];

  	/* Set some flags. */
	error = OK;
	dont_reply = FALSE;
	err_code = -999;

	/* If the call number is valid, perform the call. */
	if (mm_call < 0 || mm_call >= NCALLS)
		error = EBADCALL;
	else
		error = (*call_vec[mm_call])();

	/* Send the results back to the user to indicate completion. */
	if (dont_reply) continue;	/* no reply for EXIT and WAIT */
	if (mm_call == EXEC && error == OK) continue;
	reply(who, error, result2, res_ptr);
  }
}


/*===========================================================================*
 *				get_work				     *
 *===========================================================================*/
PRIVATE void get_work()
{  
/* Wait for the next message and extract useful information from it. */

  if (receive(ANY, &mm_in) != OK) panic("MM receive error", NO_NUM);
  who = mm_in.m_source;		/* who sent the message */
  mm_call = mm_in.m_type;	/* system call number */
}


/*===========================================================================*
 *				reply					     *
 *===========================================================================*/
PUBLIC void reply(proc_nr, result, res2, respt)
int proc_nr;			/* process to reply to */
int result;			/* result of the call (usually OK or error #)*/
int res2;			/* secondary result */
char *respt;			/* result if pointer */
{
/* Send a reply to a user process. */

  register struct mproc *proc_ptr;

  /* To make MM robust, check to see if destination is still alive. */
  proc_ptr = &mproc[proc_nr];
  if ( (proc_ptr->mp_flags&IN_USE) == 0 || (proc_ptr->mp_flags&HANGING)) return;
  reply_type = result;
  reply_i1 = res2;
  reply_p1 = respt;
  if (send(proc_nr, &mm_out) != OK) panic("MM can't reply", NO_NUM);
}


/*===========================================================================*
 *				mm_init					     *
 *===========================================================================*/
PRIVATE void mm_init()
{
/* Initialize the memory manager. */

  mem_init();			/* initialize tables to all physical mem */

  /* Initialize MM's tables. */
  mproc[MM_PROC_NR].mp_flags |= IN_USE;
  mproc[FS_PROC_NR].mp_flags |= IN_USE;
  mproc[INIT_PROC_NR].mp_flags |= IN_USE;
  mproc[INIT_PROC_NR].mp_pid = INIT_PID;
  procs_in_use = 3;
}


/*===========================================================================*
 *				do_brk2	   				     *
 *===========================================================================*/
PUBLIC int do_brk2()
{
/* This "call" is made once by FS during system initialization and then never
 * again by anyone.  It contains the origin and size of INIT, and the combined
 * size of the 1536 bytes of unused mem, MINIX and RAM disk.
 *   m1_i1 = size of INIT text in clicks
 *   m1_i2 = size of INIT data in clicks
 *   m1_i3 = number of bytes for MINIX + RAM DISK
 *   m1_p1 = origin of INIT in clicks
 */

  int mem1, mem2, mem3;
  register struct mproc *rmp;
  phys_clicks init_org, init_clicks, ram_base, ram_clicks, tot_clicks;
  phys_clicks init_text_clicks, init_data_clicks;
  phys_clicks minix_clicks;

  if (who != FS_PROC_NR) return(EPERM);	/* only FS make do BRK2 */

  /* Remove the memory used by MINIX from the memory map. */
  init_text_clicks = mm_in.m1_i1;	/* size of INIT in clicks */
  init_data_clicks = mm_in.m1_i2;	/* size of INIT in clicks */
  init_org = (phys_clicks) mm_in.m1_p1;	/* addr where INIT begins in memory */
  init_clicks = init_text_clicks + init_data_clicks;
  minix_clicks = init_org + init_clicks;	/* size of system in clicks */
  ram_base = alloc_mem(minix_clicks);	/* remove MINIX from map */
  if (ram_base != 0)
	panic("inconsistent system memory base", ram_base);

  /* Remove the memory used by the RAM disk from the memory map. */
  tot_clicks = mm_in.m1_i3;		/* total size of MINIX + RAM disk */
  ram_clicks = tot_clicks - minix_clicks;	/* size of RAM disk */
#if (CHIP == INTEL)
  /* Put RAM disk in extended memory, if any. */
  if (get_mem(&ram_base, TRUE) >= ram_clicks)
	goto got_base;
#endif
  ram_base = alloc_mem(ram_clicks);	/* remove the RAM disk from the map */
  if (ram_base == NO_MEM)
	panic("not enough memory for RAM disk", NO_NUM);
got_base:
  mm_out.POSITION = (phys_bytes) ram_base * CLICK_SIZE;	/* tell FS where */

  /* Print memory information. */
#if (MACHINE == MACINTOSH)
  /* Mac memory does not start at zero, so adjust the numbers */
  mem1 = click_to_round_k(minix_clicks-start_click()+ram_clicks+mem_left());  
  mem2 = click_to_round_k(minix_clicks-start_click());
#else
  mem1 = click_to_round_k(minix_clicks + ram_clicks + mem_left());  
  mem2 = click_to_round_k(minix_clicks);
#endif
  mem3 = click_to_round_k(ram_clicks);
#if (CHIP == INTEL)
  printf("%c[H%c[J",033, 033);	/* go to top of screen and clear screen */
#endif
  printf("Memory size = %4dK     ", mem1);
  printf("MINIX = %3dK     ", mem2);
  printf("RAM disk = %4dK     ", mem3);
  printf("Available = %dK\n\n", mem1 - mem2 - mem3);
  if (mem1 - mem2 - mem3 < 32) {
	printf("\nNot enough memory to run MINIX\n\n", NO_NUM);
	sys_abort();
  }

  /* Initialize INIT's table entry. */
  rmp = &mproc[INIT_PROC_NR];
  rmp->mp_seg[T].mem_phys = init_org;
  rmp->mp_seg[T].mem_len  = init_text_clicks;
  rmp->mp_seg[D].mem_phys = init_org + init_text_clicks;
  rmp->mp_seg[D].mem_len  = init_data_clicks;
  rmp->mp_seg[S].mem_phys = init_org + init_clicks;
#if (CHIP == M68000)
  rmp->mp_seg[T].mem_vir  = rmp->mp_seg[T].mem_phys;
  rmp->mp_seg[D].mem_vir  = rmp->mp_seg[D].mem_phys;
  rmp->mp_seg[S].mem_vir  = rmp->mp_seg[S].mem_phys;
#else
  rmp->mp_seg[S].mem_vir  = init_clicks;
#endif
  if (init_text_clicks != 0) rmp->mp_flags |= SEPARATE;

  return(OK);
}


/*===========================================================================*
 *				get_mem					     *
 *===========================================================================*/
PUBLIC phys_clicks get_mem(pbase, extflag)
phys_clicks *pbase;		/* where to return the base */
int extflag;			/* nonzero for extended memory */
{
/* Ask kernel for the next chunk of memory.  'extflag' specifies the type of
 * memory.  "Extended" memory here means memory above 1MB which is no good
 * for putting programs in but usable for the RAM disk.  MM doesn't care
 * about the locations of the 2 types of memory, except memory above 1MB is
 * unreachable unless CLICK_SIZE > 16, but still usable for the RAM disk.
 */
  mm_out.m_type = SYS_MEM;
  mm_out.DEVICE = extflag;
  if (sendrec(SYSTASK, &mm_out) != OK || mm_out.m_type != OK)
	panic("Kernel didn't respond to get_mem", NO_NUM);
  *pbase = (phys_clicks) mm_out.POSITION;
  return((phys_clicks) mm_out.COUNT);
}