From: weimin@rice.edu (Weimin Yu)
Subject: Help wanted on Mach2.5 
Originator: weimin@tone.cs.rice.edu
Reply-To: weimin@rice.edu (Weimin Yu)
Organization: Rice University
Date: Thu, 20 Aug 1992 21:40:01 GMT



Hi, I'm a new comer of the Mach circle. We have a Sun3 running Mach2.5
and I'm screwed up by the protection and exception handling mechanism.

I wrote a program which is like

  error = vm_allocate(task_self(), &addr, NUM_PAGES*vm_page_size, TRUE);
  error = vm_protect(task_self(), bkup, vm_page_size*NUM_PAGES, TRUE,
			   VM_PROT_ALL);	
  cthread_fork(foo, 0);

  for (;;) {
	  i = msg_receive(&in_msg, MSG_OPTION_NONE, 0);
	  exc_server(&in_msg, &out_msg);
	  i = msg_send(&out_msg, MSG_OPTION_NONE, 0);
	}

where foo is 
  for(;;) {
   error = vm_protect(task_self(), addr,
                              NUM_PAGES*vm_page_size, FALSE, VM_PROT_NONE);
    reading;
    writing;
}

I have 2 problems. First, after the first loop in foo(), reading will not
generate exception though all the pages have been protected to VM_PROT_NONE.
Second, with a write exception, I change the page's protection to
VM_PROT_ALL and returns with KERN_SUCCESS,  but the following reads still
get the old value, not that I'm trying to written. Are there some bugs in my
program, or the system doesn't behave itself? 

If possible, would you please compile and run the following program and
tell me the result?

Thank you very much,

Weimin
/*----------------------------------------------------------------------------*/
#include  <stdio.h>
#include <mach.h>
#include <mach/message.h>
#include <mach_error.h>
#include <cthreads.h>
#include <servers/netname.h>
#include <mach/mig_errors.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/timeb.h>

#define MAXDATA   20
#define NUM_ACCE  NUM_PAGES/STEP
#define _locked   0
#define _read     1
#define _written  2

port_t                 mport, port, eport;
port_name_t            port_set;
vm_address_t           addr, backup, bkup;
memory_object_t        mobj[2], mctrl[2];
int                    dirty_cnt = 0;
int                    flag = 0, init = 0, unlock=0,req=0, finish = 0, ppg, pg;
int                    NUM_PAGES, STEP = 2, _CNT = 3; stop = 0;
int                    exc_cnt = 0;
struct  timeb      tb[200];
struct  tms        tm[200];
struct  page_state {
  int   state, dirty;
  pointer_t    data;
} *pages;

extern   boolean_t memory_object_server();

struct  simp_msg_struct {
  msg_header_t  h;
  msg_type_t  t;
  int         inline_data[(108-sizeof(msg_header_t)-sizeof(msg_type_t))/4];
} msg_xmt[2], msg_rcv[2];
int      p_cnt = 0;
int      fd;
mutex_t  mtx;
             vm_task_t               target_task;
             vm_address_t            xaddress;               /* in/out */
             vm_size_t               xsize;                  /* out */
             vm_prot_t               xprotection;            /* out */
             vm_prot_t               xmax_protection;        /* out */
             vm_inherit_t            xinheritance;           /* out */
             boolean_t               xshared;                /* out */
             port_t                  xobject_name;           /* out */
             vm_offset_t             xoffset;                /* out */

foo()
{
         kern_return_t  error;
	 vm_address_t data, ptr1, ptr2, ptr3, ptr4;
	 int  cnt,  i, j, k;

	 for (cnt = 0; cnt < _CNT; cnt++) {
	   ftime(&(tb[2*cnt]));
	   times(&(tm[2*cnt]));
	   error = vm_protect(task_self(), addr,
			      NUM_PAGES*vm_page_size, FALSE, VM_PROT_READ);
	   if (error != KERN_SUCCESS) {
	     printf("protect errorf\n");
	     exit();
	   }
	   error = vm_copy(task_self(), addr, vm_page_size*NUM_PAGES, bkup);
	   if (error != KERN_SUCCESS) {
	     printf("vm_copy error %d \n", error);
	     exit();
	   }
	   error = vm_protect(task_self(), addr,
			      NUM_PAGES*vm_page_size, TRUE, VM_PROT_ALL);
	   if (error != KERN_SUCCESS) {
	     printf("protect error2\n");
	     exit();
	   }
	   error = vm_protect(task_self(), addr,
                              NUM_PAGES*vm_page_size, FALSE, VM_PROT_NONE);
           if (error != KERN_SUCCESS) {
             printf("protect error3\n");
             exit();
           }
	   xaddress = addr;
	   error = vm_region(task_self(), &xaddress, &xsize, &xprotection,
		     &xmax_protection, &xinheritance, &xshared,
		     &xobject_name, &xoffset);
	     printf("r: %d %d %d  cur_protection%d %d %d\n", error, xaddress, xsize,
		    xprotection, xmax_protection, xobject_name);
fflush(stdout);
	   for (i = 1; i< NUM_PAGES; i += STEP) {
	     int zz;
	     data = addr + vm_page_size*i;
printf("Beginning to read at %d:\n", data);
printf("Data read at %d is %d\n", data, *((int*) data));
printf("trying to write %d at %d\n", 2, data);
fflush(stdout);
	     (*((int*) data)) = 2;
printf ("read again at %d, value is %d, icreases it\n", data, *((int*) data));
fflush(stdout);
	     (*((int*) data))++;
printf ("read again at %d, value is %d\n", data, *((int*) data));
fflush(stdout);
	   }
	   p_cnt = 0;
  	   for (i = 0; i< NUM_PAGES; i++)
	     if (pages[i].dirty) {
	       ptr1 = addr + i*vm_page_size;
	       ptr2 = bkup + i*vm_page_size;
	       ptr3 = ptr1 + vm_page_size;
	       ptr4 = backup + i*vm_page_size;
	       /*printf("yy\n");*/
	       for (; ptr1 < ptr3; ptr1 += 4) {
		 if (*((int*) ptr1) != *((int*) ptr2)) {
		   printf("uux %d %d %d %d\n",i, ptr1, *((int*) ptr1), *((int*) ptr2));
		 }
		 ptr2 += 4;
		 ptr4 += 4;
	       }
	       pages[i].dirty = 0;
	       p_cnt++;
	       
	     }
	   ftime(&(tb[2*cnt+1]));
	   times(&(tm[2*cnt+1]));
	  
	   printf("pages modified: %d\n", p_cnt);
	 }
	 for (cnt = 0; cnt < _CNT; cnt++) {
	   i = (tb[2*cnt+1].time - tb[2*cnt+0].time)*1000 
	     + tb[2*cnt+1].millitm - tb[2*cnt+0].millitm;
	   printf("LOOP %d:\n", cnt+1);
	   printf("Elapsed time: %d milliseconds\n", i);
	   i = ((float) (tm[2*cnt+1].tms_utime 
			 - tm[2*cnt+0].tms_utime)*1000)/60;
	   printf("User time: %d milliseconds\n", i);
	   i = ((float) (tm[2*cnt+1].tms_stime 
			 - tm[2*cnt+0].tms_stime)*1000)/60;
	   printf("Sys  time: %d milliseconds\n", i);
	 }
	 exit();
	 
       }

