Re: [patch] user-vm-unlock-2.5.31-A2

Linus Torvalds (torvalds@transmeta.com)
Fri, 16 Aug 2002 09:54:16 -0700 (PDT)


On Fri, 16 Aug 2002, Ingo Molnar wrote:
>
> okay, this is the misunderstanding then. If it fork()s and then uses some
> threading (which uses clone()) then in all cases i know about it must be
> linked against some threading library. Otherwise Y couldnt do a clone()
> call and expect threading to work.

But of course it would. You can make your own async-io-like things by just
using clone() directly, that's what all the original clone() users were.

> So right now 'threading' is a property that comes with the
> process image at exec() time. But this must not be so from a conceptual
> angle, so i agree with you.

Even from a practical angle, it's not a "global" property. Sure, the code
that does the clone() itself must have come in through the execve() (or
through a loadable library later on), so in that sense you can think of it
as a global thing - since the code must obviously be in the address space
that the clone thing shares.

But a lot of the clone() decisions can be local, without anythign else
really knowing about the fact that something started up a thread. The most
trivial example is simply something like the appended, which just does a
asynchronous read (yeah yeah, stupid example, but it's basically a
threaded "cat").

Notice how none of this depends on any global state, so a library could do
the clone() without the caller even knowing that it does part of its work
in a local thread (it obviously wouldn't be doing anything this stupid,
but an async writer thread for sound output etc is not impossible to
imagine in a game library or something like that).

In fact, inside libraries there may well be reasons _not_ to use a global
threading model like pthreads, because the library might want to take
advantage of things like separate file descriptor address spaces etc that
clone() can give it.

Linus

---
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

#include <sched.h>

#define UNFINISHED (-1000)

struct iodesc { int fd, len, status; void *buffer; };

int io_fn(void *_desc) { struct iodesc *desc = _desc;

desc->status = read(desc->fd, desc->buffer, desc->len); _exit(0); }

int main() { char buffer[4096]; struct iodesc desc = { 0, sizeof(buffer), UNFINISHED, buffer };

clone(io_fn, malloc(4096)+4096, CLONE_VM | CLONE_FILES | CLONE_FS | CLONE_DETACHED, &desc); while (desc.status == UNFINISHED) sched_yield(); write(1, buffer, desc.status); }

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/