Re: restrict
On Sun, Feb 9, 2020 at 10:03 PM Bruno Haible wrote: > ... > Which function declarations could therefore profit from the 'restrict' > keyword? [SNIP ...] I think the case of interest is subobjects of arrays: char a[] = "Hello World"; char* b = a+5; memcpy(a,b,5) would get you in trouble due to restrict. memmov(a,b,5) would be OK. Punning might be another interesting case, like the way the internet functions seem to cast everything to byte arrays. Jeff
Re: restrict
On 2/10/20 4:02 AM, Bruno Haible wrote: > Tim Rühsen wrote: >> gcc -Wall tells you so (gcc 8 and upwards): >> $ gcc -Wall msg.c -o msg >> msg.c: In function ‘main’: >> msg.c:11:13: warning: passing argument 1 to restrict-qualified parameter >> aliases with argument 4 [-Wrestrict] >>11 | snprintf (msg, sizeof (msg), "%s%s", msg, WRONG_MESSAGE); >> | ^~~~~~ >> msg.c:11:35: warning: ‘%s’ directive output may be truncated writing 4 >> bytes into a region of size between 1 and 11 [-Wformat-truncation=] >>11 | snprintf (msg, sizeof (msg), "%s%s", msg, WRONG_MESSAGE); >> | ^~ >> msg.c:11:3: note: ‘snprintf’ output between 5 and 15 bytes into a >> destination of size 11 >>11 | snprintf (msg, sizeof (msg), "%s%s", msg, WRONG_MESSAGE); >> | ^~~~ >> > > Oh, the 'restrict' keyword is actually useful (other than for micro- > optimizations)! Thanks for this pointer, Tim. > > So, it would make sense to use this keyword in function declarations in > public .h files in gnulib. > > For internal .h files in gnulib, there's no point - this code is assumed > correct, no need to try to get GCC to produce warnings here. > > What does 'restrict' precisely mean? ISO C 99 § 6.7.3.(7): > "An object that is accessed through a restrict-qualified pointer has a >special association with that pointer. This association, defined in >6.7.3.1 below, requires that all accesses to that object use, directly >or indirectly, the value of that particular pointer.115) The intended >use of the restrict qualifier (like the register storage class) is to >promote optimization, and deleting all instances of the qualifier from >all preprocessing translation units composing a conforming program >does not change its meaning (i.e., observable behavior)." > > Which function declarations could therefore profit from the 'restrict' > keyword? > > - Only parameters of pointer types, excluding function pointer types, > matter. > > - If all pointer parameters are 'const SOMETHING *', the function > is not writing into them, therefore 'restrict' is redundant. > Example: int strcmp (const char *, const char *); > > - If all pointer parameters point to different types, excluding 'void *', > ISO C forbids aliasing anyway, therefore 'restrict' is redundant. > Example: void dfacomp (char const *, ptrdiff_t, struct dfa *, bool); > and https://pubs.opengroup.org/onlinepubs/9699919799/functions/glob.html > > - If, among the parameters, there are N parameters of type > [const] TYPE * > adding the 'restrict' keyword to N-1 of them is equivalent to adding > the 'restrict' keyword to all N of them. > See ISO C 99 § 6.7.3.1.(7) [Example 1]. > > GCC's warning facility understands this, regarding the non-const pointer. > Test case: > > #include > extern int smprintf (char *restrict, size_t, const char *, ...) > __attribute__ ((__format__ (__printf__, 3, 4))); > int main () > { > char msg[sizeof ("try a fool")] = "try a "; > smprintf (msg, sizeof (msg), "%s%s", msg, "fool"); > } > > > - If a function has an input parameter of type > const TYPE * > and an output parameter of type > TYPE * > then the 'restrict' keyword means that the implementation may write > the output before having finished reading all the input. > Example: > void arctwo_encrypt (arctwo_context *context, const char *inbuf, >char * restrict outbuf, size_t length); Doesn't this need 'restrict' for the 'inbuf' parameter as well ? If not, why is glibc applying restrict to both parameters of strcpy ? > Whereas the absence of the 'restrict' keyword means that the > implementation will read all the input _before_ starting to store > the output. Can we say "Whereas the absence of the 'restrict' keyword means that the implementation guarantees documented operation for any aliasing of input and output" ? > Example: > int hmac_md5 (const void *key, size_t keylen, > const void *buffer, size_t buflen, void *resbuf); > > - 'restrict' should NOT be used for multiple output parameters of the > same type, when only a single word is written through each parameter. > Example: ssize_t copy_file_range (int ifd, off_t *ipos, int ofd, off_t > *opos, > size_t len, unsigned flags); > Rationale: It is OK to have ipos and opos point to different elements > of the same off_t[] array. > > Is this all right, or did I misinterpret something? IMO, a very good interpretation and summary ! I can't add anything except the above questi
[PATCH 0/1] xnanosleep: Use pause for infinite duration.
Users have discovered that the "sleep" command accepts "infinity" as its duration argument. However, specifying the "infinity" duration does not actually cause GNU sleep to sleep for an infinite duration. This is because the duration was being unconditionally converted to a timespec value, and infinities are not representable as timespecs. Address this by using the "pause" system call (instead of "nanosleep") when the duration is a positive infinity. This allows us to avoid burdening the operating system with a timer which likely will never be reached. --- Commentary: Yes, this patch isn't too serious. There is an interesting discussion here [1] which compares a few ways to get a process to simply block indefinitely. I thought it was a shame that the most elegant-looking solution, "sleep infinity", turned out to be inferior to the other, more complicated ones. Possibly xnanosleep is not the best way to perform this change. The downside is that it changes the behavior of xnanosleep - it is no longer just a nanosleep wrapper. The upside is that this the place where the lossy conversion occurs, so the alternative would mean that all nanosleep callers would have to check the argument. I'm not sure if isfinite is the best way to check for infinity, as far as the tradeoff between portability and dependencies goes. An alternative would be "static const double infinity = 1.0 / 0.0; if (seconds == infinity)" but I don't know how good that is in terms of portability. I noticed that e.g. vasnprintf.c defines a private isfinite-like function. By the way, shouldn't xnanosleep be using the second nanosleep parameter to track how much time there's left to sleep in case of an interruption? [1]: https://stackoverflow.com/a/41655546/21501 --- Vladimir Panteleev (1): xnanosleep: Use pause for infinite duration. lib/xnanosleep.c | 42 -- 1 file changed, 28 insertions(+), 14 deletions(-) -- 2.25.0
[PATCH] xnanosleep: Use pause for infinite duration.
* lib/xnanosleep.c (xnanosleep): When the duration is the positive infinity, use pause instead of nanosleep. --- lib/xnanosleep.c | 42 -- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/lib/xnanosleep.c b/lib/xnanosleep.c index 5774f75f3..58a2f5254 100644 --- a/lib/xnanosleep.c +++ b/lib/xnanosleep.c @@ -25,7 +25,9 @@ #include #include +#include #include +#include /* Sleep until the time (call it WAKE_UP_TIME) specified as SECONDS seconds after the time this function is called. @@ -37,21 +39,33 @@ int xnanosleep (double seconds) { - struct timespec ts_sleep = dtotimespec (seconds); - - for (;;) + if (!isfinite(seconds) && seconds > 0) +{ + for (;;) +{ + pause(); + if (errno != EINTR) +return -1; +} +} + else { - /* Linux-2.6.8.1's nanosleep returns -1, but doesn't set errno - when resumed after being suspended. Earlier versions would - set errno to EINTR. nanosleep from linux-2.6.10, as well as - implementations by (all?) other vendors, doesn't return -1 - in that case; either it continues sleeping (if time remains) - or it returns zero (if the wake-up time has passed). */ - errno = 0; - if (nanosleep (&ts_sleep, NULL) == 0) -break; - if (errno != EINTR && errno != 0) -return -1; + struct timespec ts_sleep = dtotimespec (seconds); + + for (;;) +{ + /* Linux-2.6.8.1's nanosleep returns -1, but doesn't set errno + when resumed after being suspended. Earlier versions would + set errno to EINTR. nanosleep from linux-2.6.10, as well as + implementations by (all?) other vendors, doesn't return -1 + in that case; either it continues sleeping (if time remains) + or it returns zero (if the wake-up time has passed). */ + errno = 0; + if (nanosleep (&ts_sleep, NULL) == 0) +break; + if (errno != EINTR && errno != 0) +return -1; +} } return 0; -- 2.25.0
[PATCH] m4: fix --disable-rpath for AIX
Currently, --disable-rpath will add directly $found_so to the compilation line. However, on AIX, this will result on the path being hardcoded in the built binaries. The only way to avoid hardcoded paths without using linker flags (like -Wl,-bnoipath) is to add -l$name. --- m4/lib-link.m4 | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/m4/lib-link.m4 b/m4/lib-link.m4 index 0ff10731f..01bcfd5ee 100644 --- a/m4/lib-link.m4 +++ b/m4/lib-link.m4 @@ -377,7 +377,12 @@ AC_DEFUN([AC_LIB_LINKFLAGS_BODY], || test "X$found_dir" = "X/usr/$acl_libdirstem" \ || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then dnl No hardcoding is needed. -LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" +case $host_os in + dnl Using directly $found_so on AIX will result into + dnl hardcoded libraries' path inside binaries. + aix*) LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name" ;; + *) LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so" ;; +esac else dnl Use an explicit option to hardcode DIR into the resulting dnl binary. -- 2.17.1
Re: [PATCH] test-canonicalize: avoid a build failure
> * tests/test-canonicalize.c: Protect the inclusion of null-ptr.h > with the same guard as that used to protect usage of the null_ptr > function The same thing is needed in test-ptsname_r.c: 2020-02-10 Bruno Haible ptsname_r-tests: Avoid unused function warning. * tests/test-ptsname_r.c: Don't include null-ptr.h if we don't need it. diff --git a/tests/test-ptsname_r.c b/tests/test-ptsname_r.c index 24be52f..381e3da 100644 --- a/tests/test-ptsname_r.c +++ b/tests/test-ptsname_r.c @@ -36,7 +36,10 @@ SIGNATURE_CHECK (ptsname_r, int, (int, char *, size_t)); #include "same-inode.h" -#include "null-ptr.h" +#if GNULIB_defined_ptsname_r +# include "null-ptr.h" +#endif + #include "macros.h" /* Compare two slave names.
pthread-mutex-tests, pthread-rwlock-tests: Fix link errors on HP-UX
On HP-UX 11.31 / ia64, I'm seeing these link errors: cc +DD64 -AC99 -D_HPUX_SOURCE -D_XOPEN_SOURCE=600 -g -L/home/haible/prefix-hpux113ia64-64-cc/lib -o test-pthread-mutex test-pthread-mutex.o libtests.a ../gllib/libgnu.a libtests.a -lpthread ld: Unsatisfied symbol "sem_trywait" in file test-pthread-mutex.o ld: Unsatisfied symbol "sem_init" in file test-pthread-mutex.o ld: Unsatisfied symbol "sem_post" in file test-pthread-mutex.o 3 errors. gmake[4]: *** [test-pthread-mutex] Error 1 cc +DD64 -AC99 -D_HPUX_SOURCE -D_XOPEN_SOURCE=600 -g -L/home/haible/prefix-hpux113ia64-64-cc/lib -o test-pthread-rwlock test-pthread-rwlock.o libtests.a ../gllib/libgnu.a libtests.a -lpthread ld: Unsatisfied symbol "sem_trywait" in file test-pthread-rwlock.o ld: Unsatisfied symbol "sem_init" in file test-pthread-rwlock.o ld: Unsatisfied symbol "sem_post" in file test-pthread-rwlock.o 3 errors. gmake[4]: *** [test-pthread-rwlock] Error 1 This patch fixes them. 2020-02-10 Bruno Haible pthread-mutex-tests, pthread-rwlock-tests: Fix link errors on HP-UX. * modules/pthread-mutex-tests (Makefile.am): Link test-pthread-mutex with $(LIB_SEMAPHORE). * modules/pthread-rwlock-tests (Makefile.am): Link test-pthread-rwlock with $(LIB_SEMAPHORE). diff --git a/modules/pthread-mutex-tests b/modules/pthread-mutex-tests index eb6ec7b..12d386e 100644 --- a/modules/pthread-mutex-tests +++ b/modules/pthread-mutex-tests @@ -11,4 +11,4 @@ configure.ac: Makefile.am: TESTS += test-pthread-mutex check_PROGRAMS += test-pthread-mutex -test_pthread_mutex_LDADD = $(LDADD) @LIBPMULTITHREAD@ @LIB_SCHED_YIELD@ +test_pthread_mutex_LDADD = $(LDADD) @LIBPMULTITHREAD@ @LIB_SCHED_YIELD@ @LIB_SEMAPHORE@ diff --git a/modules/pthread-rwlock-tests b/modules/pthread-rwlock-tests index 7f35198..340ebf0 100644 --- a/modules/pthread-rwlock-tests +++ b/modules/pthread-rwlock-tests @@ -12,4 +12,4 @@ configure.ac: Makefile.am: TESTS += test-pthread-rwlock check_PROGRAMS += test-pthread-rwlock -test_pthread_rwlock_LDADD = $(LDADD) @LIBPMULTITHREAD@ @LIB_SCHED_YIELD@ +test_pthread_rwlock_LDADD = $(LDADD) @LIBPMULTITHREAD@ @LIB_SCHED_YIELD@ @LIB_SEMAPHORE@
copysignf: fix link error on HP-UX with cc
On HP-UX 11.31/ia64 with cc, I'm seeing this link error: cc +DD64 -AC99 -D_HPUX_SOURCE -D_XOPEN_SOURCE=600 -g -L/home/haible/prefix-hpux113ia64-64-cc/lib -o test-copysignf test-copysignf.o libtests.a ../gllib/libgnu.a libtests.a ld: Unsatisfied symbol "_copysignf" in file test-copysignf.o 1 error. gmake[4]: *** [test-copysignf] Error 1 This patch fixes it. 2020-02-10 Bruno Haible copysignf: Fix link error on HP-UX with cc. * m4/copysignf.m4 (gl_FUNC_COPYSIGNF): Require AC_CANONICAL_HOST. On HP-UX, set COPYSIGNF_LIBM to -lm. diff --git a/m4/copysignf.m4 b/m4/copysignf.m4 index c6dea3e..284eb74 100644 --- a/m4/copysignf.m4 +++ b/m4/copysignf.m4 @@ -1,4 +1,4 @@ -# copysignf.m4 serial 3 +# copysignf.m4 serial 4 dnl Copyright (C) 2011-2020 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -7,6 +7,7 @@ dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([gl_FUNC_COPYSIGNF], [ AC_REQUIRE([gl_MATH_H_DEFAULTS]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl Persuade glibc to declare copysignf(). AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) @@ -28,7 +29,12 @@ AC_DEFUN([gl_FUNC_COPYSIGNF], else HAVE_COPYSIGNF=0 HAVE_DECL_COPYSIGNF=0 -COPYSIGNF_LIBM= +dnl On HP-UX 11.31/ia64, cc has a built-in for copysignf that redirects +dnl to the symbol '_copysignf', defined in libm, not libc. +case "$host_os" in + hpux*) COPYSIGNF_LIBM='-lm' ;; + *) COPYSIGNF_LIBM= ;; +esac fi AC_SUBST([COPYSIGNF_LIBM]) ])