This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "uClibc-ng - small C library for embedded systems".
The branch, 1.0 has been updated
via 55532a6ae663cc0f20bdf62d6c5d06db766b55f3 (commit)
from fad6c6021feb6c2dd4a3bd5de1113994d4a9b04e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 55532a6ae663cc0f20bdf62d6c5d06db766b55f3
Author: Waldemar Brodkorb <wbx(a)openadk.org>
Date: Sat Jan 9 09:09:51 2016 +0100
fix compile with DODEBUG=y
Since more projects using two-stage cross-compile process we
cannot add libgcc_eh.a unconditionally. We must check if
a real file is referenced by the cross-compiler.
Toolchains with --disabel-shared build have a single
libgcc.a containing all required symbols.
Tested with a debug build for x86.
-----------------------------------------------------------------------
Summary of changes:
Rules.mak | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Rules.mak b/Rules.mak
index 38b4cc2..ab88471 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -783,8 +783,11 @@ $(eval $(call cache-output-var,LIBGCC_A,$(CC) $(LIBGCC_CFLAGS) -print-libgcc-fil
$(eval $(call cache-output-var,LIBGCC_EH,$(CC) $(LIBGCC_CFLAGS) -print-file-name=libgcc_eh.a))
# with -O0 we (e.g. lockf) might end up with references to
# _Unwind_Resume, so pull in gcc_eh in this case..
+# with a --disable-shared toolchain, libgcc_eh.a and libgcc.a are combined
+# in libgcc.a, so check if the printed file exist, before adding to the commandline
+LIBGCC_EH_FILE := $(shell if [ -f $(LIBGCC_EH) ]; then echo $(LIBGCC_EH); fi)
LIBGCC_DIR := $(dir $(LIBGCC_A))
-LIBGCC := $(LIBGCC_A) $(if $(DODEBUG),$(LIBGCC_EH))
+LIBGCC := $(LIBGCC_A) $(if $(DODEBUG),$(LIBGCC_EH_FILE))
# moved from libpthread/linuxthreads
ifeq ($(UCLIBC_CTOR_DTOR),y)
hooks/post-receive
--
uClibc-ng - small C library for embedded systems
Commit e3c3bf2b58 introduce use of pselect6, but has following disadvantages:
* Use of userspace types in args67 structure - it breaks, for example,
configs when 32-bit uClibc-ng compiled against 64-bit kernel. Syscall
will always return EINVAL. We must use __kernel_* types and
__SYSCALL_SIGSET_T_SIZE.
* It have excess checks for NSEC_PER_SEC. Original code from select()
implementation has struct timeval => struct timespec conversion,
kernel select() syscall implementation do the same.
But none of libc versions (glibc, eglibc, musl) I know, perform similar
checks for pselect() - there is no structure fields conversions,
just struct timespec through all the calls.
To have such checks in uClibc-ng we need one example, at least.
* It is possible to avoid extra userspace reads from kernel code if
sigmask == NULL. I suggest to do it, for a few bytes cost.
* Commit didn't add test case to testsuite.
Signed-off-by: Leonid Lisovskiy <lly.dev(a)gmail.com>
---
libc/sysdeps/linux/common/pselect.c | 67 ++++++++++++-------------------------
test/unistd/tst-pselect.c | 51 ++++++++++++++++++++++++++++
2 files changed, 73 insertions(+), 45 deletions(-)
create mode 100644 test/unistd/tst-pselect.c
diff --git a/libc/sysdeps/linux/common/pselect.c b/libc/sysdeps/linux/common/pselect.c
index 3f1dd28..fbe85b7 100644
--- a/libc/sysdeps/linux/common/pselect.c
+++ b/libc/sysdeps/linux/common/pselect.c
@@ -31,55 +31,32 @@ static int __NC(pselect)(int nfds, fd_set *readfds, fd_set *writefds,
const sigset_t *sigmask)
{
#ifdef __NR_pselect6
-#define NSEC_PER_SEC 1000000000L
- struct timespec _ts, *ts = 0;
- if (timeout) {
- /* The Linux kernel can in some situations update the timeout value.
- * We do not want that so use a local variable.
- */
+ /* The Linux kernel can in some situations update the timeout value.
+ * We do not want that so use a local variable.
+ */
+ struct timespec _ts;
+
+ if (timeout != NULL) {
_ts = *timeout;
+ timeout = &_ts;
+ }
+ /* Note: the system call expects 7 values but on most architectures
+ we can only pass in 6 directly. If there is an architecture with
+ support for more parameters a new version of this file needs to
+ be created. */
+ struct {
+ __kernel_ulong_t ss;
+ __kernel_size_t ss_len;
+ } data;
- /* GNU extension: allow for timespec values where the sub-sec
- * field is equal to or more than 1 second. The kernel will
- * reject this on us, so take care of the time shift ourself.
- * Some applications (like readline and linphone) do this.
- * See 'clarification on select() type calls and invalid timeouts'
- * on the POSIX general list for more information.
- */
- if (_ts.tv_nsec >= NSEC_PER_SEC) {
- _ts.tv_sec += _ts.tv_nsec / NSEC_PER_SEC;
- _ts.tv_nsec %= NSEC_PER_SEC;
- }
-
- ts = &_ts;
+ if (sigmask != NULL) {
+ data.ss = (__kernel_ulong_t) sigmask;
+ data.ss_len = __SYSCALL_SIGSET_T_SIZE;
+
+ sigmask = (void *)&data;
}
- /* The pselect6 syscall API is strange. It wants a 7th arg to be
- * the sizeof(*sigmask). However syscalls with > 6 arguments aren't
- * supported on linux. So arguments 6 and 7 are stuffed in a struct
- * and a pointer to that struct is passed as the 6th argument to
- * the syscall.
- * Glibc stuffs arguments 6 and 7 in a ulong[2]. Linux reads
- * them as if there were a struct { sigset_t*; size_t } in
- * userspace. There woudl be trouble if userspace and the kernel are
- * compiled differently enough that size_t isn't the same as ulong,
- * but not enough to trigger the compat layer in linux. I can't
- * think of such a case, so I'm using linux's struct.
- * Furthermore Glibc sets the sigsetsize to _NSIG/8. However linux
- * checks for sizeof(sigset_t), which internally is a ulong array.
- * This means that if _NSIG isn't a multiple of BITS_PER_LONG then
- * linux will refuse glibc's value. So I prefer sizeof(sigset_t) for
- * the value of sigsetsize.
- */
- struct {
- const sigset_t *sigmask;
- size_t sigsetsize;
- } args67 = {
- sigmask,
- sizeof(sigset_t),
- };
-
- return INLINE_SYSCALL(pselect6, 6, nfds, readfds, writefds, exceptfds, ts, &args67);
+ return INLINE_SYSCALL(pselect6, 6, nfds, readfds, writefds, exceptfds, timeout, sigmask);
#else
struct timeval tval;
int retval;
diff --git a/test/unistd/tst-pselect.c b/test/unistd/tst-pselect.c
new file mode 100644
index 0000000..cab9451
--- /dev/null
+++ b/test/unistd/tst-pselect.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/select.h>
+
+// our SIGALRM handler
+void handler(int signum) {
+ (void)signum;
+ puts("got signal\n");
+}
+
+static int
+do_test (void)
+{
+ int rc;
+ sigset_t wait_mask, mask_sigchld;
+ struct sigaction act;
+
+ // block SIGALRM. We want to handle it only when we're ready
+ sigemptyset(&mask_sigchld);
+ sigaddset(&mask_sigchld, SIGALRM);
+ sigprocmask(SIG_BLOCK, &mask_sigchld, &wait_mask);
+ sigdelset(&wait_mask, SIGALRM);
+
+ // register a signal handler so we can see when the signal arrives
+ memset(&act, 0, sizeof(act));
+ sigemptyset(&act.sa_mask); // just in case an empty set isn't all 0's (total paranoia)
+ act.sa_handler = handler;
+ sigaction(SIGALRM, &act, NULL);
+
+ // send ourselves a SIGARLM. It will pend until we unblock that signal in pselect()
+ printf("sending ourselves a signal\n");
+ kill(getpid(), SIGALRM);
+
+ printf("signal is pending; calling pselect()\n");
+ rc = pselect(0, NULL, NULL, NULL, NULL, &wait_mask);
+ if (rc != -1 || errno != EINTR) {
+ int e = errno;
+ printf("pselect() returned %d, errno %d (%s)\n", rc, e, strerror(e));
+ exit(1);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include <test-skeleton.c>
--
1.8.5.6
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "uClibc-ng - small C library for embedded systems".
The branch, master has been updated
via 4aed5269c44032e8ddbeb176d661350542fc05ab (commit)
from c8b14823b5325da8b51b49a121fadb7a54dbb5c9 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 4aed5269c44032e8ddbeb176d661350542fc05ab
Author: Waldemar Brodkorb <wbx(a)uclibc-ng.org>
Date: Thu Jan 7 23:03:52 2016 +0100
linuxthreads: Implement pthread_tryjoin_np(), pthread_timedjoin_np()
Some applications needs it.
Adapted to master.
Signed-off-by: Leonid Lisovskiy <lly.dev(a)gmail.com>
Signed-off-by: Waldemar Brodkorb <wbx(a)uclibc-ng.org>
-----------------------------------------------------------------------
Summary of changes:
libpthread/linuxthreads/join.c | 138 +++++++++++++++++++++
libpthread/linuxthreads/sysdeps/pthread/pthread.h | 15 +++
test/{nptl => pthread}/tst-join2.c | 5 +-
test/{nptl => pthread}/tst-join3.c | 5 +-
4 files changed, 159 insertions(+), 4 deletions(-)
copy test/{nptl => pthread}/tst-join2.c (93%)
copy test/{nptl => pthread}/tst-join3.c (94%)
diff --git a/libpthread/linuxthreads/join.c b/libpthread/linuxthreads/join.c
index 4a7c0d8..c7e5479 100644
--- a/libpthread/linuxthreads/join.c
+++ b/libpthread/linuxthreads/join.c
@@ -192,6 +192,144 @@ int pthread_join(pthread_t thread_id, void ** thread_return)
return 0;
}
+int pthread_tryjoin_np(pthread_t thread_id, void ** thread_return)
+{
+ volatile pthread_descr self = thread_self();
+ struct pthread_request request;
+ pthread_handle handle = thread_handle(thread_id);
+ pthread_descr th;
+ int result = 0;
+
+ /* Make sure the descriptor is valid. */
+ __pthread_lock(&handle->h_lock, self);
+ if (invalid_handle(handle, thread_id)) {
+ result = ESRCH;
+ goto err;
+ }
+ th = handle->h_descr;
+ /* Is the thread joinable?. */
+ if (th->p_detached || th->p_joining != NULL) {
+ result = EINVAL;
+ goto err;
+ }
+ if (th == self) {
+ result = EDEADLK;
+ goto err;
+ }
+ /* Return right away if the thread hasn't terminated yet. */
+ if (! th->p_terminated) {
+ result = EBUSY;
+ goto err;
+ }
+
+ /* Get return value */
+ if (thread_return != NULL) *thread_return = th->p_retval;
+ __pthread_unlock(&handle->h_lock);
+ /* Send notification to thread manager */
+ if (__pthread_manager_request >= 0) {
+ request.req_thread = self;
+ request.req_kind = REQ_FREE;
+ request.req_args.free.thread_id = thread_id;
+ TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
+ (char *) &request, sizeof(request)));
+ }
+ return 0;
+
+err:
+ __pthread_unlock(&handle->h_lock);
+ return result;
+}
+
+int pthread_timedjoin_np(pthread_t thread_id, void ** thread_return,
+ const struct timespec *abstime)
+{
+ volatile pthread_descr self = thread_self();
+ struct pthread_request request;
+ pthread_handle handle = thread_handle(thread_id);
+ pthread_descr th;
+ pthread_extricate_if extr;
+ int already_canceled = 0;
+ int result = 0;
+ PDEBUG("\n");
+
+ /* Set up extrication interface */
+ extr.pu_object = handle;
+ extr.pu_extricate_func = join_extricate_func;
+
+ __pthread_lock(&handle->h_lock, self);
+ if (invalid_handle(handle, thread_id)) {
+ result = ESRCH;
+ goto err;
+ }
+ th = handle->h_descr;
+ if (th == self) {
+ result = EDEADLK;
+ goto err;
+ }
+ /* If detached or already joined, error */
+ if (th->p_detached || th->p_joining != NULL) {
+ result = EINVAL;
+ goto err;
+ }
+ /* If not terminated yet, suspend ourselves. */
+ if (! th->p_terminated) {
+ /* Register extrication interface */
+ __pthread_set_own_extricate_if(self, &extr);
+ if (!(THREAD_GETMEM(self, p_canceled)
+ && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
+ th->p_joining = self;
+ else
+ already_canceled = 1;
+ __pthread_unlock(&handle->h_lock);
+
+ if (already_canceled) {
+ __pthread_set_own_extricate_if(self, 0);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+ }
+
+ PDEBUG("before suspend\n");
+ result = (timedsuspend(self, abstime) == 0) ? ETIMEDOUT : 0;
+ PDEBUG("after suspend\n");
+ /* Deregister extrication interface */
+ __pthread_set_own_extricate_if(self, 0);
+
+ /* This is a cancellation point */
+ if (result == 0
+ && THREAD_GETMEM(self, p_woken_by_cancel)
+ && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+ THREAD_SETMEM(self, p_woken_by_cancel, 0);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+ }
+ __pthread_lock(&handle->h_lock, self);
+ }
+
+ /* We might have timed out. */
+ if (result == 0) {
+ /* Get return value */
+ if (thread_return != NULL) *thread_return = th->p_retval;
+ }
+ else
+ th->p_joining = NULL;
+
+ __pthread_unlock(&handle->h_lock);
+
+ if (result == 0) {
+ /* Send notification to thread manager */
+ if (__pthread_manager_request >= 0) {
+ request.req_thread = self;
+ request.req_kind = REQ_FREE;
+ request.req_args.free.thread_id = thread_id;
+ TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
+ (char *) &request, sizeof(request)));
+ }
+ }
+ return result;
+
+err:
+ __pthread_unlock(&handle->h_lock);
+ return result;
+}
+
int pthread_detach(pthread_t thread_id)
{
int terminated;
diff --git a/libpthread/linuxthreads/sysdeps/pthread/pthread.h b/libpthread/linuxthreads/sysdeps/pthread/pthread.h
index 879bcea..3c7044d 100644
--- a/libpthread/linuxthreads/sysdeps/pthread/pthread.h
+++ b/libpthread/linuxthreads/sysdeps/pthread/pthread.h
@@ -179,6 +179,21 @@ extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__));
is not NULL. */
extern int pthread_join (pthread_t __th, void **__thread_return);
+#ifdef __USE_GNU
+/* Check whether thread TH has terminated. If yes return the status of
+ the thread in *THREAD_RETURN, if THREAD_RETURN is not NULL. */
+extern int pthread_tryjoin_np (pthread_t __th, void **__thread_return) __THROW;
+
+/* Make calling thread wait for termination of the thread TH, but only
+ until TIMEOUT. The exit status of the thread is stored in
+ *THREAD_RETURN, if THREAD_RETURN is not NULL.
+
+ This function is a cancellation point and therefore not marked with
+ __THROW. */
+extern int pthread_timedjoin_np (pthread_t __th, void **__thread_return,
+ __const struct timespec *__abstime);
+#endif
+
/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN.
The resources of TH will therefore be freed immediately when it
terminates, instead of waiting for another thread to perform PTHREAD_JOIN
diff --git a/test/nptl/tst-join2.c b/test/pthread/tst-join2.c
similarity index 93%
copy from test/nptl/tst-join2.c
copy to test/pthread/tst-join2.c
index 0320398..2cfab8b 100644
--- a/test/nptl/tst-join2.c
+++ b/test/pthread/tst-join2.c
@@ -13,8 +13,9 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
#include <errno.h>
#include <pthread.h>
diff --git a/test/nptl/tst-join3.c b/test/pthread/tst-join3.c
similarity index 94%
copy from test/nptl/tst-join3.c
copy to test/pthread/tst-join3.c
index b25ffd8..df1135f 100644
--- a/test/nptl/tst-join3.c
+++ b/test/pthread/tst-join3.c
@@ -13,8 +13,9 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
#include <errno.h>
#include <pthread.h>
hooks/post-receive
--
uClibc-ng - small C library for embedded systems