summaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r--arch/um/os-Linux/Makefile8
-rw-r--r--arch/um/os-Linux/drivers/etap.h2
-rw-r--r--arch/um/os-Linux/drivers/ethertap_kern.c2
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap.h2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_kern.c2
-rw-r--r--arch/um/os-Linux/drivers/tuntap_user.c2
-rw-r--r--arch/um/os-Linux/file.c143
-rw-r--r--arch/um/os-Linux/helper.c22
-rw-r--r--arch/um/os-Linux/irq.c18
-rw-r--r--arch/um/os-Linux/main.c34
-rw-r--r--arch/um/os-Linux/mem.c33
-rw-r--r--arch/um/os-Linux/process.c40
-rw-r--r--arch/um/os-Linux/sigio.c128
-rw-r--r--arch/um/os-Linux/signal.c61
-rw-r--r--arch/um/os-Linux/skas/process.c104
-rw-r--r--arch/um/os-Linux/start_up.c1
-rw-r--r--arch/um/os-Linux/sys-i386/Makefile2
-rw-r--r--arch/um/os-Linux/sys-i386/registers.c17
-rw-r--r--arch/um/os-Linux/sys-i386/signal.c15
-rw-r--r--arch/um/os-Linux/sys-x86_64/Makefile2
-rw-r--r--arch/um/os-Linux/sys-x86_64/registers.c17
-rw-r--r--arch/um/os-Linux/sys-x86_64/signal.c16
-rw-r--r--arch/um/os-Linux/time.c45
-rw-r--r--arch/um/os-Linux/trap.c1
-rw-r--r--arch/um/os-Linux/uaccess.c6
-rw-r--r--arch/um/os-Linux/umid.c97
-rw-r--r--arch/um/os-Linux/util.c5
28 files changed, 438 insertions, 389 deletions
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index f4bfc4c7ccac..b4183929b32c 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -4,15 +4,19 @@
#
obj-y = aio.o elf_aux.o file.o helper.o irq.o main.o mem.o process.o sigio.o \
- signal.o start_up.o time.o trap.o tt.o tty.o uaccess.o umid.o tls.o \
+ signal.o start_up.o time.o trap.o tty.o uaccess.o umid.o tls.o \
user_syms.o util.o drivers/ sys-$(SUBARCH)/
obj-$(CONFIG_MODE_SKAS) += skas/
+
+obj-$(CONFIG_MODE_TT) += tt.o
+user-objs-$(CONFIG_MODE_TT) += tt.o
+
obj-$(CONFIG_TTY_LOG) += tty_log.o
user-objs-$(CONFIG_TTY_LOG) += tty_log.o
USER_OBJS := $(user-objs-y) aio.o elf_aux.o file.o helper.o irq.o main.o mem.o \
- process.o sigio.o signal.o start_up.o time.o trap.o tt.o tty.o tls.o \
+ process.o sigio.o signal.o start_up.o time.o trap.o tty.o tls.o \
uaccess.o umid.o util.o
CFLAGS_user_syms.o += -DSUBARCH_$(SUBARCH)
diff --git a/arch/um/os-Linux/drivers/etap.h b/arch/um/os-Linux/drivers/etap.h
index b84f6c4740f7..57ecdaf2f67e 100644
--- a/arch/um/os-Linux/drivers/etap.h
+++ b/arch/um/os-Linux/drivers/etap.h
@@ -13,7 +13,7 @@ struct ethertap_data {
void *dev;
};
-extern struct net_user_info ethertap_user_info;
+extern const struct net_user_info ethertap_user_info;
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
diff --git a/arch/um/os-Linux/drivers/ethertap_kern.c b/arch/um/os-Linux/drivers/ethertap_kern.c
index 768606bec233..16385e2ada85 100644
--- a/arch/um/os-Linux/drivers/ethertap_kern.c
+++ b/arch/um/os-Linux/drivers/ethertap_kern.c
@@ -65,7 +65,7 @@ static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp)
return(net_send(fd, (*skb)->data, (*skb)->len));
}
-struct net_kern_info ethertap_kern_info = {
+const struct net_kern_info ethertap_kern_info = {
.init = etap_init,
.protocol = eth_protocol,
.read = etap_read,
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 8f49507e64ef..f559bdf746e6 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -216,7 +216,7 @@ static void etap_del_addr(unsigned char *addr, unsigned char *netmask,
etap_close_addr(addr, netmask, &pri->control_fd);
}
-struct net_user_info ethertap_user_info = {
+const struct net_user_info ethertap_user_info = {
.init = etap_user_init,
.open = etap_open,
.close = etap_close,
diff --git a/arch/um/os-Linux/drivers/tuntap.h b/arch/um/os-Linux/drivers/tuntap.h
index 25d4a2868814..d3e8d3af6245 100644
--- a/arch/um/os-Linux/drivers/tuntap.h
+++ b/arch/um/os-Linux/drivers/tuntap.h
@@ -16,7 +16,7 @@ struct tuntap_data {
void *dev;
};
-extern struct net_user_info tuntap_user_info;
+extern const struct net_user_info tuntap_user_info;
#endif
diff --git a/arch/um/os-Linux/drivers/tuntap_kern.c b/arch/um/os-Linux/drivers/tuntap_kern.c
index 190009a6f89c..0edbac63c527 100644
--- a/arch/um/os-Linux/drivers/tuntap_kern.c
+++ b/arch/um/os-Linux/drivers/tuntap_kern.c
@@ -53,7 +53,7 @@ static int tuntap_write(int fd, struct sk_buff **skb,
return(net_write(fd, (*skb)->data, (*skb)->len));
}
-struct net_kern_info tuntap_kern_info = {
+const struct net_kern_info tuntap_kern_info = {
.init = tuntap_init,
.protocol = eth_protocol,
.read = tuntap_read,
diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c
index 87c3aa0252db..e846b23f7558 100644
--- a/arch/um/os-Linux/drivers/tuntap_user.c
+++ b/arch/um/os-Linux/drivers/tuntap_user.c
@@ -205,7 +205,7 @@ static int tuntap_set_mtu(int mtu, void *data)
return(mtu);
}
-struct net_user_info tuntap_user_info = {
+const struct net_user_info tuntap_user_info = {
.init = tuntap_user_init,
.open = tuntap_open,
.close = tuntap_close,
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 09251338d99e..189fa677085a 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
@@ -18,6 +18,7 @@
#include "os.h"
#include "user.h"
#include "kern_util.h"
+#include "user_util.h"
static void copy_stat(struct uml_stat *dst, struct stat64 *src)
{
@@ -42,16 +43,13 @@ int os_stat_fd(const int fd, struct uml_stat *ubuf)
struct stat64 sbuf;
int err;
- do {
- err = fstat64(fd, &sbuf);
- } while((err < 0) && (errno == EINTR)) ;
-
+ CATCH_EINTR(err = fstat64(fd, &sbuf));
if(err < 0)
- return(-errno);
+ return -errno;
if(ubuf != NULL)
copy_stat(ubuf, &sbuf);
- return(err);
+ return err;
}
int os_stat_file(const char *file_name, struct uml_stat *ubuf)
@@ -64,11 +62,11 @@ int os_stat_file(const char *file_name, struct uml_stat *ubuf)
} while((err < 0) && (errno == EINTR)) ;
if(err < 0)
- return(-errno);
+ return -errno;
if(ubuf != NULL)
copy_stat(ubuf, &sbuf);
- return(err);
+ return err;
}
int os_access(const char* file, int mode)
@@ -80,9 +78,9 @@ int os_access(const char* file, int mode)
err = access(file, amode);
if(err < 0)
- return(-errno);
+ return -errno;
- return(0);
+ return 0;
}
void os_print_error(int error, const char* str)
@@ -99,9 +97,9 @@ int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg)
err = ioctl(fd, cmd, arg);
if(err < 0)
- return(-errno);
+ return -errno;
- return(err);
+ return err;
}
int os_window_size(int fd, int *rows, int *cols)
@@ -109,12 +107,12 @@ int os_window_size(int fd, int *rows, int *cols)
struct winsize size;
if(ioctl(fd, TIOCGWINSZ, &size) < 0)
- return(-errno);
+ return -errno;
*rows = size.ws_row;
*cols = size.ws_col;
- return(0);
+ return 0;
}
int os_new_tty_pgrp(int fd, int pid)
@@ -125,16 +123,16 @@ int os_new_tty_pgrp(int fd, int pid)
if(tcsetpgrp(fd, pid) < 0)
return -errno;
- return(0);
+ return 0;
}
/* FIXME: ensure namebuf in os_get_if_name is big enough */
int os_get_ifname(int fd, char* namebuf)
{
if(ioctl(fd, SIOCGIFNAME, namebuf) < 0)
- return(-errno);
+ return -errno;
- return(0);
+ return 0;
}
int os_set_slip(int fd)
@@ -149,7 +147,7 @@ int os_set_slip(int fd)
if(ioctl(fd, SIOCSIFENCAP, &sencap) < 0)
return -errno;
- return(0);
+ return 0;
}
int os_set_owner(int fd, int pid)
@@ -158,10 +156,10 @@ int os_set_owner(int fd, int pid)
int save_errno = errno;
if(fcntl(fd, F_GETOWN, 0) != pid)
- return(-save_errno);
+ return -save_errno;
}
- return(0);
+ return 0;
}
/* FIXME? moved wholesale from sigio_user.c to get fcntls out of that file */
@@ -192,9 +190,9 @@ int os_mode_fd(int fd, int mode)
} while((err < 0) && (errno==EINTR)) ;
if(err < 0)
- return(-errno);
+ return -errno;
- return(0);
+ return 0;
}
int os_file_type(char *file)
@@ -204,15 +202,21 @@ int os_file_type(char *file)
err = os_stat_file(file, &buf);
if(err < 0)
- return(err);
+ return err;
- if(S_ISDIR(buf.ust_mode)) return(OS_TYPE_DIR);
- else if(S_ISLNK(buf.ust_mode)) return(OS_TYPE_SYMLINK);
- else if(S_ISCHR(buf.ust_mode)) return(OS_TYPE_CHARDEV);
- else if(S_ISBLK(buf.ust_mode)) return(OS_TYPE_BLOCKDEV);
- else if(S_ISFIFO(buf.ust_mode)) return(OS_TYPE_FIFO);
- else if(S_ISSOCK(buf.ust_mode)) return(OS_TYPE_SOCK);
- else return(OS_TYPE_FILE);
+ if(S_ISDIR(buf.ust_mode))
+ return OS_TYPE_DIR;
+ else if(S_ISLNK(buf.ust_mode))
+ return OS_TYPE_SYMLINK;
+ else if(S_ISCHR(buf.ust_mode))
+ return OS_TYPE_CHARDEV;
+ else if(S_ISBLK(buf.ust_mode))
+ return OS_TYPE_BLOCKDEV;
+ else if(S_ISFIFO(buf.ust_mode))
+ return OS_TYPE_FIFO;
+ else if(S_ISSOCK(buf.ust_mode))
+ return OS_TYPE_SOCK;
+ else return OS_TYPE_FILE;
}
int os_file_mode(char *file, struct openflags *mode_out)
@@ -302,8 +306,8 @@ int os_seek_file(int fd, __u64 offset)
actual = lseek64(fd, offset, SEEK_SET);
if(actual != offset)
- return(-errno);
- return(0);
+ return -errno;
+ return 0;
}
static int fault_buffer(void *start, int len,
@@ -314,13 +318,13 @@ static int fault_buffer(void *start, int len,
for(i = 0; i < len; i += page){
if((*copy_proc)(start + i, &c, sizeof(c)))
- return(-EFAULT);
+ return -EFAULT;
}
if((len % page) != 0){
if((*copy_proc)(start + len - 1, &c, sizeof(c)))
- return(-EFAULT);
+ return -EFAULT;
}
- return(0);
+ return 0;
}
static int file_io(int fd, void *buf, int len,
@@ -334,26 +338,26 @@ static int file_io(int fd, void *buf, int len,
if((n < 0) && (errno == EFAULT)){
err = fault_buffer(buf, len, copy_user_proc);
if(err)
- return(err);
+ return err;
n = (*io_proc)(fd, buf, len);
}
} while((n < 0) && (errno == EINTR));
if(n < 0)
- return(-errno);
- return(n);
+ return -errno;
+ return n;
}
int os_read_file(int fd, void *buf, int len)
{
- return(file_io(fd, buf, len, (int (*)(int, void *, int)) read,
- copy_from_user_proc));
+ return file_io(fd, buf, len, (int (*)(int, void *, int)) read,
+ copy_from_user_proc);
}
int os_write_file(int fd, const void *buf, int len)
{
- return(file_io(fd, (void *) buf, len,
- (int (*)(int, void *, int)) write, copy_to_user_proc));
+ return file_io(fd, (void *) buf, len,
+ (int (*)(int, void *, int)) write, copy_to_user_proc);
}
int os_file_size(char *file, unsigned long long *size_out)
@@ -398,11 +402,11 @@ int os_file_modtime(char *file, unsigned long *modtime)
err = os_stat_file(file, &buf);
if(err < 0){
printk("Couldn't stat \"%s\" : err = %d\n", file, -err);
- return(err);
+ return err;
}
*modtime = buf.ust_mtime;
- return(0);
+ return 0;
}
int os_get_exec_close(int fd, int* close_on_exec)
@@ -455,7 +459,7 @@ int os_pipe(int *fds, int stream, int close_on_exec)
if(err < 0)
goto error;
- return(0);
+ return 0;
error:
printk("os_pipe : Setting FD_CLOEXEC failed, err = %d\n", -err);
@@ -486,12 +490,12 @@ int os_set_fd_async(int fd, int owner)
(fcntl(fd, F_SETOWN, owner) < 0)){
err = -errno;
printk("os_set_fd_async : Failed to fcntl F_SETOWN "
- "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
+ "(or F_SETSIG) fd %d to pid %d, errno = %d\n", fd,
owner, errno);
return err;
}
- return(0);
+ return 0;
}
int os_clear_fd_async(int fd)
@@ -500,8 +504,8 @@ int os_clear_fd_async(int fd)
flags &= ~(O_ASYNC | O_NONBLOCK);
if(fcntl(fd, F_SETFL, flags) < 0)
- return(-errno);
- return(0);
+ return -errno;
+ return 0;
}
int os_set_fd_block(int fd, int blocking)
@@ -516,7 +520,7 @@ int os_set_fd_block(int fd, int blocking)
if(fcntl(fd, F_SETFL, flags) < 0)
return -errno;
- return(0);
+ return 0;
}
int os_accept_connection(int fd)
@@ -524,9 +528,9 @@ int os_accept_connection(int fd)
int new;
new = accept(fd, NULL, 0);
- if(new < 0)
- return(-errno);
- return(new);
+ if(new < 0)
+ return -errno;
+ return new;
}
#ifndef SHUT_RD
@@ -550,12 +554,12 @@ int os_shutdown_socket(int fd, int r, int w)
else if(w) what = SHUT_WR;
else {
printk("os_shutdown_socket : neither r or w was set\n");
- return(-EINVAL);
+ return -EINVAL;
}
err = shutdown(fd, what);
if(err < 0)
- return(-errno);
- return(0);
+ return -errno;
+ return 0;
}
int os_rcv_fd(int fd, int *helper_pid_out)
@@ -578,7 +582,7 @@ int os_rcv_fd(int fd, int *helper_pid_out)
n = recvmsg(fd, &msg, 0);
if(n < 0)
- return(-errno);
+ return -errno;
else if(n != sizeof(iov.iov_len))
*helper_pid_out = -1;
@@ -586,16 +590,16 @@ int os_rcv_fd(int fd, int *helper_pid_out)
cmsg = CMSG_FIRSTHDR(&msg);
if(cmsg == NULL){
printk("rcv_fd didn't receive anything, error = %d\n", errno);
- return(-1);
+ return -1;
}
- if((cmsg->cmsg_level != SOL_SOCKET) ||
+ if((cmsg->cmsg_level != SOL_SOCKET) ||
(cmsg->cmsg_type != SCM_RIGHTS)){
printk("rcv_fd didn't receive a descriptor\n");
- return(-1);
+ return -1;
}
new = ((int *) CMSG_DATA(cmsg))[0];
- return(new);
+ return new;
}
int os_create_unix_socket(char *file, int len, int close_on_exec)
@@ -623,7 +627,7 @@ int os_create_unix_socket(char *file, int len, int close_on_exec)
if(err < 0)
return -errno;
- return(sock);
+ return sock;
}
void os_flush_stdout(void)
@@ -654,16 +658,5 @@ int os_lock_file(int fd, int excl)
printk("F_SETLK failed, file already locked by pid %d\n", lock.l_pid);
err = save;
out:
- return(err);
+ return err;
}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 6987d1d247a2..cd15b9df5b5c 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -42,7 +42,7 @@ static int helper_child(void *arg)
if(data->pre_exec != NULL)
(*data->pre_exec)(data->pre_data);
execvp(argv[0], argv);
- errval = errno;
+ errval = -errno;
printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno);
os_write_file(data->fd, &errval, sizeof(errval));
kill(os_getpid(), SIGKILL);
@@ -62,7 +62,7 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
stack = *stack_out;
else stack = alloc_stack(0, __cant_sleep());
if(stack == 0)
- return(-ENOMEM);
+ return -ENOMEM;
ret = os_pipe(fds, 1, 0);
if(ret < 0){
@@ -95,16 +95,16 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
/* Read the errno value from the child, if the exec failed, or get 0 if
* the exec succeeded because the pipe fd was set as close-on-exec. */
n = os_read_file(fds[0], &ret, sizeof(ret));
- if (n < 0) {
- printk("run_helper : read on pipe failed, ret = %d\n", -n);
- ret = n;
- kill(pid, SIGKILL);
- CATCH_EINTR(waitpid(pid, NULL, 0));
- } else if(n != 0){
- CATCH_EINTR(n = waitpid(pid, NULL, 0));
- ret = -errno;
- } else {
+ if(n == 0)
ret = pid;
+ else {
+ if(n < 0){
+ printk("run_helper : read on pipe failed, ret = %d\n",
+ -n);
+ ret = n;
+ kill(pid, SIGKILL);
+ }
+ CATCH_EINTR(waitpid(pid, NULL, 0));
}
out_close:
diff --git a/arch/um/os-Linux/irq.c b/arch/um/os-Linux/irq.c
index 3788d4568d33..a97206df5b52 100644
--- a/arch/um/os-Linux/irq.c
+++ b/arch/um/os-Linux/irq.c
@@ -52,11 +52,6 @@ int os_waiting_for_events(struct irq_fd *active_fds)
return n;
}
-int os_isatty(int fd)
-{
- return isatty(fd);
-}
-
int os_create_pollfd(int fd, int events, void *tmp_pfd, int size_tmpfds)
{
if (pollfds_num == pollfds_size) {
@@ -137,22 +132,19 @@ void os_set_pollfd(int i, int fd)
void os_set_ioignore(void)
{
- set_handler(SIGIO, SIG_IGN, 0, -1);
+ signal(SIGIO, SIG_IGN);
}
void init_irq_signals(int on_sigstack)
{
- __sighandler_t h;
int flags;
flags = on_sigstack ? SA_ONSTACK : 0;
- if (timer_irq_inited)
- h = (__sighandler_t)alarm_handler;
- else
- h = boot_timer_handler;
- set_handler(SIGVTALRM, h, flags | SA_RESTART,
- SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
+ set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
+ flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
+ set_handler(SIGALRM, (__sighandler_t) alarm_handler,
+ flags | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
signal(SIGWINCH, SIG_IGN);
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 90912aaca7aa..d1c5670787dc 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -67,13 +67,32 @@ static __init void do_uml_initcalls(void)
static void last_ditch_exit(int sig)
{
- signal(SIGINT, SIG_DFL);
- signal(SIGTERM, SIG_DFL);
- signal(SIGHUP, SIG_DFL);
uml_cleanup();
exit(1);
}
+static void install_fatal_handler(int sig)
+{
+ struct sigaction action;
+
+ /* All signals are enabled in this handler ... */
+ sigemptyset(&action.sa_mask);
+
+ /* ... including the signal being handled, plus we want the
+ * handler reset to the default behavior, so that if an exit
+ * handler is hanging for some reason, the UML will just die
+ * after this signal is sent a second time.
+ */
+ action.sa_flags = SA_RESETHAND | SA_NODEFER;
+ action.sa_restorer = NULL;
+ action.sa_handler = last_ditch_exit;
+ if(sigaction(sig, &action, NULL) < 0){
+ printf("failed to install handler for signal %d - errno = %d\n",
+ errno);
+ exit(1);
+ }
+}
+
#define UML_LIB_PATH ":/usr/lib/uml"
static void setup_env_path(void)
@@ -158,9 +177,12 @@ int main(int argc, char **argv, char **envp)
}
new_argv[argc] = NULL;
- set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
- set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
- set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1);
+ /* Allow these signals to bring down a UML if all other
+ * methods of control fail.
+ */
+ install_fatal_handler(SIGINT);
+ install_fatal_handler(SIGTERM);
+ install_fatal_handler(SIGHUP);
scan_elf_aux( envp);
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index c6432e729241..4203681e508d 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -55,7 +55,7 @@ static void __init find_tempdir(void)
*/
static int next(int fd, char *buf, int size, char c)
{
- int n;
+ int n, len;
char *ptr;
while((ptr = strchr(buf, c)) == NULL){
@@ -69,7 +69,17 @@ static int next(int fd, char *buf, int size, char c)
}
ptr++;
- memmove(buf, ptr, strlen(ptr) + 1);
+ len = strlen(ptr);
+ memmove(buf, ptr, len + 1);
+
+ /* Refill the buffer so that if there's a partial string that we care
+ * about, it will be completed, and we can recognize it.
+ */
+ n = read(fd, &buf[len], size - len - 1);
+ if(n < 0)
+ return -errno;
+
+ buf[len + n] = '\0';
return 1;
}
@@ -104,14 +114,14 @@ static void which_tmpdir(void)
}
while(1){
- found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+ found = next(fd, buf, ARRAY_SIZE(buf), ' ');
if(found != 1)
break;
if(!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
goto found;
- found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n');
+ found = next(fd, buf, ARRAY_SIZE(buf), '\n');
if(found != 1)
break;
}
@@ -122,20 +132,24 @@ err:
else if(found < 0)
printf("read returned errno %d\n", -found);
+out:
+ close(fd);
+
return;
found:
- found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+ found = next(fd, buf, ARRAY_SIZE(buf), ' ');
if(found != 1)
goto err;
if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
printf("not tmpfs\n");
- return;
+ goto out;
}
printf("OK\n");
default_tmpdir = "/dev/shm";
+ goto out;
}
/*
@@ -200,8 +214,11 @@ int create_tmp_file(unsigned long long len)
exit(1);
}
- if (lseek64(fd, len, SEEK_SET) < 0) {
- perror("os_seek_file");
+ /* Seek to len - 1 because writing a character there will
+ * increase the file size by one byte, to the desired length.
+ */
+ if (lseek64(fd, len - 1, SEEK_SET) < 0) {
+ perror("os_seek_file");
exit(1);
}
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 233be2f4f8cb..ff203625a4bd 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -7,7 +7,6 @@
#include <stdio.h>
#include <errno.h>
#include <signal.h>
-#include <setjmp.h>
#include <linux/unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
@@ -247,39 +246,48 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int))
set_sigstack(sig_stack, pages * page_size());
flags = SA_ONSTACK;
}
- if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
+ if(usr1_handler){
+ struct sigaction sa;
+
+ sa.sa_handler = usr1_handler;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = flags;
+ sa.sa_restorer = NULL;
+ if(sigaction(SIGUSR1, &sa, NULL) < 0)
+ panic("init_new_thread_stack - sigaction failed - "
+ "errno = %d\n", errno);
+ }
}
-void init_new_thread_signals(int altstack)
+void init_new_thread_signals(void)
{
- int flags = altstack ? SA_ONSTACK : 0;
-
- set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
+ set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags,
+ set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGFPE, (__sighandler_t) sig_handler, flags,
+ set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGILL, (__sighandler_t) sig_handler, flags,
+ set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
- set_handler(SIGBUS, (__sighandler_t) sig_handler, flags,
+ set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGUSR2, (__sighandler_t) sig_handler,
- flags, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
+ SA_ONSTACK, SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
+ -1);
signal(SIGHUP, SIG_IGN);
- init_irq_signals(altstack);
+ init_irq_signals(1);
}
int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
{
jmp_buf buf;
- int n, enable;
+ int n;
*jmp_ptr = &buf;
- n = UML_SETJMP(&buf, enable);
+ n = UML_SETJMP(&buf);
if(n != 0)
- return(n);
+ return n;
(*fn)(arg);
- return(0);
+ return 0;
}
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 00e9388e947a..f6457765b17d 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -43,17 +43,9 @@ struct pollfds {
/* Protected by sigio_lock(). Used by the sigio thread, but the UML thread
* synchronizes with it.
*/
-struct pollfds current_poll = {
- .poll = NULL,
- .size = 0,
- .used = 0
-};
-
-struct pollfds next_poll = {
- .poll = NULL,
- .size = 0,
- .used = 0
-};
+static struct pollfds current_poll;
+static struct pollfds next_poll;
+static struct pollfds all_sigio_fds;
static int write_sigio_thread(void *unused)
{
@@ -78,7 +70,8 @@ static int write_sigio_thread(void *unused)
n = os_read_file(sigio_private[1], &c, sizeof(c));
if(n != sizeof(c))
printk("write_sigio_thread : "
- "read failed, err = %d\n", -n);
+ "read on socket failed, "
+ "err = %d\n", -n);
tmp = current_poll;
current_poll = next_poll;
next_poll = tmp;
@@ -93,35 +86,36 @@ static int write_sigio_thread(void *unused)
n = os_write_file(respond_fd, &c, sizeof(c));
if(n != sizeof(c))
- printk("write_sigio_thread : write failed, "
- "err = %d\n", -n);
+ printk("write_sigio_thread : write on socket "
+ "failed, err = %d\n", -n);
}
}
return 0;
}
-static int need_poll(int n)
+static int need_poll(struct pollfds *polls, int n)
{
- if(n <= next_poll.size){
- next_poll.used = n;
- return(0);
+ if(n <= polls->size){
+ polls->used = n;
+ return 0;
}
- kfree(next_poll.poll);
- next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
- if(next_poll.poll == NULL){
+ kfree(polls->poll);
+ polls->poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
+ if(polls->poll == NULL){
printk("need_poll : failed to allocate new pollfds\n");
- next_poll.size = 0;
- next_poll.used = 0;
- return(-1);
+ polls->size = 0;
+ polls->used = 0;
+ return -ENOMEM;
}
- next_poll.size = n;
- next_poll.used = n;
- return(0);
+ polls->size = n;
+ polls->used = n;
+ return 0;
}
/* Must be called with sigio_lock held, because it's needed by the marked
- * critical section. */
+ * critical section.
+ */
static void update_thread(void)
{
unsigned long flags;
@@ -156,34 +150,39 @@ static void update_thread(void)
set_signals(flags);
}
-int add_sigio_fd(int fd, int read)
+int add_sigio_fd(int fd)
{
- int err = 0, i, n, events;
+ struct pollfd *p;
+ int err = 0, i, n;
sigio_lock();
+ for(i = 0; i < all_sigio_fds.used; i++){
+ if(all_sigio_fds.poll[i].fd == fd)
+ break;
+ }
+ if(i == all_sigio_fds.used)
+ goto out;
+
+ p = &all_sigio_fds.poll[i];
+
for(i = 0; i < current_poll.used; i++){
if(current_poll.poll[i].fd == fd)
goto out;
}
n = current_poll.used + 1;
- err = need_poll(n);
+ err = need_poll(&next_poll, n);
if(err)
goto out;
for(i = 0; i < current_poll.used; i++)
next_poll.poll[i] = current_poll.poll[i];
- if(read) events = POLLIN;
- else events = POLLOUT;
-
- next_poll.poll[n - 1] = ((struct pollfd) { .fd = fd,
- .events = events,
- .revents = 0 });
+ next_poll.poll[n - 1] = *p;
update_thread();
out:
sigio_unlock();
- return(err);
+ return err;
}
int ignore_sigio_fd(int fd)
@@ -191,6 +190,13 @@ int ignore_sigio_fd(int fd)
struct pollfd *p;
int err = 0, i, n = 0;
+ /* This is called from exitcalls elsewhere in UML - if
+ * sigio_cleanup has already run, then update_thread will hang
+ * or fail because the thread is no longer running.
+ */
+ if(write_sigio_pid == -1)
+ return -EIO;
+
sigio_lock();
for(i = 0; i < current_poll.used; i++){
if(current_poll.poll[i].fd == fd) break;
@@ -198,24 +204,20 @@ int ignore_sigio_fd(int fd)
if(i == current_poll.used)
goto out;
- err = need_poll(current_poll.used - 1);
+ err = need_poll(&next_poll, current_poll.used - 1);
if(err)
goto out;
for(i = 0; i < current_poll.used; i++){
p = &current_poll.poll[i];
- if(p->fd != fd) next_poll.poll[n++] = current_poll.poll[i];
- }
- if(n == i){
- printk("ignore_sigio_fd : fd %d not found\n", fd);
- err = -1;
- goto out;
+ if(p->fd != fd)
+ next_poll.poll[n++] = *p;
}
update_thread();
out:
sigio_unlock();
- return(err);
+ return err;
}
static struct pollfd *setup_initial_poll(int fd)
@@ -227,13 +229,13 @@ static struct pollfd *setup_initial_poll(int fd)
printk("setup_initial_poll : failed to allocate poll\n");
return NULL;
}
- *p = ((struct pollfd) { .fd = fd,
+ *p = ((struct pollfd) { .fd = fd,
.events = POLLIN,
.revents = 0 });
return p;
}
-void write_sigio_workaround(void)
+static void write_sigio_workaround(void)
{
unsigned long stack;
struct pollfd *p;
@@ -314,10 +316,38 @@ out_close1:
close(l_write_sigio_fds[1]);
}
-void sigio_cleanup(void)
+void maybe_sigio_broken(int fd, int read)
+{
+ int err;
+
+ if(!isatty(fd))
+ return;
+
+ if((read || pty_output_sigio) && (!read || pty_close_sigio))
+ return;
+
+ write_sigio_workaround();
+
+ sigio_lock();
+ err = need_poll(&all_sigio_fds, all_sigio_fds.used + 1);
+ if(err){
+ printk("maybe_sigio_broken - failed to add pollfd\n");
+ goto out;
+ }
+ all_sigio_fds.poll[all_sigio_fds.used++] =
+ ((struct pollfd) { .fd = fd,
+ .events = read ? POLLIN : POLLOUT,
+ .revents = 0 });
+out:
+ sigio_unlock();
+}
+
+static void sigio_cleanup(void)
{
if(write_sigio_pid != -1){
os_kill_process(write_sigio_pid, 1);
write_sigio_pid = -1;
}
}
+
+__uml_exitcall(sigio_cleanup);
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index f11b3124a0c8..6b81739279d1 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -15,7 +15,6 @@
#include "user.h"
#include "signal_kern.h"
#include "sysdep/sigcontext.h"
-#include "sysdep/signal.h"
#include "sigcontext.h"
#include "mode.h"
#include "os.h"
@@ -38,18 +37,10 @@
static int signals_enabled = 1;
static int pending = 0;
-void sig_handler(ARCH_SIGHDLR_PARAM)
+void sig_handler(int sig, struct sigcontext *sc)
{
- struct sigcontext *sc;
int enabled;
- /* Must be the first thing that this handler does - x86_64 stores
- * the sigcontext in %rdx, and we need to save it before it has a
- * chance to get trashed.
- */
-
- ARCH_GET_SIGCONTEXT(sc, sig);
-
enabled = signals_enabled;
if(!enabled && (sig == SIGIO)){
pending |= SIGIO_MASK;
@@ -64,15 +55,8 @@ void sig_handler(ARCH_SIGHDLR_PARAM)
set_signals(enabled);
}
-extern int timer_irq_inited;
-
static void real_alarm_handler(int sig, struct sigcontext *sc)
{
- if(!timer_irq_inited){
- signals_enabled = 1;
- return;
- }
-
if(sig == SIGALRM)
switch_timers(0);
@@ -84,13 +68,10 @@ static void real_alarm_handler(int sig, struct sigcontext *sc)
}
-void alarm_handler(ARCH_SIGHDLR_PARAM)
+void alarm_handler(int sig, struct sigcontext *sc)
{
- struct sigcontext *sc;
int enabled;
- ARCH_GET_SIGCONTEXT(sc, sig);
-
enabled = signals_enabled;
if(!signals_enabled){
if(sig == SIGVTALRM)
@@ -106,29 +87,6 @@ void alarm_handler(ARCH_SIGHDLR_PARAM)
set_signals(enabled);
}
-extern void do_boot_timer_handler(struct sigcontext * sc);
-
-void boot_timer_handler(ARCH_SIGHDLR_PARAM)
-{
- struct sigcontext *sc;
- int enabled;
-
- ARCH_GET_SIGCONTEXT(sc, sig);
-
- enabled = signals_enabled;
- if(!enabled){
- if(sig == SIGVTALRM)
- pending |= SIGVTALRM_MASK;
- else pending |= SIGALRM_MASK;
- return;
- }
-
- block_signals();
-
- do_boot_timer_handler(sc);
- set_signals(enabled);
-}
-
void set_sigstack(void *sig_stack, int size)
{
stack_t stack = ((stack_t) { .ss_flags = 0,
@@ -149,6 +107,10 @@ void remove_sigstack(void)
panic("disabling signal stack failed, errno = %d\n", errno);
}
+void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
+
+extern void hard_handler(int sig);
+
void set_handler(int sig, void (*handler)(int), int flags, ...)
{
struct sigaction action;
@@ -156,13 +118,16 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
sigset_t sig_mask;
int mask;
- va_start(ap, flags);
- action.sa_handler = handler;
+ handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
+ action.sa_handler = hard_handler;
+
sigemptyset(&action.sa_mask);
- while((mask = va_arg(ap, int)) != -1){
+
+ va_start(ap, flags);
+ while((mask = va_arg(ap, int)) != -1)
sigaddset(&action.sa_mask, mask);
- }
va_end(ap);
+
action.sa_flags = flags;
action.sa_restorer = NULL;
if(sigaction(sig, &action, NULL) < 0)
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index bd89c6b99d5d..cb9ab54146cc 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -8,7 +8,6 @@
#include <unistd.h>
#include <errno.h>
#include <signal.h>
-#include <setjmp.h>
#include <sched.h>
#include "ptrace_user.h"
#include <sys/wait.h>
@@ -156,11 +155,15 @@ extern int __syscall_stub_start;
static int userspace_tramp(void *stack)
{
void *addr;
+ int err;
ptrace(PTRACE_TRACEME, 0, 0, 0);
- init_new_thread_signals(1);
- enable_timer();
+ init_new_thread_signals();
+ err = set_interval(1);
+ if(err)
+ panic("userspace_tramp - setting timer failed, errno = %d\n",
+ err);
if(!proc_mm){
/* This has a pte, but it can't be mapped in with the usual
@@ -190,14 +193,25 @@ static int userspace_tramp(void *stack)
}
}
if(!ptrace_faultinfo && (stack != NULL)){
+ struct sigaction sa;
+
unsigned long v = UML_CONFIG_STUB_CODE +
(unsigned long) stub_segv_handler -
(unsigned long) &__syscall_stub_start;
set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size());
- set_handler(SIGSEGV, (void *) v, SA_ONSTACK,
- SIGIO, SIGWINCH, SIGALRM, SIGVTALRM,
- SIGUSR1, -1);
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGIO);
+ sigaddset(&sa.sa_mask, SIGWINCH);
+ sigaddset(&sa.sa_mask, SIGALRM);
+ sigaddset(&sa.sa_mask, SIGVTALRM);
+ sigaddset(&sa.sa_mask, SIGUSR1);
+ sa.sa_flags = SA_ONSTACK;
+ sa.sa_handler = (void *) v;
+ sa.sa_restorer = NULL;
+ if(sigaction(SIGSEGV, &sa, NULL) < 0)
+ panic("userspace_tramp - setting SIGSEGV handler "
+ "failed - errno = %d\n", errno);
}
os_stop_process(os_getpid());
@@ -430,59 +444,22 @@ void map_stub_pages(int fd, unsigned long code,
}
}
-void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
- void (*handler)(int))
+void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
{
- unsigned long flags;
- jmp_buf switch_buf, fork_buf;
- int enable;
-
- *switch_buf_ptr = &switch_buf;
- *fork_buf_ptr = &fork_buf;
-
- /* Somewhat subtle - siglongjmp restores the signal mask before doing
- * the longjmp. This means that when jumping from one stack to another
- * when the target stack has interrupts enabled, an interrupt may occur
- * on the source stack. This is bad when starting up a process because
- * it's not supposed to get timer ticks until it has been scheduled.
- * So, we disable interrupts around the sigsetjmp to ensure that
- * they can't happen until we get back here where they are safe.
- */
- flags = get_signals();
- block_signals();
- if(UML_SETJMP(&fork_buf, enable) == 0)
- new_thread_proc(stack, handler);
-
- remove_sigstack();
-
- set_signals(flags);
+ (*buf)[0].JB_IP = (unsigned long) handler;
+ (*buf)[0].JB_SP = (unsigned long) stack +
+ (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *);
}
#define INIT_JMP_NEW_THREAD 0
-#define INIT_JMP_REMOVE_SIGSTACK 1
-#define INIT_JMP_CALLBACK 2
-#define INIT_JMP_HALT 3
-#define INIT_JMP_REBOOT 4
+#define INIT_JMP_CALLBACK 1
+#define INIT_JMP_HALT 2
+#define INIT_JMP_REBOOT 3
-void thread_wait(void *sw, void *fb)
+void switch_threads(jmp_buf *me, jmp_buf *you)
{
- jmp_buf buf, **switch_buf = sw, *fork_buf;
- int enable;
-
- *switch_buf = &buf;
- fork_buf = fb;
- if(UML_SETJMP(&buf, enable) == 0)
- siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
-}
-
-void switch_threads(void *me, void *next)
-{
- jmp_buf my_buf, **me_ptr = me, *next_buf = next;
- int enable;
-
- *me_ptr = &my_buf;
- if(UML_SETJMP(&my_buf, enable) == 0)
- UML_LONGJMP(next_buf, 1);
+ if(UML_SETJMP(me) == 0)
+ UML_LONGJMP(you, 1);
}
static jmp_buf initial_jmpbuf;
@@ -492,23 +469,21 @@ static void (*cb_proc)(void *arg);
static void *cb_arg;
static jmp_buf *cb_back;
-int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
+int start_idle_thread(void *stack, jmp_buf *switch_buf)
{
- jmp_buf **switch_buf = switch_buf_ptr;
- int n, enable;
+ int n;
set_handler(SIGWINCH, (__sighandler_t) sig_handler,
SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
SIGVTALRM, -1);
- *fork_buf_ptr = &initial_jmpbuf;
- n = UML_SETJMP(&initial_jmpbuf, enable);
+ n = UML_SETJMP(&initial_jmpbuf);
switch(n){
case INIT_JMP_NEW_THREAD:
- new_thread_proc((void *) stack, new_thread_handler);
- break;
- case INIT_JMP_REMOVE_SIGSTACK:
- remove_sigstack();
+ (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
+ (*switch_buf)[0].JB_SP = (unsigned long) stack +
+ (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) -
+ sizeof(void *);
break;
case INIT_JMP_CALLBACK:
(*cb_proc)(cb_arg);
@@ -523,20 +498,19 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
default:
panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
}
- UML_LONGJMP(*switch_buf, 1);
+ UML_LONGJMP(switch_buf, 1);
}
void initial_thread_cb_skas(void (*proc)(void *), void *arg)
{
jmp_buf here;
- int enable;
cb_proc = proc;
cb_arg = arg;
cb_back = &here;
block_signals();
- if(UML_SETJMP(&here, enable) == 0)
+ if(UML_SETJMP(&here) == 0)
UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
unblock_signals();
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 503148504009..7fe92680c7dd 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -14,7 +14,6 @@
#include <sched.h>
#include <fcntl.h>
#include <errno.h>
-#include <setjmp.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/mman.h>
diff --git a/arch/um/os-Linux/sys-i386/Makefile b/arch/um/os-Linux/sys-i386/Makefile
index b3213613c41c..37806621b25d 100644
--- a/arch/um/os-Linux/sys-i386/Makefile
+++ b/arch/um/os-Linux/sys-i386/Makefile
@@ -3,7 +3,7 @@
# Licensed under the GPL
#
-obj-$(CONFIG_MODE_SKAS) = registers.o tls.o
+obj-$(CONFIG_MODE_SKAS) = registers.o signal.o tls.o
USER_OBJS := $(obj-y)
diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
index 516f66dd87e3..7cd0369e02b3 100644
--- a/arch/um/os-Linux/sys-i386/registers.c
+++ b/arch/um/os-Linux/sys-i386/registers.c
@@ -5,12 +5,12 @@
#include <errno.h>
#include <string.h>
-#include <setjmp.h>
#include "sysdep/ptrace_user.h"
#include "sysdep/ptrace.h"
#include "uml-config.h"
#include "skas_ptregs.h"
#include "registers.h"
+#include "longjmp.h"
#include "user.h"
/* These are set once at boot time and not changed thereafter */
@@ -130,11 +130,14 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
HOST_FP_SIZE * sizeof(unsigned long));
}
-void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer)
+unsigned long get_thread_reg(int reg, jmp_buf *buf)
{
- struct __jmp_buf_tag *jmpbuf = buffer;
-
- UPT_SET(uml_regs, EIP, jmpbuf->__jmpbuf[JB_PC]);
- UPT_SET(uml_regs, UESP, jmpbuf->__jmpbuf[JB_SP]);
- UPT_SET(uml_regs, EBP, jmpbuf->__jmpbuf[JB_BP]);
+ switch(reg){
+ case EIP: return buf[0]->__eip;
+ case UESP: return buf[0]->__esp;
+ case EBP: return buf[0]->__ebp;
+ default:
+ printk("get_thread_regs - unknown register %d\n", reg);
+ return 0;
+ }
}
diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c
new file mode 100644
index 000000000000..0d3eae518352
--- /dev/null
+++ b/arch/um/os-Linux/sys-i386/signal.c
@@ -0,0 +1,15 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+
+extern void (*handlers[])(int sig, struct sigcontext *sc);
+
+void hard_handler(int sig)
+{
+ struct sigcontext *sc = (struct sigcontext *) (&sig + 1);
+
+ (*handlers[sig])(sig, sc);
+}
diff --git a/arch/um/os-Linux/sys-x86_64/Makefile b/arch/um/os-Linux/sys-x86_64/Makefile
index 340ef26f5944..f67842a7735b 100644
--- a/arch/um/os-Linux/sys-x86_64/Makefile
+++ b/arch/um/os-Linux/sys-x86_64/Makefile
@@ -3,7 +3,7 @@
# Licensed under the GPL
#
-obj-$(CONFIG_MODE_SKAS) = registers.o
+obj-$(CONFIG_MODE_SKAS) = registers.o signal.o
USER_OBJS := $(obj-y)
diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
index becd898d9398..cb8e8a263280 100644
--- a/arch/um/os-Linux/sys-x86_64/registers.c
+++ b/arch/um/os-Linux/sys-x86_64/registers.c
@@ -5,11 +5,11 @@
#include <errno.h>
#include <string.h>
-#include <setjmp.h>
#include "ptrace_user.h"
#include "uml-config.h"
#include "skas_ptregs.h"
#include "registers.h"
+#include "longjmp.h"
#include "user.h"
/* These are set once at boot time and not changed thereafter */
@@ -78,11 +78,14 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
HOST_FP_SIZE * sizeof(unsigned long));
}
-void get_thread_regs(union uml_pt_regs *uml_regs, void *buffer)
+unsigned long get_thread_reg(int reg, jmp_buf *buf)
{
- struct __jmp_buf_tag *jmpbuf = buffer;
-
- UPT_SET(uml_regs, RIP, jmpbuf->__jmpbuf[JB_PC]);
- UPT_SET(uml_regs, RSP, jmpbuf->__jmpbuf[JB_RSP]);
- UPT_SET(uml_regs, RBP, jmpbuf->__jmpbuf[JB_RBP]);
+ switch(reg){
+ case RIP: return buf[0]->__rip;
+ case RSP: return buf[0]->__rsp;
+ case RBP: return buf[0]->__rbp;
+ default:
+ printk("get_thread_regs - unknown register %d\n", reg);
+ return 0;
+ }
}
diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c
new file mode 100644
index 000000000000..3f369e5f976b
--- /dev/null
+++ b/arch/um/os-Linux/sys-x86_64/signal.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com)
+ * Licensed under the GPL
+ */
+
+#include <signal.h>
+
+extern void (*handlers[])(int sig, struct sigcontext *sc);
+
+void hard_handler(int sig)
+{
+ struct ucontext *uc;
+ asm("movq %%rdx, %0" : "=r" (uc));
+
+ (*handlers[sig])(sig, (struct sigcontext *) &uc->uc_mcontext);
+}
diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c
index 280c4fb9b585..38be096e750f 100644
--- a/arch/um/os-Linux/time.c
+++ b/arch/um/os-Linux/time.c
@@ -17,25 +17,25 @@
#include "kern_constants.h"
#include "os.h"
-/* XXX This really needs to be declared and initialized in a kernel file since
- * it's in <linux/time.h>
- */
-extern struct timespec wall_to_monotonic;
-
-static void set_interval(int timer_type)
+int set_interval(int is_virtual)
{
int usec = 1000000/hz();
+ int timer_type = is_virtual ? ITIMER_VIRTUAL : ITIMER_REAL;
struct itimerval interval = ((struct itimerval) { { 0, usec },
{ 0, usec } });
if(setitimer(timer_type, &interval, NULL) == -1)
- panic("setitimer failed - errno = %d\n", errno);
+ return -errno;
+
+ return 0;
}
+#ifdef CONFIG_MODE_TT
void enable_timer(void)
{
- set_interval(ITIMER_VIRTUAL);
+ set_interval(1);
}
+#endif
void disable_timer(void)
{
@@ -45,8 +45,8 @@ void disable_timer(void)
printk("disnable_timer - setitimer failed, errno = %d\n",
errno);
/* If there are signals already queued, after unblocking ignore them */
- set_handler(SIGALRM, SIG_IGN, 0, -1);
- set_handler(SIGVTALRM, SIG_IGN, 0, -1);
+ signal(SIGALRM, SIG_IGN);
+ signal(SIGVTALRM, SIG_IGN);
}
void switch_timers(int to_real)
@@ -71,6 +71,7 @@ void switch_timers(int to_real)
errno);
}
+#ifdef UML_CONFIG_MODE_TT
void uml_idle_timer(void)
{
if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
@@ -78,16 +79,9 @@ void uml_idle_timer(void)
set_handler(SIGALRM, (__sighandler_t) alarm_handler,
SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
- set_interval(ITIMER_REAL);
-}
-
-void time_init(void)
-{
- if(signal(SIGVTALRM, boot_timer_handler) == SIG_ERR)
- panic("Couldn't set SIGVTALRM handler");
- set_interval(ITIMER_VIRTUAL);
- time_init_kern();
+ set_interval(0);
}
+#endif
unsigned long long os_nsecs(void)
{
@@ -105,16 +99,3 @@ void idle_sleep(int secs)
ts.tv_nsec = 0;
nanosleep(&ts, NULL);
}
-
-/* XXX This partly duplicates init_irq_signals */
-
-void user_time_init(void)
-{
- set_handler(SIGVTALRM, (__sighandler_t) alarm_handler,
- SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
- SIGALRM, SIGUSR2, -1);
- set_handler(SIGALRM, (__sighandler_t) alarm_handler,
- SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH,
- SIGVTALRM, SIGUSR2, -1);
- set_interval(ITIMER_VIRTUAL);
-}
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index 90b29ae9af46..1df231a26244 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -5,7 +5,6 @@
#include <stdlib.h>
#include <signal.h>
-#include <setjmp.h>
#include "kern_util.h"
#include "user_util.h"
#include "os.h"
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index e523719330b2..bbb73a650370 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -4,8 +4,7 @@
* Licensed under the GPL
*/
-#include <setjmp.h>
-#include <string.h>
+#include <stddef.h>
#include "longjmp.h"
unsigned long __do_user_copy(void *to, const void *from, int n,
@@ -14,11 +13,10 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
int n), int *faulted_out)
{
unsigned long *faddrp = (unsigned long *) fault_addr, ret;
- int enable;
jmp_buf jbuf;
*fault_catcher = &jbuf;
- if(UML_SETJMP(&jbuf, enable) == 0){
+ if(UML_SETJMP(&jbuf) == 0){
(*op)(to, from, n);
ret = 0;
*faulted_out = 0;
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index 362db059fe30..48092b95c8ab 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -67,32 +67,53 @@ err:
return err;
}
-static int actually_do_remove(char *dir)
+/*
+ * Unlinks the files contained in @dir and then removes @dir.
+ * Doesn't handle directory trees, so it's not like rm -rf, but almost such. We
+ * ignore ENOENT errors for anything (they happen, strangely enough - possibly due
+ * to races between multiple dying UML threads).
+ */
+static int remove_files_and_dir(char *dir)
{
DIR *directory;
struct dirent *ent;
int len;
char file[256];
+ int ret;
directory = opendir(dir);
- if(directory == NULL)
- return -errno;
+ if (directory == NULL) {
+ if (errno != ENOENT)
+ return -errno;
+ else
+ return 0;
+ }
- while((ent = readdir(directory)) != NULL){
- if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
+ while ((ent = readdir(directory)) != NULL) {
+ if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, ".."))
continue;
len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1;
- if(len > sizeof(file))
- return -E2BIG;
+ if (len > sizeof(file)) {
+ ret = -E2BIG;
+ goto out;
+ }
sprintf(file, "%s/%s", dir, ent->d_name);
- if(unlink(file) < 0)
- return -errno;
+ if (unlink(file) < 0 && errno != ENOENT) {
+ ret = -errno;
+ goto out;
+ }
}
- if(rmdir(dir) < 0)
- return -errno;
- return 0;
+ if (rmdir(dir) < 0 && errno != ENOENT) {
+ ret = -errno;
+ goto out;
+ }
+
+ ret = 0;
+out:
+ closedir(directory);
+ return ret;
}
/* This says that there isn't already a user of the specified directory even if
@@ -103,9 +124,10 @@ static int actually_do_remove(char *dir)
* something other than UML sticking stuff in the directory
* this boot racing with a shutdown of the other UML
* In any of these cases, the directory isn't useful for anything else.
+ *
+ * Boolean return: 1 if in use, 0 otherwise.
*/
-
-static int not_dead_yet(char *dir)
+static inline int is_umdir_used(char *dir)
{
char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
char pid[sizeof("nnnnn\0")], *end;
@@ -113,7 +135,7 @@ static int not_dead_yet(char *dir)
n = snprintf(file, sizeof(file), "%s/pid", dir);
if(n >= sizeof(file)){
- printk("not_dead_yet - pid filename too long\n");
+ printk("is_umdir_used - pid filename too long\n");
err = -E2BIG;
goto out;
}
@@ -123,7 +145,7 @@ static int not_dead_yet(char *dir)
if(fd < 0) {
fd = -errno;
if(fd != -ENOENT){
- printk("not_dead_yet : couldn't open pid file '%s', "
+ printk("is_umdir_used : couldn't open pid file '%s', "
"err = %d\n", file, -fd);
}
goto out;
@@ -132,18 +154,18 @@ static int not_dead_yet(char *dir)
err = 0;
n = read(fd, pid, sizeof(pid));
if(n < 0){
- printk("not_dead_yet : couldn't read pid file '%s', "
+ printk("is_umdir_used : couldn't read pid file '%s', "
"err = %d\n", file, errno);
goto out_close;
} else if(n == 0){
- printk("not_dead_yet : couldn't read pid file '%s', "
+ printk("is_umdir_used : couldn't read pid file '%s', "
"0-byte read\n", file);
goto out_close;
}
p = strtoul(pid, &end, 0);
if(end == pid){
- printk("not_dead_yet : couldn't parse pid file '%s', "
+ printk("is_umdir_used : couldn't parse pid file '%s', "
"errno = %d\n", file, errno);
goto out_close;
}
@@ -153,19 +175,32 @@ static int not_dead_yet(char *dir)
return 1;
}
- err = actually_do_remove(dir);
- if(err)
- printk("not_dead_yet - actually_do_remove failed with "
- "err = %d\n", err);
-
- return err;
-
out_close:
close(fd);
out:
return 0;
}
+/*
+ * Try to remove the directory @dir unless it's in use.
+ * Precondition: @dir exists.
+ * Returns 0 for success, < 0 for failure in removal or if the directory is in
+ * use.
+ */
+static int umdir_take_if_dead(char *dir)
+{
+ int ret;
+ if (is_umdir_used(dir))
+ return -EEXIST;
+
+ ret = remove_files_and_dir(dir);
+ if (ret) {
+ printk("is_umdir_used - remove_files_and_dir failed with "
+ "err = %d\n", ret);
+ }
+ return ret;
+}
+
static void __init create_pid_file(void)
{
char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")];
@@ -244,11 +279,7 @@ int __init make_umid(void)
if(err != -EEXIST)
goto err;
- /* 1 -> this umid is already in use
- * < 0 -> we couldn't remove the umid directory
- * In either case, we can't use this umid, so return -EEXIST.
- */
- if(not_dead_yet(tmp) != 0)
+ if (umdir_take_if_dead(tmp) < 0)
goto err;
err = mkdir(tmp, 0777);
@@ -344,9 +375,9 @@ static void remove_umid_dir(void)
char dir[strlen(uml_dir) + UMID_LEN + 1], err;
sprintf(dir, "%s%s", uml_dir, umid);
- err = actually_do_remove(dir);
+ err = remove_files_and_dir(dir);
if(err)
- printf("remove_umid_dir - actually_do_remove failed with "
+ printf("remove_umid_dir - remove_files_and_dir failed with "
"err = %d\n", err);
}
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index c47a2a7ce70e..3f5b1514e8a7 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -7,7 +7,6 @@
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
-#include <setjmp.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/utsname.h>
@@ -107,11 +106,11 @@ int setjmp_wrapper(void (*proc)(void *, void *), ...)
jmp_buf buf;
int n;
- n = sigsetjmp(buf, 1);
+ n = UML_SETJMP(&buf);
if(n == 0){
va_start(args, proc);
(*proc)(&buf, &args);
}
va_end(args);
- return(n);
+ return n;
}
OpenPOWER on IntegriCloud