emulator opengl: add OpenglOsUtils library, a set of OS utils.

This is just a set of OS dependant functionality needed by the
emulator OpenGL host renderer. It currently has implementation for
Linux and Windows only.

osDynLibrary - dlopen/dlsym abstraction
osProcess    - interface to launch a new process, wait and kill it.
osThread     - abstraction interface for creating a thread.

Change-Id: Ib0264592d8c87e865da87acf5c94e2b331801ca4
This commit is contained in:
Guy Zadikario
2011-04-10 11:34:56 +03:00
parent f7cd7ec421
commit 20368d96e0
9 changed files with 872 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
LOCAL_PATH := $(call my-dir)
emulatorOpengl := $(LOCAL_PATH)/../..
### OpenglOsUtils ##############################################
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
osProcessUnix.cpp \
osThreadUnix.cpp \
osDynLibrary.cpp
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := libOpenglOsUtils
include $(BUILD_STATIC_LIBRARY)
### OpenglOsUtils host ##############################################
include $(CLEAR_VARS)
ifeq ($(HOST_OS),linux)
LOCAL_SRC_FILES := \
osProcessUnix.cpp \
osThreadUnix.cpp \
osDynLibrary.cpp
else # !linux
ifeq ($(HOST_OS),windows)
LOCAL_SRC_FILES := \
osProcessWin.cpp \
osThreadWin.cpp \
osDynLibrary.cpp
else # !windows
LOCAL_SRC_FILES :=
endif # windows
endif # linux
ifneq (,$(LOCAL_SRC_FILES)) # do not build if host platform not supported
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := libOpenglOsUtils
include $(BUILD_HOST_STATIC_LIBRARY)
endif

View File

@@ -0,0 +1,75 @@
/*
* 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) {
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

View File

@@ -0,0 +1,48 @@
/*
* 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
#endif

View File

@@ -0,0 +1,64 @@
/*
* 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>
#elif !defined(__linux__)
#error "Unsupported platform"
#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;
#elif defined(__linux__)
return(m_pid);
#endif
}
int tryWait(bool& isAlive);
bool wait(int *exitStatus);
private:
childProcess() {};
private:
#ifdef _WIN32
PROCESS_INFORMATION m_proc;
#elif defined(__linux__)
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

View File

@@ -0,0 +1,210 @@
/*
* 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

View File

@@ -0,0 +1,171 @@
/*
* 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(m_proc.hThread);
return child;
}
childProcess::~childProcess()
{
if (m_proc.hProcess) {
CloseHandle(child->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

View File

@@ -0,0 +1,60 @@
/*
* 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

View File

@@ -0,0 +1,93 @@
/*
* 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"
namespace osUtils {
Thread::Thread() :
m_thread((pthread_t)NULL),
m_exitStatus(0),
m_isRunning(false)
{
pthread_mutex_init(&m_lock, NULL);
}
Thread::~Thread()
{
}
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;
}
long long int ret=(long long int)retval;
if (exitStatus) {
*exitStatus = (int)ret;
}
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;
void *ret = (void *)self->Main();
pthread_mutex_lock(&self->m_lock);
self->m_isRunning = false;
self->m_exitStatus = (int)ret;
pthread_mutex_unlock(&self->m_lock);
return ret;
}
} // of namespace osUtils

View File

@@ -0,0 +1,101 @@
/*
* 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"
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;
return ret;
}
} // of namespace osUtils