main(argc, argv)
int argc;
char **argv;
{
	struct simp_msg_struct	in_msg;
	death_pill_t	out_msg;
	kern_return_t   i, j, error;

	NUM_PAGES = 6;
	STEP = 2;
	_CNT = 2;
	if (argc > 1) {
	  argc--;
	  sscanf(argv[1], "%d", &NUM_PAGES);
	}
	pages = (struct page_state*)malloc(sizeof(struct page_state)*NUM_PAGES);
	if (argc > 1) {
	  argc--;
	  sscanf(argv[2], "%d", &STEP);
	}
	if (argc > 1) {
	  argc--;
	  sscanf(argv[3], "%d", &_CNT);
	}
	if (_CNT >100) _CNT = 100;

	for (i = 0; i < MAXDATA; i++) {
	  pages[i].state = _locked;
	  pages[i].dirty = 0;
	}
	error = port_allocate(task_self(), &mport);
	if (error != KERN_SUCCESS) {
	  printf("Port allocateed error\n");
	  exit();
	}
	error = port_allocate(task_self(), &port);
	if (error != KERN_SUCCESS) {
	  printf("Port allocateed error\n");
	  exit();
	}
	error = vm_allocate(task_self(),&backup, NUM_PAGES*vm_page_size, TRUE);
	if (error != KERN_SUCCESS) {
	  printf("VM_ allocation error\n");
	  exit();
	}
	error = vm_allocate(task_self(),&bkup, NUM_PAGES*vm_page_size, TRUE);
	if (error != KERN_SUCCESS) {
	  printf("VM_ allocation error\n");
	  exit();
	}
	error = vm_allocate(task_self(), &addr, NUM_PAGES*vm_page_size, TRUE);
	if (error != KERN_SUCCESS) {
	  printf("VM_ allocation error\n");
	  exit();
	}
	error = vm_protect(task_self(), addr, vm_page_size*NUM_PAGES, TRUE,
			      VM_PROT_ALL);
	if (error != KERN_SUCCESS) {
	  printf("protect errora\n");
	  exit();
	}
	error = vm_protect(task_self(), backup, vm_page_size*NUM_PAGES, TRUE,
			   VM_PROT_NONE);
	if (error != KERN_SUCCESS) {
	  printf("protect errorb\n");
	  exit();
	}
	error = vm_protect(task_self(), bkup, vm_page_size*NUM_PAGES, TRUE,
			   VM_PROT_ALL);
	if (error != KERN_SUCCESS) {
	  printf("protect errorc\n");
	  exit();
	}
	error = task_set_special_port(task_self(), TASK_EXCEPTION_PORT, mport);
	if (error != KERN_SUCCESS) {
	  printf("EXC wrong\n");
	  exit();
	}
	cthread_fork(foo, 0);
	in_msg.h.msg_size = sizeof(in_msg);
	in_msg.h.msg_local_port = mport;

	for (;;) {
	  i = msg_receive(&in_msg, MSG_OPTION_NONE, 0);
	  exc_server(&in_msg, &out_msg);
	  i = msg_send(&out_msg, MSG_OPTION_NONE, 0);
	}
}


kern_return_t catch_exception_raise(request_port, thread, task,
				    exception, code, subcode)
                 /* Code contains kern_return_t describing error. */
                /* Subcode contains bad memory address. */
port_t  request_port, thread, task;
int     exception, code, subcode; {
        int   error;
        printf("%d %d %d %d %d %d %d\n", request_port, thread, task,
				    exception, code, subcode, addr);
	if (exception == 1) {
	  int pg;
	  pg = (subcode - addr) / vm_page_size;
	  pages[pg].dirty++;
	  error = vm_protect(task_self(), subcode, vm_page_size, FALSE,
			     VM_PROT_ALL);
	  if (error != KERN_SUCCESS) {
	     printf("protect error in exc handler\n");
	     exit();
	   }
	}
	return(KERN_SUCCESS);
	
}























 
Newsgroups: comp.os.mach