2006-03-27 17:14:32 +08:00
|
|
|
/*
|
2005-04-17 06:20:36 +08:00
|
|
|
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
|
|
|
|
* Licensed under the GPL
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <pty.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sched.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/poll.h>
|
|
|
|
#include "init.h"
|
|
|
|
#include "user.h"
|
|
|
|
#include "kern_util.h"
|
|
|
|
#include "user_util.h"
|
|
|
|
#include "sigio.h"
|
|
|
|
#include "os.h"
|
|
|
|
|
|
|
|
/* Protected by sigio_lock(), also used by sigio_cleanup, which is an
|
|
|
|
* exitcall.
|
|
|
|
*/
|
|
|
|
static int write_sigio_pid = -1;
|
|
|
|
|
|
|
|
/* These arrays are initialized before the sigio thread is started, and
|
|
|
|
* the descriptors closed after it is killed. So, it can't see them change.
|
|
|
|
* On the UML side, they are changed under the sigio_lock.
|
|
|
|
*/
|
|
|
|
static int write_sigio_fds[2] = { -1, -1 };
|
|
|
|
static int sigio_private[2] = { -1, -1 };
|
|
|
|
|
|
|
|
struct pollfds {
|
|
|
|
struct pollfd *poll;
|
|
|
|
int size;
|
|
|
|
int used;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* 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 int write_sigio_thread(void *unused)
|
|
|
|
{
|
|
|
|
struct pollfds *fds, tmp;
|
|
|
|
struct pollfd *p;
|
|
|
|
int i, n, respond_fd;
|
|
|
|
char c;
|
|
|
|
|
2005-05-06 07:15:32 +08:00
|
|
|
signal(SIGWINCH, SIG_IGN);
|
2005-04-17 06:20:36 +08:00
|
|
|
fds = ¤t_poll;
|
|
|
|
while(1){
|
|
|
|
n = poll(fds->poll, fds->used, -1);
|
|
|
|
if(n < 0){
|
|
|
|
if(errno == EINTR) continue;
|
|
|
|
printk("write_sigio_thread : poll returned %d, "
|
|
|
|
"errno = %d\n", n, errno);
|
|
|
|
}
|
|
|
|
for(i = 0; i < fds->used; i++){
|
|
|
|
p = &fds->poll[i];
|
|
|
|
if(p->revents == 0) continue;
|
|
|
|
if(p->fd == sigio_private[1]){
|
|
|
|
n = os_read_file(sigio_private[1], &c, sizeof(c));
|
|
|
|
if(n != sizeof(c))
|
|
|
|
printk("write_sigio_thread : "
|
|
|
|
"read failed, err = %d\n", -n);
|
|
|
|
tmp = current_poll;
|
|
|
|
current_poll = next_poll;
|
|
|
|
next_poll = tmp;
|
|
|
|
respond_fd = sigio_private[1];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
respond_fd = write_sigio_fds[1];
|
|
|
|
fds->used--;
|
|
|
|
memmove(&fds->poll[i], &fds->poll[i + 1],
|
|
|
|
(fds->used - i) * sizeof(*fds->poll));
|
|
|
|
}
|
|
|
|
|
|
|
|
n = os_write_file(respond_fd, &c, sizeof(c));
|
|
|
|
if(n != sizeof(c))
|
|
|
|
printk("write_sigio_thread : write failed, "
|
|
|
|
"err = %d\n", -n);
|
|
|
|
}
|
|
|
|
}
|
2006-01-06 16:18:49 +08:00
|
|
|
|
|
|
|
return 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int need_poll(int n)
|
|
|
|
{
|
|
|
|
if(n <= next_poll.size){
|
|
|
|
next_poll.used = n;
|
|
|
|
return(0);
|
|
|
|
}
|
2005-11-07 17:01:35 +08:00
|
|
|
kfree(next_poll.poll);
|
2005-04-17 06:20:36 +08:00
|
|
|
next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd));
|
|
|
|
if(next_poll.poll == NULL){
|
|
|
|
printk("need_poll : failed to allocate new pollfds\n");
|
|
|
|
next_poll.size = 0;
|
|
|
|
next_poll.used = 0;
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
next_poll.size = n;
|
|
|
|
next_poll.used = n;
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Must be called with sigio_lock held, because it's needed by the marked
|
|
|
|
* critical section. */
|
|
|
|
static void update_thread(void)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
int n;
|
|
|
|
char c;
|
|
|
|
|
|
|
|
flags = set_signals(0);
|
|
|
|
n = os_write_file(sigio_private[0], &c, sizeof(c));
|
|
|
|
if(n != sizeof(c)){
|
|
|
|
printk("update_thread : write failed, err = %d\n", -n);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
n = os_read_file(sigio_private[0], &c, sizeof(c));
|
|
|
|
if(n != sizeof(c)){
|
|
|
|
printk("update_thread : read failed, err = %d\n", -n);
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_signals(flags);
|
|
|
|
return;
|
|
|
|
fail:
|
|
|
|
/* Critical section start */
|
|
|
|
if(write_sigio_pid != -1)
|
|
|
|
os_kill_process(write_sigio_pid, 1);
|
|
|
|
write_sigio_pid = -1;
|
2006-03-27 17:14:32 +08:00
|
|
|
close(sigio_private[0]);
|
|
|
|
close(sigio_private[1]);
|
|
|
|
close(write_sigio_fds[0]);
|
|
|
|
close(write_sigio_fds[1]);
|
2005-04-17 06:20:36 +08:00
|
|
|
/* Critical section end */
|
|
|
|
set_signals(flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
int add_sigio_fd(int fd, int read)
|
|
|
|
{
|
|
|
|
int err = 0, i, n, events;
|
|
|
|
|
|
|
|
sigio_lock();
|
|
|
|
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);
|
|
|
|
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 });
|
|
|
|
update_thread();
|
|
|
|
out:
|
|
|
|
sigio_unlock();
|
|
|
|
return(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
int ignore_sigio_fd(int fd)
|
|
|
|
{
|
|
|
|
struct pollfd *p;
|
|
|
|
int err = 0, i, n = 0;
|
|
|
|
|
|
|
|
sigio_lock();
|
|
|
|
for(i = 0; i < current_poll.used; i++){
|
|
|
|
if(current_poll.poll[i].fd == fd) break;
|
|
|
|
}
|
|
|
|
if(i == current_poll.used)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
err = need_poll(current_poll.used - 1);
|
|
|
|
if(err)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
for(i = 0; i < current_poll.used; i++){
|
|
|
|
p = ¤t_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;
|
|
|
|
}
|
|
|
|
|
|
|
|
update_thread();
|
|
|
|
out:
|
|
|
|
sigio_unlock();
|
|
|
|
return(err);
|
|
|
|
}
|
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
static struct pollfd* setup_initial_poll(int fd)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct pollfd *p;
|
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
p = um_kmalloc(sizeof(struct pollfd));
|
|
|
|
if (p == NULL) {
|
2005-04-17 06:20:36 +08:00
|
|
|
printk("setup_initial_poll : failed to allocate poll\n");
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
return NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
*p = ((struct pollfd) { .fd = fd,
|
|
|
|
.events = POLLIN,
|
|
|
|
.revents = 0 });
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
return p;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void write_sigio_workaround(void)
|
|
|
|
{
|
|
|
|
unsigned long stack;
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
struct pollfd *p;
|
2005-04-17 06:20:36 +08:00
|
|
|
int err;
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
int l_write_sigio_fds[2];
|
|
|
|
int l_sigio_private[2];
|
|
|
|
int l_write_sigio_pid;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
/* We call this *tons* of times - and most ones we must just fail. */
|
2005-04-17 06:20:36 +08:00
|
|
|
sigio_lock();
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
l_write_sigio_pid = write_sigio_pid;
|
|
|
|
sigio_unlock();
|
2005-04-17 06:20:36 +08:00
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
if (l_write_sigio_pid != -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
err = os_pipe(l_write_sigio_fds, 1, 1);
|
2005-04-17 06:20:36 +08:00
|
|
|
if(err < 0){
|
|
|
|
printk("write_sigio_workaround - os_pipe 1 failed, "
|
|
|
|
"err = %d\n", -err);
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
err = os_pipe(l_sigio_private, 1, 1);
|
2005-04-17 06:20:36 +08:00
|
|
|
if(err < 0){
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
printk("write_sigio_workaround - os_pipe 1 failed, "
|
2005-04-17 06:20:36 +08:00
|
|
|
"err = %d\n", -err);
|
|
|
|
goto out_close1;
|
|
|
|
}
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
|
|
|
|
p = setup_initial_poll(l_sigio_private[1]);
|
|
|
|
if(!p)
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out_close2;
|
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
sigio_lock();
|
|
|
|
|
|
|
|
/* Did we race? Don't try to optimize this, please, it's not so likely
|
|
|
|
* to happen, and no more than once at the boot. */
|
|
|
|
if(write_sigio_pid != -1)
|
|
|
|
goto out_unlock;
|
|
|
|
|
|
|
|
write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
|
2005-04-17 06:20:36 +08:00
|
|
|
CLONE_FILES | CLONE_VM, &stack, 0);
|
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
if (write_sigio_pid < 0)
|
|
|
|
goto out_clear;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
if (write_sigio_irq(l_write_sigio_fds[0]))
|
2005-04-17 06:20:36 +08:00
|
|
|
goto out_kill;
|
|
|
|
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
/* Success, finally. */
|
|
|
|
memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
|
|
|
|
memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
|
|
|
|
|
|
|
|
current_poll = ((struct pollfds) { .poll = p,
|
|
|
|
.used = 1,
|
|
|
|
.size = 1 });
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
sigio_unlock();
|
|
|
|
return;
|
|
|
|
|
|
|
|
out_kill:
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
l_write_sigio_pid = write_sigio_pid;
|
2005-04-17 06:20:36 +08:00
|
|
|
write_sigio_pid = -1;
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
sigio_unlock();
|
|
|
|
/* Going to call waitpid, avoid holding the lock. */
|
|
|
|
os_kill_process(l_write_sigio_pid, 1);
|
|
|
|
goto out_free;
|
|
|
|
|
|
|
|
out_clear:
|
|
|
|
write_sigio_pid = -1;
|
|
|
|
out_unlock:
|
|
|
|
sigio_unlock();
|
|
|
|
out_free:
|
|
|
|
kfree(p);
|
2005-04-17 06:20:36 +08:00
|
|
|
out_close2:
|
2006-03-27 17:14:32 +08:00
|
|
|
close(l_sigio_private[0]);
|
|
|
|
close(l_sigio_private[1]);
|
2005-04-17 06:20:36 +08:00
|
|
|
out_close1:
|
2006-03-27 17:14:32 +08:00
|
|
|
close(l_write_sigio_fds[0]);
|
|
|
|
close(l_write_sigio_fds[1]);
|
[PATCH] uml: sigio code - reduce spinlock hold time
In a previous patch I shifted an allocation to being atomic.
In this patch, a better but more intrusive solution is implemented, i.e. hold
the lock only when really needing it, especially not over pipe operations, nor
over the culprit allocation.
Additionally, while at it, add a missing kfree in the failure path, and make
sure that if we fail in forking, write_sigio_pid is -1 and not, say, -ENOMEM.
And fix whitespace, at least for things I was touching anyway.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-01-19 09:42:57 +08:00
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-03-27 17:14:32 +08:00
|
|
|
void sigio_cleanup(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
if (write_sigio_pid != -1) {
|
|
|
|
os_kill_process(write_sigio_pid, 1);
|
|
|
|
write_sigio_pid = -1;
|
|
|
|
}
|
|
|
|
}
|