who knows the function umap_local() in minix

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
chenrvmldd
Posts: 10
Joined: Sat Mar 01, 2008 11:27 pm

who knows the function umap_local() in minix

Post 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
User avatar
Zacariaz
Member
Member
Posts: 1069
Joined: Tue May 22, 2007 2:36 pm
Contact:

Post 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.
This was supposed to be a cool signature...
Ready4Dis
Member
Member
Posts: 571
Joined: Sat Nov 18, 2006 9:11 am

Post 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
Last edited by Ready4Dis on Mon Apr 21, 2008 12:42 am, edited 1 time in total.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Post by Combuster »

@chenrvmldd: please use

Code: Select all

...
tags when posting code
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
cyr1x
Member
Member
Posts: 207
Joined: Tue Aug 21, 2007 1:41 am
Location: Germany

Post by cyr1x »

Ready4Dis wrote:Well, it just looks like a slightly modified version of C
It actually is C, namely K&R syntax.
z180
Member
Member
Posts: 32
Joined: Tue Mar 04, 2008 12:32 pm

Post 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
jal
Member
Member
Posts: 1385
Joined: Wed Oct 31, 2007 9:09 am

Re: who knows the function umap_local() in minix

Post 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
Post Reply