@@ -0,0 +1,251 @@ | |||
#define LOG_TAG "JAMSHMSERVICE" | |||
#include <stddef.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include <binder/MemoryHeapBase.h> | |||
#include <binder/IServiceManager.h> | |||
#include <binder/IPCThreadState.h> | |||
#include <utils/Log.h> | |||
#include <sys/stat.h> | |||
#include <sys/socket.h> | |||
#include <sys/types.h> | |||
#include <sys/un.h> | |||
#include <sys/wait.h> | |||
#include "BnAndroidShm.h" | |||
#include "AndroidShm.h" | |||
#include "JackConstants.h" | |||
#include <fcntl.h> | |||
#include <signal.h> | |||
#include <limits.h> | |||
#include <errno.h> | |||
#include <dirent.h> | |||
#include <sys/mman.h> | |||
#include <linux/ashmem.h> | |||
#include <cutils/ashmem.h> | |||
#include "JackError.h" | |||
#include <semaphore.h> | |||
#define MEMORY_SIZE 10*1024 | |||
#define SEMAPHORE_NULL_CHAR '\0' | |||
// remove ALOGI log | |||
#undef ALOGI | |||
#define ALOGI | |||
namespace android { | |||
int AndroidShm::instantiate() { | |||
defaultServiceManager()->addService(String16("com.samsung.android.jam.IAndroidShm"), new AndroidShm); // SINGLETON WITH SAME NAME | |||
return 0; | |||
} | |||
int AndroidShm::sendCommand(const char* command) { | |||
ALOGI("I(pid:%d) send command is %s\n", getpid(), command); | |||
if(strcmp(command, "semaphore") == 0) { | |||
// print debug message about semaphore simulation | |||
for(int i = MAX_SEMAPHORE_MEMORY_COUNT -1 ; i >= 0; i--) { | |||
printf("index[%3d] = ptr[%p] name[%s]\n", i, (mSemaphore[i] != NULL)?mSemaphore[i]->getBase():0, mSemaphoreName[i]); | |||
ALOGI("index[%3d] = ptr[%p] name[%s]\n", i, (mSemaphore[i] != NULL)?mSemaphore[i]->getBase():0, mSemaphoreName[i]); | |||
} | |||
} | |||
return NO_ERROR; | |||
} | |||
int AndroidShm::testGetBufferByNewProcess() { | |||
ALOGI("testGetBufferByNewProcess..."); | |||
int status; | |||
int childPid = fork(); | |||
if(childPid > 0) { | |||
ALOGI("I(pid%d) made a child process(pid:%d)", getpid(), childPid); | |||
ALOGI("I(pid%d) wait until child(%d) was finish", getpid(), childPid); | |||
wait(&status); | |||
// wait ํ์ง ์์ผ๋ฉด child process๊ฐ ๋จ์ ์์. | |||
ALOGI("child(%d) was finished. ", childPid); | |||
} else if(childPid == 0) { | |||
ALOGI("im a new child process(pid:%d) ", getpid()); | |||
if(-1 == execlp("/system/bin/getbufferclient","getbufferclient",NULL)) { | |||
ALOGE("failed to execute getbufferclient"); | |||
} | |||
exit(0); | |||
} else { | |||
ALOGI("failed creating child process"); | |||
} | |||
return 0; | |||
} | |||
int AndroidShm::testGetBuffer() { | |||
ALOGI("I(pid:%d) trying to test get buffer...", getpid()); | |||
sp<IServiceManager> sm = defaultServiceManager(); | |||
ALOGI("get default ServiceManager is done"); | |||
sp<IBinder> b; | |||
//String16* serviceName = new String16("com.samsung.android.jam.IAndroidShm"); | |||
do { | |||
//ALOGI("here"); | |||
b = sm->getService(String16("com.samsung.android.jam.IAndroidShm")); | |||
//ALOGI("getservice is done"); | |||
if(b != 0) | |||
break; | |||
//ALOGI("AndroidShm is not working, waiting..."); | |||
usleep(500000); | |||
} while(true); | |||
sp<IAndroidShm> service = interface_cast<IAndroidShm>(b); | |||
//shared buffer. | |||
sp<IMemoryHeap> receiverMemBase = service->getBuffer(0); | |||
unsigned int *base = (unsigned int *) receiverMemBase->getBase(); | |||
int ret = 0; | |||
if(base != (unsigned int *) -1) { | |||
ALOGD("AndroidShm::testGetBuffer base=%p Data=0x%x\n",base, *base); | |||
*base = (*base)+1; | |||
ret = (unsigned int)(*base); | |||
ALOGI("AndroidShm::testGetBuffer base=%p Data=0x%x CHANGED\n",base, *base); | |||
receiverMemBase = 0; | |||
} else { | |||
ALOGE("Error shared memory not available\n"); | |||
} | |||
return 0; | |||
} | |||
sp<IMemoryHeap> AndroidShm::getBuffer(int index) { | |||
ALOGI("I(pid:%d) getBuffer index:%d", getpid(), index); | |||
if(index < 0 || index >= MAX_SHARED_MEMORY_COUNT) { | |||
ALOGE("error : out of index [%d]", index); | |||
return NULL; | |||
} | |||
return mMemHeap[index]; | |||
} | |||
int AndroidShm::MemAlloc(unsigned int size) { | |||
ALOGI("try to allocate memory size[%d]", size); | |||
for(int i = 0; i < MAX_SHARED_MEMORY_COUNT; i++) { | |||
if(mMemHeap[i] == NULL) { | |||
mMemHeap[i] = new MemoryHeapBase(size); | |||
if(mMemHeap[i] == NULL){ | |||
ALOGI("fail to alloc, try one more..."); | |||
continue; // try one more. | |||
} | |||
return i; | |||
} | |||
} | |||
ALOGE("fail to MemAlloc"); | |||
return -1; // fail to alloc | |||
} | |||
AndroidShm::AndroidShm() { | |||
ALOGI("AndroidShm is created"); | |||
for(int i = 0; i < MAX_SHARED_MEMORY_COUNT; i++) { | |||
mMemHeap[i] = NULL; | |||
} | |||
mRegistryIndex = 10000; | |||
//mMemHeap = new MemoryHeapBase(MEMORY_SIZE); | |||
//unsigned int *base = (unsigned int*) mMemHeap->getBase(); | |||
//*base = 0xdeadcafe;// | |||
for(int j = 0; j < MAX_SEMAPHORE_MEMORY_COUNT; j++) { | |||
mSemaphore[j] = NULL; | |||
memset(mSemaphoreName[j], SEMAPHORE_NULL_CHAR, MAX_SEMAPHORE_NAME_LENGTH); | |||
} | |||
} | |||
AndroidShm::~AndroidShm() { | |||
ALOGI("AndroidShm is destroyed"); | |||
for(int i = 0; i < MAX_SHARED_MEMORY_COUNT; i++) { | |||
(mMemHeap[i]).clear(); | |||
} | |||
for(int j = 0; j < MAX_SEMAPHORE_MEMORY_COUNT; j++) { | |||
(mSemaphore[j]).clear(); | |||
} | |||
} | |||
//status_t AndroidShm::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { | |||
// return BnAndroidShm::onTransact(code, data, reply, flags); | |||
//} | |||
int AndroidShm::allocShm(const int size) { // if negative return value is error | |||
ALOGI("try to alloc shared memory size[%d]", size); | |||
return MemAlloc(size); | |||
} | |||
int AndroidShm::removeShm(const unsigned int index) { // shared memory ์ ๊ฑฐ | |||
ALOGI("try to remove shared memory index[%d]", index); | |||
if(index >= MAX_SHARED_MEMORY_COUNT) { | |||
ALOGE("remove shared memory: out of index"); | |||
return -1; | |||
} | |||
(mMemHeap[index]).clear(); | |||
return 1; | |||
} | |||
int AndroidShm::isAllocated(const unsigned int index) { // allocated ์ฌ๋ถ ํ์ธ | |||
ALOGI("try to check the memory allocation index[%d]", index); | |||
if(index >= MAX_SHARED_MEMORY_COUNT) { | |||
ALOGE("shared memory: out of index"); | |||
return 0; | |||
} | |||
if(mMemHeap[index] == NULL) | |||
return 0; | |||
else | |||
return 1; | |||
} | |||
int AndroidShm::setRegistryIndex(const unsigned int index) { | |||
ALOGI("set registry index %d", index); | |||
mRegistryIndex = index; | |||
return 1; | |||
} | |||
int AndroidShm::getRegistryIndex() { | |||
return mRegistryIndex; | |||
} | |||
sp<IMemoryHeap> AndroidShm::InitSemaphore(const char* name) { | |||
ALOGI("init semaphore [%s]", name); | |||
for(int i = 0; i < MAX_SEMAPHORE_MEMORY_COUNT; i++) { | |||
if(mSemaphoreName[i][0] == SEMAPHORE_NULL_CHAR) { | |||
mSemaphore[i] = new MemoryHeapBase(sizeof(sem_t)); | |||
if(mSemaphore[i] == NULL){ | |||
ALOGI("fail to alloc, try one more..."); | |||
continue; | |||
} | |||
if(sem_init((sem_t*)(mSemaphore[i]->getBase()), 1, 0) == 0) { | |||
strncpy(mSemaphoreName[i], name, MAX_SEMAPHORE_NAME_LENGTH - 1); | |||
mSemaphoreName[i][MAX_SEMAPHORE_NAME_LENGTH - 1] = '\0'; | |||
ALOGI("sem_init success"); | |||
return mSemaphore[i]; | |||
} else { | |||
(mSemaphore[i]).clear(); | |||
ALOGE("sem_init failed null returned"); | |||
return NULL; | |||
} | |||
} else { | |||
// find already exist name | |||
if(strcmp(mSemaphoreName[i], name) == 0) { // found | |||
ALOGI("found - return alread allocated semaphore"); | |||
return mSemaphore[i]; | |||
} | |||
} | |||
} | |||
ALOGE("sem_init failed null returned 2"); | |||
return NULL; | |||
} | |||
}; | |||
@@ -0,0 +1,51 @@ | |||
#ifndef ANDROIDSHM | |||
#define ANDROIDSHM | |||
#include <binder/Parcel.h> | |||
#include "BnAndroidShm.h" | |||
#include <utils/Log.h> | |||
#include <binder/MemoryHeapBase.h> | |||
#include "shm.h" | |||
#include "android/Shm.h" //android extension of shm.h | |||
namespace android { | |||
class AndroidShm : public BnAndroidShm | |||
{ | |||
#define MAX_SHARED_MEMORY_COUNT 257 | |||
private: | |||
int MemAlloc(unsigned int size); | |||
public: | |||
virtual ~AndroidShm(); | |||
static int instantiate(); | |||
virtual int sendCommand(const char* command); | |||
virtual int allocShm(const int size); // if negative return value is error | |||
virtual int removeShm(const unsigned int index); // shared memory รยฆยฐร | |||
virtual int isAllocated(const unsigned int index); // allocated ยฟยฉยบร รยฎรร | |||
virtual int setRegistryIndex(const unsigned int index); | |||
virtual int getRegistryIndex(); | |||
virtual sp<IMemoryHeap> InitSemaphore(const char* name); | |||
virtual sp<IMemoryHeap> getBuffer(int index); | |||
//virtual status_t onTransact( | |||
// uint32_t code, | |||
// const Parcel& data, | |||
// Parcel* reply, | |||
// uint32_t flags); | |||
private: | |||
int testGetBuffer(); | |||
int testGetBufferByNewProcess(); | |||
AndroidShm(); | |||
sp<MemoryHeapBase> mMemHeap[MAX_SHARED_MEMORY_COUNT]; | |||
unsigned int mRegistryIndex; | |||
// for named semaphore simulation | |||
#define MAX_SEMAPHORE_MEMORY_COUNT 300 | |||
#define MAX_SEMAPHORE_NAME_LENGTH 300 | |||
sp<MemoryHeapBase> mSemaphore[MAX_SEMAPHORE_MEMORY_COUNT]; | |||
char mSemaphoreName[MAX_SEMAPHORE_MEMORY_COUNT][MAX_SEMAPHORE_NAME_LENGTH]; | |||
}; | |||
}; | |||
#endif |
@@ -0,0 +1,19 @@ | |||
#define LOG_TAG "main_androidshmservice" | |||
#include <binder/IPCThreadState.h> | |||
#include <binder/ProcessState.h> | |||
#include <binder/IServiceManager.h> | |||
#include <utils/Log.h> | |||
#include "../../common/shm.h" | |||
#include "../Shm.h" //android extension of shm.h | |||
using namespace android; | |||
int main(int argc, char *argv[]) { | |||
jack_instantiate(); | |||
ProcessState::self()->startThreadPool(); | |||
ALOGI("AndroidShmService is starting now"); | |||
IPCThreadState::self()->joinThreadPool(); | |||
return 0; | |||
} |
@@ -0,0 +1,23 @@ | |||
IAndroidShm์ ๊ธฐ๋ฅ์ ํ ์คํธ ํ๊ธฐ ์ํ ์ฉ๋๋ก ์ฌ์ฉ๋๋ ํ๋ก๊ทธ๋จ์ ๋๋ค. | |||
AndroidShm์ service manager์ shared memory๋ฅผ ํ ๋นํด์ฃผ๋ ์๋น์ค์ ๋๋ค. | |||
service name: com.sec.apa.IAndroidShm | |||
์คํ ํ์ผ: | |||
/system/bin/androidshmservice | |||
------------------------------------------- | |||
./test | |||
AndroidShmService๋ฅผ ํ ์คํธํ๋ ํ๋ก๊ทธ๋จ | |||
/system/bin/shmservicetest | |||
AndroidShmService์์ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ UnitTestํฉ๋๋ค. | |||
๋์ ํ์ธ ๋ฐฉ๋ฒ: | |||
adb logcat ์ผ๋ก ๋ก๊ทธ๋ก ์ฑ๊ณต/์คํจ ํ์ธํจ. | |||
์ ์ ์กฐ๊ฑด: | |||
/system/bin/androidshmservice๋ฅผ ์คํ์ค์ธ ์ํ์ด์ด์ผ ํฉ๋๋ค. |
@@ -0,0 +1,177 @@ | |||
#include "../../IAndroidShm.h" | |||
#include <binder/MemoryHeapBase.h> | |||
#include <binder/IServiceManager.h> | |||
#include "../../../common/shm.h" | |||
namespace android { | |||
static sp<IMemoryHeap> receiverMemBase; | |||
#define MAX_SHARED_MEMORY_COUNT 257 | |||
sp<IAndroidShm> getAndroidShmService() { | |||
sp<IAndroidShm> shm = 0; | |||
/* Get the buffer service */ | |||
if (shm == NULL) { | |||
sp<IServiceManager> sm = defaultServiceManager(); | |||
sp<IBinder> binder; | |||
binder = sm->getService(String16("com.samsung.android.jam.IAndroidShm")); | |||
if (binder != 0) { | |||
shm = IAndroidShm::asInterface(binder); | |||
//shm = interface_cast<IAndroidShm>(binder); | |||
} | |||
} | |||
return shm; | |||
} | |||
unsigned int * getBufferMemPointer(int index) | |||
{ | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if (shm == NULL) { | |||
printf("The EneaBufferServer is not published\n"); | |||
return (unsigned int *)-1; /* return an errorcode... */ | |||
} else { | |||
receiverMemBase = shm->getBuffer(index); | |||
if(receiverMemBase != NULL) | |||
return (unsigned int *) receiverMemBase->getBase(); | |||
else | |||
return (unsigned int*)-1; | |||
} | |||
} | |||
} | |||
using namespace android; | |||
void showStatus() { | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if(shm == NULL) { | |||
printf("shm service is not available\n"); | |||
return; | |||
} | |||
printf("<<<<<<<<<<< dump memory allocation status >>>>>>>>>>\n"); | |||
for(int i = 256; i >= 0; i--) { | |||
if(shm->isAllocated(i) == 1) { | |||
printf("Mem[%3d] == 0x%x\n", i, (unsigned int)getBufferMemPointer(i)); | |||
} else { | |||
printf("Mem[%3d] == NULL\n", i); | |||
} | |||
} | |||
} | |||
void showRegistryIndex() { | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if(shm == NULL) { | |||
printf("shm service is not available\n"); | |||
return; | |||
} | |||
printf("<<<<<<<<<<< show registry index >>>>>>>>>>\n"); | |||
printf("index [%3d]\n",shm->getRegistryIndex()); | |||
} | |||
void showHeader() { | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if(shm == NULL) { | |||
printf("shm service is not available\n"); | |||
return; | |||
} | |||
if(shm->getRegistryIndex() > 256) { | |||
printf("don't have a registry header\n"); | |||
return; | |||
} | |||
unsigned int* buffer = getBufferMemPointer(shm->getRegistryIndex()); | |||
if(buffer) { | |||
jack_shm_header_t * header = (jack_shm_header_t*)buffer; | |||
printf("<<<<<<<<<< register header value >>>>>>>>>>\n"); | |||
printf("memory address 0x%x 0x%x\n", (unsigned int)(header), (unsigned int)buffer); | |||
printf("magic = %d\n", header->magic); | |||
printf("protocol = %d\n", header->protocol); | |||
printf("type = %d\n", header->type); | |||
printf("size = %d\n", header->size); | |||
printf("hdr_len = %d\n", header->hdr_len); | |||
printf("entry_len = %d\n", header->entry_len); | |||
for(int j = 0; j < MAX_SERVERS; j++) { | |||
//char name[256]; | |||
//memset(name, '\0', 256); | |||
//strncpy(name, header->server[j].name, 10); | |||
printf("server[%d] pid = %d, name = %s\n", j, header->server[j].pid, header->server[j].name); | |||
} | |||
} | |||
} | |||
void showBody() { | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if(shm == NULL) { | |||
printf("shm service is not available\n"); | |||
return; | |||
} | |||
if(shm->getRegistryIndex() > 256) { | |||
printf("don't have a registry body\n"); | |||
return; | |||
} | |||
unsigned int* buffer = getBufferMemPointer(shm->getRegistryIndex()); | |||
if(buffer) { | |||
jack_shm_header_t * header = (jack_shm_header_t*)buffer; | |||
printf("<<<<<<<<<< registry body value >>>>>>>>>>\n"); | |||
jack_shm_registry_t * registry = (jack_shm_registry_t *) (header + 1); | |||
for(int k = 255; k >= 0; k--) { | |||
printf("registry[%3d] index[%3d],allocator[%3d],size[%6d],id[%10s],fd[%3d]\n", k, | |||
registry[k].index, registry[k].allocator, registry[k].size, | |||
registry[k].id, | |||
registry[k].fd); | |||
} | |||
} | |||
} | |||
void showSemaphore() { | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if(shm == NULL) { | |||
printf("shm service is not available\n"); | |||
return; | |||
} | |||
shm->sendCommand("semaphore"); | |||
printf("log will be shown in the logcat log\n"); | |||
} | |||
int main(int argc, char** argv) { | |||
// base could be on same address as Servers base but this | |||
// is purely by luck do NEVER rely on this. Linux memory | |||
// management may put it wherever it likes. | |||
if(argc < 2) { | |||
printf("usage\n shmservicedump [status|header|body|index|semaphore]\n"); | |||
printf(" status: show the shared memory allocation status\n"); | |||
printf(" header: show the registry header infomations if the registry exist\n"); | |||
printf(" body: show the registry body infomations if the registry exist\n"); | |||
printf(" index: show the index of array that is allocated registry shared memory\n"); | |||
printf(" semaphore: show the memory array about semaphore simulation\n"); | |||
return 0; | |||
} | |||
if(strcmp(argv[1], "semaphore") == 0) { | |||
showSemaphore(); | |||
} else if(strcmp(argv[1], "index") == 0) { | |||
showRegistryIndex(); | |||
} else if(strcmp(argv[1], "status") == 0) { | |||
showStatus(); | |||
} else if(strcmp(argv[1], "header") == 0) { | |||
showHeader(); | |||
} else if(strcmp(argv[1], "body") == 0) { | |||
showBody(); | |||
} else { | |||
printf("%s is invalid parameter\n", argv[1]); | |||
} | |||
return 0; | |||
} |
@@ -0,0 +1,189 @@ | |||
#include "../../IAndroidShm.h" | |||
#include <binder/MemoryHeapBase.h> | |||
#include <binder/IServiceManager.h> | |||
namespace android { | |||
static sp<IMemoryHeap> receiverMemBase; | |||
#define MAX_SHARED_MEMORY_COUNT 257 | |||
sp<IAndroidShm> getAndroidShmService() { | |||
sp<IAndroidShm> shm = 0; | |||
/* Get the buffer service */ | |||
if (shm == NULL) { | |||
sp<IServiceManager> sm = defaultServiceManager(); | |||
sp<IBinder> binder; | |||
binder = sm->getService(String16("com.samsung.android.jam.IAndroidShm")); | |||
if (binder != 0) { | |||
shm = IAndroidShm::asInterface(binder); | |||
//shm = interface_cast<IAndroidShm>(binder); | |||
} | |||
} | |||
return shm; | |||
} | |||
unsigned int * getBufferMemPointer(int index) { | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if (shm == NULL) { | |||
ALOGE("The EneaBufferServer is not published"); | |||
return (unsigned int *)-1; /* return an errorcode... */ | |||
} else { | |||
receiverMemBase = shm->getBuffer(index); | |||
if(receiverMemBase != NULL) | |||
return (unsigned int *) receiverMemBase->getBase(); | |||
else | |||
return (unsigned int*)-1; | |||
} | |||
} | |||
} | |||
using namespace android; | |||
void setup_test() { | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if(shm == NULL) return; | |||
for(int i = 0; i < MAX_SHARED_MEMORY_COUNT; i++) { | |||
shm->removeShm(i); | |||
} | |||
} | |||
void teardown_test() { | |||
} | |||
void increase_value_once() { | |||
ALOGD("*****test: increase_value_once*****\n"); | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if(shm == NULL) return; | |||
int slot = shm->allocShm(10000); | |||
unsigned int *base = getBufferMemPointer(slot); | |||
if(base != (unsigned int *)-1) { | |||
ALOGD("ShmServiceTest base=%p Data=0x%x\n",base, *base); | |||
*base = (*base)+1; | |||
ALOGD("ShmServiceTest base=%p Data=0x%x CHANGED\n",base, *base); | |||
//receiverMemBase = 0; | |||
} else { | |||
ALOGE("Error shared memory not available\n"); | |||
} | |||
} | |||
void increase_value_10times() { | |||
ALOGD("*****test: increase_value_10times*****\n"); | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if(shm == NULL) return; | |||
int slot = shm->allocShm(10000); | |||
for(int i = 0; i < 10; i++) { | |||
unsigned int *base = getBufferMemPointer(slot); | |||
if(base != (unsigned int *)-1) { | |||
ALOGD("ShmServiceTest base=%p Data=0x%x\n",base, *base); | |||
*base = (*base)+1; | |||
ALOGD("ShmServiceTest base=%p Data=0x%x CHANGED\n",base, *base); | |||
//receiverMemBase = 0; | |||
} else { | |||
ALOGE("Error shared memory not available\n"); | |||
} | |||
} | |||
} | |||
void check_allocated() { | |||
ALOGD("*****test: check_allocated*****\n"); | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if(shm == NULL) return; | |||
int slot = shm->allocShm(10000); | |||
int i = 0; | |||
for(; i < MAX_SHARED_MEMORY_COUNT; i++) { | |||
if(slot == i) { | |||
if(shm->isAllocated(i) == 1) { | |||
//ALOGD("pass\n"); | |||
} else { | |||
ALOGD("failed\n"); | |||
} | |||
} else { | |||
if(shm->isAllocated(i) == 0) { | |||
//ALOGD("pass\n"); | |||
} else { | |||
ALOGD("failed\n"); | |||
} | |||
} | |||
} | |||
if(i == MAX_SHARED_MEMORY_COUNT) { | |||
ALOGD("pass\n"); | |||
} | |||
} | |||
void test_set_get_registry_index() { | |||
ALOGD("*****test: test_set_get_registry_index*****\n"); | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if(shm == NULL) return; | |||
int registry = 1; | |||
shm->setRegistryIndex(registry); | |||
if(registry == shm->getRegistryIndex()) { | |||
ALOGD("pass\n"); | |||
} else { | |||
ALOGD("fail\n"); | |||
} | |||
registry = 0; | |||
shm->setRegistryIndex(registry); | |||
if(registry == shm->getRegistryIndex()) { | |||
ALOGD("pass\n"); | |||
} else { | |||
ALOGD("fail\n"); | |||
} | |||
} | |||
void test_memset() { | |||
ALOGD("*****test: test_memset*****\n"); | |||
sp<IAndroidShm> shm = getAndroidShmService(); | |||
if(shm == NULL) return; | |||
int slot = shm->allocShm(10000); | |||
unsigned int * pnt = getBufferMemPointer(slot); | |||
memset (pnt, 0, 10000); | |||
ALOGD("result : 0 0 0 0\n"); | |||
ALOGD("memory dump : %d %d %d %d\n", pnt[0], pnt[1], pnt[2], pnt[3]); | |||
memset (pnt, 0xffffffff, 10000); | |||
ALOGD("result : -1 -1 -1 -1\n"); | |||
ALOGD("memory dump : %d %d %d %d", pnt[0], pnt[1], pnt[2], pnt[3]); | |||
} | |||
int main(int argc, char** argv) { | |||
// base could be on same address as Servers base but this | |||
// is purely by luck do NEVER rely on this. Linux memory | |||
// management may put it wherever it likes. | |||
setup_test(); | |||
increase_value_once(); | |||
teardown_test(); | |||
setup_test(); | |||
increase_value_10times(); | |||
teardown_test(); | |||
setup_test(); | |||
check_allocated(); | |||
teardown_test(); | |||
setup_test(); | |||
test_set_get_registry_index(); | |||
teardown_test(); | |||
setup_test(); | |||
test_memset(); | |||
teardown_test(); | |||
return 0; | |||
} | |||
@@ -0,0 +1,83 @@ | |||
#include "BnAndroidShm.h" | |||
#include <binder/Parcel.h> | |||
namespace android { | |||
status_t BnAndroidShm::onTransact( uint32_t code, | |||
const Parcel &data, | |||
Parcel *reply, | |||
uint32_t flags) | |||
{ | |||
switch(code) { | |||
case HW_SENDCOMMAND:{ | |||
CHECK_INTERFACE(IAndroidShm, data, reply); | |||
const char *str; | |||
str = data.readCString(); | |||
reply->writeInt32(sendCommand(str)); | |||
return NO_ERROR; | |||
}break; | |||
case HW_GETBUFFER:{ | |||
CHECK_INTERFACE(IAndroidShm, data, reply); | |||
int32_t index; | |||
data.readInt32(&index); | |||
sp<IMemoryHeap> Data = getBuffer(index); | |||
if(Data != NULL){ | |||
reply->writeStrongBinder(Data->asBinder()); | |||
} | |||
return NO_ERROR; | |||
}break; | |||
case HW_ALLOC_SHM:{ | |||
CHECK_INTERFACE(IAndroidShm, data, reply); | |||
int32_t size; | |||
data.readInt32(&size); | |||
reply->writeInt32(allocShm(size)); | |||
return NO_ERROR; | |||
}break; | |||
case HW_REMOVE_SHM:{ | |||
CHECK_INTERFACE(IAndroidShm, data, reply); | |||
int32_t index; | |||
data.readInt32(&index); | |||
reply->writeInt32(removeShm(index)); | |||
return NO_ERROR; | |||
}break; | |||
case HW_IS_ALLOCATED:{ | |||
CHECK_INTERFACE(IAndroidShm, data, reply); | |||
int32_t index; | |||
data.readInt32(&index); | |||
reply->writeInt32(isAllocated(index)); | |||
return NO_ERROR; | |||
}break; | |||
case HW_SET_REGISTRY_INDEX:{ | |||
CHECK_INTERFACE(IAndroidShm, data, reply); | |||
int32_t index; | |||
data.readInt32(&index); | |||
reply->writeInt32(setRegistryIndex(index)); | |||
return NO_ERROR; | |||
}break; | |||
case HW_GET_REGISTRY_INDEX:{ | |||
CHECK_INTERFACE(IAndroidShm, data, reply); | |||
reply->writeInt32(getRegistryIndex()); | |||
return NO_ERROR; | |||
}break; | |||
case HW_INIT_SEMAPHORE:{ | |||
CHECK_INTERFACE(IAndroidShm, data, reply); | |||
const char *name; | |||
name = data.readCString(); | |||
sp<IMemoryHeap> Data = InitSemaphore(name); | |||
if(Data != NULL){ | |||
reply->writeStrongBinder(Data->asBinder()); | |||
} | |||
return NO_ERROR; | |||
}break; | |||
default: | |||
return BBinder::onTransact(code, data, reply, flags); | |||
} | |||
} | |||
}; |
@@ -0,0 +1,16 @@ | |||
#ifndef BNANDROIDSHM | |||
#define BNANDROIDSHM | |||
#include <binder/Parcel.h> | |||
#include "IAndroidShm.h" | |||
namespace android { | |||
class BnAndroidShm : public BnInterface<IAndroidShm> { | |||
public: | |||
virtual status_t onTransact( uint32_t code, | |||
const Parcel& data, | |||
Parcel* reply, | |||
uint32_t flags = 0); | |||
}; | |||
}; | |||
#endif |
@@ -0,0 +1,111 @@ | |||
#include <binder/Parcel.h> | |||
#include <utils/Log.h> | |||
#include "BpAndroidShm.h" | |||
namespace android{ | |||
int BpAndroidShm::sendCommand(const char*command) { | |||
Parcel data, reply; | |||
data.writeInterfaceToken( | |||
IAndroidShm::getInterfaceDescriptor()); | |||
data.writeCString(command); | |||
status_t status = remote()->transact(HW_SENDCOMMAND, data, &reply); | |||
if(status != NO_ERROR) { | |||
ALOGE("print sendCommand error: %s", strerror(-status)); | |||
} else { | |||
status= reply.readInt32(); | |||
} | |||
return status; | |||
} | |||
sp<IMemoryHeap> BpAndroidShm::getBuffer(int index) { | |||
Parcel data, reply; | |||
sp<IMemoryHeap> memHeap = NULL; | |||
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); | |||
data.writeInt32(index); | |||
remote()->transact(HW_GETBUFFER, data, &reply); | |||
memHeap = interface_cast<IMemoryHeap> (reply.readStrongBinder()); | |||
return memHeap; | |||
} | |||
BpAndroidShm::BpAndroidShm( const sp<IBinder>& impl) | |||
: BpInterface<IAndroidShm>(impl) | |||
{} | |||
BpAndroidShm::~BpAndroidShm() | |||
{} | |||
int BpAndroidShm::allocShm(const int size) { // if negative return value is error | |||
Parcel data, reply; | |||
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); | |||
data.writeInt32(size); | |||
status_t status = remote()->transact(HW_ALLOC_SHM, data, &reply); | |||
if(status != NO_ERROR) { | |||
ALOGE("print allocShm error: %s", strerror(-status)); | |||
} else { | |||
status= reply.readInt32(); | |||
} | |||
return status; | |||
} | |||
int BpAndroidShm::removeShm(const unsigned int index) { // shared memory รยฆยฐร | |||
Parcel data, reply; | |||
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); | |||
data.writeInt32(index); | |||
status_t status = remote()->transact(HW_REMOVE_SHM, data, &reply); | |||
if(status != NO_ERROR) { | |||
ALOGE("print removeShm error: %s", strerror(-status)); | |||
} else { | |||
status= reply.readInt32(); | |||
} | |||
return status; | |||
} | |||
int BpAndroidShm::isAllocated(const unsigned int index) { // allocated ยฟยฉยบร รยฎรร | |||
Parcel data, reply; | |||
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); | |||
data.writeInt32(index); | |||
status_t status = remote()->transact(HW_IS_ALLOCATED, data, &reply); | |||
if(status != NO_ERROR) { | |||
ALOGE("print isAllocated error: %s", strerror(-status)); | |||
} else { | |||
status= reply.readInt32(); | |||
} | |||
return status; | |||
} | |||
int BpAndroidShm::setRegistryIndex(const unsigned int index) { | |||
Parcel data, reply; | |||
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); | |||
data.writeInt32(index); | |||
status_t status = remote()->transact(HW_SET_REGISTRY_INDEX, data, &reply); | |||
if(status != NO_ERROR) { | |||
ALOGE("print setRegistryIndex error: %s", strerror(-status)); | |||
} else { | |||
status= reply.readInt32(); | |||
} | |||
return status; | |||
} | |||
int BpAndroidShm::getRegistryIndex() { | |||
Parcel data, reply; | |||
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); | |||
status_t status = remote()->transact(HW_GET_REGISTRY_INDEX, data, &reply); | |||
if(status != NO_ERROR) { | |||
ALOGE("print getRegistryIndex error: %s", strerror(-status)); | |||
} else { | |||
status= reply.readInt32(); | |||
} | |||
return status; | |||
} | |||
sp<IMemoryHeap> BpAndroidShm::InitSemaphore(const char* name) { | |||
Parcel data, reply; | |||
sp<IMemoryHeap> memHeap = NULL; | |||
data.writeInterfaceToken(IAndroidShm::getInterfaceDescriptor()); | |||
data.writeCString(name); | |||
status_t status = remote()->transact(HW_INIT_SEMAPHORE, data, &reply); | |||
memHeap = interface_cast<IMemoryHeap> (reply.readStrongBinder()); | |||
return memHeap; | |||
} | |||
}; |
@@ -0,0 +1,25 @@ | |||
#ifndef BPANDROIDSHM | |||
#define BPANDROIDSHM | |||
#include <binder/Parcel.h> | |||
#include "IAndroidShm.h" | |||
#include <binder/IMemory.h> | |||
namespace android { | |||
class BpAndroidShm: public BpInterface<IAndroidShm> { | |||
public: | |||
BpAndroidShm( const sp<IBinder> & impl); | |||
virtual ~BpAndroidShm(); | |||
virtual sp<IMemoryHeap> getBuffer(int index); | |||
virtual int sendCommand(const char *command); | |||
virtual int allocShm(const int size); // if negative return value is error | |||
virtual int removeShm(const unsigned int index); // shared memory รยฆยฐร | |||
virtual int isAllocated(const unsigned int index); // allocated ยฟยฉยบร รยฎรร | |||
virtual int setRegistryIndex(const unsigned int index); | |||
virtual int getRegistryIndex(); | |||
virtual sp<IMemoryHeap> InitSemaphore(const char* name); | |||
}; | |||
}; | |||
#endif |
@@ -0,0 +1,66 @@ | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/common) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/alsa_in_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/alsa_out_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/androidshmservice_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/shmservicetest_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/shmservicedump_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_samplerate_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_freewheel_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_connect_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_disconnect_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_latent_client_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_midiseq_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_zombie_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_lsp_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_load_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jackd_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_monitor_client_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_looper_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_client_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_cpu_load_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_iodelay_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_midisine_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_cpu_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_keyboard_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_unload_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_wait_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_alias_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_metro_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_bufsize_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_thru_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_session_notify_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_midi_latency_test_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_rec_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_netsource_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_net_master_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_net_slave_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_showtime_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_server_control_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_evmon_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_test_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_transport_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_session_client_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_simple_effect_intermediates) | |||
$(call add_clean_step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_multiple_metro_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/EXECUTABLES/jack_midi_dump_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/common) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/posix) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjack_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjacknet_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjackserver_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/libjackshm_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_alsa_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_dummy_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_net_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_loopback_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_netone_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/audioadapter_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/example_lib_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/netadapter_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/netmanager_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/profiler_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_goldfish_intermediates) | |||
$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/SHARED_LIBRARIES/jack_opensles_intermediates) | |||
@@ -0,0 +1,6 @@ | |||
#include "IAndroidShm.h" | |||
#include "BpAndroidShm.h" | |||
namespace android{ | |||
IMPLEMENT_META_INTERFACE(AndroidShm, "com.samsung.android.jam.IAndroidShm"); | |||
}; |
@@ -0,0 +1,41 @@ | |||
#ifndef IANDROIDSHM | |||
#define IANDROIDSHM | |||
#include <binder/IInterface.h> | |||
#include <binder/IMemory.h> | |||
namespace android { | |||
enum { | |||
HW_GETBUFFER = IBinder::FIRST_CALL_TRANSACTION, | |||
HW_MULTIPLY, | |||
HW_STARTSERVER, | |||
HW_MAKECLIENT, | |||
HW_SENDCOMMAND, | |||
HW_LOADSO, | |||
HW_ALLOC_SHM, | |||
HW_REMOVE_SHM, | |||
HW_IS_ALLOCATED, | |||
HW_SET_REGISTRY_INDEX, | |||
HW_GET_REGISTRY_INDEX, | |||
HW_INIT_SEMAPHORE | |||
}; | |||
class IAndroidShm: public IInterface { | |||
public: | |||
DECLARE_META_INTERFACE(AndroidShm); | |||
virtual sp<IMemoryHeap> getBuffer(int index) = 0; | |||
virtual int sendCommand(const char *command) = 0; | |||
virtual int allocShm(const int size) = 0; // if negative return value is error | |||
virtual int removeShm(const unsigned int index) = 0; // shared memory รยฆยฐร | |||
virtual int isAllocated(const unsigned int index) = 0; // allocated ยฟยฉยบร รยฎรร | |||
virtual int setRegistryIndex(const unsigned int index) = 0; | |||
virtual int getRegistryIndex() = 0; | |||
// for named semaphore simulation | |||
virtual sp<IMemoryHeap> InitSemaphore(const char* name) = 0; | |||
}; | |||
}; | |||
#endif |
@@ -0,0 +1,262 @@ | |||
/* | |||
Copyright (C) 2004-2008 Grame | |||
Copyright (C) 2013 Samsung Electronics | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
#include "JackAndroidSemaphore.h" | |||
#include "JackTools.h" | |||
#include "JackConstants.h" | |||
#include "JackError.h" | |||
#include <fcntl.h> | |||
#include <stdio.h> | |||
#include <sys/time.h> | |||
#include "IAndroidShm.h" | |||
#include "shm.h" | |||
#include "android/Shm.h" //android extension of shm.h | |||
namespace Jack | |||
{ | |||
pthread_mutex_t JackAndroidSemaphore::mutex = PTHREAD_MUTEX_INITIALIZER; | |||
void JackAndroidSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size) | |||
{ | |||
char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; | |||
JackTools::RewriteName(client_name, ext_client_name); | |||
if (getenv("JACK_PROMISCUOUS_SERVER")) { | |||
snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name); | |||
} else { | |||
snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); | |||
} | |||
} | |||
bool JackAndroidSemaphore::Signal() | |||
{ | |||
int res; | |||
if (!fSemaphore) { | |||
jack_error("JackAndroidSemaphore::Signal name = %s already deallocated!!", fName); | |||
return false; | |||
} | |||
if (fFlush) | |||
return true; | |||
if ((res = sem_post(fSemaphore)) != 0) { | |||
jack_error("JackAndroidSemaphore::Signal name = %s err = %s", fName, strerror(errno)); | |||
} | |||
return (res == 0); | |||
} | |||
bool JackAndroidSemaphore::SignalAll() | |||
{ | |||
int res; | |||
if (!fSemaphore) { | |||
jack_error("JackAndroidSemaphore::SignalAll name = %s already deallocated!!", fName); | |||
return false; | |||
} | |||
if (fFlush) | |||
return true; | |||
if ((res = sem_post(fSemaphore)) != 0) { | |||
jack_error("JackAndroidSemaphore::SignalAll name = %s err = %s", fName, strerror(errno)); | |||
} | |||
return (res == 0); | |||
} | |||
/* | |||
bool JackAndroidSemaphore::Wait() | |||
{ | |||
int res; | |||
if (!fSemaphore) { | |||
jack_error("JackAndroidSemaphore::Wait name = %s already deallocated!!", fName); | |||
return false; | |||
} | |||
if ((res = sem_wait(fSemaphore)) != 0) { | |||
jack_error("JackAndroidSemaphore::Wait name = %s err = %s", fName, strerror(errno)); | |||
} | |||
return (res == 0); | |||
} | |||
*/ | |||
bool JackAndroidSemaphore::Wait() | |||
{ | |||
int res; | |||
while ((res = sem_wait(fSemaphore) < 0)) { | |||
jack_error("JackAndroidSemaphore::Wait name = %s err = %s", fName, strerror(errno)); | |||
if (errno != EINTR) { | |||
break; | |||
} | |||
} | |||
return (res == 0); | |||
} | |||
bool JackAndroidSemaphore::TimedWait(long usec) | |||
{ | |||
int res; | |||
struct timeval now; | |||
timespec time; | |||
if (!fSemaphore) { | |||
jack_error("JackAndroidSemaphore::TimedWait name = %s already deallocated!!", fName); | |||
return false; | |||
} | |||
gettimeofday(&now, 0); | |||
time.tv_sec = now.tv_sec + usec / 1000000; | |||
long tv_usec = (now.tv_usec + (usec % 1000000)); | |||
time.tv_sec += tv_usec / 1000000; | |||
time.tv_nsec = (tv_usec % 1000000) * 1000; | |||
while ((res = sem_timedwait(fSemaphore, &time)) < 0) { | |||
jack_error("JackAndroidSemaphore::TimedWait err = %s", strerror(errno)); | |||
jack_log("JackAndroidSemaphore::TimedWait now : %ld %ld ", now.tv_sec, now.tv_usec); | |||
jack_log("JackAndroidSemaphore::TimedWait next : %ld %ld ", time.tv_sec, time.tv_nsec/1000); | |||
if (errno == ETIMEDOUT) { | |||
timespec ts; | |||
clock_gettime(CLOCK_REALTIME, &ts); | |||
ts.tv_sec = time.tv_sec - ts.tv_sec; | |||
ts.tv_nsec = time.tv_nsec - ts.tv_nsec; | |||
if (ts.tv_nsec < 0) { | |||
ts.tv_nsec += 1000000000; | |||
ts.tv_sec -= 1; | |||
} | |||
if (ts.tv_sec < 0 || ts.tv_nsec < 0) { | |||
jack_error("JackAndroidSemaphore::TimedWait time may changed or client killed already! wait again!"); | |||
gettimeofday(&now, 0); | |||
time.tv_sec = now.tv_sec + usec / 1000000; | |||
long tv_usec = (now.tv_usec + (usec % 1000000)); | |||
time.tv_sec += tv_usec / 1000000; | |||
time.tv_nsec = (tv_usec % 1000000) * 1000; | |||
if ((res = sem_timedwait(fSemaphore, &time)) < 0) { | |||
jack_error("JackAndroidSemaphore::TimedWait err = %s", strerror(errno)); | |||
jack_log("JackAndroidSemaphore::TimedWait now : %ld %ld ", now.tv_sec, now.tv_usec); | |||
jack_log("JackAndroidSemaphore::TimedWait next : %ld %ld ", time.tv_sec, time.tv_nsec/1000); | |||
} | |||
} | |||
} | |||
if (errno != EINTR) { | |||
break; | |||
} | |||
} | |||
return (res == 0); | |||
} | |||
// Server side : publish the semaphore in the global namespace | |||
bool JackAndroidSemaphore::Allocate(const char* name, const char* server_name, int value) | |||
{ | |||
pthread_mutex_lock (&mutex); | |||
BuildName(name, server_name, fName, sizeof(fName)); | |||
jack_log("JackAndroidSemaphore::Allocate name = %s val = %ld", fName, value); | |||
android::sp<android::IAndroidShm> service = android::Shm::getShmService(); | |||
if(service == NULL){ | |||
jack_error("shm service is null"); | |||
return false; | |||
} | |||
fSemaphoreMemory = service->InitSemaphore(fName); | |||
if(fSemaphoreMemory != NULL){ | |||
fSemaphore = (sem_t*)(fSemaphoreMemory->getBase()); | |||
} | |||
if(fSemaphore == NULL) { | |||
jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno)); | |||
pthread_mutex_unlock (&mutex); | |||
return false; | |||
} else { | |||
sem_init(fSemaphore, 1, 0); | |||
jack_log("sem_init()"); | |||
pthread_mutex_unlock (&mutex); | |||
return true; | |||
} | |||
} | |||
// Client side : get the published semaphore from server | |||
bool JackAndroidSemaphore::ConnectInput(const char* name, const char* server_name) | |||
{ | |||
pthread_mutex_lock (&mutex); | |||
BuildName(name, server_name, fName, sizeof(fName)); | |||
jack_log("JackAndroidSemaphore::Connect name = %s", fName); | |||
// Temporary... | |||
if (fSemaphore) { | |||
jack_log("Already connected name = %s", name); | |||
pthread_mutex_unlock (&mutex); | |||
return true; | |||
} | |||
android::sp<android::IAndroidShm> service = android::Shm::getShmService(); | |||
if(service == NULL){ | |||
jack_error("shm service is null"); | |||
return false; | |||
} | |||
fSemaphoreMemory = service->InitSemaphore(fName); | |||
if(fSemaphoreMemory != NULL){ | |||
fSemaphore = (sem_t*)(fSemaphoreMemory->getBase()); | |||
} | |||
if(fSemaphore == NULL) { | |||
jack_error("Connect: can't connect named semaphore name = %s err = %s", fName, strerror(errno)); | |||
pthread_mutex_unlock (&mutex); | |||
return false; | |||
} else { | |||
int val = 0; | |||
sem_getvalue(fSemaphore, &val); | |||
jack_log("JackAndroidSemaphore::Connect sem_getvalue %ld", val); | |||
pthread_mutex_unlock (&mutex); | |||
return true; | |||
} | |||
} | |||
bool JackAndroidSemaphore::Connect(const char* name, const char* server_name) | |||
{ | |||
return ConnectInput(name, server_name); | |||
} | |||
bool JackAndroidSemaphore::ConnectOutput(const char* name, const char* server_name) | |||
{ | |||
return ConnectInput(name, server_name); | |||
} | |||
bool JackAndroidSemaphore::Disconnect() | |||
{ | |||
if (fSemaphore) { | |||
jack_log("JackAndroidSemaphore::Disconnect name = %s", fName); | |||
fSemaphore = NULL; | |||
} | |||
return true; | |||
} | |||
// Server side : destroy the semaphore | |||
void JackAndroidSemaphore::Destroy() | |||
{ | |||
if (fSemaphore != NULL) { | |||
jack_log("JackAndroidSemaphore::Disconnect name = %s", fName); | |||
fSemaphore = NULL; | |||
} else { | |||
jack_error("JackAndroidSemaphore::Destroy semaphore == NULL"); | |||
} | |||
} | |||
} // end of namespace | |||
@@ -0,0 +1,76 @@ | |||
/* | |||
Copyright (C) 2004-2008 Grame | |||
Copyright (C) 2013 Samsung Electronics | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
#ifndef __JackAndroidSemaphore__ | |||
#define __JackAndroidSemaphore__ | |||
#include "JackSynchro.h" | |||
#include "JackCompilerDeps.h" | |||
#include <semaphore.h> | |||
#include <time.h> | |||
#include <assert.h> | |||
#include <binder/IMemory.h> | |||
#include <binder/MemoryHeapBase.h> | |||
#include <utils/RefBase.h> | |||
namespace Jack | |||
{ | |||
/*! | |||
\brief Inter process synchronization using POSIX semaphore. | |||
*/ | |||
class SERVER_EXPORT JackAndroidSemaphore : public detail::JackSynchro | |||
{ | |||
private: | |||
sem_t* fSemaphore; | |||
android::sp<android::IMemoryHeap> fSemaphoreMemory; | |||
static pthread_mutex_t mutex; | |||
protected: | |||
void BuildName(const char* name, const char* server_name, char* res, int size); | |||
public: | |||
JackAndroidSemaphore():JackSynchro(), fSemaphore(NULL) | |||
{} | |||
bool Signal(); | |||
bool SignalAll(); | |||
bool Wait(); | |||
bool TimedWait(long usec); | |||
bool Allocate(const char* name, const char* server_name, int value); | |||
bool Connect(const char* name, const char* server_name); | |||
bool ConnectInput(const char* name, const char* server_name); | |||
bool ConnectOutput(const char* name, const char* server_name); | |||
bool Disconnect(); | |||
void Destroy(); | |||
}; | |||
} // end of namespace | |||
#endif | |||
@@ -0,0 +1,374 @@ | |||
/* | |||
Copyright (C) 2001 Paul Davis | |||
Copyright (C) 2004-2008 Grame | |||
Copyright (C) 2013 Samsung Electronics | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
#include "JackAndroidThread.h" | |||
#include "JackError.h" | |||
#include "JackTime.h" | |||
#include "JackGlobals.h" | |||
#include <string.h> // for memset | |||
#include <unistd.h> // for _POSIX_PRIORITY_SCHEDULING check | |||
#include <signal.h> | |||
//#define JACK_SCHED_POLICY SCHED_RR | |||
#define JACK_SCHED_POLICY SCHED_FIFO | |||
namespace Jack | |||
{ | |||
void JackAndroidThread::thread_exit_handler(int sig) | |||
{ | |||
printf("this signal is %d \n", sig); | |||
pthread_exit(0); | |||
} | |||
void* JackAndroidThread::ThreadHandler(void* arg) | |||
{ | |||
JackAndroidThread* obj = (JackAndroidThread*)arg; | |||
JackRunnableInterface* runnable = obj->fRunnable; | |||
int err; | |||
struct sigaction actions; | |||
memset(&actions, 0, sizeof(actions)); | |||
sigemptyset(&actions.sa_mask); | |||
actions.sa_flags = 0; | |||
actions.sa_handler = thread_exit_handler; | |||
sigaction(SIGUSR1,&actions,NULL); | |||
// Signal creation thread when started with StartSync | |||
jack_log("JackAndroidThread::ThreadHandler : start"); | |||
obj->fStatus = kIniting; | |||
// Call Init method | |||
if (!runnable->Init()) { | |||
jack_error("Thread init fails: thread quits"); | |||
return 0; | |||
} | |||
obj->fStatus = kRunning; | |||
// If Init succeed, start the thread loop | |||
bool res = true; | |||
while (obj->fStatus == kRunning && res) { | |||
res = runnable->Execute(); | |||
} | |||
jack_log("JackAndroidThread::ThreadHandler : exit"); | |||
pthread_exit(0); | |||
return 0; // never reached | |||
} | |||
int JackAndroidThread::Start() | |||
{ | |||
fStatus = kStarting; | |||
// Check if the thread was correctly started | |||
if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { | |||
fStatus = kIdle; | |||
return -1; | |||
} else { | |||
return 0; | |||
} | |||
} | |||
int JackAndroidThread::StartSync() | |||
{ | |||
fStatus = kStarting; | |||
if (StartImp(&fThread, fPriority, fRealTime, ThreadHandler, this) < 0) { | |||
fStatus = kIdle; | |||
return -1; | |||
} else { | |||
int count = 0; | |||
while (fStatus == kStarting && ++count < 1000) { | |||
JackSleep(1000); | |||
} | |||
return (count == 1000) ? -1 : 0; | |||
} | |||
} | |||
int JackAndroidThread::StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg) | |||
{ | |||
pthread_attr_t attributes; | |||
struct sched_param rt_param; | |||
pthread_attr_init(&attributes); | |||
int res; | |||
if ((res = pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_JOINABLE))) { | |||
jack_error("Cannot request joinable thread creation for thread res = %d", res); | |||
return -1; | |||
} | |||
if ((res = pthread_attr_setscope(&attributes, PTHREAD_SCOPE_SYSTEM))) { | |||
jack_error("Cannot set scheduling scope for thread res = %d", res); | |||
return -1; | |||
} | |||
if (realtime) { | |||
jack_log("JackAndroidThread::StartImp : create RT thread"); | |||
if ((res = pthread_attr_setschedpolicy(&attributes, JACK_SCHED_POLICY))) { | |||
jack_error("Cannot set RR scheduling class for RT thread res = %d", res); | |||
return -1; | |||
} | |||
memset(&rt_param, 0, sizeof(rt_param)); | |||
rt_param.sched_priority = priority; | |||
if ((res = pthread_attr_setschedparam(&attributes, &rt_param))) { | |||
jack_error("Cannot set scheduling priority for RT thread res = %d", res); | |||
return -1; | |||
} | |||
} else { | |||
jack_log("JackAndroidThread::StartImp : create non RT thread"); | |||
} | |||
if ((res = pthread_attr_setstacksize(&attributes, THREAD_STACK))) { | |||
jack_error("Cannot set thread stack size res = %d", res); | |||
return -1; | |||
} | |||
if ((res = JackGlobals::fJackThreadCreator(thread, &attributes, start_routine, arg))) { | |||
jack_error("Cannot create thread res = %d", res); | |||
return -1; | |||
} | |||
pthread_attr_destroy(&attributes); | |||
return 0; | |||
} | |||
int JackAndroidThread::Kill() | |||
{ | |||
if (fThread != (jack_native_thread_t)NULL) { // If thread has been started | |||
jack_log("JackAndroidThread::Kill"); | |||
void* status; | |||
pthread_kill(fThread, SIGUSR1); | |||
pthread_join(fThread, &status); | |||
fStatus = kIdle; | |||
fThread = (jack_native_thread_t)NULL; | |||
return 0; | |||
} else { | |||
return -1; | |||
} | |||
} | |||
int JackAndroidThread::Stop() | |||
{ | |||
if (fThread != (jack_native_thread_t)NULL) { // If thread has been started | |||
jack_log("JackAndroidThread::Stop"); | |||
void* status; | |||
fStatus = kIdle; // Request for the thread to stop | |||
pthread_join(fThread, &status); | |||
fThread = (jack_native_thread_t)NULL; | |||
return 0; | |||
} else { | |||
return -1; | |||
} | |||
} | |||
int JackAndroidThread::KillImp(jack_native_thread_t thread) | |||
{ | |||
if (thread != (jack_native_thread_t)NULL) { // If thread has been started | |||
jack_log("JackAndroidThread::Kill"); | |||
void* status; | |||
pthread_kill(thread, SIGUSR1); | |||
pthread_join(thread, &status); | |||
return 0; | |||
} else { | |||
return -1; | |||
} | |||
} | |||
int JackAndroidThread::StopImp(jack_native_thread_t thread) | |||
{ | |||
if (thread != (jack_native_thread_t)NULL) { // If thread has been started | |||
jack_log("JackAndroidThread::Stop"); | |||
void* status; | |||
pthread_join(thread, &status); | |||
return 0; | |||
} else { | |||
return -1; | |||
} | |||
} | |||
int JackAndroidThread::AcquireRealTime() | |||
{ | |||
return (fThread != (jack_native_thread_t)NULL) ? AcquireRealTimeImp(fThread, fPriority) : -1; | |||
} | |||
int JackAndroidThread::AcquireSelfRealTime() | |||
{ | |||
return AcquireRealTimeImp(pthread_self(), fPriority); | |||
} | |||
int JackAndroidThread::AcquireRealTime(int priority) | |||
{ | |||
fPriority = priority; | |||
return AcquireRealTime(); | |||
} | |||
int JackAndroidThread::AcquireSelfRealTime(int priority) | |||
{ | |||
fPriority = priority; | |||
return AcquireSelfRealTime(); | |||
} | |||
int JackAndroidThread::AcquireRealTimeImp(jack_native_thread_t thread, int priority) | |||
{ | |||
struct sched_param rtparam; | |||
int res; | |||
memset(&rtparam, 0, sizeof(rtparam)); | |||
rtparam.sched_priority = priority; | |||
jack_log("JackAndroidThread::AcquireRealTimeImp priority = %d", priority); | |||
if ((res = pthread_setschedparam(thread, JACK_SCHED_POLICY, &rtparam)) != 0) { | |||
jack_error("Cannot use real-time scheduling (RR/%d)" | |||
"(%d: %s)", rtparam.sched_priority, res, | |||
strerror(res)); | |||
return -1; | |||
} | |||
return 0; | |||
} | |||
int JackAndroidThread::DropRealTime() | |||
{ | |||
return (fThread != (jack_native_thread_t)NULL) ? DropRealTimeImp(fThread) : -1; | |||
} | |||
int JackAndroidThread::DropSelfRealTime() | |||
{ | |||
return DropRealTimeImp(pthread_self()); | |||
} | |||
int JackAndroidThread::DropRealTimeImp(jack_native_thread_t thread) | |||
{ | |||
struct sched_param rtparam; | |||
int res; | |||
memset(&rtparam, 0, sizeof(rtparam)); | |||
rtparam.sched_priority = 0; | |||
if ((res = pthread_setschedparam(thread, SCHED_OTHER, &rtparam)) != 0) { | |||
jack_error("Cannot switch to normal scheduling priority(%s)", strerror(errno)); | |||
return -1; | |||
} | |||
return 0; | |||
} | |||
jack_native_thread_t JackAndroidThread::GetThreadID() | |||
{ | |||
return fThread; | |||
} | |||
bool JackAndroidThread::IsThread() | |||
{ | |||
return pthread_self() == fThread; | |||
} | |||
void JackAndroidThread::Terminate() | |||
{ | |||
jack_log("JackAndroidThread::Terminate"); | |||
pthread_exit(0); | |||
} | |||
SERVER_EXPORT void ThreadExit() | |||
{ | |||
jack_log("ThreadExit"); | |||
pthread_exit(0); | |||
} | |||
} // end of namespace | |||
bool jack_get_thread_realtime_priority_range(int * min_ptr, int * max_ptr) | |||
{ | |||
#if defined(_POSIX_PRIORITY_SCHEDULING) && !defined(__APPLE__) | |||
int min, max; | |||
min = sched_get_priority_min(JACK_SCHED_POLICY); | |||
if (min == -1) | |||
{ | |||
jack_error("sched_get_priority_min() failed."); | |||
return false; | |||
} | |||
max = sched_get_priority_max(JACK_SCHED_POLICY); | |||
if (max == -1) | |||
{ | |||
jack_error("sched_get_priority_max() failed."); | |||
return false; | |||
} | |||
*min_ptr = min; | |||
*max_ptr = max; | |||
return true; | |||
#else | |||
return false; | |||
#endif | |||
} | |||
bool jack_tls_allocate_key(jack_tls_key *key_ptr) | |||
{ | |||
int ret; | |||
ret = pthread_key_create(key_ptr, NULL); | |||
if (ret != 0) | |||
{ | |||
jack_error("pthread_key_create() failed with error %d", ret); | |||
return false; | |||
} | |||
return true; | |||
} | |||
bool jack_tls_free_key(jack_tls_key key) | |||
{ | |||
int ret; | |||
ret = pthread_key_delete(key); | |||
if (ret != 0) | |||
{ | |||
jack_error("pthread_key_delete() failed with error %d", ret); | |||
return false; | |||
} | |||
return true; | |||
} | |||
bool jack_tls_set(jack_tls_key key, void *data_ptr) | |||
{ | |||
int ret; | |||
ret = pthread_setspecific(key, (const void *)data_ptr); | |||
if (ret != 0) | |||
{ | |||
jack_error("pthread_setspecific() failed with error %d", ret); | |||
return false; | |||
} | |||
return true; | |||
} | |||
void *jack_tls_get(jack_tls_key key) | |||
{ | |||
return pthread_getspecific(key); | |||
} |
@@ -0,0 +1,97 @@ | |||
/* | |||
Copyright (C) 2001 Paul Davis | |||
Copyright (C) 2004-2008 Grame | |||
Copyright (C) 2013 Samsung Electronics | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
#ifndef __JackAndroidThread__ | |||
#define __JackAndroidThread__ | |||
#include "JackThread.h" | |||
#include <pthread.h> | |||
namespace Jack | |||
{ | |||
/* use 512KB stack per thread - the default is way too high to be feasible | |||
* with mlockall() on many systems */ | |||
#define THREAD_STACK 524288 | |||
enum | |||
{ | |||
PTHREAD_CANCEL_DEFERRED, | |||
PTHREAD_CANCEL_ASYNCHRONOUS | |||
}; | |||
/*! | |||
\brief The POSIX thread base class. | |||
*/ | |||
class SERVER_EXPORT JackAndroidThread : public detail::JackThreadInterface | |||
{ | |||
protected: | |||
jack_native_thread_t fThread; | |||
static void* ThreadHandler(void* arg); | |||
static void thread_exit_handler(int sig); | |||
public: | |||
JackAndroidThread(JackRunnableInterface* runnable, bool real_time, int priority, int cancellation) | |||
: JackThreadInterface(runnable, priority, real_time, cancellation), fThread((jack_native_thread_t)NULL) | |||
{} | |||
JackAndroidThread(JackRunnableInterface* runnable, int cancellation = PTHREAD_CANCEL_ASYNCHRONOUS) | |||
: JackThreadInterface(runnable, 0, false, cancellation), fThread((jack_native_thread_t)NULL) | |||
{} | |||
int Start(); | |||
int StartSync(); | |||
int Kill(); | |||
int Stop(); | |||
void Terminate(); | |||
int AcquireRealTime(); // Used when called from another thread | |||
int AcquireSelfRealTime(); // Used when called from thread itself | |||
int AcquireRealTime(int priority); // Used when called from another thread | |||
int AcquireSelfRealTime(int priority); // Used when called from thread itself | |||
int DropRealTime(); // Used when called from another thread | |||
int DropSelfRealTime(); // Used when called from thread itself | |||
jack_native_thread_t GetThreadID(); | |||
bool IsThread(); | |||
static int AcquireRealTimeImp(jack_native_thread_t thread, int priority); | |||
static int AcquireRealTimeImp(jack_native_thread_t thread, int priority, UInt64 period, UInt64 computation, UInt64 constraint) | |||
{ | |||
return JackAndroidThread::AcquireRealTimeImp(thread, priority); | |||
} | |||
static int DropRealTimeImp(jack_native_thread_t thread); | |||
static int StartImp(jack_native_thread_t* thread, int priority, int realtime, void*(*start_routine)(void*), void* arg); | |||
static int StopImp(jack_native_thread_t thread); | |||
static int KillImp(jack_native_thread_t thread); | |||
}; | |||
SERVER_EXPORT void ThreadExit(); | |||
} // end of namespace | |||
#endif |
@@ -0,0 +1,42 @@ | |||
/* | |||
Copyright (C) 2004-2008 Grame | |||
Copyright (C) 2013 Samsung Electronics | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
#ifndef __JackAtomic_android__ | |||
#define __JackAtomic_android__ | |||
#include "JackTypes.h" | |||
#include <sys/atomics.h> | |||
static inline char CAS(volatile UInt32 value, UInt32 newvalue, volatile void* addr) | |||
{ | |||
#if 1 | |||
return !__atomic_cmpxchg(value, newvalue, (volatile int *)addr); | |||
#else | |||
//slow compare_and_swap_32 | |||
if (*(UInt32*)addr == value) { | |||
*(UInt32*)addr = newvalue; | |||
return true; | |||
} | |||
return false; | |||
#endif | |||
} | |||
#endif | |||
@@ -0,0 +1,48 @@ | |||
/* | |||
Copyright (C) 2004-2008 Grame | |||
Copyright (C) 2013 Samsung Electronics | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 of the License, or | |||
(at your option) any later version. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
#ifndef __JackCompilerDeps_android__ | |||
#define __JackCompilerDeps_android__ | |||
#include "JackConstants.h" | |||
#if __GNUC__ | |||
#define MEM_ALIGN(x,y) x __attribute__((aligned(y))) | |||
#define LIB_EXPORT __attribute__((visibility("default"))) | |||
#ifdef SERVER_SIDE | |||
#if (__GNUC__< 4) | |||
#define SERVER_EXPORT | |||
#else | |||
#define SERVER_EXPORT __attribute__((visibility("default"))) | |||
#endif | |||
#else | |||
#define SERVER_EXPORT __attribute__((visibility("hidden"))) | |||
#endif | |||
#else | |||
#define MEM_ALIGN(x,y) x | |||
#define LIB_EXPORT | |||
#define SERVER_EXPORT | |||
/* Add other things here for non-gcc platforms */ | |||
#endif | |||
#endif /* __JackCompilerDeps_android__ */ |
@@ -0,0 +1,89 @@ | |||
// u/* -*- Mode: C++ ; c-basic-offset: 4 -*- */ | |||
/* | |||
JACK control API implementation | |||
Copyright (C) 2008 Nedko Arnaudov | |||
Copyright (C) 2008 Grame | |||
Copyright (C) 2013 Samsung Electronics | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; version 2 of the License. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
*/ | |||
#ifndef WIN32 | |||
#include <stdint.h> | |||
#include <dirent.h> | |||
#include <pthread.h> | |||
#endif | |||
#include "types.h" | |||
#include <string.h> | |||
#include <errno.h> | |||
#include <stdio.h> | |||
#include <assert.h> | |||
#include <signal.h> | |||
#include "JackControlAPIAndroid.h" | |||
#include "JackConstants.h" | |||
#include "JackServerGlobals.h" | |||
using namespace Jack; | |||
struct jackctl_sigmask | |||
{ | |||
sigset_t signals; | |||
}; | |||
static jackctl_sigmask sigmask; | |||
SERVER_EXPORT int | |||
jackctl_wait_signals_and_return(jackctl_sigmask_t * sigmask) | |||
{ | |||
int sig; | |||
bool waiting = true; | |||
while (waiting) { | |||
#if defined(sun) && !defined(__sun__) // SUN compiler only, to check | |||
sigwait(&sigmask->signals); | |||
#else | |||
sigwait(&sigmask->signals, &sig); | |||
#endif | |||
fprintf(stderr, "Jack main caught signal %d\n", sig); | |||
switch (sig) { | |||
case SIGUSR1: | |||
//jack_dump_configuration(engine, 1); | |||
break; | |||
case SIGUSR2: | |||
// driver exit | |||
waiting = false; | |||
break; | |||
case SIGTTOU: | |||
break; | |||
default: | |||
waiting = false; | |||
break; | |||
} | |||
} | |||
if (sig != SIGSEGV) { | |||
// unblock signals so we can see them during shutdown. | |||
// this will help prod developers not to lose sight of | |||
// bugs that cause segfaults etc. during shutdown. | |||
sigprocmask(SIG_UNBLOCK, &sigmask->signals, 0); | |||
} | |||
return sig; | |||
} | |||
@@ -0,0 +1,44 @@ | |||
/* | |||
JACK control API | |||
Copyright (C) 2008 Nedko Arnaudov | |||
Copyright (C) 2008 Grame | |||
Copyright (C) 2013 Samsung Electronics | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU General Public License as published by | |||
the Free Software Foundation; version 2 of the License. | |||
This program is distributed in the hope that it will be useful, | |||
but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
GNU General Public License for more details. | |||
You should have received a copy of the GNU General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
*/ | |||
#ifndef __JackControlAPIAndroid__ | |||
#define __JackControlAPIAndroid__ | |||
#include "JackCompilerDeps.h" | |||
/** opaque type for sigmask object */ | |||
typedef struct jackctl_sigmask jackctl_sigmask_t; | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
SERVER_EXPORT int | |||