text: #include "type.h"
  #include "config.h"
  #include "stdio.h"
  #include "const.h"
  #include "protect.h"
  #include "string.h"
  #include "fs.h"
  #include "proc.h"
  #include "tty.h"
  #include "console.h"
  #include "global.h"
  #include "keyboard.h"
  #include "proto.h"
  
  PUBLIC void do_fork_test();
  
  PRIVATE void init_mm();
  
  /**
   * task_mm
   *
   * <Ring 1> The main loop of TASK MM.
   *
   */
  PUBLIC void task_mm()
  {
  	init_mm();
  
  	while(1) {
  		send_recv(RECEIVE, ANY, &mm_msg);
  		int src = mm_msg.source;
  		int reply = 1;
  
  		int msgtype = mm_msg.type;
  
  		switch(msgtype) {
  			case FORK:
  				mm_msg.RETVAL = do_fork();
  				break;
  			case EXIT:
  				do_exit(mm_msg.STATUS);
  				reply = 0;
  				break;
  			case EXEC:
  				mm_msg.RETVAL = do_exec();
  				break;
  			case WAIT:
  				do_wait();
  				reply = 0;
  				break;
  			default:
  				dump_msg("MM::unknown msg", &mm_msg);
  				assert(0);
  				break;		
  		}
  
  		if(reply) {
  			mm_msg.type = SYSCALL_RET;
  			send_recv(SEND, src, &mm_msg);
  		}
  	}
  }
  
  /**
   * init_mm()
   *
   * Do some initialization work.
   *
   */
  PRIVATE void init_mm()
  {
  	struct boot_params bp;
  	get_boot_params(&bp);
  
  	memory_size = bp.mem_size;
  
  	/* print memory size */
  	printl("{MM} memsize: %dMB\n", memory_size / (1024 * 1024));
  }
  
  /**
   * alloc_mem()
   *
   * Allocate a memory block for a proc.
   *
   * @param pid: Which proc the memory is for.
   * @param memsize: How many bytes is needed.
   * 
   * @return The base of the memory just allocated.
   *
   */
  PUBLIC int alloc_mem(int pid, int memsize)
  {
  	assert(pid >= (NR_TASKS + NR_NATIVE_PROCS));
  	if(memsize > PROC_IMAGE_SIZE_DEFAULT) {
  		panic("unsupported memory request: %d. (should be less than %d)", \
  			memsize, PROC_IMAGE_SIZE_DEFAULT);
  	}
  
  	int base = PROCS_BASE + (pid - (NR_TASKS + NR_NATIVE_PROCS)) * PROC_IMAGE_SIZE_DEFAULT;
  
  	if(base + memsize >= memory_size)
  		panic("memory allocation failed. pid:%d", pid);
  
  	return base;
  }
  
  /**
   * free_mem
   *
   * Free a memory block.
   * Because a memory block is corresponding with a PID, so we don't
   * need to really `free` anything. In another word, a memory block
   * is dedicated to one and only one PID, no matter waht proc actually uses
   * this PID.
   *
   * @param pid: whose memory is to be freed.
   * @return 0 if success.
   *
   */
  PUBLIC int free_mem(int pid)
  {
  	return 0;
  }
  
  