Re: Copying pthread_t
- From: David Schwartz <davids@xxxxxxxxxxxxx>
- Date: Wed, 25 Jul 2007 00:56:04 -0700
On Jul 24, 10:10 pm, Hallvard B Furuseth <h.b.furus...@xxxxxxxxxxx>
wrote:
You mean *normal* C functions. But there is no rule that says that the
pthread_* functions must be normal C functions.
The Posix standard just calls them functions, as far as I can tell.
Where is this different from all the other functions in the standard?
Or can't other Posix functions be relied on to be normal functions
either.
Any apparent function that has specific caveats cannot be relied upon
to act like a normal function. For example, some compiler 'magic'
might be needed around the mutex functions to inhibit inter-procedure
optimization. This may make those functions different from every
other functions.
What you cannot do is combine implementation limits from one standard
to get shoehorn guarantees out of another. Nothing in the POSIX
standard requires it to be implement by pure standards-conformant C
code, and in fact it would be impossible to do so.
And, as you pointed
out, the compiler can optimize things so long as compliant code is not
broken.
Yes...
Copying pthread_t's is not permitted, so code that does so is not
compliant. The compiler is allowed to make optimizations that
breaks such code.
Where does the standard say that? (Same place as the warning you
mentioned that it may need not follow normal C type semantics, I guess,
so maybe the answer fits better in the other thread.)
I don't have the standard handy, but it's the same section that warns
about copying mutexes, condition variables, and the other pthread_*
types.
Or are you saying that one cannot even _store_ the result from
pthread_self(), even though there is no warning about that in the
pthread_self() definition? Or has there been a warning about that in a
draft, but not in the final version?
No, you can store the result of pthread_self in a pthread_t. However,
assigning a new value to the same pthread_t might destroy the original
value such that a copy of it now points to something that was
destroyed.
After foo() returns, the internal thread structure points to an
out-of-scope variable, and unless the compiler uses a garbage collected
stack structure with closures, the next function call might reuse that
memory for something else.
In this case, it doesn't matter what 'tid' points to since 'tid' will
never be accessed again. I am not suggesting that 'tid' point to an
internal thread structure, I am suggesting that 'tid' point to a
structure whose sole purpose is to identify a thread.
If you are not even talking about it referring back to itself, I'm
_really_ at loss about how this could be different from having two
pointers to some other object.
Two pointers to any object can cause confusion and problems if the
object is modified through one pointer while the other pointer is
expected to refer to the same thing all along. Imagine if a pthread_t
worked like many string classes do. If you copy a pthread_t, they may
both winding up pointing to the same place, causing a reassignment of
one to change the value of the other.
Consider:
int *i, *j;
i=malloc(sizeof(void *));
j=malloc(sizeof(void *));
i=GetSomeValue();
SomeFunction(i);
j=i;
i=GetSomeOtherValue(); // oops, we just broke j
Under the hood, each 'pthread_t' could have some memory allocated to
it to copy the information needed to identify a thread. Setting one
pthread_t equal to another could cause them to point to the same
structure, causing a subsequent chance of one to change the other.
Consider:
void get_id(pthread_t *j)
{
pthread_t tid; // this could allocate memory for the structure
tid=pthread_self(); // this could fill in the structure
(*j)=tid; // this could copy a pointer to the structure
return; // this could release the memory for 'tid' since it went out
of scope
}
The net result would be filling in 'j' with a pointer to memory that
has been freed.
No it would not. Your 'tid' here is a pointer, remember? It _points_
to the allocated memory you refer to. *j points to that structure, not
to tid. After the return from get_id(), the structure is still
allocated, and *j points to it, only the tid pointer is out of scope.
I am assuming the implementation uses destructors. When a pthread_t
goes out of scope, the object has to be freed for this to work or
there will be memory leaks.
That means I can't safely write a function which takes a pthread_t
argument. It must take a pthread_t pointer.
(...)
Which also means if I call pthread_self() and pass the result to such a
private function, I must keep the place where that pthread_t was stored
in scope until that private function is done with the pthread_t*.
You have no choice. If you call a function, everything that called it
will stay in scope until the function returns.
Oops, I should have said that memory must be kept valid. E.g if I put
the pthread_t in malloced memory.
I think this has to work.
I don't think you have to worry about passing a pthread_t by
value. You just have to avoid copying that value into another
pthread_t. Even I won't go so far as to say it's not safe to *pass* a
'pthread_t' by value.
Are you only talking about not overwriting an initialized pthread_t with
another pthread_t, then? While it's OK to initialize a pthread_t with
another one? That's what passing by values does - it initializes the
new one. But then, what if you return from that function with the
initialized copy and call it again so the same memory area gets
initialized with another pthread_t value?
You cannot assume that copying a pthread_t does anything but a shallow
copy. It violates the standard to assume the two pthread_t's can then
go their separate ways without breaking. The only legal way to
initialize a pthread_t is by one of the pthread_* functions like
pthread_self or pthread_create.
That said, since there is no pthread_copy function, I'm not sure you
have much choice. It would be fair to consider any implementation that
did this legal but brain damaged. You don't have to work on every
possible legal implementation. An implementation that gave each thread
one CPU cycle every decade is legal.
DS
.
- Follow-Ups:
- Re: Copying pthread_t
- From: Hallvard B Furuseth
- Re: Copying pthread_t
- References:
- Copying pthread_t
- From: Hallvard B Furuseth
- Re: Copying pthread_t
- From: David Schwartz
- Re: Copying pthread_t
- From: Hallvard B Furuseth
- Re: Copying pthread_t
- From: David Schwartz
- Re: Copying pthread_t
- From: Hallvard B Furuseth
- Copying pthread_t
- Prev by Date: "Intel open sources multicore programming tool""
- Next by Date: Re: A bit more portable DCL (DCI/DCCI) implementation
- Previous by thread: Re: Copying pthread_t
- Next by thread: Re: Copying pthread_t
- Index(es):
Relevant Pages
|
Loading