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
who knows the function umap_local() in minix
-
- Posts: 10
- Joined: Sat Mar 01, 2008 11:27 pm
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.
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...
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?).
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:
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
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.
- Combuster
- 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:
@chenrvmldd: please use tags when posting code
Code: Select all
...
Re: who knows the function umap_local() in minix
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.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
JAL