shmembase.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 975 行 · 第 1/2 页

C
975
字号
/* * @(#)shmemBase.c	1.10 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License version   * 2 only, as published by the Free Software Foundation.    *    * 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 version 2 for more details (a copy is   * included at /legal/license.txt).    *    * You should have received a copy of the GNU General Public License   * version 2 along with this work; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA   * 02110-1301 USA    *    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.com if you need additional   * information or have any questions.  * */#include <stdio.h>#include <string.h>#include <errno.h>#include <stdlib.h>#include "sysShmem.h"#include "shmemBase.h"#include "transportSPI.h"  /* for Packet, TransportCallback */#include "util.h" /* for MIN *//* * This is the base shared memory transport implementation that is used * by both front-end transports (through com.sun.tools.jdi) and  * back-end transports (through JDWP_OnLoad and the function tables  * it requires). It supports multiple connections for the benefit of the  * front-end client; the back end interface assumes only a single connection. */  #define MAX_IPC_PREFIX 50   /* user-specified or generated name for */                            /* shared memory seg and prefix for other IPC */#define MAX_IPC_SUFFIX 25   /* suffix to shmem name for other IPC names */#define MAX_IPC_NAME   (MAX_IPC_PREFIX + MAX_IPC_SUFFIX)#define MAX_GENERATION_RETRIES 20#define SHARED_BUFFER_SIZE 5000#define CHECK_ERROR(expr) do { \                              jint error = (expr); \                              if (error != SYS_OK) { \                                  return error; \                              } \                          } while (0)/* * The following assertions should hold anytime the stream's mutex is not held */#define STREAM_INVARIANT(stream) \        do { \            SHMEM_ASSERT((stream->shared->readOffset < SHARED_BUFFER_SIZE) \                         && (stream->shared->readOffset >= 0)); \            SHMEM_ASSERT((stream->shared->writeOffset < SHARED_BUFFER_SIZE) \                         && (stream->shared->writeOffset >= 0)); \        } while (0)/*    * Transports are duplex, so carve the shared memory into "streams", * one used to send from client to server, the other vice versa. */typedef struct SharedMemoryListener {    char mutexName[MAX_IPC_NAME];    char acceptEventName[MAX_IPC_NAME];    char attachEventName[MAX_IPC_NAME];    jboolean isListening;    jboolean isAccepted;    jlong acceptingPID;    jlong attachingPID;} SharedListener;typedef struct SharedMemoryTransport {    char name[MAX_IPC_PREFIX];    sys_ipmutex_t mutex;    sys_event_t acceptEvent;    sys_event_t attachEvent;    sys_shmem_t sharedMemory;    SharedListener *shared;} SharedMemoryTransport;typedef struct SharedStream {    char mutexName[MAX_IPC_NAME];    char hasDataEventName[MAX_IPC_NAME];    char hasSpaceEventName[MAX_IPC_NAME];    int readOffset;    int writeOffset;    jboolean isFull;    jbyte buffer[SHARED_BUFFER_SIZE];} SharedStream;typedef struct SharedMemory {    SharedStream toClient;    SharedStream toServer;} SharedMemory;typedef struct Stream {    sys_ipmutex_t mutex;    sys_event_t hasData;    sys_event_t hasSpace;    SharedStream *shared;} Stream;typedef struct SharedMemoryConnection {    char name[MAX_IPC_NAME];    SharedMemory *shared;    sys_shmem_t sharedMemory;    Stream incoming;       Stream outgoing;    sys_process_t otherProcess;} SharedMemoryConnection;static TransportCallback *callback;static JavaVM *jvm;typedef jint (*CreateFunc)(char *name, void *arg);static void exitWithError(char *fileName, char *date, int lineNumber,               char *message, jint errorCode){    char buf[500];    /* Get past path info */    char *p1 = strrchr(fileName, '\\');    char *p2 = strrchr(fileName, '/');    p1 = ((p1 > p2) ? p1 : p2);    if (p1 != NULL) {        fileName = p1 + 1;    }    if (errorCode != 0) {		                                      sprintf(buf, "JDI \"%s\" (%s), line %d: %s, error code = %d (%s)\n",                fileName, date, lineNumber, message, errorCode,                 "");             \    } else {                                                               sprintf(buf, "JDI \"%s\" (%s), line %d: %s\n",                                    fileName, date, lineNumber, message);             \    }                                                                  printf("%s", buf);    exit(0);}jint shmemBase_initialize(JavaVM *vm, TransportCallback *cbPtr){    jvm = vm;    callback = cbPtr;    return SYS_OK;}static jintcreateWithGeneratedName(char *prefix, char *nameBuffer, CreateFunc func, void *arg){    jint error;    jint i = 0;    do {        strcpy(nameBuffer, prefix);        if (i > 0) {            char buf[10];            sprintf(buf, ".%d", i+1);            strcat(nameBuffer, buf);        }        error = func(nameBuffer, arg);        i++;    } while ((error == SYS_INUSE) && (i < MAX_GENERATION_RETRIES));    return error;}typedef struct SharedMemoryArg {    jint size;    sys_shmem_t memory;    void *start;} SharedMemoryArg;static jint createSharedMem(char *name, void *ptr){    SharedMemoryArg *arg = ptr;    return sysSharedMemCreate(name, arg->size, &arg->memory, &arg->start);}static jint createMutex(char *name, void *arg){    sys_ipmutex_t *retArg = arg;    return sysIPMutexCreate(name, retArg);}static jint createEvent(char *name, void *arg){    sys_event_t *retArg = arg;    return sysEventCreate(name, retArg);}#define ADD_OFFSET(o1, o2) ((o1 + o2) % SHARED_BUFFER_SIZE)#define FULL(stream) (stream->shared->isFull)#define EMPTY(stream) ((stream->shared->writeOffset == stream->shared->readOffset) \                       && !stream->shared->isFull)static jintenterMutex(Stream *stream){    return sysIPMutexEnter(stream->mutex);}static jintleaveMutex(Stream *stream){    return sysIPMutexExit(stream->mutex);}static jint waitForSpace(SharedMemoryConnection *connection, Stream *stream){    jint error = SYS_OK;     /* Assumes mutex is held on call */    while (FULL(stream) && (error == SYS_OK)) {        CHECK_ERROR(leaveMutex(stream));        error = sysEventWait(connection->otherProcess, stream->hasSpace);        CHECK_ERROR(enterMutex(stream));    }    return error;}static jintsignalSpace(Stream *stream){    return sysEventSignal(stream->hasSpace);}static jintwaitForData(SharedMemoryConnection *connection, Stream *stream){    jint error = SYS_OK;    /* Assumes mutex is held on call */    while (EMPTY(stream) && (error == SYS_OK)) {        CHECK_ERROR(leaveMutex(stream));        error = sysEventWait(connection->otherProcess, stream->hasData);        CHECK_ERROR(enterMutex(stream));    }    return error;}static jintsignalData(Stream *stream){    return sysEventSignal(stream->hasData);}static voidcloseStream(Stream *stream) {    sysIPMutexClose(stream->mutex);    sysEventClose(stream->hasData);    sysEventClose(stream->hasSpace);}static intcreateStream(char *name, Stream *stream){    jint error;    char prefix[MAX_IPC_PREFIX];    sprintf(prefix, "%s.mutex", name);    error = createWithGeneratedName(prefix, stream->shared->mutexName,                                    createMutex, &stream->mutex);    if (error != SYS_OK) {        fprintf(stderr,"Error creating mutex, rc = %d\n", error);        return error;    }    sprintf(prefix, "%s.hasData", name);    error = createWithGeneratedName(prefix, stream->shared->hasDataEventName,                                    createEvent, &stream->hasData);    if (error != SYS_OK) {        fprintf(stderr,"Error creating event, rc = %d\n", error);        closeStream(stream);        return error;    }    sprintf(prefix, "%s.hasSpace", name);    error = createWithGeneratedName(prefix, stream->shared->hasSpaceEventName,                                    createEvent, &stream->hasSpace);    if (error != SYS_OK) {        fprintf(stderr,"Error creating event, rc = %d\n", error);        closeStream(stream);        return error;    }    stream->shared->readOffset = 0;    stream->shared->writeOffset = 0;    stream->shared->isFull = JNI_FALSE;    return SYS_OK;}/* * Initialization for the stream opened by the other process */static intopenStream(Stream *stream){    jint error;    error = sysIPMutexOpen(stream->shared->mutexName, &stream->mutex);    if (error != SYS_OK) {        fprintf(stderr,"Error accessing mutex, rc = %d\n", error);        return error;    }    error = sysEventOpen(stream->shared->hasDataEventName,                             &stream->hasData);    if (error != SYS_OK) {        fprintf(stderr,"Error accessing mutex, rc = %d\n", error);        closeStream(stream);        return error;    }    error = sysEventOpen(stream->shared->hasSpaceEventName,                             &stream->hasSpace);    if (error != SYS_OK) {        fprintf(stderr,"Error accessing mutex, rc = %d\n", error);        closeStream(stream);        return error;    }    return SYS_OK;}/********************************************************************/static SharedMemoryConnection *allocConnection(void){    /*     * TO DO: Track all allocated connections for clean shutdown?     */    return (*callback->alloc)(sizeof(SharedMemoryConnection));}static void freeConnection(SharedMemoryConnection *connection){    (*callback->free)(connection);}static voidcloseConnection(SharedMemoryConnection *connection){    closeStream(&connection->incoming);    closeStream(&connection->outgoing);    sysSharedMemClose(connection->sharedMemory, connection->shared);    sysProcessClose(connection->otherProcess);    freeConnection(connection);}static jintopenConnection(SharedMemoryTransport *transport, jlong otherPID,                SharedMemoryConnection **connectionPtr){    jint error;    SharedMemoryConnection *connection = allocConnection();    if (connection == NULL) {        return SYS_NOMEM;    }    memset(connection, 0, sizeof(*connection));    sprintf(connection->name, "%s.%ld", transport->name, sysProcessGetID());    error = sysSharedMemOpen(connection->name, &connection->sharedMemory,                             &connection->shared);    if (error != SYS_OK) {        closeConnection(connection);        return error;    }    /* This process is the client */    connection->incoming.shared = &connection->shared->toClient;    connection->outgoing.shared = &connection->shared->toServer;    error = openStream(&connection->incoming);    if (error != SYS_OK) {        closeConnection(connection);        return error;    }    error = openStream(&connection->outgoing);    if (error != SYS_OK) {        closeConnection(connection);        return error;    }    error = sysProcessOpen(otherPID, &connection->otherProcess);    if (error != SYS_OK) {        fprintf(stderr,"Error accessing process, rc = %d\n", error);        closeConnection(connection);        return error;    }    *connectionPtr = connection;    return SYS_OK;}static jintcreateConnection(SharedMemoryTransport *transport, jlong otherPID,                  SharedMemoryConnection **connectionPtr){    jint error;    char streamPrefix[MAX_IPC_NAME];    SharedMemoryConnection *connection = allocConnection();    if (connection == NULL) {        return SYS_NOMEM;    }    memset(connection, 0, sizeof(*connection));    sprintf(connection->name, "%s.%ld", transport->name, otherPID);    error = sysSharedMemCreate(connection->name, sizeof(SharedMemory),                               &connection->sharedMemory, &connection->shared);    if (error != SYS_OK) {        closeConnection(connection);        return error;    }    memset(connection->shared, 0, sizeof(SharedMemory));    /* This process is the server */    connection->incoming.shared = &connection->shared->toServer;    connection->outgoing.shared = &connection->shared->toClient;    strcpy(streamPrefix, connection->name);    strcat(streamPrefix, ".ctos");    error = createStream(streamPrefix, &connection->incoming);    if (error != SYS_OK) {        closeConnection(connection);        return error;    }    strcpy(streamPrefix, connection->name);    strcat(streamPrefix, ".stoc");    error = createStream(streamPrefix, &connection->outgoing);    if (error != SYS_OK) {        closeConnection(connection);        return error;    }    error = sysProcessOpen(otherPID, &connection->otherProcess);    if (error != SYS_OK) {        fprintf(stderr,"Error accessing process, rc = %d\n", error);        closeConnection(connection);        return error;    }    *connectionPtr = connection;    return SYS_OK;}/********************************************************************/static SharedMemoryTransport *allocTransport(void){    /*     * TO DO: Track all allocated transports for clean shutdown?     */    return (*callback->alloc)(sizeof(SharedMemoryTransport));}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?