Ted Baker wrote:
I've rethought this, and it now seems to me that it would be
legitimate for an implementation to use the list-of-valid-objects
method to check for attempts to re-initialize. I'll explain.
For starters, let's distinguish memory objects from the
corresponding C or POSIX semantic objects that may happen to be
associated with them at a point in time. That is, if you look at
the specific pthread_xxx_init calls, they refer to specific types
of objects. For example, for pthread_mutex_init(), we have "mutex
object". A semantic mutex object necessarily corresponds to some
implementation memory object(s) (maybe more than one, if
implemented as a discontiguous structure, linked together with
pointers).
Thinking logically, regardless of whether it is spelled out in the
standard, common sense tells us the following:
We cannot speak of an "XXX object" until it has been intialized by
pthread_XXX_init(). Thereafter, it would be erroneous to
deallocate, overwrite, or reuse the storage associated with an XXX
object for another purpose while there are still references to the
XXX object.
For storage allocated by the application (stack or heap), it is
the application's responsibility to preserve the integrity of the
storage object whose address it passed to pthread_XXX_init()
until the application calls pthread_XXX_destroy() (which breaks
the binding).
If the system allocates additional storage for the XXX object,
via pthread_XXX_init(), it is the system's responsibility to
preserve the integrity of that storage until the system determines
that it is safe to deallocate and reuse it, from both the application's
view and from the system's view.
The pthread_XXX_destroy() tells the system when it is safe to
destroy the system's XXX object, from the applications's view. In
that sense, it is a contract that binds the application to no
longer use the corresponding pointer value as a reference to an
XXX object until and unless it is once again bound to a semantic
XXX object by a call to pthread_XXX_init(). The same contract
binds the system not to assume anything about the corresponding
user-supplied storage object past this point.
It remains for the system to determine when it is safe for the
system to free system memory that has been allocated for the XXX
object. That might be when the user calls pthread_XXX_destroy(),
but it might be later. For example, an imaginary system might
choose to protect against the effects of an application
accidentally deallocating storage for a mutex by putting the real
mutex in system space, and using the user-provided storage to hold
a reference to the corresponding system object. This would reduce
the potential for catastrophic side-effects if, say the user
storage for the mutex is deallocated while the system is
concurrently accessing it. In this case, pthread_XXX_destroy()
might reduce a reference count, and the storage of the system
object would not be freed until the count goes to zero.
As others have pointed out, it would be a clear violation of the
standard to attempt to enforce application compliance with the
contract by putting a hash-sum or other magic value into the
user-supplied storage object. Since the standard does not require
users to zero the memory object whose address they pass to
pthread_XXX_init, you can't eliminate the possibility of denying a
valid call.
On the other hand, I'm not convinced it would be a violation of
the standard for a system to check the pointer provided as
parameter to pthread_XXX_init against a list (in system space) of
known initialized userspace XXX objects that have not yet been
destroyed. The only way, it seems, to get a false positive for
this check would be if an application were to reuse (whether by
function return and subsequent call, free and malloc, etc.) the
storage of an initialized XXX object without first calling
pthread_XXX_destroy().
This *ought* to be a violation of the contract model, even if we
have difficulty finding where it is spelled out in the standard.
I hope everyone would agree that it would be a violation for
and application to overwrite the storage of an initialized XXX
object while it is still in scope. That is effectively the same
as what happens when an application frees or pops from the stack
a storage object that is still bound to an XXX object.
--Ted
, but since the standard does not (apparently)
require that pthread_XXX_destroy() be called before the user-managed
storage object is reused, you could again
?? But, yes; that's the point. Although I think most people agree that
your contract model is reasonable, and it was certainly the INTENT,
nobody's aware of where (if anywhere) this contract is actually spelled
out in the standard. If it's not, then the intended (hoped for?)
contract doesn't actually bind anyone, and doesn't help.
david.butenhof.vcf
Description: Text Data
|