Stub sleep in glibc (XCC)
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 19 Nov 2013 00:25:08 +0000 (16:25 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 16 Jan 2014 19:46:33 +0000 (11:46 -0800)
Some plan9 programs are calling sleep, and that links to some old
half-built POSIX sleep in glibc that ends up just busy waiting.

We don't support the regular sleep() directly; specifically, we don't
inrerupt sleep on signal delivery.  2LSs could build this if they want,
though signals are sent to processes, not to threads.  In that sense,
sleep is a bit wrong for what we want to do.

If you want to just put a uthread to sleep for a certain amount of time,
you can call uthread_sleep().  Its dumb and just uses the debugging
sys_block to wait in the kernel (we could do it in userspace, for
instance, with an alarm system).

Anyway, I mostly wanted to see stub warnings when compiling something
that calls sleep(), since that is a sign that the program will have
issues with signal handling / porting.

You need to copy over the sleep file into glibc-2.14.1/ and rebuild, or
do a make clean and rebuild your cross compiler.

tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/sleep.c [new file with mode: 0644]
user/parlib/include/uthread.h
user/parlib/uthread.c

diff --git a/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/sleep.c b/tools/compilers/gcc-glibc/glibc-2.14.1-ros/sysdeps/ros/sleep.c
new file mode 100644 (file)
index 0000000..f9d2a65
--- /dev/null
@@ -0,0 +1,41 @@
+/* Copyright (C) 1991, 1992, 1995, 1996, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   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, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <signal.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* Make the process sleep for SECONDS seconds, or until a signal arrives
+   and is not ignored.  The function returns the number of seconds less
+   than SECONDS which it actually slept (zero if it slept the full time).
+   If a signal handler does a `longjmp' or modifies the handling of the
+   SIGALRM signal while inside `sleep' call, the handling of the SIGALRM
+   signal afterwards is undefined.  There is no return value to indicate
+   error, but if `sleep' returns SECONDS, it probably didn't work.  */
+unsigned int
+__sleep (seconds)
+     unsigned int seconds;
+{
+  __set_errno (ENOSYS);
+  return seconds;
+}
+weak_alias (__sleep, sleep)
+
+stub_warning (sleep)
+#include <stub-tag.h>
index cdd2fbc..639090a 100644 (file)
@@ -71,6 +71,7 @@ void uthread_cleanup(struct uthread *uthread);
 void uthread_runnable(struct uthread *uthread);
 void uthread_yield(bool save_state, void (*yield_func)(struct uthread*, void*),
                    void *yield_arg);
+void uthread_sleep(unsigned int seconds);
 
 /* Utility functions */
 bool __check_preempt_pending(uint32_t vcoreid);        /* careful: check the code */
index 81e6b26..c3b85de 100644 (file)
@@ -364,6 +364,15 @@ yield_return_path:
        printd("[U] Uthread %08p returning from a yield!\n", uthread);
 }
 
+/* We explicitly don't support sleep(), since old callers of it have
+ * expectations of being woken up by signal handlers.  If we need that, we can
+ * build it in to sleep() later.  If you just want to sleep for a while, call
+ * this helper. */
+void uthread_sleep(unsigned int seconds)
+{
+       sys_block(seconds * 1000000);   /* usec sleep */
+}
+
 /* Cleans up the uthread (the stuff we did in uthread_init()).  If you want to
  * destroy a currently running uthread, you'll want something like
  * pthread_exit(), which yields, and calls this from its sched_ops yield. */