Age | Commit message (Collapse) | Author | Lines |
|
these changes are motivated by a functionally similar patch by Hauke
Mehrtens to address the needs of the new mips vdso clock_gettime,
which wrongly fails with ENOSYS rather than falling back to making a
syscall for clock ids it cannot handle from userspace. in the process
of preparing to handle that case, it was noticed that the old
clock_gettime use of the vdso was actually wrong with respect to error
handling -- the tail call to the vdso function failed to set errno and
instead returned an error code.
since tail calls to vdso are no longer possible and since the plain
syscall code is now needed as a fallback path anyway, it does not make
sense to use a function pointer to call the plain syscall code path.
instead, it's inlined at the end of the main clock_gettime function.
the new code also avoids the need to test for initialization of the
vdso function pointer by statically initializing it to a self-init
function, and eliminates redundant loads from the volatile pointer
object.
finally, the use of a_cas_p on an object of type other than void *,
which is not permitted aliasing, is replaced by using an object with
the correct type and casting the value.
|
|
the memory model we use internally for atomics permits plain loads of
values which may be subject to concurrent modification without
requiring that a special load function be used. since a compiler is
free to make transformations that alter the number of loads or the way
in which loads are performed, the compiler is theoretically free to
break this usage. the most obvious concern is with atomic cas
constructs: something of the form tmp=*p;a_cas(p,tmp,f(tmp)); could be
transformed to a_cas(p,*p,f(*p)); where the latter is intended to show
multiple loads of *p whose resulting values might fail to be equal;
this would break the atomicity of the whole operation. but even more
fundamental breakage is possible.
with the changes being made now, objects that may be modified by
atomics are modeled as volatile, and the atomic operations performed
on them by other threads are modeled as asynchronous stores by
hardware which happens to be acting on the request of another thread.
such modeling of course does not itself address memory synchronization
between cores/cpus, but that aspect was already handled. this all
seems less than ideal, but it's the best we can do without mandating a
C11 compiler and using the C11 model for atomics.
in the case of pthread_once_t, the ABI type of the underlying object
is not volatile-qualified. so we are assuming that accessing the
object through a volatile-qualified lvalue via casts yields volatile
access semantics. the language of the C standard is somewhat unclear
on this matter, but this is an assumption the linux kernel also makes,
and seems to be the correct interpretation of the standard.
|
|
the vdso symbol lookup code is based on the original 2011 patch by
Nicholas J. Kain, with some streamlining, pointer arithmetic fixes,
and one symbol version matching fix.
on the consumer side (clock_gettime), per-arch macros for the
particular symbol name and version to lookup are added in
syscall_arch.h, and no vdso code is pulled in on archs which do not
define these macros. at this time, vdso is enabled only on x86_64.
the vdso support at the dynamic linker level is no longer useful to
libc, but is left in place for the sake of debuggers (which may need
the vdso in the link map to find its functions) and possibly use with
dlsym.
|
|
|
|
this works around pcc's lack of working support for weak references,
and in principle is nice because it gets us back to the stage where
the only weak symbol feature we use is weak aliases, nothing else.
having fewer dependencies on fancy linker features is a good thing.
|
|
|
|
|
|
these changes also make it so clock_gettime(CLOCK_REALTIME, &ts) works
even on pre-2.6 kernels, emulated via the gettimeofday syscall. there
is no cost for the fallback check, as it falls under the error case
that already must be checked for storing the error code in errno, but
which would normally be hidden inside __syscall_ret.
|
|
|
|
these functions are specified inconsistent in whether they're
specified to return an error value, or return -1 and set errno.
hopefully now they all match what POSIX requires.
|
|
|
|
|