0

In kernel 2.4.37, there is a macro in page.h like this:

struct page *mem_map;
struct page *page;

#define VALID_PAGE(page)  ((page - mem_map) < max_mapnr)

I know mem_map is an array of struct page, page is a struct, so what does page - mem_map mean?

HuangJie
  • 1,488
  • 1
  • 16
  • 33

2 Answers2

1

It will compute the index of corresponding page in mem_map array means which number of page it is in mem_map array, let say it as pfn or page frame number for linux (linux assumes that mem_map array starts with 0th pfn to the max pfn) , adding a PHYS_PFN_OFFSET to pfn will give you the actual physical page frame in your memory map. __page_to_pfn

max_mapnr is the limit of maximum number of mapped pages or maximum page frame number. set_max_mapnr

I hope it clears your doubts.

AnshuMan Gupta
  • 323
  • 3
  • 14
-1

Humm, I'm not sure but maybe a pointer adresses comparaison ?

I mean, if one of them is a array and it's not dereferenced the operations are apply on adresses I suppose.

Edit: (precision)

So, in this case I think this operation is for check if "page" is in range of the adresses array "mem_map".

We can represent like this: Graphic representation


Utility of Macro:

So, "mem_map" is adresses of the begin of array, suppose: 0x0...5. The size of "mem_map"(max_mapnr) array is: 5.

We want to know if "page" adresses is in the range of "mem_map" array.

True Case:

Suppose "page" is in "mem_map", 2e element. We can suppose his adresses is something like: 0x0...7;

Now we do operation: ((0x0...7 - 0x0...5) < 5). We obtain 2. So "page" adresse is in mem_map.

False Case:

Otherwise if "page" is out of the array (0x0...D): We the result will be 8. So, 8 is not less than "max_mapnr"(5). So this page is not in the "mem_map" array.


And if the adresses is bellow the array adresse (0x0...2): The result of ((0x0...2 - 0x0...2)) will be a negative value. And in that case they comparaison with "max_mapnr"(unsigned long) is not possible.

I found this topic explain why better than me:

Signed/unsigned comparisons

So for resume: You canno't do operations between negative(signed) and unsigned value in C cause he cast them automaticaly. In others terms, when you do (-3 - U_nbr), it's same if you do: (((unsigned)-3) - U_nbr). And in option, normaly if you compile with gcc -Wall flags, and you don't cast manually your value you will have an compilation Warning message.

For testing I tried to run this code:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
        unsigned long test = 0x0000F;
        unsigned long test2 = 0x0000A;
        unsigned long weird = 0x00002;
        char* pt1 = "This is first test string !";
        char* pt2 = "This is a test string";

        printf("Try to make operation on two unsigned long result must be 5: %lu\n", (test - test2));
        printf("Try to make operation between unsigned long result must be negative, so he will be cast: %lu\n", (weird - test2));
        printf("Let's try the same with real adresses: %lu\n", (pt2 - pt1));
        printf("And this is what happens with negative value: %lu\n", (pt1 - pt2));
        printf("For be sure, this is the lenght of string 1. %lu\n", strlen(pt1));
        return (0);
}

The ouput is:

Try to make operation on two unsigned long result must be 5: 5
Try to make operation between unsigned long result must be negative, so he will be cast: 18446744073709551608
Let's try the same with real adresses: 28
And this is what happens with negative value: 18446744073709551588
For be sure, this is the lenght of string 1. 27

So, as we can see, the negative value is casted in Unsigned long and return a overflowed one. And if you make this comparaison with max_mapnr you will see he is "out of range".


Thank's to AnshuMan Gupta for the "weird case".

Community
  • 1
  • 1
avallete
  • 53
  • 8
  • "But I'm not sure of the behavior of this MACRO with a pointer not in array but less than "mem_map" pointer". i think that is not the case because you will have to always pass a page to to VALID_PAGE after converting it to page either by pfn_to_page or virt_to_page. – AnshuMan Gupta Oct 24 '15 at 13:53
  • @avallete Yes,what I care about is the Weird Case. What if the pointer does not point to the array. – HuangJie Oct 25 '15 at 08:14
  • @HuangJie if page is pointing to below mem_map then (page - mem_map) yields a negative value and thus comparison of negative value with max_mapnr (lxr.free-electrons.com/source/mm/memory.c#L80) which is a unsigned long (negative value < max_mapnr) will always false and page will not be valid page. thus there is no weird case. hope this will clear the weird case doubt – AnshuMan Gupta Oct 25 '15 at 09:46
  • @AnshuManGupta Thank you for your explanations I edit my post in consequences. – avallete Oct 25 '15 at 11:24