On Wed, Nov 3, 2010 at 10:24 AM, Robert P. J. Day <rpjday@xxxxxxxxxxxxxx> wrote: > > somewhat embarrassed to admit i'd never noticed this before, but it > has to do with pages and page flags. > > LKD3, on p. 232, discusses the "_count" member field of "struct > page", and states that that field, when it reaches *negative one*, > represents a page that is no longer in use and is now available for > another allocation. however, it recommends that no one look at that > field directly; instead, use the page_count() function, which takes as > its argument a page structure. also, the book claims that, while the > _count field internally will use -1 to show free, page_count() will > return a zero to show the same thing. > > ok, so knowing that, we can examine the page_count() function in > <linux/mm.h> and see how it represents that: > > static inline int page_count(struct page *page) > { > return atomic_read(&compound_head(page)->_count); > } > > um ... ok, so it's an atomic read of that member field (not > surprising), but it pulls in something called "compound_head()". and > that's defined right above that routine: > > static inline struct page *compound_head(struct page *page) > { > if (unlikely(PageTail(page))) > return page->first_page; > return page; > } > > ok, now i'm confused by this "first_page" field, so let's check out > <linux/page-flags.h> for this "PageTail" routine. now, everything > related to that can be found in that header file surrounded by: > > #ifdef CONFIG_PAGEFLAGS_EXTENDED > /* > * System with lots of page flags available. This allows separate > * flags for PageHead() and PageTail() checks of compound pages so that bit > * tests can be used in performance sensitive paths. PageCompound is > * generally not used in hot code paths. > */ > __PAGEFLAG(Head, head) > __PAGEFLAG(Tail, tail) > ... snip ... > #endif > > and further up that same file, we have: > > enum pageflags { > ... snip ... > #ifdef CONFIG_PAGEFLAGS_EXTENDED > PG_head, /* A head page */ > PG_tail, /* A tail page */ > #else > PG_compound, /* A compound page */ > #endif > ... > }; > > i can see the entry in the mm/Kconfig file: > > # If we have space for more page flags then we can enable additional > # optimizations and functionality. > # > # Regular Sparsemem takes page flag bits for the sectionid if it does not > # use a virtual memmap. Disable extended page flags for 32 bit platforms > # that require the use of a sectionid in the page flags. > # > config PAGEFLAGS_EXTENDED > def_bool y > depends on 64BIT || SPARSEMEM_VMEMMAP || !SPARSEMEM > > but i have to admit, i don't know what that means. thoughts? and how > does all that map back to the proper use of the page_count() routine? Compound Page is a page which has greater size than the system-wide page size. Compound pages are mainly used by HugeTLB code. In some architectures, multiple page sizes are supported. For Ex. x86_64 also supports 2 MB also in addition to 4KB pages which is the default setting when you compile a kernel. So, on a kernel configured with 4KB page size, if you do a alloc_pages (..) of say order 9, you will have a total 2MB worth of pages. As the architecture supports 2MB page sizes, basically one TLB entry is enough for 2MB worth of memory instead of 512 entries, if HugeTLB is used. So, the way it works on a 4KB page size kernel is you get the following : HTTTTTT.......T (total of 512) . 'H' indicating a head page & 'T' indicating a tail page. For a tail page, the 'first_page' field of 'struct page' will point to the head page. This 2 MB worh of memory will be treated as a single page conceptually. What that means, the refcounts on these individual 512 4K pages are equal. They are equal to the refcount of the head page. Everytime, you get a ref on a page, the refcount on the head page is modified. If you have support for extended page flags, these flags can be used to indicate whether a given page is a head page or a tail page. Thats all there's to it. Venkatram Tummala > > rday > > -- > > ======================================================================== > Robert P. J. Day Waterloo, Ontario, CANADA > http://crashcourse.ca > > Twitter: http://twitter.com/rpjday > LinkedIn: http://ca.linkedin.com/in/rpjday > ======================================================================== > > -- > To unsubscribe from this list: send an email with > "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx > Please read the FAQ at http://kernelnewbies.org/FAQ > > -- To unsubscribe from this list: send an email with "unsubscribe kernelnewbies" to ecartis@xxxxxxxxxxxx Please read the FAQ at http://kernelnewbies.org/FAQ