Hi James,
Yes, I ran into this last fall and fixed it in our local tree (though
unfortunately after the 1.1 release). So it's FITNR. Here's my patch
to tide you over until then.
Steve
James Srinivasan wrote:
I've recently noticed that file descriptors in m5's syscall emulation
mode aren't reused where I think they may be able to. Process::open_fd
(called by openFunc) iterates over the fd_map array looking for a free
fd; however, closeFunc does not change the respective array entry when
the file is closed. If MAX_FD is large enough, this doesn't usually
cause any problems but I have run into one SPEC2000 benchmark (wupwise)
in which this isn't the case. Off the top of my head, adding
Process::close_fd which sets the array entry to -1 and calling it
from closeFunc ought to work.
James
diff -Nru a/sim/process.cc b/sim/process.cc
--- a/sim/process.cc 2006-05-18 07:24:58 -04:00
+++ b/sim/process.cc 2006-05-18 07:24:58 -04:00
@@ -194,23 +194,32 @@
// generate new target fd for sim_fd
int
-Process::open_fd(int sim_fd)
+Process::alloc_fd(int sim_fd)
{
- int free_fd;
-
// in case open() returns an error, don't allocate a new fd
if (sim_fd == -1)
return -1;
// find first free target fd
- for (free_fd = 0; fd_map[free_fd] >= 0; ++free_fd) {
- if (free_fd == MAX_FD)
- panic("Process::open_fd: out of file descriptors!");
+ for (int free_fd = 0; free_fd < MAX_FD; ++free_fd) {
+ if (fd_map[free_fd] == -1) {
+ fd_map[free_fd] = sim_fd;
+ return free_fd;
+ }
}
- fd_map[free_fd] = sim_fd;
+ panic("Process::alloc_fd: out of file descriptors!");
+}
+
+
+// free target fd (e.g., after close)
+void
+Process::free_fd(int tgt_fd)
+{
+ if (fd_map[tgt_fd] == -1)
+ warn("Process::free_fd: request to free unused fd %d", tgt_fd);
- return free_fd;
+ fd_map[tgt_fd] = -1;
}
diff -Nru a/sim/process.hh b/sim/process.hh
--- a/sim/process.hh 2006-05-18 07:24:58 -04:00
+++ b/sim/process.hh 2006-05-18 07:24:58 -04:00
@@ -127,7 +127,7 @@
private:
// file descriptor remapping support
- static const int MAX_FD = 100; // max legal fd value
+ static const int MAX_FD = 256; // max legal fd value
int fd_map[MAX_FD+1];
public:
@@ -149,7 +149,10 @@
void dup_fd(int sim_fd, int tgt_fd);
// generate new target fd for sim_fd
- int open_fd(int sim_fd);
+ int alloc_fd(int sim_fd);
+
+ // free target fd (e.g., after close)
+ void free_fd(int tgt_fd);
// look up simulator fd for given target fd
int sim_fd(int tgt_fd);
diff -Nru a/sim/syscall_emul.cc b/sim/syscall_emul.cc
--- a/sim/syscall_emul.cc 2006-05-18 07:24:58 -04:00
+++ b/sim/syscall_emul.cc 2006-05-18 07:24:58 -04:00
@@ -113,8 +113,11 @@
SyscallReturn
closeFunc(SyscallDesc *desc, int num, Process *p, ExecContext *xc)
{
- int fd = p->sim_fd(xc->getSyscallArg(0));
- return close(fd);
+ int target_fd = xc->getSyscallArg(0);
+ int status = close(p->sim_fd(target_fd));
+ if (status >= 0)
+ p->free_fd(target_fd);
+ return status;
}
diff -Nru a/sim/syscall_emul.hh b/sim/syscall_emul.hh
--- a/sim/syscall_emul.hh 2006-05-18 07:24:58 -04:00
+++ b/sim/syscall_emul.hh 2006-05-18 07:24:58 -04:00
@@ -342,7 +342,7 @@
// open the file
int fd = open(path.c_str(), hostFlags, mode);
- return (fd == -1) ? -errno : process->open_fd(fd);
+ return (fd == -1) ? -errno : process->alloc_fd(fd);
}