-1

How do I get a pointer to the beginning of a page?

I tried the following to no success:

#define PAGESIZE 4096

 bool is_page_aligned(void *p)
 {
    return !((long int)p & 0xFFF);
 }

 int main(void)
 {
     bool res;
     void *buffer;

     buffer = malloc(PAGESIZE*2);
     printf("%p\n", (void *) &buffer);
     res = is_page_aligned(&buffer);
     fputs(res ? "true\n" : "false\n", stdout);
     return 0;
}

I'm trying to mitigate TLB misses. Any possible assistance is greatly appreciated.

rflc
  • 3
  • 4
  • Questions seeking debugging help ("why isn't this code working?") must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself. Questions without a clear problem statement are not useful to other readers. See: How to create a Minimal, Complete, and Verifiable example. – too honest for this site Sep 27 '16 at 18:01
  • 3
    You are checking if the location of the variable `buffer` is page aligned, not the memory pointed to by `buffer`. – Some programmer dude Sep 27 '16 at 18:01
  • For a starter: your code invokes undefined behaviour. At least use the correct integer type to do arithmetic on a pointer (it still is UB, but more likely to work on your platform). – too honest for this site Sep 27 '16 at 18:02
  • Also, your question is about getting a pointer to the beginning of a page, but the code you show does nothing like that, it just checks if a pointer is aligned in some specific way. – Some programmer dude Sep 27 '16 at 18:04
  • @Olaf, the behavior of converting either way between pointers and integers is *implementation defined*, provided that the integer type is large enough to accommodate the pointer's converted value. – John Bollinger Sep 27 '16 at 18:08
  • Whatever `is_page_aligned` is supposed to do, it ignores the macro definition by hard coding. – Weather Vane Sep 27 '16 at 18:14
  • @JohnBollinger: The standard does not define any arithmetic on such an integer value and what happens if you this value back. So it very well is UB. But - as I wrote in the second sentence, using the correct type provides a good chance to get the expected result. `long` is a bad idea for this for two reason: possible width-missmatch and being signed. The standard intentionally provides `uintptr_t`. – too honest for this site Sep 27 '16 at 18:24
  • Thank you for all of your responses and thank you, Joachim for pointing out the obvious. – rflc Sep 27 '16 at 18:29
  • @Olaf Hi I googled that it seems `uintptr_t` is a data type in `C++`, Does it support in `C` language. – litao3rd Sep 27 '16 at 18:45
  • @Olaf yep, it is supported in C99. I find it [here](http://stackoverflow.com/questions/1845482/what-is-uintptr-t-data-type). – litao3rd Sep 27 '16 at 18:48

1 Answers1

0

To get the address of the beginning of the page containing the address a, divide by the page size and then multiply by the page size.

long int page_beginning = PAGESIZE * (a / PAGESIZE);

This works because of the truncation performed during integer division.

You can also subtract the modulus:

long int page_beginning = a - (a % PAGESIZE);
Barmar
  • 741,623
  • 53
  • 500
  • 612