Page 1 of 1

who knows the function umap_local() in minix

Posted: Sun Apr 20, 2008 8:20 pm
by chenrvmldd
PUBLIC phys_bytes umap_local(rp, seg, vir_addr, bytes)
register struct proc *rp; /* pointer to proc table entry for process */
int seg; /* T, D, or S segment */
vir_bytes vir_addr; /* virtual address in bytes within the seg */
vir_bytes bytes; /* # of bytes to be copied */
{
/* Calculate the physical memory address for a given virtual address. */
vir_clicks vc; /* the virtual address in clicks */
phys_bytes pa; /* intermediate variables as phys_bytes */
#if (CHIP == INTEL)
phys_bytes seg_base;
#endif

/* If 'seg' is D it could really be S and vice versa. T really means T.
* If the virtual address falls in the gap, it causes a problem. On the
* 8088 it is probably a legal stack reference, since "stackfaults" are
* not detected by the hardware. On 8088s, the gap is called S and
* accepted, but on other machines it is called D and rejected.
* The Atari ST behaves like the 8088 in this respect.
*/

if (bytes <= 0) return( (phys_bytes) 0);
if (vir_addr + bytes <= vir_addr) return 0; /* overflow */
vc = (vir_addr + bytes - 1) >> CLICK_SHIFT; /* last click of data */

#if (CHIP == INTEL) || (CHIP == M68000)
if (seg != T)
seg = (vc < rp->p_memmap[D].mem_vir + rp->p_memmap[D].mem_len ? D : S);
#else
if (seg != T)
seg = (vc < rp->p_memmap.mem_vir ? D : S);
#endif

if ((vir_addr>>CLICK_SHIFT) >= rp->p_memmap[seg].mem_vir +
rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );

if (vc >= rp->p_memmap[seg].mem_vir +
rp->p_memmap[seg].mem_len) return( (phys_bytes) 0 );

#if (CHIP == INTEL)
seg_base = (phys_bytes) rp->p_memmap[seg].mem_phys;
seg_base = seg_base << CLICK_SHIFT; /* segment origin in bytes */
#endif
pa = (phys_bytes) vir_addr;
#if (CHIP != M68000)
pa -= rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
return(seg_base + pa);
#endif
#if (CHIP == M68000)
pa -= (phys_bytes)rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
pa += (phys_bytes)rp->p_memmap[seg].mem_phys << CLICK_SHIFT;
return(pa);
#endif

I do not understand the code,why should do like that ,if who know these codes very clearly,can you analyse by lines for me

Posted: Sun Apr 20, 2008 9:46 pm
by Zacariaz
You can start by writing your question in an understandable language.
Read what you've writen before posting.

"I do not understand the code..."
I know the feeling.

"...why should do like that..."

What?

"...if who know these codes very clearly,can you analyse by lines for me"

Gesundheit...


I trust you'll do a better effort in the future.

Posted: Mon Apr 21, 2008 12:30 am
by Ready4Dis
Well, it just looks like a slightly modified version of C (kind of a C/Pascal mix) where the function parameters are written between the declaration and the {. Anyways, it's pretty easy to break down or re-write in C...

I'm not a minix programmer, and have never even seen it, but I presume S,D and T are some sort of descriptions for segment types (stack ,data and task?).

Code: Select all

int umap_local(register struct proc *rp, int seg, int vir_addr, int bytes) 
{ 
/* Calculate the physical memory address for a given virtual address. */ 
int vc; /* the virtual address in clicks */ 
int pa; /* intermediate variables as phys_bytes */ 

#if (CHIP == INTEL)   //Check for x86 CPU
int seg_base;
#endif 

/* If 'seg' is D it could really be S and vice versa. T really means T. 
* If the virtual address falls in the gap, it causes a problem. On the 
* 8088 it is probably a legal stack reference, since "stackfaults" are 
* not detected by the hardware. On 8088s, the gap is called S and 
* accepted, but on other machines it is called D and rejected. 
* The Atari ST behaves like the 8088 in this respect. 
*/ 

if (bytes <= 0) return 0;
if (vir_addr + bytes <= vir_addr) return 0; /* overflow */

//This just gets a page count basically
vc = (vir_addr + bytes - 1) >> CLICK_SHIFT;


#if (CHIP == INTEL) || (CHIP == M68000) 
if (seg != T)   //Not a T type segment?
{
  if (vc < rp->p_memmap[D].mem_vir + rp->p_memmap[D].mem_len)
   seg = D;
  else
   seg = S;
//Made this simpler to read :)  Just checks if it's within this range of D segment
//  seg = (vc < rp->p_memmap[D].mem_vir + rp->p_memmap[D].mem_len ? D : S); 
}
#else 
if (seg != T) 
{
  if (vc < rp->p_memmap[S].mem_vir) //Is it less than this segment's start?
    seg = D;
  else
    seg = S;
//And again for readability
//  seg = (vc < rp->p_memmap[S].mem_vir ? D : S); 
}
#endif 

//Check if the virtual address is within our segment
if ((vir_addr>>CLICK_SHIFT) >= rp->p_memmap[seg].mem_vir + 
rp->p_memmap[seg].mem_len) return 0;

//Check if vc is within our segment
if (vc >= rp->p_memmap[seg].mem_vir + 
rp->p_memmap[seg].mem_len) return 0;

#if (CHIP == INTEL)  //if x86
seg_base = rp->p_memmap[seg].mem_phys;  //Grab the physical page#
seg_base = seg_base << CLICK_SHIFT; //Calculate the physical address from page #
#endif 
pa = vir_addr;   //Store vir_addr for a minute
#if (CHIP != M68000)  //all but the Motorola 68000
//Subtract this segments virtual address from the virtual address passed in
pa -= rp->p_memmap[seg].mem_vir << CLICK_SHIFT; 
return seg_base + pa;  //Return the physical address (seg_base) and the offset into the segment
#endif 
#if (CHIP == M68000)  //Otherwise for the motorola 68000
pa -= (phys_bytes)rp->p_memmap[seg].mem_vir << CLICK_SHIFT; 
//Same as above, excent we want to add the physical start of the segment after we're done, since INTEL chips had seg_base to do this, we don't
pa += (phys_bytes)rp->p_memmap[seg].mem_phys << CLICK_SHIFT; 
return pa;
#endif

Let me know if you're only developing on the x86 and I will strip all the crap out and try to make it more readable, but which parts are you having problems with. From what I can gather, it is just the conversion from address to page count (they call them CLICK's). So assume a page size of 4096, CLICK_SHIFT would be 12. So I will write this for an x86 only just to simplify it a bit:

Code: Select all

int umap_local(register struct proc *rp, int seg, int vir_addr, int bytes) 
{ 

/* Calculate the physical memory address for a given virtual address. */ 
int vc; /* the virtual address in clicks */ 
int pa; /* intermediate variables as phys_bytes */ 
int seg_base;

if (bytes <= 0) return 0; //Return NULL
if (vir_addr + bytes <= vir_addr) return 0; /* overflow */

//This just gets a page count basically
//Gets the LAST Page index of this mapping
vc = (vir_addr + bytes - 1) >> CLICK_SHIFT;

if (seg != T)   //Not a T type segment?
{  //Determine if it's a D or S segment
  if (vc < rp->p_memmap[D].mem_vir + rp->p_memmap[D].mem_len)
   seg = D;
  else
   seg = S;
}

//Check if the starting virtual address is within this segment
if ((vir_addr>>CLICK_SHIFT) >= rp->p_memmap[seg].mem_vir + 
rp->p_memmap[seg].mem_len) return 0; ///Return NULL

//Check if vc is within our segment (vc was our page index calculated based on vir_addr + bytes), aka, our ending page index!
if (vc >= rp->p_memmap[seg].mem_vir + 
rp->p_memmap[seg].mem_len) return 0;  //return NULL

/* Ok, at this point, we know which segment we're in, and that the entire range vir_addr -> vir_addr+bytes is within this segment */

seg_base = rp->p_memmap[seg].mem_phys;  //Grab the physical page #
seg_base = seg_base << CLICK_SHIFT; //Calculate the physical address from page #

pa = vir_addr;   //Grab vir_addr into a variable
//Subtract this segments virtual address from the virtual address passed in, basically gives us offset into this segment
pa -= rp->p_memmap[seg].mem_vir << CLICK_SHIFT;
return seg_base + pa;  //Return the physical address (seg_base) and the offset into the segment

I am not 100% sure what you are trying to do, but if you have specific questions, let us know. As I stated, I know nothing about minix, nor this modified langauge, but this is basically what is going on if you can understand what I mean. If you know what pages are, then this should make some sense to you.


*** Edit ***
Just added a few comments to hopefully make it a bit clearer

Posted: Mon Apr 21, 2008 12:30 am
by Combuster
@chenrvmldd: please use

Code: Select all

...
tags when posting code

Posted: Mon Apr 21, 2008 7:32 am
by cyr1x
Ready4Dis wrote:Well, it just looks like a slightly modified version of C
It actually is C, namely K&R syntax.

Posted: Mon Apr 21, 2008 12:21 pm
by z180
i think this is not the best mm code for a 32 bit system that uses virtual memory and mmap, but for a 286 mode system it is ok and small code

Re: who knows the function umap_local() in minix

Posted: Tue Apr 22, 2008 7:59 am
by jal
chenrvmldd wrote:I do not understand the code,why should do like that ,if who know these codes very clearly,can you analyse by lines for me
It is analyzed line by line in the book that comes with that code (or rather, the code comes with the book). Try finding yourself a copy of Andy's original 1st edition (or maybe 2nd?) of Operating Systems: Design and Implementation and there you go.


JAL