aboutsummaryrefslogtreecommitdiff
path: root/sim/common/callback.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/common/callback.c')
-rw-r--r--sim/common/callback.c53
1 files changed, 39 insertions, 14 deletions
diff --git a/sim/common/callback.c b/sim/common/callback.c
index 62848e8..bbb3fe5 100644
--- a/sim/common/callback.c
+++ b/sim/common/callback.c
@@ -110,7 +110,7 @@ fdbad (p, fd)
host_callback *p;
int fd;
{
- if (fd < 0 || fd > MAX_CALLBACK_FDS || !p->fdopen[fd])
+ if (fd < 0 || fd > MAX_CALLBACK_FDS || p->fd_buddy[fd] < 0)
{
p->last_errno = EINVAL;
return -1;
@@ -132,13 +132,20 @@ os_close (p, fd)
int fd;
{
int result;
+ int i, next;
result = fdbad (p, fd);
if (result)
return result;
- result = wrap (p, close (fdmap (p, fd)));
- if (result == 0 && !p->alwaysopen[fd])
- p->fdopen[fd] = 0;
+ /* If this file descripter has one or more buddies (originals /
+ duplicates from a dup), just remove it from the circular list. */
+ for (i = fd; (next = p->fd_buddy[i]) != fd; )
+ i = next;
+ if (fd != i)
+ p->fd_buddy[i] = p->fd_buddy[fd];
+ else
+ result = wrap (p, close (fdmap (p, fd)));
+ p->fd_buddy[fd] = -1;
return result;
}
@@ -234,7 +241,7 @@ os_open (p, name, flags)
int i;
for (i = 0; i < MAX_CALLBACK_FDS; i++)
{
- if (!p->fdopen[i])
+ if (p->fd_buddy[i] < 0)
{
int f = open (name, cb_target_to_host_open (p, flags), 0644);
if (f < 0)
@@ -242,7 +249,7 @@ os_open (p, name, flags)
p->last_errno = errno;
return f;
}
- p->fdopen[i] = 1;
+ p->fd_buddy[i] = i;
p->fdmap[i] = f;
return i;
}
@@ -428,13 +435,31 @@ static int
os_shutdown (p)
host_callback *p;
{
- int i;
+ int i, next, j;
for (i = 0; i < MAX_CALLBACK_FDS; i++)
{
- if (p->fdopen[i] && !p->alwaysopen[i]) {
+ int do_close = 1;
+
+ next = p->fd_buddy[i];
+ if (next < 0)
+ continue;
+ do
+ {
+ j = next;
+ if (j == MAX_CALLBACK_FDS)
+ do_close = 0;
+ next = p->fd_buddy[j];
+ p->fd_buddy[j] = -1;
+ /* At the initial call of os_init, we got -1, 0, 0, 0, ... */
+ if (next < 0)
+ {
+ do_close = 0;
+ break;
+ }
+ }
+ while (j != i);
+ if (do_close)
close (p->fdmap[i]);
- p->fdopen[i] = 0;
- }
}
return 1;
}
@@ -449,9 +474,10 @@ os_init (p)
for (i = 0; i < 3; i++)
{
p->fdmap[i] = i;
- p->fdopen[i] = 1;
- p->alwaysopen[i] = 1;
+ p->fd_buddy[i] = i - 1;
}
+ p->fd_buddy[0] = MAX_CALLBACK_FDS;
+ p->fd_buddy[MAX_CALLBACK_FDS] = 2;
p->syscall_map = cb_init_syscall_map;
p->errno_map = cb_init_errno_map;
@@ -580,8 +606,7 @@ host_callback default_callback =
0, /* last errno */
{ 0, }, /* fdmap */
- { 0, }, /* fdopen */
- { 0, }, /* alwaysopen */
+ { -1, }, /* fd_buddy */
0, /* syscall_map */
0, /* errno_map */