mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Linus Torvalds <torvalds@linux-foundation.org>
To: Johannes Weiner <hannes@saeurebad.de>
Cc: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
	clameter@sgi.com, penberg@cs.helsinki.fi
Subject: Re: Why is the kfree() argument const?
Date: Wed, 16 Jan 2008 15:16:45 -0800 (PST)	[thread overview]
Message-ID: <alpine.LFD.1.00.0801161454010.2806@woody.linux-foundation.org> (raw)
In-Reply-To: <87odblct19.fsf@saeurebad.de>



On Wed, 16 Jan 2008, Johannes Weiner wrote:
> 
> Okay, I understood that now.  A const qualifier just forbids modifying
> the underlying memory _through this particular pointer_, right?

Yes, exactly.

> In the case of slub's kfree(), which takes a const pointer, you pass it
> on to slab_free() which actually _DOES_ modification of the underlying
> memory when linking the object to the freelist (as far as I understood
> the code).

First off, the whole concept of "underlying memory" is all about the fact 
that pointers point not to separate objects with its own existence, but 
point to a shared resource ("memory") that can be accessed many different 
ways.

So immediately when you talk about "underlying memory", you need to 
realize that now you're not talking about "that pointer" any more, but you 
are talking about the stuff that *other* pointers can access.

And the whole (and *only*) point of a memory allocator is turning that 
amorphous notion of "infinitely aliasable underlying memory" model into 
more of a "C pointer to separate objects" model.

That *is* what a memory allocator does.

> So if I got it right and you actually modify the memory you only got a
> const pointer to

No. YOU DO NOT.

You *invalidate* the pointer. Then, the memory allocator releases that 
portion of the "infinitely aliasable underlying memory", but that means 
that THAT POINTER NO LONGER EXISTS ON A C LEVEL.

So no, you don't "modify the memory you only got a const pointer to".

What you do is that the memory allocator 

 - keeps track of the NON-const memory that it always had
 - it sees the const pointer you gave it, and uses that pointer to look up 
   ITS OWN DATA STRUCTURES.
 - it then accesses those memory locations using its own pointers.

The "const pointer" you passed to kfree() simply no longer exists. The 
object it pointed to has gone away. That particular pointer simply isn't 
valid any more.

But the memory management code, which maintains its own structures for 
what it has allocated and not allocated, can (and will) generally use the 
knowledge *it* has about its own pointers to modify its own data 
structures.

The fact that they (obviously) alias in memory is irrelevant. It has no 
meaning for the "const void *" you passed in. That pointer is not usable 
for the caller any more.

And no, this is not just a semantic argument. It's a real issue. The 
pointer you pass in to kfree() is obviously used to *find* the data 
structures that the memory allocator maintains, and there is almost 
inevitably a rather direct mapping between the passed-in pointers and the 
data structures that a memory manager maintains itself, but they really 
are different. 

So to take a kfree() a pointer, the memory manager will use the "binary 
value" of that pointer to find its own data structures, and sometimes the 
values are so closely related that it ends up being a direct cast 
(possibly with an offset), but the end result of that direct cast really 
is now the memory management internal data, not the original pointer.

