/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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 in the LICENSE file that
* accompanied this code).
*
* 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.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 "jdwpTransport.h" /* for Packet, TransportCallback */
#define MIN(x,y) ((x)<(y)?(x):(y))
/*
* 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.
*/
/* shared memory seg and prefix for other IPC */
setLastError(error); \
return error; \
} \
} while (0)
/*
* The following assertions should hold anytime the stream's mutex is not held
*/
do { \
} 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 {
typedef struct SharedMemoryTransport {
/*
* Access must be syncronized. Holds one shared
* memory buffer and its state.
*/
typedef struct SharedStream {
int readOffset;
int writeOffset;
} SharedStream;
/*
* The two shared streams: client to server and
* server to client.
*/
typedef struct SharedMemory {
} SharedMemory;
/*
* Local (to process) access to the shared memory
* stream. access to hasData and hasSpace synchronized
* by OS.
*/
typedef struct Stream {
} Stream;
/*
* Values for Stream.state field above.
*/
/*
* State checking macro. We compare against the STATE_OPEN value so
* that STATE_CLOSED and any other value will be considered closed.
* This catches a freed Stream as long as the memory page is still
* valid. If the memory page is gone, then there is little that we
* can do.
*/
typedef struct SharedMemoryConnection {
static int tlsIndex;
/*
* Set the per-thread error message (if not already set)
*/
static void
char *msg;
}
}
}
/*
* Clear last per-thread error message
*/
static void
clearLastError() {
}
}
/*
* Set the per-thread error message to the textual representation
* of the last system error (if not already set)
*/
static void
switch (error) {
case SYS_OK : return; /* no-op */
}
}
{
tlsIndex = sysTlsAlloc();
return SYS_OK;
}
static jint
{
jint i = 0;
do {
if (i > 0) {
}
i++;
}
return error;
}
typedef struct SharedMemoryArg {
void *start;
static jint
{
}
static jint
{
}
/*
* Creates named or unnamed event that is automatically reset
* (in other words, no need to reset event after it has signalled
* a thread).
*/
static jint
{
}
static jint
{
}
/* enter the stream's mutex and (optionally) check for a closed stream */
static jint
{
setLastErrorMsg("stream closed");
}
return ret;
}
setLastErrorMsg("stream closed");
(void)leaveMutex(stream);
return SYS_ERR;
}
return SYS_OK;
}
/*
* On error, does not hold the stream mutex.
*/
static jint
{
/* Assumes mutex is held on call */
} else {
}
}
return error;
}
static jint
{
}
/*
* On error, does not hold the stream mutex.
*/
static jint
{
/* Assumes mutex is held on call */
} else {
}
}
return error;
}
static jint
{
}
static jint
{
/*
* Lock stream during close - ignore shutdown event as we are
* closing down and shutdown should be signalled.
*/
/* mark the stream as closed */
/* wake up waitForData() if it is in sysEventWait() */
/* wake up waitForSpace() if it is in sysEventWait() */
/*
* If linger requested then give the stream a few seconds to
* drain before closing it.
*/
if (linger) {
sysSleep(200);
attempts--;
}
}
return SYS_OK;
}
/*
* Server creates stream.
*/
static int
{
return error;
}
return error;
}
return error;
}
return SYS_OK;
}
/*
* Initialization for the stream opened by the other process
*/
static int
{
return error;
}
return error;
}
return SYS_OK;
}
/********************************************************************/
static SharedMemoryConnection *
allocConnection(void)
{
/*
* TO DO: Track all allocated connections for clean shutdown?
*/
}
return conn;
}
static void
{
}
static void
{
/*
* Signal all threads accessing this connection that we are
* shutting down.
*/
if (connection->shutdown) {
}
if (connection->sharedMemory) {
}
if (connection->otherProcess) {
}
/*
* Ideally we should close the connection->shutdown event and
* free the connection structure. However as closing the
* connection is asynchronous it means that other threads may
* still be accessing the connection structure. On Win32 this
* means we leak 132 bytes and one event per connection. This
* memory will be reclaim at process exit.
*
* if (connection->shutdown)
* sysEventClose(connection->shutdown);
* freeConnection(connection);
*/
}
/*
* For client: connect to the shared memory. Open incoming and
* outgoing streams.
*/
static jint
{
if (connection == NULL) {
return SYS_NOMEM;
}
&connection->shared);
return error;
}
/* This process is the client */
return error;
}
return error;
}
return error;
}
/*
* Create an event that signals that the connection is shutting
* down. The event is unnamed as it's process local, and is
* manually reset (so that signalling the event will signal
* all threads waiting on it).
*/
return error;
}
return SYS_OK;
}
/*
* For server: create the shared memory. Create incoming and
* outgoing streams.
*/
static jint
{
if (connection == NULL) {
return SYS_NOMEM;
}
return error;
}
/* This process is the server */
return error;
}
return error;
}
return error;
}
/*
* Create an event that signals that the connection is shutting
* down. The event is unnamed as it's process local, and is
* manually reset (so that a signalling the event will signal
* all threads waiting on it).
*/
return error;
}
return SYS_OK;
}
/********************************************************************/
static SharedMemoryTransport *
allocTransport(void)
{
/*
* TO DO: Track all allocated transports for clean shutdown?
*/
}
static void
{
}
static void
{
}
static int
{
transport = allocTransport();
return SYS_NOMEM;
}
return SYS_ERR;
}
return error;
}
return error;
}
&transport->acceptEvent);
return error;
}
&transport->attachEvent);
return error;
}
return SYS_OK;
}
static jint
{
transport = allocTransport();
return SYS_NOMEM;
}
createSharedMem, &arg);
} else {
return SYS_ERR;
}
}
return error;
}
return error;
}
return error;
}
return error;
}
return SYS_OK;
}
{
int error;
}
return error;
}
long timeout,
{
&connection);
/*
* Reject the attacher
*/
return error;
}
/*
* No real point trying to reject it.
*/
return error;
}
return SYS_OK;
}
static jint
{
return SYS_OK;
}
{
int error;
return error;
}
/* lock transport - no additional event to wait on as no connection yet */
return error;
}
}
} else {
/* Not listening: error */
}
return error;
}
return error;
}
void
{
}
void
{
}
{
int offset;
return SYS_OK;
}
{
int offset;
return SYS_OK;
}
static jint
{
} else {
}
index += fragmentLength;
}
return SYS_OK;
}
/*
* Send packet header followed by data.
*/
{
} else {
}
SHMEM_GUARANTEE(data_length >= 0);
if (data_length > 0) {
}
return SYS_OK;
}
static jint
{
} else {
}
index += fragmentLength;
}
return SYS_OK;
}
/*
* Read packet header and insert into packet structure.
* Allocate space for the data and fill it in.
*/
{
} else {
}
if (data_length < 0) {
return SYS_ERR;
} else if (data_length == 0) {
} else {
return SYS_ERR;
}
return error;
}
}
return SYS_OK;
}
{
return SYS_OK;
}
return SYS_OK;
} else {
return SYS_ERR;
}
}
void
char *date, int lineNumber)
{
/*
* We're forced into a direct call to exit()
*/
exit(-1);
} else {
}
}