Add support for dup()ing fake file descriptors to the simulator.
diff --git a/simulator/wrapsim/Android.mk b/simulator/wrapsim/Android.mk
index 0a995a2..f9a2414 100644
--- a/simulator/wrapsim/Android.mk
+++ b/simulator/wrapsim/Android.mk
@@ -22,7 +22,8 @@
Intercept.c \
Log.c \
SimMgr.c \
- SysPower.c
+ SysPower.c \
+ Util.c
LOCAL_C_INCLUDES += prebuilt/common/esd
diff --git a/simulator/wrapsim/Common.h b/simulator/wrapsim/Common.h
index a9c3bb8..463262f 100644
--- a/simulator/wrapsim/Common.h
+++ b/simulator/wrapsim/Common.h
@@ -14,5 +14,6 @@
#include "Log.h"
#include "SimMgr.h"
#include "Globals.h"
+#include "Util.h"
#endif /*_WRAPSIM_COMMON_H*/
diff --git a/simulator/wrapsim/DevFb.c b/simulator/wrapsim/DevFb.c
index c54403e..bfdbb22 100644
--- a/simulator/wrapsim/DevFb.c
+++ b/simulator/wrapsim/DevFb.c
@@ -14,6 +14,10 @@
#include <linux/fb.h>
typedef struct FbState {
+
+ /* refcount for dup() */
+ int refCount;
+
/* index into gWrapSim.display[] */
int displayIdx;
@@ -77,7 +81,13 @@
*/
static void freeState(FbState* fbState)
{
- free(fbState);
+ int oldcount;
+
+ oldcount = wsAtomicAdd(&fbState->refCount, -1);
+
+ if (oldcount == 0) {
+ free(fbState);
+ }
}
/*
@@ -242,6 +252,28 @@
}
/*
+ * dup() an existing fake descriptor
+ */
+static FakeDev* dupFb(FakeDev* dev, int fd)
+{
+ FakeDev* newDev = wsCreateFakeDev(dev->debugName);
+ if (newDev != NULL) {
+ newDev->mmap = mmapFb;
+ newDev->ioctl = ioctlFb;
+ newDev->close = closeFb;
+ newDev->dup = dupFb;
+
+ /* use state from existing FakeDev */
+ FbState* fbState = dev->state;
+ wsAtomicAdd(&fbState->refCount, 1);
+
+ newDev->state = fbState;
+ }
+
+ return newDev;
+}
+
+/*
* Open the console TTY device, which responds to a collection of ioctl()s.
*/
FakeDev* wsOpenDevFb(const char* pathName, int flags)
@@ -251,6 +283,7 @@
newDev->mmap = mmapFb;
newDev->ioctl = ioctlFb;
newDev->close = closeFb;
+ newDev->dup = dupFb;
FbState* fbState = calloc(1, sizeof(FbState));
diff --git a/simulator/wrapsim/FakeDev.c b/simulator/wrapsim/FakeDev.c
index 7d2494e..f03dd29 100644
--- a/simulator/wrapsim/FakeDev.c
+++ b/simulator/wrapsim/FakeDev.c
@@ -99,6 +99,11 @@
{
return 0;
}
+static FakeDev* noDup(FakeDev* dev, ...)
+{
+ notImplemented(dev, "dup");
+ return NULL;
+}
static int noRead(FakeDev* dev, ...)
{
return notImplemented(dev, "read");
@@ -146,6 +151,7 @@
newDev->state = NULL;
newDev->close = (Fake_close) noClose;
+ newDev->dup = (Fake_dup) noDup;
newDev->read = (Fake_read) noRead;
newDev->readv = (Fake_readv) noReadv;
newDev->write = (Fake_write) noWrite;
diff --git a/simulator/wrapsim/FakeDev.h b/simulator/wrapsim/FakeDev.h
index 4781cfc..65f47ae 100644
--- a/simulator/wrapsim/FakeDev.h
+++ b/simulator/wrapsim/FakeDev.h
@@ -12,13 +12,14 @@
typedef struct FakeDev FakeDev;
-typedef int (*Fake_close)(FakeDev* dev, int);
-typedef ssize_t (*Fake_read)(FakeDev* dev, int, void*, size_t);
-typedef ssize_t (*Fake_readv)(FakeDev* dev, int, const struct iovec*, int);
-typedef ssize_t (*Fake_write)(FakeDev* dev, int, const void*, size_t);
-typedef ssize_t (*Fake_writev)(FakeDev* dev, int, const struct iovec*, int);
-typedef void* (*Fake_mmap)(FakeDev* dev, void*, size_t, int, int, int, __off_t);
-typedef int (*Fake_ioctl)(FakeDev* dev, int, int, void*);
+typedef int (*Fake_close)(FakeDev* dev, int);
+typedef FakeDev* (*Fake_dup)(FakeDev* dev, int);
+typedef ssize_t (*Fake_read)(FakeDev* dev, int, void*, size_t);
+typedef ssize_t (*Fake_readv)(FakeDev* dev, int, const struct iovec*, int);
+typedef ssize_t (*Fake_write)(FakeDev* dev, int, const void*, size_t);
+typedef ssize_t (*Fake_writev)(FakeDev* dev, int, const struct iovec*, int);
+typedef void* (*Fake_mmap)(FakeDev* dev, void*, size_t, int, int, int, __off_t);
+typedef int (*Fake_ioctl)(FakeDev* dev, int, int, void*);
/*
* An open fake device entry.
@@ -42,6 +43,7 @@
* All other file descriptor operations should fail, usually with EBADF.
*/
Fake_close close;
+ Fake_dup dup;
Fake_read read;
Fake_readv readv;
Fake_write write;
diff --git a/simulator/wrapsim/Globals.h b/simulator/wrapsim/Globals.h
index 75c98d8..a8d834c 100644
--- a/simulator/wrapsim/Globals.h
+++ b/simulator/wrapsim/Globals.h
@@ -29,6 +29,7 @@
typedef int (*Func_open64)(const char*, int, mode_t);
typedef int (*Func_close)(int);
+typedef int (*Func_dup)(int);
typedef ssize_t (*Func_read)(int, void*, size_t);
typedef ssize_t (*Func_readv)(int, const struct iovec*, int);
typedef ssize_t (*Func_write)(int, const void*, size_t);
@@ -95,6 +96,7 @@
EXTERN_FUNC Func_open64 _ws_open64;
EXTERN_FUNC Func_close _ws_close;
+EXTERN_FUNC Func_dup _ws_dup;
EXTERN_FUNC Func_read _ws_read;
EXTERN_FUNC Func_readv _ws_readv;
EXTERN_FUNC Func_write _ws_write;
@@ -201,6 +203,9 @@
pthread_mutex_t fakeFdLock;
BitVector* fakeFdMap;
FakeDev* fakeFdList[kMaxFakeFdCount];
+
+ /* used for wsAtomicAdd */
+ pthread_mutex_t atomicLock;
};
extern struct WrapSimGlobals gWrapSim;
diff --git a/simulator/wrapsim/Init.c b/simulator/wrapsim/Init.c
index eed650b..3df0efe 100644
--- a/simulator/wrapsim/Init.c
+++ b/simulator/wrapsim/Init.c
@@ -40,6 +40,7 @@
_ws_open64 = dlsym(RTLD_NEXT, "open64");
_ws_close = dlsym(RTLD_NEXT, "close");
+ _ws_dup = dlsym(RTLD_NEXT, "dup");
_ws_read = dlsym(RTLD_NEXT, "read");
_ws_readv = dlsym(RTLD_NEXT, "readv");
_ws_write = dlsym(RTLD_NEXT, "write");
@@ -108,6 +109,8 @@
gWrapSim.fakeFdMap = wsAllocBitVector(kMaxFakeFdCount, 0);
memset(gWrapSim.fakeFdList, 0, sizeof(gWrapSim.fakeFdList));
+ pthread_mutex_init(&gWrapSim.atomicLock, NULL);
+
gWrapSim.numDisplays = 0;
gWrapSim.keyInputDevice = NULL;
diff --git a/simulator/wrapsim/Intercept.c b/simulator/wrapsim/Intercept.c
index 49d77ee..09547fb 100644
--- a/simulator/wrapsim/Intercept.c
+++ b/simulator/wrapsim/Intercept.c
@@ -160,7 +160,7 @@
_rtype _fname( __VA_ARGS__ )
#define PASS_THROUGH_BODY(_fname, _patharg, ...) \
{ \
- CALLTRACEV("%s\n", __FUNCTION__); \
+ CALLTRACEV("%s(%s)\n", __FUNCTION__, _patharg); \
char pathBuf[PATH_MAX]; \
return _ws_##_fname(rewritePath(#_fname, pathBuf, _patharg), \
##__VA_ARGS__); \
@@ -631,6 +631,30 @@
}
+int dup(int fd)
+{
+ CALLTRACEV("%s(%d)\n", __FUNCTION__, fd);
+
+ FakeDev* dev = wsFakeDevFromFd(fd);
+ if (dev != NULL) {
+ FakeDev* newDev = dev->dup(dev, fd);
+ if (newDev != NULL) {
+ /*
+ * Now that the device entry is ready, add it to the list.
+ */
+ wsLog("## dup'ed fake dev %d: '%s' %p\n",
+ newDev->fd, newDev->debugName, newDev->state);
+ gWrapSim.fakeFdList[newDev->fd - kFakeFdBase] = newDev;
+ return newDev->fd;
+ }
+ return -1;
+ } else {
+ CALLTRACE("dup(%d)\n", fd);
+ return _ws_dup(fd);
+ }
+}
+
+
/*
* Close a file descriptor.
*/
diff --git a/simulator/wrapsim/Util.c b/simulator/wrapsim/Util.c
new file mode 100644
index 0000000..33d903b
--- /dev/null
+++ b/simulator/wrapsim/Util.c
@@ -0,0 +1,13 @@
+
+#include "Common.h"
+
+int wsAtomicAdd(int *var, int val)
+{
+ int cc;
+ int ret;
+ cc = pthread_mutex_lock(&gWrapSim.atomicLock);
+ ret = *var;
+ *var = *var + val;
+ cc = pthread_mutex_unlock(&gWrapSim.atomicLock);
+ return ret;
+}
diff --git a/simulator/wrapsim/Util.h b/simulator/wrapsim/Util.h
new file mode 100644
index 0000000..e470802
--- /dev/null
+++ b/simulator/wrapsim/Util.h
@@ -0,0 +1,4 @@
+
+
+
+int wsAtomicAdd(int *var, int val);