887 lines
28 KiB
C++
887 lines
28 KiB
C++
/*
|
|
Copyright (C) 2001-2003 Paul Davis
|
|
Copyright (C) 2005-2012 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.
|
|
|
|
*/
|
|
|
|
#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"
|
|
|
|
// remove ALOGI log
|
|
#define jack_d
|
|
//#define jack_d ALOGI
|
|
#define jack_error ALOGE
|
|
#define MEMORY_SIZE 10*1024
|
|
|
|
|
|
namespace android {
|
|
|
|
jack_shmtype_t Shm::jack_shmtype = shm_ANDROID;
|
|
|
|
/* The JACK SHM registry is a chunk of memory for keeping track of the
|
|
* shared memory used by each active JACK server. This allows the
|
|
* server to clean up shared memory when it exits. To avoid memory
|
|
* leakage due to kill -9, crashes or debugger-driven exits, this
|
|
* cleanup is also done when a new instance of that server starts.
|
|
*/
|
|
|
|
/* per-process global data for the SHM interfaces */
|
|
jack_shm_id_t Shm::registry_id; /* SHM id for the registry */
|
|
jack_shm_fd_t Shm::registry_fd = JACK_SHM_REGISTRY_FD;
|
|
|
|
jack_shm_info_t Shm::registry_info = {
|
|
JACK_SHM_NULL_INDEX, 0, 0, { MAP_FAILED }
|
|
};
|
|
|
|
/* pointers to registry header and array */
|
|
jack_shm_header_t *Shm::jack_shm_header = NULL;
|
|
jack_shm_registry_t *Shm::jack_shm_registry = NULL;
|
|
char Shm::jack_shm_server_prefix[JACK_SERVER_NAME_SIZE+1] = "";
|
|
|
|
/* jack_shm_lock_registry() serializes updates to the shared memory
|
|
* segment JACK uses to keep track of the SHM segments allocated to
|
|
* all its processes, including multiple servers.
|
|
*
|
|
* This is not a high-contention lock, but it does need to work across
|
|
* multiple processes. High transaction rates and realtime safety are
|
|
* not required. Any solution needs to at least be portable to POSIX
|
|
* and POSIX-like systems.
|
|
*
|
|
* We must be particularly careful to ensure that the lock be released
|
|
* if the owning process terminates abnormally. Otherwise, a segfault
|
|
* or kill -9 at the wrong moment could prevent JACK from ever running
|
|
* again on that machine until after a reboot.
|
|
*/
|
|
|
|
#define JACK_SEMAPHORE_KEY 0x282929
|
|
#define JACK_SHM_REGISTRY_KEY JACK_SEMAPHORE_KEY
|
|
#define JACK_REGISTRY_NAME "/jack-shm-registry"
|
|
|
|
int Shm::semid = -1;
|
|
pthread_mutex_t Shm::mutex = PTHREAD_MUTEX_INITIALIZER;
|
|
|
|
//sp<IAndroidShm> Shm::mShmService;
|
|
sp<IMemoryHeap> Shm::mShmMemBase[JACK_SHM_HEAP_ENOUGH_COUNT] = {0,};
|
|
|
|
Shm* Shm::ref = NULL;
|
|
|
|
Shm* Shm::Instantiate() {
|
|
if(Shm::ref == NULL) {
|
|
jack_d("shm::Instantiate is called");
|
|
Shm::ref = new Shm;
|
|
//AndroidShm::instantiate();
|
|
}
|
|
return ref;
|
|
}
|
|
|
|
Shm::Shm() { }
|
|
|
|
Shm::~Shm() { }
|
|
|
|
sp<IAndroidShm> Shm::getShmService(){
|
|
return interface_cast<IAndroidShm>(defaultServiceManager()->getService(String16("com.samsung.android.jam.IAndroidShm")));
|
|
}
|
|
|
|
//sp<IAndroidShm>& Shm::getShmService() {
|
|
// if (mShmService.get() == 0) {
|
|
// sp<IServiceManager> sm = defaultServiceManager();
|
|
// sp<IBinder> binder;
|
|
// do {
|
|
// binder = sm->getService(String16("com.samsung.android.jam.IAndroidShm"));
|
|
// if (binder != 0)
|
|
// break;
|
|
// ALOGW("CameraService not published, waiting...");
|
|
// usleep(500000); // 0.5 s
|
|
// } while(true);
|
|
// mShmService = interface_cast<IAndroidShm>(binder);
|
|
// }
|
|
// ALOGE_IF(mShmService==0, "no CameraService!?");
|
|
// return mShmService;
|
|
//}
|
|
|
|
void Shm::shm_copy_from_registry (jack_shm_info_t* /*si*/, jack_shm_registry_index_t ) {
|
|
// not used
|
|
}
|
|
void Shm::shm_copy_to_registry (jack_shm_info_t* /*si*/, jack_shm_registry_index_t*) {
|
|
// not used
|
|
}
|
|
|
|
void Shm::jack_release_shm_entry (jack_shm_registry_index_t index) {
|
|
/* the registry must be locked */
|
|
jack_shm_registry[index].size = 0;
|
|
jack_shm_registry[index].allocator = 0;
|
|
memset (&jack_shm_registry[index].id, 0,
|
|
sizeof (jack_shm_registry[index].id));
|
|
jack_shm_registry[index].fd = 0;
|
|
}
|
|
|
|
int Shm::release_shm_info (jack_shm_registry_index_t index) {
|
|
/* must NOT have the registry locked */
|
|
if (jack_shm_registry[index].allocator == GetPID()) {
|
|
if (jack_shm_lock_registry () < 0) {
|
|
jack_error ("jack_shm_lock_registry fails...");
|
|
return -1;
|
|
}
|
|
jack_release_shm_entry (index);
|
|
jack_shm_unlock_registry ();
|
|
jack_d ("release_shm_info: success!");
|
|
}
|
|
else
|
|
jack_error ("release_shm_info: error!");
|
|
|
|
return 0;
|
|
}
|
|
char* Shm::shm_addr (unsigned int fd) {
|
|
if(fd >= JACK_SHM_HEAP_ENOUGH_COUNT) {
|
|
jack_error("ignore to get memory buffer : index[%d] is too big", fd);
|
|
return NULL;
|
|
}
|
|
|
|
sp<IAndroidShm> service = Shm::getShmService();
|
|
if(service == NULL){
|
|
jack_error("shm service is null");
|
|
return NULL;
|
|
}
|
|
mShmMemBase[fd] = service->getBuffer(fd);
|
|
if(mShmMemBase[fd] == NULL) {
|
|
jack_error("fail to get memory buffer");
|
|
return NULL;
|
|
}
|
|
|
|
return ((char *) mShmMemBase[fd]->getBase());
|
|
}
|
|
|
|
int Shm::shm_lock_registry (void) {
|
|
pthread_mutex_lock (&mutex);
|
|
return 0;
|
|
}
|
|
|
|
void Shm::shm_unlock_registry (void) {
|
|
pthread_mutex_unlock (&mutex);
|
|
}
|
|
|
|
void Shm::release_shm_entry (jack_shm_registry_index_t index) {
|
|
/* the registry must be locked */
|
|
jack_shm_registry[index].size = 0;
|
|
jack_shm_registry[index].allocator = 0;
|
|
memset (&jack_shm_registry[index].id, 0,
|
|
sizeof (jack_shm_registry[index].id));
|
|
}
|
|
|
|
void Shm::remove_shm (jack_shm_id_t *id) {
|
|
int shm_fd = -1;
|
|
jack_d("remove_id [%s]",(char*)id);
|
|
if(!strcmp((const char*)id, JACK_REGISTRY_NAME)) {
|
|
shm_fd = registry_fd;
|
|
} else {
|
|
for (int i = 0; i < MAX_SHM_ID; i++) {
|
|
if(!strcmp((const char*)id, jack_shm_registry[i].id)) {
|
|
shm_fd = jack_shm_registry[i].fd;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (shm_fd >= 0) {
|
|
sp<IAndroidShm> service = getShmService();
|
|
if(service != NULL) {
|
|
service->removeShm(shm_fd);
|
|
} else {
|
|
jack_error("shm service is null");
|
|
}
|
|
}
|
|
jack_d ("[APA] jack_remove_shm : ok ");
|
|
}
|
|
|
|
int Shm::access_registry (jack_shm_info_t * ri) {
|
|
jack_d("access_registry\n");
|
|
/* registry must be locked */
|
|
sp<IAndroidShm> service = getShmService();
|
|
if(service == NULL){
|
|
jack_error("shm service is null");
|
|
return EINVAL;
|
|
}
|
|
int shm_fd = service->getRegistryIndex();
|
|
|
|
strncpy (registry_id, JACK_REGISTRY_NAME, sizeof (registry_id) - 1);
|
|
registry_id[sizeof (registry_id) - 1] = '\0';
|
|
|
|
if(service->isAllocated(shm_fd) == FALSE) {
|
|
//jack_error ("Cannot mmap shm registry segment (%s)",
|
|
// strerror (errno));
|
|
jack_error ("Cannot mmap shm registry segment");
|
|
//close (shm_fd);
|
|
ri->ptr.attached_at = NULL;
|
|
registry_fd = JACK_SHM_REGISTRY_FD;
|
|
return EINVAL;
|
|
}
|
|
|
|
ri->fd = shm_fd;
|
|
registry_fd = shm_fd;
|
|
ri->ptr.attached_at = shm_addr(shm_fd);
|
|
|
|
if(ri->ptr.attached_at == NULL) {
|
|
ALOGE("attached pointer is null !");
|
|
jack_shm_header = NULL;
|
|
jack_shm_registry = NULL;
|
|
return 0;
|
|
}
|
|
|
|
/* set up global pointers */
|
|
ri->index = JACK_SHM_REGISTRY_INDEX;
|
|
jack_shm_header = (jack_shm_header_t*)(ri->ptr.attached_at);
|
|
jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
|
|
|
|
jack_d("jack_shm_header[%p],jack_shm_registry[%p]", jack_shm_header, jack_shm_registry);
|
|
//close (shm_fd); // steph
|
|
return 0;
|
|
}
|
|
|
|
int Shm::GetUID() {
|
|
return geteuid();
|
|
}
|
|
|
|
int Shm::GetPID() {
|
|
return getpid();
|
|
}
|
|
|
|
int Shm::jack_shm_lock_registry (void) {
|
|
// TODO: replace semaphore to mutex
|
|
pthread_mutex_lock (&mutex);
|
|
return 0;
|
|
}
|
|
|
|
void Shm::jack_shm_unlock_registry (void) {
|
|
// TODO: replace semaphore to mutex
|
|
pthread_mutex_unlock (&mutex);
|
|
return;
|
|
}
|
|
|
|
void Shm::shm_init_registry () {
|
|
if(jack_shm_header == NULL)
|
|
return;
|
|
|
|
/* registry must be locked */
|
|
|
|
memset (jack_shm_header, 0, JACK_SHM_REGISTRY_SIZE);
|
|
|
|
jack_shm_header->magic = JACK_SHM_MAGIC;
|
|
//jack_shm_header->protocol = JACK_PROTOCOL_VERSION;
|
|
jack_shm_header->type = jack_shmtype;
|
|
jack_shm_header->size = JACK_SHM_REGISTRY_SIZE;
|
|
jack_shm_header->hdr_len = sizeof (jack_shm_header_t);
|
|
jack_shm_header->entry_len = sizeof (jack_shm_registry_t);
|
|
|
|
for (int i = 0; i < MAX_SHM_ID; ++i) {
|
|
jack_shm_registry[i].index = i;
|
|
}
|
|
}
|
|
|
|
void Shm::set_server_prefix (const char *server_name) {
|
|
snprintf (jack_shm_server_prefix, sizeof (jack_shm_server_prefix),
|
|
"jack-%d:%s:", GetUID(), server_name);
|
|
}
|
|
|
|
/* create a new SHM registry segment
|
|
*
|
|
* sets up global registry pointers, if successful
|
|
*
|
|
* returns: 0 if registry created successfully
|
|
* nonzero error code if unable to allocate a new registry
|
|
*/
|
|
int Shm::create_registry (jack_shm_info_t * ri) {
|
|
jack_d("create_registry\n");
|
|
/* registry must be locked */
|
|
int shm_fd = 0;
|
|
|
|
strncpy (registry_id, JACK_REGISTRY_NAME, sizeof (registry_id) - 1);
|
|
registry_id[sizeof (registry_id) - 1] = '\0';
|
|
|
|
sp<IAndroidShm> service = getShmService();
|
|
if(service == NULL){
|
|
jack_error("shm service is null");
|
|
return EINVAL;
|
|
}
|
|
|
|
if((shm_fd = service->allocShm(JACK_SHM_REGISTRY_SIZE)) < 0) {
|
|
jack_error("Cannot create shm registry segment");
|
|
registry_fd = JACK_SHM_REGISTRY_FD;
|
|
return EINVAL;
|
|
}
|
|
|
|
service->setRegistryIndex(shm_fd);
|
|
|
|
/* set up global pointers */
|
|
ri->fd = shm_fd;
|
|
ri->index = JACK_SHM_REGISTRY_INDEX;
|
|
registry_fd = shm_fd;
|
|
ri->ptr.attached_at = shm_addr(shm_fd);
|
|
ri->size = JACK_SHM_REGISTRY_SIZE;
|
|
|
|
jack_shm_header = (jack_shm_header_t*)(ri->ptr.attached_at);
|
|
jack_shm_registry = (jack_shm_registry_t *) (jack_shm_header + 1);
|
|
|
|
jack_d("create_registry jack_shm_header[%p], jack_shm_registry[%p]", jack_shm_header, jack_shm_registry);
|
|
|
|
/* initialize registry contents */
|
|
shm_init_registry ();
|
|
//close (shm_fd); // steph
|
|
|
|
return 0;
|
|
}
|
|
|
|
int Shm::shm_validate_registry () {
|
|
/* registry must be locked */
|
|
if(jack_shm_header == NULL) {
|
|
return -1;
|
|
}
|
|
|
|
if ((jack_shm_header->magic == JACK_SHM_MAGIC)
|
|
//&& (jack_shm_header->protocol == JACK_PROTOCOL_VERSION)
|
|
&& (jack_shm_header->type == jack_shmtype)
|
|
&& (jack_shm_header->size == JACK_SHM_REGISTRY_SIZE)
|
|
&& (jack_shm_header->hdr_len == sizeof (jack_shm_header_t))
|
|
&& (jack_shm_header->entry_len == sizeof (jack_shm_registry_t))) {
|
|
|
|
return 0; /* registry OK */
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
int Shm::server_initialize_shm (int new_registry) {
|
|
int rc;
|
|
|
|
jack_d("server_initialize_shm\n");
|
|
|
|
if (jack_shm_header)
|
|
return 0; /* already initialized */
|
|
|
|
if (shm_lock_registry () < 0) {
|
|
jack_error ("jack_shm_lock_registry fails...");
|
|
return -1;
|
|
}
|
|
|
|
rc = access_registry (®istry_info);
|
|
|
|
if (new_registry) {
|
|
remove_shm (®istry_id);
|
|
rc = ENOENT;
|
|
}
|
|
|
|
switch (rc) {
|
|
case ENOENT: /* registry does not exist */
|
|
rc = create_registry (®istry_info);
|
|
break;
|
|
case 0: /* existing registry */
|
|
if (shm_validate_registry () == 0)
|
|
break;
|
|
/* else it was invalid, so fall through */
|
|
case EINVAL: /* bad registry */
|
|
/* Apparently, this registry was created by an older
|
|
* JACK version. Delete it so we can try again. */
|
|
release_shm (®istry_info);
|
|
remove_shm (®istry_id);
|
|
if ((rc = create_registry (®istry_info)) != 0) {
|
|
//jack_error ("incompatible shm registry (%s)",
|
|
// strerror (errno));
|
|
jack_error ("incompatible shm registry");
|
|
//#ifndef USE_POSIX_SHM
|
|
// jack_error ("to delete, use `ipcrm -M 0x%0.8x'", JACK_SHM_REGISTRY_KEY);
|
|
//#endif
|
|
}
|
|
break;
|
|
default: /* failure return code */
|
|
break;
|
|
}
|
|
|
|
shm_unlock_registry ();
|
|
return rc;
|
|
}
|
|
|
|
// here begin the API
|
|
int Shm::register_server (const char *server_name, int new_registry) {
|
|
int i, res = 0;
|
|
|
|
jack_d("register_server new_registry[%d]\n", new_registry);
|
|
|
|
set_server_prefix (server_name);
|
|
|
|
if (server_initialize_shm (new_registry))
|
|
return ENOMEM;
|
|
|
|
if (shm_lock_registry () < 0) {
|
|
jack_error ("jack_shm_lock_registry fails...");
|
|
return -1;
|
|
}
|
|
|
|
/* See if server_name already registered. Since server names
|
|
* are per-user, we register the unique server prefix string.
|
|
*/
|
|
for (i = 0; i < MAX_SERVERS; i++) {
|
|
|
|
if (strncmp (jack_shm_header->server[i].name,
|
|
jack_shm_server_prefix,
|
|
JACK_SERVER_NAME_SIZE) != 0)
|
|
continue; /* no match */
|
|
|
|
if (jack_shm_header->server[i].pid == GetPID()) {
|
|
res = 0; /* it's me */
|
|
goto unlock;
|
|
}
|
|
|
|
/* see if server still exists */
|
|
if (kill (jack_shm_header->server[i].pid, 0) == 0) {
|
|
res = EEXIST; /* other server running */
|
|
goto unlock;
|
|
}
|
|
|
|
/* it's gone, reclaim this entry */
|
|
memset (&jack_shm_header->server[i], 0,
|
|
sizeof (jack_shm_server_t));
|
|
}
|
|
|
|
/* find a free entry */
|
|
for (i = 0; i < MAX_SERVERS; i++) {
|
|
if (jack_shm_header->server[i].pid == 0)
|
|
break;
|
|
}
|
|
|
|
if (i >= MAX_SERVERS) {
|
|
res = ENOSPC; /* out of space */
|
|
goto unlock;
|
|
}
|
|
|
|
/* claim it */
|
|
jack_shm_header->server[i].pid = GetPID();
|
|
strncpy (jack_shm_header->server[i].name,
|
|
jack_shm_server_prefix,
|
|
JACK_SERVER_NAME_SIZE - 1);
|
|
jack_shm_header->server[i].name[JACK_SERVER_NAME_SIZE - 1] = '\0';
|
|
|
|
unlock:
|
|
shm_unlock_registry ();
|
|
return res;
|
|
}
|
|
|
|
int Shm::unregister_server (const char * /* server_name */) {
|
|
int i;
|
|
if (shm_lock_registry () < 0) {
|
|
jack_error ("jack_shm_lock_registry fails...");
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0; i < MAX_SERVERS; i++) {
|
|
if (jack_shm_header->server[i].pid == GetPID()) {
|
|
memset (&jack_shm_header->server[i], 0,
|
|
sizeof (jack_shm_server_t));
|
|
}
|
|
}
|
|
|
|
shm_unlock_registry ();
|
|
return 0;
|
|
}
|
|
|
|
int Shm::initialize_shm (const char *server_name) {
|
|
int rc;
|
|
|
|
if (jack_shm_header)
|
|
return 0; /* already initialized */
|
|
|
|
set_server_prefix (server_name);
|
|
|
|
if (shm_lock_registry () < 0) {
|
|
jack_error ("jack_shm_lock_registry fails...");
|
|
return -1;
|
|
}
|
|
|
|
if ((rc = access_registry (®istry_info)) == 0) {
|
|
if ((rc = shm_validate_registry ()) != 0) {
|
|
jack_error ("Incompatible shm registry, "
|
|
"are jackd and libjack in sync?");
|
|
}
|
|
}
|
|
shm_unlock_registry ();
|
|
|
|
return rc;
|
|
}
|
|
|
|
int Shm::initialize_shm_server (void) {
|
|
// not used
|
|
return 0;
|
|
}
|
|
|
|
int Shm::initialize_shm_client (void) {
|
|
// not used
|
|
return 0;
|
|
}
|
|
|
|
int Shm::cleanup_shm (void) {
|
|
int i;
|
|
int destroy;
|
|
jack_shm_info_t copy;
|
|
|
|
if (shm_lock_registry () < 0) {
|
|
jack_error ("jack_shm_lock_registry fails...");
|
|
return -1;
|
|
}
|
|
|
|
for (i = 0; i < MAX_SHM_ID; i++) {
|
|
jack_shm_registry_t* r;
|
|
|
|
r = &jack_shm_registry[i];
|
|
memcpy (©, r, sizeof (jack_shm_info_t));
|
|
destroy = FALSE;
|
|
|
|
/* ignore unused entries */
|
|
if (r->allocator == 0)
|
|
continue;
|
|
|
|
/* is this my shm segment? */
|
|
if (r->allocator == GetPID()) {
|
|
|
|
/* allocated by this process, so unattach
|
|
and destroy. */
|
|
release_shm (©);
|
|
destroy = TRUE;
|
|
|
|
} else {
|
|
|
|
/* see if allocator still exists */
|
|
if (kill (r->allocator, 0)) {
|
|
if (errno == ESRCH) {
|
|
/* allocator no longer exists,
|
|
* so destroy */
|
|
destroy = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (destroy) {
|
|
|
|
int index = copy.index;
|
|
|
|
if ((index >= 0) && (index < MAX_SHM_ID)) {
|
|
remove_shm (&jack_shm_registry[index].id);
|
|
release_shm_entry (index);
|
|
}
|
|
r->size = 0;
|
|
r->allocator = 0;
|
|
}
|
|
}
|
|
|
|
shm_unlock_registry ();
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
jack_shm_registry_t * Shm::get_free_shm_info () {
|
|
/* registry must be locked */
|
|
jack_shm_registry_t* si = NULL;
|
|
int i;
|
|
|
|
for (i = 0; i < MAX_SHM_ID; ++i) {
|
|
if (jack_shm_registry[i].size == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i < MAX_SHM_ID) {
|
|
si = &jack_shm_registry[i];
|
|
}
|
|
|
|
return si;
|
|
}
|
|
|
|
int Shm::shmalloc (const char * /*shm_name*/, jack_shmsize_t size, jack_shm_info_t* si) {
|
|
jack_shm_registry_t* registry;
|
|
int shm_fd;
|
|
int rc = -1;
|
|
char name[SHM_NAME_MAX+1];
|
|
|
|
if (shm_lock_registry () < 0) {
|
|
jack_error ("jack_shm_lock_registry fails...");
|
|
return -1;
|
|
}
|
|
|
|
sp<IAndroidShm> service = getShmService();
|
|
if(service == NULL){
|
|
rc = errno;
|
|
jack_error("shm service is null");
|
|
goto unlock;
|
|
}
|
|
|
|
if ((registry = get_free_shm_info ()) == NULL) {
|
|
jack_error ("shm registry full");
|
|
goto unlock;
|
|
}
|
|
|
|
snprintf (name, sizeof (name), "/jack-%d-%d", GetUID(), registry->index);
|
|
if (strlen (name) >= sizeof (registry->id)) {
|
|
jack_error ("shm segment name too long %s", name);
|
|
goto unlock;
|
|
}
|
|
|
|
if((shm_fd = service->allocShm(size)) < 0) {
|
|
rc = errno;
|
|
jack_error ("Cannot create shm segment %s", name);
|
|
goto unlock;
|
|
}
|
|
|
|
//close (shm_fd);
|
|
registry->size = size;
|
|
strncpy (registry->id, name, sizeof (registry->id) - 1);
|
|
registry->id[sizeof (registry->id) - 1] = '\0';
|
|
registry->allocator = GetPID();
|
|
registry->fd = shm_fd;
|
|
si->fd = shm_fd;
|
|
si->index = registry->index;
|
|
si->ptr.attached_at = MAP_FAILED; /* not attached */
|
|
rc = 0; /* success */
|
|
|
|
jack_d ("[APA] jack_shmalloc : ok ");
|
|
|
|
unlock:
|
|
shm_unlock_registry ();
|
|
return rc;
|
|
}
|
|
|
|
void Shm::release_shm (jack_shm_info_t* /*si*/) {
|
|
// do nothing
|
|
}
|
|
|
|
void Shm::release_lib_shm (jack_shm_info_t* /*si*/) {
|
|
// do nothing
|
|
}
|
|
|
|
void Shm::destroy_shm (jack_shm_info_t* si) {
|
|
/* must NOT have the registry locked */
|
|
if (si->index == JACK_SHM_NULL_INDEX)
|
|
return; /* segment not allocated */
|
|
|
|
remove_shm (&jack_shm_registry[si->index].id);
|
|
release_shm_info (si->index);
|
|
}
|
|
|
|
int Shm::attach_shm (jack_shm_info_t* si) {
|
|
jack_shm_registry_t *registry = &jack_shm_registry[si->index];
|
|
|
|
if((si->ptr.attached_at = shm_addr(registry->fd)) == NULL) {
|
|
jack_error ("Cannot mmap shm segment %s", registry->id);
|
|
close (si->fd);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Shm::attach_lib_shm (jack_shm_info_t* si) {
|
|
int res = attach_shm(si);
|
|
if (res == 0)
|
|
si->size = jack_shm_registry[si->index].size; // Keep size in si struct
|
|
return res;
|
|
}
|
|
|
|
int Shm::attach_shm_read (jack_shm_info_t* si) {
|
|
jack_shm_registry_t *registry = &jack_shm_registry[si->index];
|
|
|
|
if((si->ptr.attached_at = shm_addr(registry->fd)) == NULL) {
|
|
jack_error ("Cannot mmap shm segment %s", registry->id);
|
|
close (si->fd);
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int Shm::attach_lib_shm_read (jack_shm_info_t* si) {
|
|
int res = attach_shm_read(si);
|
|
if (res == 0)
|
|
si->size = jack_shm_registry[si->index].size; // Keep size in si struct
|
|
return res;
|
|
}
|
|
|
|
int Shm::resize_shm (jack_shm_info_t* si, jack_shmsize_t size) {
|
|
jack_shm_id_t id;
|
|
|
|
/* The underlying type of `id' differs for SYSV and POSIX */
|
|
memcpy (&id, &jack_shm_registry[si->index].id, sizeof (id));
|
|
|
|
release_shm (si);
|
|
destroy_shm (si);
|
|
|
|
if (shmalloc ((char *) id, size, si)) {
|
|
return -1;
|
|
}
|
|
return attach_shm (si);
|
|
}
|
|
|
|
void Shm::jack_shm_copy_from_registry (jack_shm_info_t* si, jack_shm_registry_index_t t) {
|
|
Shm::Instantiate()->shm_copy_from_registry(si,t);
|
|
}
|
|
void Shm::jack_shm_copy_to_registry (jack_shm_info_t* si, jack_shm_registry_index_t* t) {
|
|
Shm::Instantiate()->shm_copy_to_registry(si,t);
|
|
}
|
|
int Shm::jack_release_shm_info (jack_shm_registry_index_t t) {
|
|
return Shm::Instantiate()->release_shm_info(t);
|
|
}
|
|
char* Shm::jack_shm_addr (jack_shm_info_t* si) {
|
|
if(si != NULL) {
|
|
return (char*)si->ptr.attached_at;
|
|
} else {
|
|
jack_error ("jack_shm_addr : jack_shm_info_t is NULL!");
|
|
return NULL;
|
|
}
|
|
}
|
|
int Shm::jack_register_server (const char *server_name, int new_registry) {
|
|
return Shm::Instantiate()->register_server(server_name, new_registry);
|
|
}
|
|
int Shm::jack_unregister_server (const char *server_name) {
|
|
return Shm::Instantiate()->unregister_server(server_name);
|
|
}
|
|
int Shm::jack_initialize_shm (const char *server_name) {
|
|
return Shm::Instantiate()->initialize_shm(server_name);
|
|
}
|
|
int Shm::jack_initialize_shm_server (void) {
|
|
return Shm::Instantiate()->initialize_shm_server();
|
|
}
|
|
int Shm::jack_initialize_shm_client () {
|
|
return Shm::Instantiate()->initialize_shm_client();
|
|
}
|
|
int Shm::jack_cleanup_shm (void) {
|
|
return Shm::Instantiate()->cleanup_shm();
|
|
}
|
|
int Shm::jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* result) {
|
|
return Shm::Instantiate()->shmalloc(shm_name, size, result);
|
|
}
|
|
void Shm::jack_release_shm (jack_shm_info_t* si) {
|
|
Shm::Instantiate()->release_shm(si);
|
|
}
|
|
void Shm::jack_release_lib_shm (jack_shm_info_t* si) {
|
|
Shm::Instantiate()->release_lib_shm(si);
|
|
}
|
|
void Shm::jack_destroy_shm (jack_shm_info_t* si) {
|
|
Shm::Instantiate()->destroy_shm(si);
|
|
}
|
|
int Shm::jack_attach_shm (jack_shm_info_t* si) {
|
|
return Shm::Instantiate()->attach_shm(si);
|
|
}
|
|
int Shm::jack_attach_lib_shm (jack_shm_info_t* si) {
|
|
return Shm::Instantiate()->attach_lib_shm(si);
|
|
}
|
|
int Shm::jack_attach_shm_read (jack_shm_info_t* si) {
|
|
return Shm::Instantiate()->attach_shm_read(si);
|
|
}
|
|
int Shm::jack_attach_lib_shm_read (jack_shm_info_t* si) {
|
|
return Shm::Instantiate()->attach_lib_shm_read(si);
|
|
}
|
|
int Shm::jack_resize_shm (jack_shm_info_t* si, jack_shmsize_t size) {
|
|
return Shm::Instantiate()->resize_shm(si, size);
|
|
}
|
|
};
|
|
|
|
void jack_shm_copy_from_registry (jack_shm_info_t* si, jack_shm_registry_index_t t) {
|
|
android::Shm::jack_shm_copy_from_registry(si, t);
|
|
}
|
|
void jack_shm_copy_to_registry (jack_shm_info_t* si, jack_shm_registry_index_t* t) {
|
|
android::Shm::jack_shm_copy_to_registry(si, t);
|
|
}
|
|
int jack_release_shm_info (jack_shm_registry_index_t t) {
|
|
return android::Shm::jack_release_shm_info(t);
|
|
}
|
|
char* jack_shm_addr (jack_shm_info_t* si) {
|
|
return android::Shm::jack_shm_addr(si);
|
|
}
|
|
int jack_register_server (const char *server_name, int new_registry) {
|
|
return android::Shm::jack_register_server(server_name, new_registry);
|
|
}
|
|
int jack_unregister_server (const char *server_name) {
|
|
return android::Shm::jack_unregister_server(server_name);
|
|
}
|
|
int jack_initialize_shm (const char *server_name) {
|
|
return android::Shm::jack_initialize_shm(server_name);
|
|
}
|
|
int jack_initialize_shm_server (void) {
|
|
return android::Shm::jack_initialize_shm_server();
|
|
}
|
|
int jack_initialize_shm_client (void) {
|
|
return android::Shm::jack_initialize_shm_client();
|
|
}
|
|
int jack_cleanup_shm (void) {
|
|
return android::Shm::jack_cleanup_shm();
|
|
}
|
|
int jack_shmalloc (const char *shm_name, jack_shmsize_t size, jack_shm_info_t* result) {
|
|
return android::Shm::jack_shmalloc(shm_name, size, result);
|
|
}
|
|
void jack_release_shm (jack_shm_info_t* si) {
|
|
android::Shm::jack_release_shm(si);
|
|
}
|
|
void jack_release_lib_shm (jack_shm_info_t* si) {
|
|
android::Shm::jack_release_lib_shm(si);
|
|
}
|
|
void jack_destroy_shm (jack_shm_info_t* si) {
|
|
android::Shm::jack_destroy_shm(si);
|
|
}
|
|
int jack_attach_shm (jack_shm_info_t* si) {
|
|
return android::Shm::jack_attach_shm(si);
|
|
}
|
|
int jack_attach_lib_shm (jack_shm_info_t* si) {
|
|
return android::Shm::jack_attach_lib_shm(si);
|
|
}
|
|
int jack_attach_shm_read (jack_shm_info_t* si) {
|
|
return android::Shm::jack_attach_shm_read(si);
|
|
}
|
|
int jack_attach_lib_shm_read (jack_shm_info_t* si) {
|
|
return android::Shm::jack_attach_lib_shm_read(si);
|
|
}
|
|
int jack_resize_shm (jack_shm_info_t* si, jack_shmsize_t size) {
|
|
return android::Shm::jack_resize_shm(si, size);
|
|
}
|
|
void jack_instantiate() {
|
|
android::AndroidShm::instantiate();
|
|
}
|
|
|