A real example of this is the actual kfree() implementation in the kernel 
(let's take the one from SLAB):

	struct kmem_cache *c;
	..
	c = virt_to_cache(objp);

which then actually ends up doing a 

	struct page *page = virt_to_head_page(obj);
	return page_get_cache(page);

which literally does math on the binary representation of the pointer to 
look up the backing store values (because the memory manager by definition 
is the thing that knows how the low-level representation of pointers 
actually works).

So now the kernel has turned that user-supplied pointer into ITS OWN data 
structures, that contain the NON-CONST aliases for the data.

(It will actually use the const pointer to further get offsets into those 
things, of course, so it's several levels of indirection off that pointer)

And yes, then it will write to those non-const aliases, but that's really 
no different from the same old thing: the pointer *you* passed kmalloc() 
may be "const",  but the memory manager itself has its own data structures 
to keep track of *its* aliases to the same memory, and those are the ones 
that are actually used to re-use the memory for others (and poison it 
etc).

So the particular pointer you passed in is "const". But that never *ever* 
guarantees that there aren't other non-const pointers around to be used 
that can modify the memory. And the memory manegement definitely has all 
those aliased pointers around - it's the whole *point* of memory 
management.

			Linus

  parent reply	other threads:[~2008-01-16 23:22 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-16 16:32 Johannes Weiner
2008-01-16 16:48 ` Christoph Lameter
2008-01-16 17:34   ` Bernd Petrovitsch
2008-01-16 17:45   ` Pekka J Enberg
2008-01-16 18:39 ` Linus Torvalds
2008-01-16 22:19   ` Johannes Weiner
2008-01-16 22:20     ` Christoph Lameter
2008-01-16 22:37       ` Johannes Weiner
2008-01-16 23:13       ` Johannes Weiner
2008-01-16 23:18       ` Linus Torvalds
2008-01-16 23:16     ` Linus Torvalds [this message]
2008-01-16 22:33   ` Steven Rostedt
     [not found] <MDEHLPKNGKAHNMBLJOLKIEGIJJAC.davids@webmaster.com>
2008-01-17 21:25 ` Linus Torvalds
2008-01-17 22:28   ` David Schwartz
2008-01-17 23:10     ` Linus Torvalds
2008-01-18  0:56       ` David Schwartz
2008-01-18  1:15         ` Linus Torvalds
2008-01-18  5:02           ` David Schwartz
2008-01-18 15:38             ` Chris Friesen
2008-01-18 16:10             ` Linus Torvalds
2008-01-18 20:55               ` David Schwartz
2008-01-18 17:37             ` Olivier Galibert
2008-01-18 18:06             ` DM
2008-01-18  7:51           ` Giacomo Catenazzi
2008-01-18  8:20             ` Giacomo Catenazzi
2008-01-18 13:53               ` Andy Lutomirski
2008-01-18 17:24                 ` Olivier Galibert
2008-01-18 22:29                   ` J.A. Magallón
2008-01-18 23:44                     ` Krzysztof Halasa
2008-01-18 13:54               ` Andy Lutomirski
2008-01-18 19:14                 ` Vadim Lobanov
2008-01-18 19:31                   ` Zan Lynx
2008-01-18 19:55                     ` Vadim Lobanov
2008-01-18  8:30             ` Vadim Lobanov
2008-01-18  9:48   ` Jakob Oestergaard
2008-01-18 11:47     ` Giacomo A. Catenazzi
2008-01-18 14:39       ` Jakob Oestergaard
2008-01-18 19:06       ` Vadim Lobanov
2008-01-18 13:31     ` Björn Steinbrink
2008-01-18 14:53       ` Jakob Oestergaard
2008-01-18 12:45 ecolbus
2008-01-18 15:20 ` Giacomo A. Catenazzi
2008-01-18 16:45 ecolbus
2008-01-18 18:20 ` Olivier Galibert
2008-01-18 19:10 ecolbus
     [not found] <fa.cHMztHfqJXv7vw5O0nQ8SdTrma0@ifi.uio.no>
     [not found] ` <fa.V9M+5l8C/um5KEiBtZOjbJDQmu4@ifi.uio.no>
2013-01-12 19:18   ` antoine.trux
2013-01-13  8:10     ` Chen Gang F T
2013-01-13 17:41       ` Guenter Roeck
2013-01-14  1:45         ` Chen Gang F T
2013-01-13 20:54       ` Cong Ding
2013-01-14  1:18         ` Chen Gang F T

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.LFD.1.00.0801161454010.2806@woody.linux-foundation.org \
    --to=torvalds@linux-foundation.org \
    --cc=clameter@sgi.com \
    --cc=hannes@saeurebad.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=penberg@cs.helsinki.fi \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®