diff options
author | David 'Digit' Turner <digit@google.com> | 2014-07-21 16:22:38 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2014-07-21 16:22:38 +0000 |
commit | c245592b0d472437ade15a22076c2193441f0eea (patch) | |
tree | 889f16f76567054ea5fc085f274ceade0a09bd81 /emulator | |
parent | 245fae139423eb268ecb3eaa06f6ce8c7044c4f4 (diff) | |
parent | 4e4233679d4ef4e25d13fe3b56bd8cdaa3b822cc (diff) | |
download | sdk-c245592b0d472437ade15a22076c2193441f0eea.zip sdk-c245592b0d472437ade15a22076c2193441f0eea.tar.gz sdk-c245592b0d472437ade15a22076c2193441f0eea.tar.bz2 |
Merge changes I551e0f3d,I26d84cf5,I27c993d1 into idea133
automerge: 4e42336
* commit '4e4233679d4ef4e25d13fe3b56bd8cdaa3b822cc':
emulator/opengl: Remove out-of-process handling code.
emulator/opengl: refactor Thread class.
emulator/opengl: refactor shared library handling.
Diffstat (limited to 'emulator')
40 files changed, 876 insertions, 1077 deletions
diff --git a/emulator/opengl/Android.mk b/emulator/opengl/Android.mk index 856826a..7906fdd 100644 --- a/emulator/opengl/Android.mk +++ b/emulator/opengl/Android.mk @@ -73,7 +73,6 @@ include $(EMUGL_PATH)/host/tools/emugen/Android.mk include $(EMUGL_PATH)/googletest.mk include $(EMUGL_PATH)/shared/emugl/common/Android.mk -include $(EMUGL_PATH)/shared/OpenglOsUtils/Android.mk include $(EMUGL_PATH)/shared/OpenglCodecCommon/Android.mk # Host static libraries diff --git a/emulator/opengl/host/libs/GLESv1_dec/Android.mk b/emulator/opengl/host/libs/GLESv1_dec/Android.mk index 7ab3f0a..e0eca6e 100644 --- a/emulator/opengl/host/libs/GLESv1_dec/Android.mk +++ b/emulator/opengl/host/libs/GLESv1_dec/Android.mk @@ -10,7 +10,7 @@ host_common_debug_CFLAGS := ### host library ######################################### $(call emugl-begin-host-static-library,libGLESv1_dec) -$(call emugl-import, libOpenglCodecCommon libOpenglOsUtils) +$(call emugl-import, libOpenglCodecCommon) $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) $(call emugl-gen-decoder,$(LOCAL_PATH),gl) @@ -27,7 +27,7 @@ $(call emugl-end-module) ifdef EMUGL_BUILD_64BITS $(call emugl-begin-host64-static-library,lib64GLESv1_dec) - $(call emugl-import, lib64OpenglCodecCommon lib64OpenglOsUtils) + $(call emugl-import, lib64OpenglCodecCommon) $(call emugl-export,C_INCLUDES,$(LOCAL_PATH)) $(call emugl-gen-decoder,$(LOCAL_PATH),gl) diff --git a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp index 3c5bd70..7aa6ede 100644 --- a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp +++ b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.cpp @@ -47,7 +47,7 @@ int GLDecoder::initGL(get_proc_func_t getProcFunc, void *getProcFuncData) libname = getenv(GLES_LIBNAME_VAR); } - m_glesDso = osUtils::dynLibrary::open(libname); + m_glesDso = emugl::SharedLibrary::open(libname); if (m_glesDso == NULL) { fprintf(stderr, "Couldn't find %s \n", GLES_LIBNAME); return -1; diff --git a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h index 14ca222..0d26090 100644 --- a/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h +++ b/emulator/opengl/host/libs/GLESv1_dec/GLDecoder.h @@ -19,7 +19,7 @@ #include "gl_dec.h" #include "FixedBuffer.h" #include "GLDecoderContextData.h" -#include <osDynLibrary.h> +#include "emugl/common/shared_library.h" #define GLES_LIBNAME_VAR "ANDROID_GLESv1_LIB" #define GLES_LIBNAME "libGLES_CM.so" @@ -65,7 +65,7 @@ private: static void * s_getProc(const char *name, void *userData); GLDecoderContextData *m_contextData; - osUtils::dynLibrary* m_glesDso; + emugl::SharedLibrary* m_glesDso; }; #endif diff --git a/emulator/opengl/host/libs/GLESv2_dec/Android.mk b/emulator/opengl/host/libs/GLESv2_dec/Android.mk index bc04c25..f658f11 100644 --- a/emulator/opengl/host/libs/GLESv2_dec/Android.mk +++ b/emulator/opengl/host/libs/GLESv2_dec/Android.mk @@ -9,7 +9,7 @@ host_common_debug_CFLAGS := ### host library ########################################## $(call emugl-begin-host-static-library,libGLESv2_dec) -$(call emugl-import, libOpenglCodecCommon libOpenglOsUtils) +$(call emugl-import, libOpenglCodecCommon) $(call emugl-gen-decoder,$(LOCAL_PATH),gl2) # For gl2_types.h ! @@ -24,7 +24,7 @@ $(call emugl-end-module) ### host library, 64-bit #################################### ifdef EMUGL_BUILD_64BITS $(call emugl-begin-host64-static-library,lib64GLESv2_dec) - $(call emugl-import, lib64OpenglCodecCommon lib64OpenglOsUtils) + $(call emugl-import, lib64OpenglCodecCommon) $(call emugl-gen-decoder,$(LOCAL_PATH),gl2) # For gl2_types.h ! diff --git a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp index ccf2f06..2ef306e 100644 --- a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp +++ b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.cpp @@ -60,7 +60,7 @@ int GL2Decoder::initGL(get_proc_func_t getProcFunc, void *getProcFuncData) libname = getenv(GLES2_LIBNAME_VAR); } - m_GL2library = osUtils::dynLibrary::open(libname); + m_GL2library = emugl::SharedLibrary::open(libname); if (m_GL2library == NULL) { fprintf(stderr, "%s: Couldn't find %s \n", __FUNCTION__, libname); return -1; diff --git a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h index dcf2c07..8910da9 100644 --- a/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h +++ b/emulator/opengl/host/libs/GLESv2_dec/GL2Decoder.h @@ -21,9 +21,8 @@ #define GLES2_LIBNAME "libGLESv2.so" #include "gl2_dec.h" -#include "osDynLibrary.h" #include "GLDecoderContextData.h" - +#include "emugl/common/shared_library.h" class GL2Decoder : public gl2_decoder_context_t { @@ -35,7 +34,7 @@ public: void setContextData(GLDecoderContextData *contextData) { m_contextData = contextData; } private: GLDecoderContextData *m_contextData; - osUtils::dynLibrary * m_GL2library; + emugl::SharedLibrary* m_GL2library; static void *s_getProc(const char *name, void *userData); static void gl2_APIENTRY s_glGetCompressedTextureFormats(void *self, int count, GLint *formats); diff --git a/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp b/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp index 06dcf67..30d358f 100644 --- a/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp +++ b/emulator/opengl/host/libs/Translator/EGL/EglImp.cpp @@ -24,7 +24,7 @@ #include <stdio.h> #include "ThreadInfo.h" #include <GLcommon/TranslatorIfaces.h> -#include <OpenglOsUtils/osDynLibrary.h> +#include "emugl/common/shared_library.h" #include "EglWindowSurface.h" #include "EglPbufferSurface.h" @@ -175,7 +175,7 @@ EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) { #define TRANSLATOR_GETIFACE_NAME "__translator_getIfaces" static __translator_getGLESIfaceFunc loadIfaces(const char* libName){ - osUtils::dynLibrary* libGLES = osUtils::dynLibrary::open(libName); + emugl::SharedLibrary* libGLES = emugl::SharedLibrary::open(libName); if(!libGLES) return NULL; __translator_getGLESIfaceFunc func = (__translator_getGLESIfaceFunc)libGLES->findSymbol(TRANSLATOR_GETIFACE_NAME); diff --git a/emulator/opengl/host/libs/Translator/GLcommon/Android.mk b/emulator/opengl/host/libs/Translator/GLcommon/Android.mk index b215329..fdbedad 100644 --- a/emulator/opengl/host/libs/Translator/GLcommon/Android.mk +++ b/emulator/opengl/host/libs/Translator/GLcommon/Android.mk @@ -35,7 +35,6 @@ endif $(call emugl-begin-host-static-library,libGLcommon) -$(call emugl-import,libOpenglOsUtils) translator_path := $(LOCAL_PATH)/.. LOCAL_SRC_FILES := $(host_common_SRC_FILES) $(call emugl-export,LDLIBS,$(host_common_LDLIBS)) @@ -50,7 +49,6 @@ $(call emugl-end-module) ifdef EMUGL_BUILD_64BITS $(call emugl-begin-host64-static-library,lib64GLcommon) - $(call emugl-import,lib64OpenglOsUtils) translator_path := $(LOCAL_PATH)/.. LOCAL_SRC_FILES := $(host_common_SRC_FILES) LOCAL_CFLAGS += -fPIC diff --git a/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp b/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp index 7b217fd..5da7247 100644 --- a/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp +++ b/emulator/opengl/host/libs/Translator/GLcommon/GLDispatch.cpp @@ -16,7 +16,7 @@ #include <GLcommon/GLDispatch.h> #include <stdio.h> -#include <OpenglOsUtils/osDynLibrary.h> +#include "emugl/common/shared_library.h" #ifdef __linux__ #include <GL/glx.h> @@ -31,13 +31,13 @@ typedef void (*GL_FUNC_PTR)(); static GL_FUNC_PTR getGLFuncAddress(const char *funcName) { GL_FUNC_PTR ret = NULL; #ifdef __linux__ - static osUtils::dynLibrary* libGL = osUtils::dynLibrary::open("libGL.so"); + static emugl::SharedLibrary* libGL = emugl::SharedLibrary::open("libGL"); ret = (GL_FUNC_PTR)glXGetProcAddress((const GLubyte*)funcName); #elif defined(WIN32) - static osUtils::dynLibrary* libGL = osUtils::dynLibrary::open("opengl32"); + static emugl::SharedLibrary* libGL = emugl::SharedLibrary::open("opengl32"); ret = (GL_FUNC_PTR)wglGetProcAddress(funcName); #elif defined(__APPLE__) - static osUtils::dynLibrary* libGL = osUtils::dynLibrary::open("/System/Library/Frameworks/OpenGL.framework/OpenGL"); + static emugl::SharedLibrary* libGL = emugl::SharedLibrary::open("/System/Library/Frameworks/OpenGL.framework/OpenGL"); #endif if(!ret && libGL){ ret = libGL->findSymbol(funcName); diff --git a/emulator/opengl/host/libs/libOpenglRender/Android.mk b/emulator/opengl/host/libs/libOpenglRender/Android.mk index 787ae83..ca5a08a 100644 --- a/emulator/opengl/host/libs/libOpenglRender/Android.mk +++ b/emulator/opengl/host/libs/libOpenglRender/Android.mk @@ -5,7 +5,7 @@ host_common_LDLIBS := ifeq ($(HOST_OS),linux) host_OS_SRCS = NativeLinuxSubWindow.cpp - host_common_LDLIBS += -lX11 + host_common_LDLIBS += -lX11 -lrt endif ifeq ($(HOST_OS),darwin) @@ -43,7 +43,7 @@ host_common_CFLAGS := ### host libOpenglRender ################################################# $(call emugl-begin-host-shared-library,libOpenglRender) -$(call emugl-import,libGLESv1_dec libGLESv2_dec lib_renderControl_dec libOpenglCodecCommon libOpenglOsUtils) +$(call emugl-import,libGLESv1_dec libGLESv2_dec lib_renderControl_dec libOpenglCodecCommon) LOCAL_LDLIBS += $(host_common_LDLIBS) @@ -65,7 +65,7 @@ $(call emugl-end-module) ifdef EMUGL_BUILD_64BITS $(call emugl-begin-host64-shared-library,lib64OpenglRender) - $(call emugl-import,lib64GLESv1_dec lib64GLESv2_dec lib64_renderControl_dec lib64OpenglCodecCommon lib64OpenglOsUtils) + $(call emugl-import,lib64GLESv1_dec lib64GLESv2_dec lib64_renderControl_dec lib64OpenglCodecCommon) #LOCAL_LDFLAGS += -m64 # adding -m64 here doesn't work, because it somehow appear BEFORE -m32 in command-line. LOCAL_LDLIBS += $(host_common_LDLIBS) -m64 # Put -m64 it in LOCAL_LDLIBS instead. diff --git a/emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp b/emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp index 3cf5dbc..7d514e8 100644 --- a/emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/EGLDispatch.cpp @@ -16,7 +16,8 @@ #include "EGLDispatch.h" #include <stdio.h> #include <stdlib.h> -#include "osDynLibrary.h" + +#include "emugl/common/shared_library.h" EGLDispatch s_egl; @@ -28,7 +29,7 @@ bool init_egl_dispatch() const char *libName = getenv("ANDROID_EGL_LIB"); if (!libName) libName = DEFAULT_EGL_LIB; - osUtils::dynLibrary *lib = osUtils::dynLibrary::open(libName); + emugl::SharedLibrary *lib = emugl::SharedLibrary::open(libName); if (!lib) { printf("Failed to open %s\n", libName); return NULL; diff --git a/emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp b/emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp index cda205f..8c51a4e 100644 --- a/emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/GL2Dispatch.cpp @@ -17,12 +17,13 @@ #include "GL2Dispatch.h" #include <stdio.h> #include <stdlib.h> -#include "osDynLibrary.h" + +#include "emugl/common/shared_library.h" gl2_decoder_context_t s_gl2; int s_gl2_enabled; -static osUtils::dynLibrary *s_gles2_lib = NULL; +static emugl::SharedLibrary *s_gles2_lib = NULL; #define DEFAULT_GLES_V2_LIB EMUGL_LIBNAME("GLES_V2_translator") @@ -38,7 +39,7 @@ bool init_gl2_dispatch() // // Load the GLES library // - s_gles2_lib = osUtils::dynLibrary::open(libName); + s_gles2_lib = emugl::SharedLibrary::open(libName); if (!s_gles2_lib) return false; // diff --git a/emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp b/emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp index 089512a..c127dc3 100644 --- a/emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/GLDispatch.cpp @@ -16,11 +16,12 @@ #include "GLDispatch.h" #include <stdio.h> #include <stdlib.h> -#include "osDynLibrary.h" + +#include "emugl/common/shared_library.h" GLDispatch s_gl; -static osUtils::dynLibrary *s_gles_lib = NULL; +static emugl::SharedLibrary *s_gles_lib = NULL; // // This function is called only once during initialiation before @@ -34,7 +35,7 @@ bool init_gl_dispatch() const char *libName = getenv("ANDROID_GLESv1_LIB"); if (!libName) libName = DEFAULT_GLES_CM_LIB; - s_gles_lib = osUtils::dynLibrary::open(libName); + s_gles_lib = emugl::SharedLibrary::open(libName); if (!s_gles_lib) return false; s_gl.glAlphaFunc = (glAlphaFunc_t) s_gles_lib->findSymbol("glAlphaFunc"); diff --git a/emulator/opengl/host/libs/libOpenglRender/RenderServer.cpp b/emulator/opengl/host/libs/libOpenglRender/RenderServer.cpp index de28f8f..53c65ee 100644 --- a/emulator/opengl/host/libs/libOpenglRender/RenderServer.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/RenderServer.cpp @@ -77,7 +77,7 @@ RenderServer *RenderServer::create(char* addr, size_t addrLen) return server; } -int RenderServer::Main() +intptr_t RenderServer::main() { RenderThreadsSet threads; @@ -146,8 +146,7 @@ int RenderServer::Main() for (RenderThreadsSet::iterator t = threads.begin(); t != threads.end(); t++) { - int exitStatus; - (*t)->wait(&exitStatus); + (*t)->wait(NULL); delete (*t); } threads.clear(); diff --git a/emulator/opengl/host/libs/libOpenglRender/RenderServer.h b/emulator/opengl/host/libs/libOpenglRender/RenderServer.h index ff63c94..8be8a17 100644 --- a/emulator/opengl/host/libs/libOpenglRender/RenderServer.h +++ b/emulator/opengl/host/libs/libOpenglRender/RenderServer.h @@ -18,15 +18,15 @@ #include "SocketStream.h" #include "emugl/common/mutex.h" -#include "osThread.h" +#include "emugl/common/thread.h" -class RenderServer : public osUtils::Thread +class RenderServer : public emugl::Thread { public: static RenderServer *create(char* addr, size_t addrLen); virtual ~RenderServer(); - virtual int Main(); + virtual intptr_t main(); bool isExiting() const { return m_exiting; } diff --git a/emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp b/emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp index 19d6c1f..3dcfdb5 100644 --- a/emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/RenderThread.cpp @@ -26,7 +26,7 @@ #define STREAM_BUFFER_SIZE 4*1024*1024 RenderThread::RenderThread(IOStream *stream, emugl::Mutex *lock) : - osUtils::Thread(), + emugl::Thread(), m_lock(lock), m_stream(stream), m_finished(false) @@ -43,7 +43,7 @@ RenderThread *RenderThread::create(IOStream *p_stream, emugl::Mutex *lock) return new RenderThread(p_stream, lock); } -int RenderThread::Main() +intptr_t RenderThread::main() { RenderThreadInfo tInfo; diff --git a/emulator/opengl/host/libs/libOpenglRender/RenderThread.h b/emulator/opengl/host/libs/libOpenglRender/RenderThread.h index e94d782..c1f919a 100644 --- a/emulator/opengl/host/libs/libOpenglRender/RenderThread.h +++ b/emulator/opengl/host/libs/libOpenglRender/RenderThread.h @@ -21,9 +21,9 @@ #include "renderControl_dec.h" #include "emugl/common/mutex.h" -#include "osThread.h" +#include "emugl/common/thread.h" -class RenderThread : public osUtils::Thread +class RenderThread : public emugl::Thread { public: static RenderThread* create(IOStream* p_stream, emugl::Mutex* mutex); @@ -32,7 +32,7 @@ public: private: RenderThread(IOStream* p_stream, emugl::Mutex* mutex); - virtual int Main(); + virtual intptr_t main(); private: emugl::Mutex *m_lock; diff --git a/emulator/opengl/host/libs/libOpenglRender/render_api.cpp b/emulator/opengl/host/libs/libOpenglRender/render_api.cpp index 5c9ffb1..9586091 100644 --- a/emulator/opengl/host/libs/libOpenglRender/render_api.cpp +++ b/emulator/opengl/host/libs/libOpenglRender/render_api.cpp @@ -17,7 +17,6 @@ #include "IOStream.h" #include "FrameBuffer.h" #include "RenderServer.h" -#include "osProcess.h" #include "TimeUtils.h" #include "TcpStream.h" @@ -31,25 +30,12 @@ #include "GLDispatch.h" #include "GL2Dispatch.h" -static osUtils::childProcess *s_renderProc = NULL; static RenderServer *s_renderThread = NULL; static char s_renderAddr[256]; static IOStream *createRenderThread(int p_stream_buffer_size, unsigned int clientFlags); -// -// For now run the renderer as a thread inside the calling -// process instead as running it in a separate process for all -// platforms. -// at the future we want it to run as a seperate process except for -// Mac OS X since it is imposibble on this platform to make one process -// render to a window created by another process. -// -//#ifdef __APPLE__ -#define RENDER_API_USE_THREAD -//#endif - int initLibrary(void) { // @@ -82,11 +68,10 @@ int initOpenGLRenderer(int width, int height, char* addr, size_t addrLen) // // Fail if renderer is already initialized // - if (s_renderProc || s_renderThread) { + if (s_renderThread) { return false; } -#ifdef RENDER_API_USE_THREAD // should be defined for mac // // initialize the renderer and listen to connections // on a thread in the current process. @@ -104,110 +89,15 @@ int initOpenGLRenderer(int width, int height, char* addr, size_t addrLen) s_renderThread->start(); -#else - if (onPost) { - // onPost callback not supported with separate renderer process. - // - // If we ever revive separate process support, we could make the choice - // between thread and process at runtime instead of compile time, and - // choose the thread path if an onPost callback is requested. Or, the - // callback could be supported with a separate process using shmem or - // other IPC mechanism. - return false; - } - - // - // Launch emulator_renderer - // - char cmdLine[128]; - snprintf(cmdLine, 128, "emulator_renderer -windowid %d -port %d -x %d -y %d -width %d -height %d", - (int)window, portNum, x, y, width, height); - - s_renderProc = osUtils::childProcess::create(cmdLine, NULL); - if (!s_renderProc) { - return false; - } - - // - // try to connect to the renderer in order to check it - // was successfully initialized. - // - int nTrys = 0; - IOStream *dummy = NULL; - do { - ++nTrys; - - // - // Wait a bit to make the renderer process a chance to be - // initialized. - // On Windows we need during this time to handle windows - // events since the renderer generates a subwindow of this - // process's window, we need to be responsive for windows - // during this time to let the renderer generates this subwindow. - // -#ifndef _WIN32 - TimeSleepMS(300); -#else - long long t0 = GetCurrentTimeMS(); - while( (GetCurrentTimeMS() - t0) < 300 ) { - MSG msg; - int n = 0; - while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) - { - n++; - TranslateMessage( &msg ); - DispatchMessage( &msg ); - } - if (n == 0) TimeSleepMS(10); - } -#endif - - dummy = createRenderThread(8, 0); - - if (!dummy) { - // stop if the process is no longer running - if (!osUtils::isProcessRunning(s_renderProc->getPID())) { - break; - } - } - } while(!dummy && nTrys < 10); // give up after 3 seconds, XXX: ??? - - if (!dummy) { - // - // Failed - make sure the process is killed - // - osUtils::KillProcess(s_renderProc->getPID(), true); - delete s_renderProc; - s_renderProc = NULL; - return false; - } - - // destroy the dummy connection - delete dummy; -#endif - return true; } void setPostCallback(OnPostFn onPost, void* onPostContext) { -#ifdef RENDER_API_USE_THREAD // should be defined for mac FrameBuffer* fb = FrameBuffer::getFB(); if (fb) { fb->setPostCallback(onPost, onPostContext); } -#else - if (onPost) { - // onPost callback not supported with separate renderer process. - // - // If we ever revive separate process support, we could make the choice - // between thread and process at runtime instead of compile time, and - // choose the thread path if an onPost callback is requested. Or, the - // callback could be supported with a separate process using shmem or - // other IPC mechanism. - return false; - } -#endif } void getHardwareStrings(const char** vendor, const char** renderer, const char** version) @@ -230,21 +120,10 @@ int stopOpenGLRenderer(void) IOStream *dummy = createRenderThread(8, IOSTREAM_CLIENT_EXIT_SERVER); if (!dummy) return false; - if (s_renderProc) { - // - // wait for the process to exit - // - int exitStatus; - ret = s_renderProc->wait(&exitStatus); - - delete s_renderProc; - s_renderProc = NULL; - } - else if (s_renderThread) { + if (s_renderThread) { // wait for the thread to exit - int status; - ret = s_renderThread->wait(&status); + ret = s_renderThread->wait(NULL); delete s_renderThread; s_renderThread = NULL; diff --git a/emulator/opengl/host/renderer/Android.mk b/emulator/opengl/host/renderer/Android.mk index 55fcb80..81dcaf7 100644 --- a/emulator/opengl/host/renderer/Android.mk +++ b/emulator/opengl/host/renderer/Android.mk @@ -6,9 +6,9 @@ $(call emugl-import,libOpenglRender) LOCAL_SRC_FILES := main.cpp LOCAL_CFLAGS += -O0 -g -#ifeq ($(HOST_OS),windows) -#LOCAL_LDLIBS += -lws2_32 -#endif +ifeq ($(HOST_OS),linux) +LOCAL_LDLIBS += -lX11 +endif $(call emugl-end-module) diff --git a/emulator/opengl/host/renderer/main.cpp b/emulator/opengl/host/renderer/main.cpp index 2c3f8e2..470e692 100644 --- a/emulator/opengl/host/renderer/main.cpp +++ b/emulator/opengl/host/renderer/main.cpp @@ -141,7 +141,7 @@ int main(int argc, char *argv[]) // // run the server listener loop // - server->Main(); + server->main(); #else // // on windows we need to handle messages for the diff --git a/emulator/opengl/shared/OpenglCodecCommon/Android.mk b/emulator/opengl/shared/OpenglCodecCommon/Android.mk index 83090d8..0c3f827 100644 --- a/emulator/opengl/shared/OpenglCodecCommon/Android.mk +++ b/emulator/opengl/shared/OpenglCodecCommon/Android.mk @@ -13,8 +13,11 @@ commonSources := \ host_commonSources := $(commonSources) +host_commonLdLibs := -lstdc++ + ifeq ($(HOST_OS),windows) host_commonSources += Win32PipeStream.cpp + host_commonLdLibs += -lws2_32 -lpsapi else host_commonSources += UnixStream.cpp endif @@ -26,7 +29,7 @@ $(call emugl-begin-host-static-library,libOpenglCodecCommon) LOCAL_SRC_FILES := $(host_commonSources) $(call emugl-import, libemugl_common) $(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/host/include/libOpenglRender $(LOCAL_PATH)) -$(call emugl-export,LDLIBS,-lstdc++) +$(call emugl-export,LDLIBS,$(host_commonLdLibs)) $(call emugl-end-module) @@ -39,6 +42,6 @@ ifdef EMUGL_BUILD_64BITS $(call emugl-import, lib64emugl_common) $(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/host/include/libOpenglRender $(LOCAL_PATH)) $(call emugl-export,CFLAGS,-m64 -fPIC) - $(call emugl-export,LDLIBS,-lstdc++) + $(call emugl-export,LDLIBS,$(host_commonLdLibs)) $(call emugl-end-module) endif diff --git a/emulator/opengl/shared/OpenglOsUtils/Android.mk b/emulator/opengl/shared/OpenglOsUtils/Android.mk deleted file mode 100644 index f9673fc..0000000 --- a/emulator/opengl/shared/OpenglOsUtils/Android.mk +++ /dev/null @@ -1,48 +0,0 @@ -# This build script corresponds to a small library containing -# OS-specific support functions for: -# - thread-local storage -# - dynamic library loading -# - child process creation and wait (probably not needed in guest) -# -LOCAL_PATH := $(call my-dir) - -### Host library ############################################## - -host_common_SRC_FILES := osDynLibrary.cpp -host_common_LDLIBS := -host_common_INCLUDES := $(LOCAL_PATH) - -ifeq ($(HOST_OS),windows) - host_common_SRC_FILES += \ - osProcessWin.cpp \ - osThreadWin.cpp - host_common_LDLIBS += -lws2_32 -lpsapi -else - host_common_SRC_FILES += \ - osProcessUnix.cpp \ - osThreadUnix.cpp - host_common_LDLIBS += -ldl -endif - -ifeq ($(HOST_OS),linux) - host_common_LDLIBS += -lpthread -lrt -lX11 -endif - -### 32-bit host library #### -$(call emugl-begin-host-static-library,libOpenglOsUtils) - $(call emugl-export,C_INCLUDES,$(host_common_INCLUDES)) - LOCAL_SRC_FILES = $(host_common_SRC_FILES) - $(call emugl-export,LDLIBS,$(host_common_LDLIBS)) - $(call emugl-import,libemugl_common) -$(call emugl-end-module) - -### 64-bit host library #### -ifdef EMUGL_BUILD_64BITS - $(call emugl-begin-host64-static-library,lib64OpenglOsUtils) - $(call emugl-export,C_INCLUDES,$(host_common_INCLUDES)) - LOCAL_SRC_FILES = $(host_common_SRC_FILES) - $(call emugl-export,LDLIBS,$(host_common_LDLIBS)) - $(call emugl-import,lib64emugl_common) - $(call emugl-export,CFLAGS,-m64 -fPIC) - $(call emugl-end-module) -endif diff --git a/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.cpp b/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.cpp deleted file mode 100644 index e8e6ab7..0000000 --- a/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* -* Copyright (C) 2011 The Android Open Source Project -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#include "osDynLibrary.h" - -#ifndef _WIN32 -#include <dlfcn.h> -#endif -#include <stdio.h> - -namespace osUtils { - -dynLibrary *dynLibrary::open(const char *p_libName) -{ - dynLibrary *lib = new dynLibrary(); - if (!lib) { - return NULL; - } - -#ifdef _WIN32 - lib->m_lib = LoadLibrary(p_libName); -#else // !WIN32 - lib->m_lib = dlopen(p_libName, RTLD_NOW); -#endif - - if (lib->m_lib == NULL) { - printf("Failed to load %s\n", p_libName); -#ifndef _WIN32 - printf("error %s\n", dlerror()); //only on linux -#endif - delete lib; - return NULL; - } - - return lib; -} - -dynLibrary::dynLibrary() : - m_lib(NULL) -{ -} - -dynLibrary::~dynLibrary() -{ - if (NULL != m_lib) { -#ifdef _WIN32 - FreeLibrary(m_lib); -#else // !WIN32 - dlclose(m_lib); -#endif - } -} - -dynFuncPtr dynLibrary::findSymbol(const char *p_symName) -{ - if (NULL == m_lib) { - return NULL; - } - -#ifdef _WIN32 - return (dynFuncPtr) GetProcAddress(m_lib, p_symName); -#else // !WIN32 - return (dynFuncPtr) dlsym(m_lib, p_symName); -#endif -} - -} // of namespace osUtils diff --git a/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.h b/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.h deleted file mode 100644 index c83fbf3..0000000 --- a/emulator/opengl/shared/OpenglOsUtils/osDynLibrary.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -* Copyright (C) 2011 The Android Open Source Project -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#ifndef _OSUTILS_DYN_LIBRARY_H -#define _OSUTILS_DYN_LIBRARY_H - -#ifdef _WIN32 -#include <windows.h> -#endif - -namespace osUtils { - -typedef void (*dynFuncPtr)(void); - -class dynLibrary -{ -public: - static dynLibrary *open(const char *p_libName); - ~dynLibrary(); - - dynFuncPtr findSymbol(const char *p_symName); - -private: - dynLibrary(); - -private: -#ifdef _WIN32 - HMODULE m_lib; -#else - void *m_lib; -#endif -}; - -} // of namespace osUtils - - - -// Macro to compose emugl shared library name under various OS and bitness -// eg. -// on x86_64, EMUGL_LIBNAME("foo") --> "lib64foo.so" - -#ifdef _WIN32 -# define DLL_EXTENSION "" // _WIN32 LoadLibrary only accept name w/o .dll extension -#elif defined(__APPLE__) -# define DLL_EXTENSION ".dylib" -#else -# define DLL_EXTENSION ".so" -#endif - -#if defined(__x86_64__) -# define EMUGL_LIBNAME(name) "lib64" name DLL_EXTENSION -#elif defined(__i386__) -# define EMUGL_LIBNAME(name) "lib" name DLL_EXTENSION -#else -/* This header is included by target w/o using EMUGL_LIBNAME(). Don't #error, leave it undefined */ -#endif - - -#endif diff --git a/emulator/opengl/shared/OpenglOsUtils/osProcess.h b/emulator/opengl/shared/OpenglOsUtils/osProcess.h deleted file mode 100644 index 82b31b3..0000000 --- a/emulator/opengl/shared/OpenglOsUtils/osProcess.h +++ /dev/null @@ -1,62 +0,0 @@ -/* -* Copyright (C) 2011 The Android Open Source Project -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#ifndef _OSUTILS_PROCESS_H -#define _OSUTILS_PROCESS_H - -#ifdef _WIN32 -#include <windows.h> -#endif - -namespace osUtils { - -class childProcess -{ -public: - static childProcess *create(const char *p_cmdLine, const char *p_startdir); - ~childProcess(); - - int getPID() - { -#ifdef _WIN32 - return m_proc.dwProcessId; -#else - return(m_pid); -#endif - } - - int tryWait(bool& isAlive); - bool wait(int *exitStatus); - -private: - childProcess() {}; - -private: -#ifdef _WIN32 - PROCESS_INFORMATION m_proc; -#else - int m_pid; -#endif -}; - -int ProcessGetPID(); -int ProcessGetTID(); -bool ProcessGetName(char *p_outName, int p_outNameLen); -int KillProcess(int pid, bool wait); -bool isProcessRunning(int pid); - -} // of namespace osUtils - -#endif diff --git a/emulator/opengl/shared/OpenglOsUtils/osProcessUnix.cpp b/emulator/opengl/shared/OpenglOsUtils/osProcessUnix.cpp deleted file mode 100644 index c97ff58..0000000 --- a/emulator/opengl/shared/OpenglOsUtils/osProcessUnix.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* -* Copyright (C) 2011 The Android Open Source Project -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#include "osProcess.h" -#include <stdio.h> -#include <stdlib.h> -#include <sys/wait.h> -#include <sys/types.h> -#include <poll.h> -#include <pthread.h> -#include <string.h> -#include <pwd.h> -#include <paths.h> -#include <errno.h> -#include <signal.h> -#include <unistd.h> -#include <assert.h> - -namespace osUtils { - -// -// buildArgList converts a command line into null terminated argument list. -// to be used with execv or execvp. -// each argument is seperated by space or tab, to specify multiple words -// at the same argument place it inside single-quoted or double-quoted string. -// -static char **buildArgList(const char *command) -{ - char **argv = NULL; - int argvSize = 0; - int nArgs = 0; - char *tmpcmd = strdup(command); - char *t = tmpcmd; - char *strStart = NULL; - int i = 0; - - #define ADD_ARG \ - { \ - nArgs++; \ - if (!argv) { \ - argvSize = 12; \ - argv = (char **)malloc(argvSize * sizeof(char *)); \ - } \ - else if (nArgs > argvSize) { \ - argvSize += 12; \ - argv = (char **)realloc(argv, argvSize * sizeof(char *)); \ - } \ - argv[nArgs-1] = t; \ - t = NULL; \ - } - - while( tmpcmd[i] != '\0' ) { - if (!strStart) { - if (tmpcmd[i] == '"' || tmpcmd[i] == '\'') { - strStart = &tmpcmd[i]; - } - else if (tmpcmd[i] == ' ' || tmpcmd[i] == '\t') { - tmpcmd[i] = '\0'; - if (t) ADD_ARG; - } - else if (!t) { - t = &tmpcmd[i]; - } - } - else if (tmpcmd[i] == *strStart) { - t = strStart; - strStart = NULL; - } - - i++; - } - if (t) { - ADD_ARG; - } - if (nArgs > 0) { - ADD_ARG; // for NULL terminating list - } - - return argv; -} - -static pid_t start_process(const char *command,const char *startDir) -{ - pid_t pid; - - pid = fork(); - - if (pid < 0) { - return pid; - } - else if (pid == 0) { - // - // Close all opened file descriptors - // - for (int i=3; i<256; i++) { - close(i); - } - - if (startDir) { - chdir(startDir); - } - - char **argv = buildArgList(command); - if (!argv) { - return -1; - } - execvp(argv[0], argv); - - perror("execl"); - exit(-101); - } - - return pid; -} - -childProcess * -childProcess::create(const char *p_cmdLine, const char *p_startdir) -{ - childProcess *child = new childProcess(); - if (!child) { - return NULL; - } - - child->m_pid = start_process(p_cmdLine, p_startdir); - if (child->m_pid < 0) { - delete child; - return NULL; - } - - return child; -} - -childProcess::~childProcess() -{ -} - -bool -childProcess::wait(int *exitStatus) -{ - int ret=0; - if (m_pid>0) { - pid_t pid = waitpid(m_pid,&ret,0); - if (pid != -1) { - m_pid=-1; - if (exitStatus) { - *exitStatus = ret; - } - return true; - } - } - return false; -} - -int -childProcess::tryWait(bool &isAlive) -{ - int ret=0; - isAlive = false; - if (m_pid>0) { - pid_t pid = waitpid(m_pid,&ret,WNOHANG); - if (pid == 0) { - isAlive = true; - } - } - - return ((char)WEXITSTATUS(ret)); -} - -int ProcessGetPID() -{ - return getpid(); -} - -int KillProcess(int pid, bool wait) -{ - if (pid<1) { - return false; - } - - if (0!=kill(pid,SIGTERM)) { - return false; - } - - if (wait) { - if (waitpid(pid,NULL,0)<0) { - return false; - } - } - - return true; -} - -bool isProcessRunning(int pid) -{ - return (kill(pid,0) == 0); -} - -} // of namespace osUtils diff --git a/emulator/opengl/shared/OpenglOsUtils/osProcessWin.cpp b/emulator/opengl/shared/OpenglOsUtils/osProcessWin.cpp deleted file mode 100644 index 6ff0fdf..0000000 --- a/emulator/opengl/shared/OpenglOsUtils/osProcessWin.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* -* Copyright (C) 2011 The Android Open Source Project -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#include "osProcess.h" -#include <windows.h> -#include <string> -#include <stdlib.h> -#include <psapi.h> - -namespace osUtils { - -childProcess * -childProcess::create(const char *p_cmdLine, const char *p_startdir) -{ - childProcess *child = new childProcess(); - if (!child) { - return NULL; - } - - STARTUPINFOA si; - ZeroMemory(&si, sizeof(si)); - - ZeroMemory(&child->m_proc, sizeof(child->m_proc)); - BOOL ret = CreateProcessA( - NULL , - (LPSTR)p_cmdLine, - NULL, - NULL, - FALSE, - CREATE_DEFAULT_ERROR_MODE, - NULL, - (p_startdir != NULL ? p_startdir : ".\\"), - &si, - &child->m_proc); - if (ret == 0) { - delete child; - return NULL; - } - - // close the thread handle we do not need it, - // keep the process handle for wait/trywait operations, will - // be closed on destruction - CloseHandle(child->m_proc.hThread); - - return child; -} - -childProcess::~childProcess() -{ - if (m_proc.hProcess) { - CloseHandle(m_proc.hProcess); - } -} - -bool -childProcess::wait(int *exitStatus) -{ -DWORD _exitStatus; - - if (WaitForSingleObject(m_proc.hProcess, INFINITE) == WAIT_FAILED) { - return false; - } - - if (!GetExitCodeProcess(m_proc.hProcess, &_exitStatus)) - { - return false; - } - - if (exitStatus) { - *exitStatus = _exitStatus; - } - - return true; -} - -int -childProcess::tryWait(bool& isAlive) -{ - DWORD status = WaitForSingleObject(m_proc.hProcess, 0); - - if(status == WAIT_OBJECT_0) - { - // process has exited - isAlive = false; - GetExitCodeProcess(m_proc.hProcess, &status); - } - else if (status == WAIT_TIMEOUT) - { - isAlive = true; - status = 0; - } - - return status; - -} - -int ProcessGetPID() -{ - return GetCurrentProcessId(); -} - -int ProcessGetTID() -{ - return GetCurrentThreadId(); -} - -bool ProcessGetName(char *p_outName, int p_outNameLen) -{ - return 0 != GetModuleFileNameEx( GetCurrentProcess(), NULL, p_outName, p_outNameLen); -} - -int KillProcess(int pid, bool wait) -{ - DWORD exitStatus = 1; - HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); - - if (NULL == hProc) { - return 0; - } - - // - // Terminate the process - // - TerminateProcess(hProc, 0x55); - - if (wait) { - // - // Wait for it to be terminated - // - if(WaitForSingleObject(hProc, INFINITE) == WAIT_FAILED) { - CloseHandle(hProc); - return 0; - } - - if (!GetExitCodeProcess(hProc, &exitStatus)) { - CloseHandle(hProc); - return 0; - } - } - - CloseHandle(hProc); - - return exitStatus; -} - -bool isProcessRunning(int pid) -{ - bool isRunning = false; - - HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, pid); - if (NULL != process) { - DWORD ret = WaitForSingleObject(process, 0); - CloseHandle(process); - isRunning = (ret == WAIT_TIMEOUT); - } - return isRunning; -} - -} // of namespace osUtils diff --git a/emulator/opengl/shared/OpenglOsUtils/osThread.h b/emulator/opengl/shared/OpenglOsUtils/osThread.h deleted file mode 100644 index 970396d..0000000 --- a/emulator/opengl/shared/OpenglOsUtils/osThread.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -* Copyright (C) 2011 The Android Open Source Project -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#ifndef _OSUTILS_THREAD_H -#define _OSUTILS_THREAD_H - -#ifdef _WIN32 -#include <windows.h> -#else // !WIN32 -#include <pthread.h> -#endif - -namespace osUtils { - -class Thread -{ -public: - Thread(); - virtual ~Thread(); - - virtual int Main() = 0; - - bool start(); - bool wait(int *exitStatus); - bool trywait(int *exitStatus); - -private: -#ifdef _WIN32 - static DWORD WINAPI thread_main(void *p_arg); -#else // !WIN32 - static void* thread_main(void *p_arg); -#endif - -private: -#ifdef _WIN32 - HANDLE m_thread; - DWORD m_threadId; -#else // !WIN32 - pthread_t m_thread; - int m_exitStatus; - pthread_mutex_t m_lock; -#endif - bool m_isRunning; -}; - -} // of namespace osUtils - -#endif diff --git a/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp b/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp deleted file mode 100644 index ef2bebc..0000000 --- a/emulator/opengl/shared/OpenglOsUtils/osThreadUnix.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* -* Copyright (C) 2011 The Android Open Source Project -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#include "osThread.h" - -#include "emugl/common/thread_store.h" - -#include <stdint.h> - -namespace osUtils { - -Thread::Thread() : - m_thread((pthread_t)NULL), - m_exitStatus(0), - m_isRunning(false) -{ - pthread_mutex_init(&m_lock, NULL); -} - -Thread::~Thread() -{ - pthread_mutex_destroy(&m_lock); -} - -bool -Thread::start() -{ - pthread_mutex_lock(&m_lock); - m_isRunning = true; - int ret = pthread_create(&m_thread, NULL, Thread::thread_main, this); - if(ret) { - m_isRunning = false; - } - pthread_mutex_unlock(&m_lock); - return m_isRunning; -} - -bool -Thread::wait(int *exitStatus) -{ - if (!m_isRunning) { - return false; - } - - void *retval; - if (pthread_join(m_thread,&retval)) { - return false; - } - - if (exitStatus) { - *exitStatus = (int)(uintptr_t)retval; - } - return true; -} - -bool -Thread::trywait(int *exitStatus) -{ - bool ret = false; - - pthread_mutex_lock(&m_lock); - if (!m_isRunning) { - *exitStatus = m_exitStatus; - ret = true; - } - pthread_mutex_unlock(&m_lock); - return ret; -} - -void * -Thread::thread_main(void *p_arg) -{ - Thread *self = (Thread *)p_arg; - int ret = self->Main(); - - pthread_mutex_lock(&self->m_lock); - self->m_isRunning = false; - self->m_exitStatus = ret; - pthread_mutex_unlock(&self->m_lock); - - ::emugl::ThreadStore::OnThreadExit(); - return (void*)(uintptr_t)ret; -} - -} // of namespace osUtils - diff --git a/emulator/opengl/shared/OpenglOsUtils/osThreadWin.cpp b/emulator/opengl/shared/OpenglOsUtils/osThreadWin.cpp deleted file mode 100644 index 1a30b97..0000000 --- a/emulator/opengl/shared/OpenglOsUtils/osThreadWin.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* -* Copyright (C) 2011 The Android Open Source Project -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -#include "osThread.h" - -#include "emugl/common/thread_store.h" - -namespace osUtils { - -Thread::Thread() : - m_thread(NULL), - m_threadId(0), - m_isRunning(false) -{ -} - -Thread::~Thread() -{ - if(m_thread) { - CloseHandle(m_thread); - } -} - -bool -Thread::start() -{ - m_isRunning = true; - m_thread = CreateThread(NULL, 0, &Thread::thread_main, this, 0, &m_threadId); - if(!m_thread) { - m_isRunning = false; - } - return m_isRunning; -} - -bool -Thread::wait(int *exitStatus) -{ - if (!m_isRunning) { - return false; - } - - if(WaitForSingleObject(m_thread, INFINITE) == WAIT_FAILED) { - return false; - } - - DWORD retval; - if (!GetExitCodeThread(m_thread,&retval)) { - return false; - } - - m_isRunning = 0; - - if (exitStatus) { - *exitStatus = retval; - } - return true; -} - -bool -Thread::trywait(int *exitStatus) -{ - if (!m_isRunning) { - return false; - } - - if(WaitForSingleObject(m_thread, 0) == WAIT_OBJECT_0) { - - DWORD retval; - if (!GetExitCodeThread(m_thread,&retval)) { - return true; - } - - if (exitStatus) { - *exitStatus = retval; - } - return true; - } - - return false; -} - -DWORD WINAPI -Thread::thread_main(void *p_arg) -{ - Thread *self = (Thread *)p_arg; - int ret = self->Main(); - self->m_isRunning = false; - ::emugl::ThreadStore::OnThreadExit(); - return ret; -} - -} // of namespace osUtils diff --git a/emulator/opengl/shared/emugl/common/Android.mk b/emulator/opengl/shared/emugl/common/Android.mk index 58dd6da..fb9ab57 100644 --- a/emulator/opengl/shared/emugl/common/Android.mk +++ b/emulator/opengl/shared/emugl/common/Android.mk @@ -9,16 +9,26 @@ commonSources := \ id_to_object_map.cpp \ lazy_instance.cpp \ pod_vector.cpp \ + shared_library.cpp \ smart_ptr.cpp \ sockets.cpp \ thread_store.cpp \ host_commonSources := $(commonSources) +host_commonLdLibs := -lstdc++ + +ifneq (windows,$(HOST_OS)) + host_commonSources += thread_pthread.cpp + host_commonLdLibs += -ldl -lpthread +else + host_commonSources += thread_win32.cpp +endif + $(call emugl-begin-host-static-library,libemugl_common) LOCAL_SRC_FILES := $(host_commonSources) $(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/shared) -$(call emugl-export,LDLIBS,-lstdc++) +$(call emugl-export,LDLIBS,$(host_commonLdLibs)) $(call emugl-end-module) ifdef EMUGL_BUILD_64BITS @@ -26,7 +36,7 @@ ifdef EMUGL_BUILD_64BITS LOCAL_SRC_FILES := $(host_commonSources) $(call emugl-export,CFLAGS,-m64 -fPIC) $(call emugl-export,C_INCLUDES,$(EMUGL_PATH)/shared) - $(call emugl-export,LDLIBS,-lstdc++) + $(call emugl-export,LDLIBS,$(host_commonLdLibs)) $(call emugl-end-module) endif @@ -38,8 +48,10 @@ host_commonSources := \ lazy_instance_unittest.cpp \ pod_vector_unittest.cpp \ mutex_unittest.cpp \ + shared_library_unittest.cpp \ smart_ptr_unittest.cpp \ thread_store_unittest.cpp \ + thread_unittest.cpp \ $(call emugl-begin-host-executable,emugl_common_host_unittests) LOCAL_SRC_FILES := $(host_commonSources) @@ -52,3 +64,13 @@ ifdef EMUGL_BUILD_64BITS $(call emugl-import,lib64emugl_common lib64emugl_gtest) $(call emugl-end-module) endif + +$(call emugl-begin-host-shared-library,libemugl_test_shared_library) +LOCAL_SRC_FILES := testing/test_shared_library.cpp +$(call emugl-end-module) + +ifdef EMUGL_BUILD_64BITS + $(call emugl-begin-host64-shared-library,lib64emugl_test_shared_library) + LOCAL_SRC_FILES := testing/test_shared_library.cpp + $(call emugl-end-module) +endif diff --git a/emulator/opengl/shared/emugl/common/shared_library.cpp b/emulator/opengl/shared/emugl/common/shared_library.cpp new file mode 100644 index 0000000..db1c75c --- /dev/null +++ b/emulator/opengl/shared/emugl/common/shared_library.cpp @@ -0,0 +1,105 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "emugl/common/shared_library.h" + +#include <stddef.h> +#include <string.h> +#include <stdio.h> + +#ifndef _WIN32 +#include <dlfcn.h> +#include <stdlib.h> +#endif + +namespace emugl { + +#ifdef _WIN32 + +// static +SharedLibrary* SharedLibrary::open(const char* libraryName) { + HMODULE lib = LoadLibrary(libraryName); + return lib ? new SharedLibrary(lib) : NULL; +} + +SharedLibrary::SharedLibrary(HandleType lib) : mLib(lib) {} + +SharedLibrary::~SharedLibrary() { + if (mLib) { + FreeLibrary(mLib); + } +} + +SharedLibrary::FunctionPtr SharedLibrary::findSymbol( + const char* symbolName) { + if (!mLib || !symbolName) { + return NULL; + } + return reinterpret_cast<FunctionPtr>( + GetProcAddress(mLib, symbolName)); +} + +#else // !_WIN32 + +// static +SharedLibrary* SharedLibrary::open(const char* libraryName) { + const char* libPath = libraryName; + char* path = NULL; + + const char* libBaseName = strrchr(libraryName, '/'); + if (!libBaseName) { + libBaseName = libraryName; + } + + if (!strchr(libBaseName, '.')) { + // There is no extension in this library name, so append one. +#ifdef __APPLE__ + static const char kDllExtension[] = ".dylib"; +#else + static const char kDllExtension[] = ".so"; +#endif + size_t pathLen = strlen(libraryName) + sizeof(kDllExtension); + path = static_cast<char*>(malloc(pathLen)); + snprintf(path, pathLen, "%s%s", libraryName, kDllExtension); + libPath = path; + } + + void* lib = dlopen(libPath, RTLD_NOW); + + if (path) { + free(path); + } + + return lib ? new SharedLibrary(lib) : NULL; +} + +SharedLibrary::SharedLibrary(HandleType lib) : mLib(lib) {} + +SharedLibrary::~SharedLibrary() { + if (mLib) { + dlclose(mLib); + } +} + +SharedLibrary::FunctionPtr SharedLibrary::findSymbol( + const char* symbolName) { + if (!mLib || !symbolName) { + return NULL; + } + return reinterpret_cast<FunctionPtr>(dlsym(mLib, symbolName)); +} + +#endif // !_WIN32 + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/shared_library.h b/emulator/opengl/shared/emugl/common/shared_library.h new file mode 100644 index 0000000..38d25bd --- /dev/null +++ b/emulator/opengl/shared/emugl/common/shared_library.h @@ -0,0 +1,85 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef EMUGL_COMMON_SHARED_LIBRARY_H +#define EMUGL_COMMON_SHARED_LIBRARY_H + +#ifdef _WIN32 +#include <windows.h> +#endif + +namespace emugl { + +// A class used to open a platform-specific shared library, and probe +// it for symbols. Usage is the following: +// +// // Open the library. +// SharedLibrary* library = SharedLibrary::open("libFoo"); +// if (!library) { +// ... could not find / open library! +// } +// +// //Probe for function symbol. +// FunctionPtr my_func = library->findSymbol("my_func"); +// +// // Closes library/ +// delete library; +// +class SharedLibrary { +public: + // Open a given library. |libraryName| can be either a full library + // path, or a simple name without an extension. On success, returns + // a new SharedLibrary instance that must be deleted by the caller. + static SharedLibrary* open(const char* libraryName); + + // Closes an existing SharedLibrary instance. + ~SharedLibrary(); + + // Generic function pointer type, for values returned by the + // findSymbol() method. + typedef void (*FunctionPtr)(void); + + // Probe a given SharedLibrary instance to find a symbol named + // |symbolName| in it. Return its address as a FunctionPtr, or + // NULL if the symbol is not found. + FunctionPtr findSymbol(const char* symbolName); + +private: +#ifdef _WIN32 + typedef HMODULE HandleType; +#else + typedef void* HandleType; +#endif + + // Constructor intentionally hidden. + SharedLibrary(HandleType); + + HandleType mLib; +}; + +// Macro to compose emugl shared library name under various OS and bitness +// eg. +// on x86_64, EMUGL_LIBNAME("foo") --> "lib64foo" + +#if defined(__x86_64__) +# define EMUGL_LIBNAME(name) "lib64" name +#elif defined(__i386__) +# define EMUGL_LIBNAME(name) "lib" name +#else +/* This header is included by target w/o using EMUGL_LIBNAME(). Don't #error, leave it undefined */ +#endif + +} // namespace emugl + +#endif // EMUGL_COMMON_SHARED_LIBRARY_H diff --git a/emulator/opengl/shared/emugl/common/shared_library_unittest.cpp b/emulator/opengl/shared/emugl/common/shared_library_unittest.cpp new file mode 100644 index 0000000..cec4c73 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/shared_library_unittest.cpp @@ -0,0 +1,141 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "emugl/common/shared_library.h" + +#include <gtest/gtest.h> + +#include <string> + +#include <limits.h> +#include <string.h> + +// Hack to get the current executable's full path. +namespace testing { +namespace internal { + +extern std::string g_executable_path; + +} // namespace internal +} // namespace testing + +namespace emugl { + +namespace { + +// Return the name/path of the test shared library to load. +// Note that this doesn't include a platform-specific extension. +// This assumes that the test shared library is under the lib/ sub-directory +// of the current executable's path! +std::string GetTestLibraryName() { + static const char kSubDir[] = "lib/"; +#ifdef __x86_64__ + static const char kLibraryPrefix[] = "lib64"; +#else + static const char kLibraryPrefix[] = "lib"; +#endif + static const char kTestLibrarySuffix[] = "emugl_test_shared_library"; + + const char* exec_path = testing::internal::g_executable_path.c_str(); + +#ifdef _WIN32 + const char* p = strrchr(exec_path, '/'); + const char* p2 = strrchr(exec_path, '\\'); + if (p2) { + if (!p || p2 > p) { + p = p2; + } + } +#else + const char* p = strrchr(exec_path, '/'); +#endif + + std::string path; + + if (!p) { + path = "./"; + } else { + path = std::string(exec_path, p - exec_path + 1U); + } + path += kSubDir; + path += kLibraryPrefix; + path += kTestLibrarySuffix; + printf("Library path: %s\n", path.c_str()); + return path; +} + +class SharedLibraryTest : public testing::Test { +public: + SharedLibraryTest() { + // Locate the shared library + mLibraryPath = GetTestLibraryName(); + } + + ~SharedLibraryTest() {} + + const char* library_path() const { return mLibraryPath.c_str(); } + +private: + std::string mLibraryPath; +}; + +class ScopedSharedLibrary { +public: + explicit ScopedSharedLibrary(SharedLibrary* lib) : mLib(lib) {} + ~ScopedSharedLibrary() { + delete mLib; + } + SharedLibrary* get() const { return mLib; } + + SharedLibrary* operator->() { return mLib; } + +private: + SharedLibrary* mLib; +}; + +} // namespace + +TEST_F(SharedLibraryTest, Open) { + ScopedSharedLibrary lib(SharedLibrary::open(library_path())); + EXPECT_TRUE(lib.get()); +} + +TEST_F(SharedLibraryTest, OpenWithExtension) { + std::string path = library_path(); +#ifdef _WIN32 + path += ".dll"; +#elif defined(__APPLE__) + path += ".dylib"; +#else + path += ".so"; +#endif + ScopedSharedLibrary lib(SharedLibrary::open(path.c_str())); + EXPECT_TRUE(lib.get()); +} + +TEST_F(SharedLibraryTest, FindSymbol) { + ScopedSharedLibrary lib(SharedLibrary::open(library_path())); + EXPECT_TRUE(lib.get()); + + if (lib.get()) { + typedef int (*FooFunction)(void); + + FooFunction foo_func = reinterpret_cast<FooFunction>( + lib->findSymbol("foo_function")); + EXPECT_TRUE(foo_func); + EXPECT_EQ(42, (*foo_func)()); + } +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp b/emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp new file mode 100644 index 0000000..598a963 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/testing/test_shared_library.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// This source file must be compiled into a simple shared library which +// will be used by shared_library_unittest.cpp to verify that the +// emugl::SharedLibrary class works properly. + + +extern "C" int foo_function(void) { + return 42; +} diff --git a/emulator/opengl/shared/emugl/common/thread.h b/emulator/opengl/shared/emugl/common/thread.h new file mode 100644 index 0000000..d0f7d20 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/thread.h @@ -0,0 +1,102 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef EMUGL_COMMON_THREAD_H +#define EMUGL_COMMON_THREAD_H + +#ifdef _WIN32 +#include <windows.h> +#else +#include <pthread.h> +#endif + +#include <stdint.h> + +namespace emugl { + +// Wrapper class for platform-specific threads. +// To create your own thread, define a sub-class of emugl::Thread +// and override its main() method. +// +// For example: +// +// class MyThread : public emugl::Thread { +// public: +// MyThread() : Thread() {} +// +// virtual intptr_t main() { +// ... main thread loop implementation +// return 0; +// } +// }; +// +// ... +// +// // Create new instance, but does not start it. +// MyThread* thread = new MyThread(); +// +// // Start the thread. +// thread->start(); +// +// // Wait for thread completion, and gets result into |exitStatus|. +// int exitStatus; +// thread->wait(&exitStatus); +// +class Thread { +public: + // Public constructor. + Thread(); + + // Virtual destructor. + virtual ~Thread(); + + // Override this method in your own thread sub-classes. This will + // be called when start() is invoked on the Thread instance. + virtual intptr_t main() = 0; + + // Start a thread instance. Return true on success, false otherwise + // (e.g. if the thread was already started or terminated). + bool start(); + + // Wait for thread termination and retrieve exist status into + // |*exitStatus|. Return true on success, false otherwise. + // NOTE: |exitStatus| can be NULL. + bool wait(intptr_t *exitStatus); + + // Check whether a thread has terminated. On success, return true + // and sets |*exitStatus|. On failure, return false. + // NOTE: |exitStatus| can be NULL. + bool tryWait(intptr_t *exitStatus); + +private: +#ifdef _WIN32 + static DWORD WINAPI thread_main(void* arg); + + HANDLE mThread; + DWORD mThreadId; + CRITICAL_SECTION mLock; +#else // !WIN32 + static void* thread_main(void* arg); + + pthread_t mThread; + pthread_mutex_t mLock; +#endif + intptr_t mExitStatus; + bool mIsRunning; +}; + +} // namespace emugl + +#endif // EMUGL_COMMON_THREAD_H + diff --git a/emulator/opengl/shared/emugl/common/thread_pthread.cpp b/emulator/opengl/shared/emugl/common/thread_pthread.cpp new file mode 100644 index 0000000..5dbc3ab --- /dev/null +++ b/emulator/opengl/shared/emugl/common/thread_pthread.cpp @@ -0,0 +1,114 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "emugl/common/thread.h" + +#include "emugl/common/thread_store.h" + +#include <stdio.h> + +namespace emugl { + +namespace { + +class ScopedLocker { +public: + ScopedLocker(pthread_mutex_t* mutex) : mMutex(mutex) { + pthread_mutex_lock(mMutex); + } + + ~ScopedLocker() { + pthread_mutex_unlock(mMutex); + } +private: + pthread_mutex_t* mMutex; +}; + +} // namespace + +Thread::Thread() : + mThread((pthread_t)NULL), + mExitStatus(0), + mIsRunning(false) { + pthread_mutex_init(&mLock, NULL); +} + +Thread::~Thread() { + pthread_mutex_destroy(&mLock); +} + +bool Thread::start() { + bool ret = true; + pthread_mutex_lock(&mLock); + mIsRunning = true; + if (pthread_create(&mThread, NULL, thread_main, this)) { + ret = false; + mIsRunning = false; + } + pthread_mutex_unlock(&mLock); + return ret; +} + +bool Thread::wait(intptr_t *exitStatus) { + { + ScopedLocker locker(&mLock); + if (!mIsRunning) { + // Thread already stopped. + if (exitStatus) { + *exitStatus = mExitStatus; + } + return true; + } + } + + // NOTE: Do not hold the lock when waiting for the thread to ensure + // it can update mIsRunning and mExitStatus properly in thread_main + // without blocking. + void *retval; + if (pthread_join(mThread, &retval)) { + return false; + } + if (exitStatus) { + *exitStatus = (intptr_t)retval; + } + return true; +} + +bool Thread::tryWait(intptr_t *exitStatus) { + ScopedLocker locker(&mLock); + if (!mIsRunning) { + return false; + } + if (exitStatus) { + *exitStatus = mExitStatus; + } + return true; +} + +// static +void* Thread::thread_main(void *arg) { + Thread* self = reinterpret_cast<Thread*>(arg); + intptr_t ret = self->main(); + + pthread_mutex_lock(&self->mLock); + self->mIsRunning = false; + self->mExitStatus = ret; + pthread_mutex_unlock(&self->mLock); + + ::emugl::ThreadStore::OnThreadExit(); + + return (void*)ret; +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/thread_unittest.cpp b/emulator/opengl/shared/emugl/common/thread_unittest.cpp new file mode 100644 index 0000000..db1931f --- /dev/null +++ b/emulator/opengl/shared/emugl/common/thread_unittest.cpp @@ -0,0 +1,109 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "emugl/common/thread.h" + +#include "emugl/common/mutex.h" + +#include <gtest/gtest.h> + +namespace emugl { + +namespace { + +// A simple thread instance that does nothing at all and exits immediately. +class EmptyThread : public ::emugl::Thread { +public: + intptr_t main() { return 42; } +}; + +class CountingThread : public ::emugl::Thread { +public: + class State { + public: + State() : mLock(), mCount(0) {} + ~State() {} + + void increment() { + mLock.lock(); + mCount++; + mLock.unlock(); + } + + int count() const { + int ret; + mLock.lock(); + ret = mCount; + mLock.unlock(); + return ret; + } + + private: + mutable Mutex mLock; + int mCount; + }; + + CountingThread(State* state) : mState(state) {} + + intptr_t main() { + mState->increment(); + return 0; + } + +private: + State* mState; +}; + +} // namespace + +TEST(ThreadTest, SimpleThread) { + Thread* thread = new EmptyThread(); + EXPECT_TRUE(thread); + EXPECT_TRUE(thread->start()); + intptr_t status; + EXPECT_TRUE(thread->wait(&status)); + EXPECT_EQ(42, status); +} + +TEST(ThreadTest, MultipleThreads) { + CountingThread::State state; + const size_t kMaxThreads = 100; + Thread* threads[kMaxThreads]; + + // Create all threads. + for (size_t n = 0; n < kMaxThreads; ++n) { + threads[n] = new CountingThread(&state); + EXPECT_TRUE(threads[n]) << "thread " << n; + } + + // Start them all. + for (size_t n = 0; n < kMaxThreads; ++n) { + EXPECT_TRUE(threads[n]->start()) << "thread " << n; + } + + // Wait for them all. + for (size_t n = 0; n < kMaxThreads; ++n) { + EXPECT_TRUE(threads[n]->wait(NULL)) << "thread " << n; + } + + // Check state. + EXPECT_EQ((int)kMaxThreads, state.count()); + + // Delete them all. + for (size_t n = 0; n < kMaxThreads; ++n) { + delete threads[n]; + } +} + +} // namespace emugl diff --git a/emulator/opengl/shared/emugl/common/thread_win32.cpp b/emulator/opengl/shared/emugl/common/thread_win32.cpp new file mode 100644 index 0000000..f348ca8 --- /dev/null +++ b/emulator/opengl/shared/emugl/common/thread_win32.cpp @@ -0,0 +1,122 @@ +// Copyright (C) 2014 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "emugl/common/thread.h" + +#include "emugl/common/thread_store.h" + +namespace emugl { + +namespace { + +class ScopedLocker { +public: + ScopedLocker(CRITICAL_SECTION* section) : mSection(section) { + EnterCriticalSection(mSection); + } + + ~ScopedLocker() { + LeaveCriticalSection(mSection); + } +private: + CRITICAL_SECTION* mSection; +}; + +} // namespace + +Thread::Thread() : + mThread(INVALID_HANDLE_VALUE), + mThreadId(0), + mExitStatus(0), + mIsRunning(false) { + InitializeCriticalSection(&mLock); +} + +Thread::~Thread() { + if(mThread != INVALID_HANDLE_VALUE) { + CloseHandle(mThread); + } + DeleteCriticalSection(&mLock); +} + +bool Thread::start() { + ScopedLocker locker(&mLock); + + bool ret = true; + mIsRunning = true; + mThread = CreateThread(NULL, 0, &Thread::thread_main, this, 0, &mThreadId); + if (!mThread) { + ret = false; + mIsRunning = false; + } + return ret; +} + +bool Thread::wait(intptr_t* exitStatus) { + { + ScopedLocker locker(&mLock); + if (!mIsRunning) { + // Thread already stopped. + if (exitStatus) { + *exitStatus = mExitStatus; + } + return true; + } + } + + // NOTE: Do not hold lock during wait to aloow thread_main to + // properly update mIsRunning and mExitStatus on thread exit. + if (WaitForSingleObject(mThread, INFINITE) == WAIT_FAILED) { + return false; + } + + if (exitStatus) { + ScopedLocker locker(&mLock); + *exitStatus = mExitStatus; + } + return true; +} + +bool Thread::tryWait(intptr_t* exitStatus) { + ScopedLocker locker(&mLock); + + if (!mIsRunning || + WaitForSingleObject(mThread, 0) != WAIT_OBJECT_0) { + return false; + } + + if (exitStatus) { + *exitStatus = mExitStatus; + } + return true; +} + +// static +DWORD WINAPI Thread::thread_main(void *arg) +{ + Thread* self = reinterpret_cast<Thread*>(arg); + intptr_t ret = self->main(); + + EnterCriticalSection(&self->mLock); + self->mIsRunning = false; + self->mExitStatus = ret; + LeaveCriticalSection(&self->mLock); + + // Ensure all thread-local values are released for this thread. + ::emugl::ThreadStore::OnThreadExit(); + + return static_cast<DWORD>(ret); +} + +} // namespace emugl |