diff options
Diffstat (limited to 'sim/common/callback.c')
-rw-r--r-- | sim/common/callback.c | 53 |
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 */ |