Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/transport/shmem/shmemBase.c
38813 views
1
/*
2
* Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
#include <stdio.h>
26
#include <string.h>
27
#include <errno.h>
28
#include <stdlib.h>
29
30
#include "sysShmem.h"
31
#include "shmemBase.h"
32
#include "jdwpTransport.h" /* for Packet, TransportCallback */
33
34
#define MIN(x,y) ((x)<(y)?(x):(y))
35
36
/*
37
* This is the base shared memory transport implementation that is used
38
* by both front-end transports (through com.sun.tools.jdi) and
39
* back-end transports (through JDWP_OnLoad and the function tables
40
* it requires). It supports multiple connections for the benefit of the
41
* front-end client; the back end interface assumes only a single connection.
42
*/
43
44
#define MAX_IPC_PREFIX 50 /* user-specified or generated name for */
45
/* shared memory seg and prefix for other IPC */
46
#define MAX_IPC_SUFFIX 25 /* suffix to shmem name for other IPC names */
47
#define MAX_IPC_NAME (MAX_IPC_PREFIX + MAX_IPC_SUFFIX)
48
49
#define MAX_GENERATION_RETRIES 20
50
#define SHARED_BUFFER_SIZE 5000
51
52
#define CHECK_ERROR(expr) do { \
53
jint error = (expr); \
54
if (error != SYS_OK) { \
55
setLastError(error); \
56
return error; \
57
} \
58
} while (0)
59
60
/*
61
* The following assertions should hold anytime the stream's mutex is not held
62
*/
63
#define STREAM_INVARIANT(stream) \
64
do { \
65
SHMEM_ASSERT((stream->shared->readOffset < SHARED_BUFFER_SIZE) \
66
&& (stream->shared->readOffset >= 0)); \
67
SHMEM_ASSERT((stream->shared->writeOffset < SHARED_BUFFER_SIZE) \
68
&& (stream->shared->writeOffset >= 0)); \
69
} while (0)
70
71
/*
72
* Transports are duplex, so carve the shared memory into "streams",
73
* one used to send from client to server, the other vice versa.
74
*/
75
typedef struct SharedMemoryListener {
76
char mutexName[MAX_IPC_NAME];
77
char acceptEventName[MAX_IPC_NAME];
78
char attachEventName[MAX_IPC_NAME];
79
jboolean isListening;
80
jboolean isAccepted;
81
jlong acceptingPID;
82
jlong attachingPID;
83
} SharedListener;
84
85
typedef struct SharedMemoryTransport {
86
char name[MAX_IPC_PREFIX];
87
sys_ipmutex_t mutex;
88
sys_event_t acceptEvent;
89
sys_event_t attachEvent;
90
sys_shmem_t sharedMemory;
91
SharedListener *shared;
92
} SharedMemoryTransport;
93
94
/*
95
* Access must be syncronized. Holds one shared
96
* memory buffer and its state.
97
*/
98
typedef struct SharedStream {
99
char mutexName[MAX_IPC_NAME];
100
char hasDataEventName[MAX_IPC_NAME];
101
char hasSpaceEventName[MAX_IPC_NAME];
102
int readOffset;
103
int writeOffset;
104
jboolean isFull;
105
jbyte buffer[SHARED_BUFFER_SIZE];
106
} SharedStream;
107
108
/*
109
* The two shared streams: client to server and
110
* server to client.
111
*/
112
typedef struct SharedMemory {
113
SharedStream toClient;
114
SharedStream toServer;
115
} SharedMemory;
116
117
/*
118
* Local (to process) access to the shared memory
119
* stream. access to hasData and hasSpace synchronized
120
* by OS.
121
*/
122
typedef struct Stream {
123
sys_ipmutex_t mutex;
124
sys_event_t hasData;
125
sys_event_t hasSpace;
126
SharedStream *shared;
127
jint state;
128
} Stream;
129
130
/*
131
* Values for Stream.state field above.
132
*/
133
#define STATE_CLOSED 0xDEAD
134
#define STATE_OPEN (STATE_CLOSED -1)
135
/*
136
* State checking macro. We compare against the STATE_OPEN value so
137
* that STATE_CLOSED and any other value will be considered closed.
138
* This catches a freed Stream as long as the memory page is still
139
* valid. If the memory page is gone, then there is little that we
140
* can do.
141
*/
142
#define IS_STATE_CLOSED(state) (state != STATE_OPEN)
143
144
145
typedef struct SharedMemoryConnection {
146
char name[MAX_IPC_NAME];
147
SharedMemory *shared;
148
sys_shmem_t sharedMemory;
149
Stream incoming;
150
Stream outgoing;
151
sys_process_t otherProcess;
152
sys_event_t shutdown; /* signalled to indicate shutdown */
153
} SharedMemoryConnection;
154
155
static jdwpTransportCallback *callback;
156
static JavaVM *jvm;
157
static int tlsIndex;
158
159
typedef jint (*CreateFunc)(char *name, void *arg);
160
161
/*
162
* Set the per-thread error message (if not already set)
163
*/
164
static void
165
setLastErrorMsg(char *newmsg) {
166
char *msg;
167
168
msg = (char *)sysTlsGet(tlsIndex);
169
if (msg == NULL) {
170
msg = (*callback->alloc)((int)strlen(newmsg)+1);
171
if (msg != NULL) {
172
strcpy(msg, newmsg);
173
}
174
sysTlsPut(tlsIndex, (void *)msg);
175
}
176
}
177
178
/*
179
* Clear last per-thread error message
180
*/
181
static void
182
clearLastError() {
183
char* msg = (char *)sysTlsGet(tlsIndex);
184
if (msg != NULL) {
185
(*callback->free)(msg);
186
sysTlsPut(tlsIndex, NULL);
187
}
188
}
189
190
/*
191
* Set the per-thread error message to the textual representation
192
* of the last system error (if not already set)
193
*/
194
static void
195
setLastError(jint error) {
196
char buf[128];
197
198
switch (error) {
199
case SYS_OK : return; /* no-op */
200
case SYS_DIED : strcpy(buf, "Other process terminated"); break;
201
case SYS_TIMEOUT : strcpy(buf, "Timed out"); break;
202
default : sysGetLastError(buf, sizeof(buf));
203
}
204
setLastErrorMsg(buf);
205
}
206
207
jint
208
shmemBase_initialize(JavaVM *vm, jdwpTransportCallback *cbPtr)
209
{
210
jvm = vm;
211
callback = cbPtr;
212
tlsIndex = sysTlsAlloc();
213
return SYS_OK;
214
}
215
216
static jint
217
createWithGeneratedName(char *prefix, char *nameBuffer, CreateFunc func, void *arg)
218
{
219
jint error;
220
jint i = 0;
221
222
do {
223
strcpy(nameBuffer, prefix);
224
if (i > 0) {
225
char buf[10];
226
sprintf(buf, ".%d", i+1);
227
strcat(nameBuffer, buf);
228
}
229
error = func(nameBuffer, arg);
230
i++;
231
} while ((error == SYS_INUSE) && (i < MAX_GENERATION_RETRIES));
232
233
if (error != SYS_OK) {
234
setLastError(error);
235
}
236
237
return error;
238
}
239
240
typedef struct SharedMemoryArg {
241
jint size;
242
sys_shmem_t memory;
243
void *start;
244
} SharedMemoryArg;
245
246
static jint
247
createSharedMem(char *name, void *ptr)
248
{
249
SharedMemoryArg *arg = ptr;
250
return sysSharedMemCreate(name, arg->size, &arg->memory, &arg->start);
251
}
252
253
static jint
254
createMutex(char *name, void *arg)
255
{
256
sys_ipmutex_t *retArg = arg;
257
return sysIPMutexCreate(name, retArg);
258
}
259
260
/*
261
* Creates named or unnamed event that is automatically reset
262
* (in other words, no need to reset event after it has signalled
263
* a thread).
264
*/
265
static jint
266
createEvent(char *name, void *arg)
267
{
268
sys_event_t *retArg = arg;
269
return sysEventCreate(name, retArg, JNI_FALSE);
270
}
271
272
#define ADD_OFFSET(o1, o2) ((o1 + o2) % SHARED_BUFFER_SIZE)
273
#define FULL(stream) (stream->shared->isFull)
274
#define EMPTY(stream) ((stream->shared->writeOffset == stream->shared->readOffset) \
275
&& !stream->shared->isFull)
276
277
static jint
278
leaveMutex(Stream *stream)
279
{
280
return sysIPMutexExit(stream->mutex);
281
}
282
283
/* enter the stream's mutex and (optionally) check for a closed stream */
284
static jint
285
enterMutex(Stream *stream, sys_event_t event)
286
{
287
jint ret = sysIPMutexEnter(stream->mutex, event);
288
if (ret != SYS_OK) {
289
if (IS_STATE_CLOSED(stream->state)) {
290
setLastErrorMsg("stream closed");
291
}
292
return ret;
293
}
294
if (IS_STATE_CLOSED(stream->state)) {
295
setLastErrorMsg("stream closed");
296
(void)leaveMutex(stream);
297
return SYS_ERR;
298
}
299
return SYS_OK;
300
}
301
302
/*
303
* Enter/exit with stream mutex held.
304
* On error, does not hold the stream mutex.
305
*/
306
static jint
307
waitForSpace(SharedMemoryConnection *connection, Stream *stream)
308
{
309
jint error = SYS_OK;
310
311
/* Assumes mutex is held on call */
312
while ((error == SYS_OK) && FULL(stream)) {
313
CHECK_ERROR(leaveMutex(stream));
314
error = sysEventWait(connection->otherProcess, stream->hasSpace, 0);
315
if (error == SYS_OK) {
316
CHECK_ERROR(enterMutex(stream, connection->shutdown));
317
} else {
318
setLastError(error);
319
}
320
}
321
return error;
322
}
323
324
static jint
325
signalSpace(Stream *stream)
326
{
327
return sysEventSignal(stream->hasSpace);
328
}
329
330
/*
331
* Enter/exit with stream mutex held.
332
* On error, does not hold the stream mutex.
333
*/
334
static jint
335
waitForData(SharedMemoryConnection *connection, Stream *stream)
336
{
337
jint error = SYS_OK;
338
339
/* Assumes mutex is held on call */
340
while ((error == SYS_OK) && EMPTY(stream)) {
341
CHECK_ERROR(leaveMutex(stream));
342
error = sysEventWait(connection->otherProcess, stream->hasData, 0);
343
if (error == SYS_OK) {
344
CHECK_ERROR(enterMutex(stream, connection->shutdown));
345
} else {
346
setLastError(error);
347
}
348
}
349
return error;
350
}
351
352
static jint
353
signalData(Stream *stream)
354
{
355
return sysEventSignal(stream->hasData);
356
}
357
358
359
static jint
360
closeStream(Stream *stream, jboolean linger)
361
{
362
/*
363
* Lock stream during close - ignore shutdown event as we are
364
* closing down and shutdown should be signalled.
365
*/
366
CHECK_ERROR(enterMutex(stream, NULL));
367
368
/* mark the stream as closed */
369
stream->state = STATE_CLOSED;
370
/* wake up waitForData() if it is in sysEventWait() */
371
sysEventSignal(stream->hasData);
372
sysEventClose(stream->hasData);
373
/* wake up waitForSpace() if it is in sysEventWait() */
374
sysEventSignal(stream->hasSpace);
375
sysEventClose(stream->hasSpace);
376
377
/*
378
* If linger requested then give the stream a few seconds to
379
* drain before closing it.
380
*/
381
if (linger) {
382
int attempts = 10;
383
while (!EMPTY(stream) && attempts>0) {
384
CHECK_ERROR(leaveMutex(stream));
385
sysSleep(200);
386
CHECK_ERROR(enterMutex(stream, NULL));
387
attempts--;
388
}
389
}
390
391
CHECK_ERROR(leaveMutex(stream));
392
sysIPMutexClose(stream->mutex);
393
return SYS_OK;
394
}
395
396
/*
397
* Server creates stream.
398
*/
399
static int
400
createStream(char *name, Stream *stream)
401
{
402
jint error;
403
char prefix[MAX_IPC_PREFIX];
404
405
sprintf(prefix, "%s.mutex", name);
406
error = createWithGeneratedName(prefix, stream->shared->mutexName,
407
createMutex, &stream->mutex);
408
if (error != SYS_OK) {
409
return error;
410
}
411
412
sprintf(prefix, "%s.hasData", name);
413
error = createWithGeneratedName(prefix, stream->shared->hasDataEventName,
414
createEvent, &stream->hasData);
415
if (error != SYS_OK) {
416
(void)closeStream(stream, JNI_FALSE);
417
return error;
418
}
419
420
sprintf(prefix, "%s.hasSpace", name);
421
error = createWithGeneratedName(prefix, stream->shared->hasSpaceEventName,
422
createEvent, &stream->hasSpace);
423
if (error != SYS_OK) {
424
(void)closeStream(stream, JNI_FALSE);
425
return error;
426
}
427
428
stream->shared->readOffset = 0;
429
stream->shared->writeOffset = 0;
430
stream->shared->isFull = JNI_FALSE;
431
stream->state = STATE_OPEN;
432
return SYS_OK;
433
}
434
435
436
/*
437
* Initialization for the stream opened by the other process
438
*/
439
static int
440
openStream(Stream *stream)
441
{
442
jint error;
443
444
CHECK_ERROR(sysIPMutexOpen(stream->shared->mutexName, &stream->mutex));
445
446
error = sysEventOpen(stream->shared->hasDataEventName,
447
&stream->hasData);
448
if (error != SYS_OK) {
449
setLastError(error);
450
(void)closeStream(stream, JNI_FALSE);
451
return error;
452
}
453
454
error = sysEventOpen(stream->shared->hasSpaceEventName,
455
&stream->hasSpace);
456
if (error != SYS_OK) {
457
setLastError(error);
458
(void)closeStream(stream, JNI_FALSE);
459
return error;
460
}
461
462
stream->state = STATE_OPEN;
463
464
return SYS_OK;
465
}
466
467
/********************************************************************/
468
469
static SharedMemoryConnection *
470
allocConnection(void)
471
{
472
/*
473
* TO DO: Track all allocated connections for clean shutdown?
474
*/
475
SharedMemoryConnection *conn = (*callback->alloc)(sizeof(SharedMemoryConnection));
476
if (conn != NULL) {
477
memset(conn, 0, sizeof(SharedMemoryConnection));
478
}
479
return conn;
480
}
481
482
static void
483
freeConnection(SharedMemoryConnection *connection)
484
{
485
(*callback->free)(connection);
486
}
487
488
static void
489
closeConnection(SharedMemoryConnection *connection)
490
{
491
/*
492
* Signal all threads accessing this connection that we are
493
* shutting down.
494
*/
495
if (connection->shutdown) {
496
sysEventSignal(connection->shutdown);
497
}
498
499
500
(void)closeStream(&connection->outgoing, JNI_TRUE);
501
(void)closeStream(&connection->incoming, JNI_FALSE);
502
503
if (connection->sharedMemory) {
504
sysSharedMemClose(connection->sharedMemory, connection->shared);
505
}
506
if (connection->otherProcess) {
507
sysProcessClose(connection->otherProcess);
508
}
509
510
/*
511
* Ideally we should close the connection->shutdown event and
512
* free the connection structure. However as closing the
513
* connection is asynchronous it means that other threads may
514
* still be accessing the connection structure. On Win32 this
515
* means we leak 132 bytes and one event per connection. This
516
* memory will be reclaim at process exit.
517
*
518
* if (connection->shutdown)
519
* sysEventClose(connection->shutdown);
520
* freeConnection(connection);
521
*/
522
}
523
524
525
/*
526
* For client: connect to the shared memory. Open incoming and
527
* outgoing streams.
528
*/
529
static jint
530
openConnection(SharedMemoryTransport *transport, jlong otherPID,
531
SharedMemoryConnection **connectionPtr)
532
{
533
jint error;
534
535
SharedMemoryConnection *connection = allocConnection();
536
if (connection == NULL) {
537
return SYS_NOMEM;
538
}
539
540
sprintf(connection->name, "%s.%ld", transport->name, sysProcessGetID());
541
error = sysSharedMemOpen(connection->name, &connection->sharedMemory,
542
&connection->shared);
543
if (error != SYS_OK) {
544
closeConnection(connection);
545
return error;
546
}
547
548
/* This process is the client */
549
connection->incoming.shared = &connection->shared->toClient;
550
connection->outgoing.shared = &connection->shared->toServer;
551
552
error = openStream(&connection->incoming);
553
if (error != SYS_OK) {
554
closeConnection(connection);
555
return error;
556
}
557
558
error = openStream(&connection->outgoing);
559
if (error != SYS_OK) {
560
closeConnection(connection);
561
return error;
562
}
563
564
error = sysProcessOpen(otherPID, &connection->otherProcess);
565
if (error != SYS_OK) {
566
setLastError(error);
567
closeConnection(connection);
568
return error;
569
}
570
571
/*
572
* Create an event that signals that the connection is shutting
573
* down. The event is unnamed as it's process local, and is
574
* manually reset (so that signalling the event will signal
575
* all threads waiting on it).
576
*/
577
error = sysEventCreate(NULL, &connection->shutdown, JNI_TRUE);
578
if (error != SYS_OK) {
579
setLastError(error);
580
closeConnection(connection);
581
return error;
582
}
583
584
*connectionPtr = connection;
585
return SYS_OK;
586
}
587
588
/*
589
* For server: create the shared memory. Create incoming and
590
* outgoing streams.
591
*/
592
static jint
593
createConnection(SharedMemoryTransport *transport, jlong otherPID,
594
SharedMemoryConnection **connectionPtr)
595
{
596
jint error;
597
char streamPrefix[MAX_IPC_NAME];
598
599
SharedMemoryConnection *connection = allocConnection();
600
if (connection == NULL) {
601
return SYS_NOMEM;
602
}
603
604
sprintf(connection->name, "%s.%ld", transport->name, otherPID);
605
error = sysSharedMemCreate(connection->name, sizeof(SharedMemory),
606
&connection->sharedMemory, &connection->shared);
607
if (error != SYS_OK) {
608
closeConnection(connection);
609
return error;
610
}
611
612
memset(connection->shared, 0, sizeof(SharedMemory));
613
614
/* This process is the server */
615
connection->incoming.shared = &connection->shared->toServer;
616
connection->outgoing.shared = &connection->shared->toClient;
617
618
strcpy(streamPrefix, connection->name);
619
strcat(streamPrefix, ".ctos");
620
error = createStream(streamPrefix, &connection->incoming);
621
if (error != SYS_OK) {
622
closeConnection(connection);
623
return error;
624
}
625
626
strcpy(streamPrefix, connection->name);
627
strcat(streamPrefix, ".stoc");
628
error = createStream(streamPrefix, &connection->outgoing);
629
if (error != SYS_OK) {
630
closeConnection(connection);
631
return error;
632
}
633
634
error = sysProcessOpen(otherPID, &connection->otherProcess);
635
if (error != SYS_OK) {
636
setLastError(error);
637
closeConnection(connection);
638
return error;
639
}
640
641
/*
642
* Create an event that signals that the connection is shutting
643
* down. The event is unnamed as it's process local, and is
644
* manually reset (so that a signalling the event will signal
645
* all threads waiting on it).
646
*/
647
error = sysEventCreate(NULL, &connection->shutdown, JNI_TRUE);
648
if (error != SYS_OK) {
649
setLastError(error);
650
closeConnection(connection);
651
return error;
652
}
653
654
*connectionPtr = connection;
655
return SYS_OK;
656
}
657
658
/********************************************************************/
659
660
static SharedMemoryTransport *
661
allocTransport(void)
662
{
663
/*
664
* TO DO: Track all allocated transports for clean shutdown?
665
*/
666
return (*callback->alloc)(sizeof(SharedMemoryTransport));
667
}
668
669
static void
670
freeTransport(SharedMemoryTransport *transport)
671
{
672
(*callback->free)(transport);
673
}
674
675
static void
676
closeTransport(SharedMemoryTransport *transport)
677
{
678
sysIPMutexClose(transport->mutex);
679
sysEventClose(transport->acceptEvent);
680
sysEventClose(transport->attachEvent);
681
sysSharedMemClose(transport->sharedMemory, transport->shared);
682
freeTransport(transport);
683
}
684
685
static int
686
openTransport(const char *address, SharedMemoryTransport **transportPtr)
687
{
688
jint error;
689
SharedMemoryTransport *transport;
690
691
transport = allocTransport();
692
if (transport == NULL) {
693
return SYS_NOMEM;
694
}
695
memset(transport, 0, sizeof(*transport));
696
697
if (strlen(address) >= MAX_IPC_PREFIX) {
698
char buf[128];
699
sprintf(buf, "Error: address strings longer than %d characters are invalid\n", MAX_IPC_PREFIX);
700
setLastErrorMsg(buf);
701
closeTransport(transport);
702
return SYS_ERR;
703
}
704
705
error = sysSharedMemOpen(address, &transport->sharedMemory, &transport->shared);
706
if (error != SYS_OK) {
707
setLastError(error);
708
closeTransport(transport);
709
return error;
710
}
711
strcpy(transport->name, address);
712
713
error = sysIPMutexOpen(transport->shared->mutexName, &transport->mutex);
714
if (error != SYS_OK) {
715
setLastError(error);
716
closeTransport(transport);
717
return error;
718
}
719
720
error = sysEventOpen(transport->shared->acceptEventName,
721
&transport->acceptEvent);
722
if (error != SYS_OK) {
723
setLastError(error);
724
closeTransport(transport);
725
return error;
726
}
727
728
error = sysEventOpen(transport->shared->attachEventName,
729
&transport->attachEvent);
730
if (error != SYS_OK) {
731
setLastError(error);
732
closeTransport(transport);
733
return error;
734
}
735
736
*transportPtr = transport;
737
return SYS_OK;
738
}
739
740
static jint
741
createTransport(const char *address, SharedMemoryTransport **transportPtr)
742
{
743
SharedMemoryTransport *transport;
744
jint error;
745
char prefix[MAX_IPC_PREFIX];
746
747
748
749
transport = allocTransport();
750
if (transport == NULL) {
751
return SYS_NOMEM;
752
}
753
memset(transport, 0, sizeof(*transport));
754
755
if ((address == NULL) || (address[0] == '\0')) {
756
SharedMemoryArg arg;
757
arg.size = sizeof(SharedListener);
758
error = createWithGeneratedName("javadebug", transport->name,
759
createSharedMem, &arg);
760
transport->shared = arg.start;
761
transport->sharedMemory = arg.memory;
762
} else {
763
if (strlen(address) >= MAX_IPC_PREFIX) {
764
char buf[128];
765
sprintf(buf, "Error: address strings longer than %d characters are invalid\n", MAX_IPC_PREFIX);
766
setLastErrorMsg(buf);
767
closeTransport(transport);
768
return SYS_ERR;
769
}
770
strcpy(transport->name, address);
771
error = sysSharedMemCreate(address, sizeof(SharedListener),
772
&transport->sharedMemory, &transport->shared);
773
}
774
if (error != SYS_OK) {
775
setLastError(error);
776
closeTransport(transport);
777
return error;
778
}
779
780
memset(transport->shared, 0, sizeof(SharedListener));
781
transport->shared->acceptingPID = sysProcessGetID();
782
783
sprintf(prefix, "%s.mutex", transport->name);
784
error = createWithGeneratedName(prefix, transport->shared->mutexName,
785
createMutex, &transport->mutex);
786
if (error != SYS_OK) {
787
closeTransport(transport);
788
return error;
789
}
790
791
sprintf(prefix, "%s.accept", transport->name);
792
error = createWithGeneratedName(prefix, transport->shared->acceptEventName,
793
createEvent, &transport->acceptEvent);
794
if (error != SYS_OK) {
795
closeTransport(transport);
796
return error;
797
}
798
799
sprintf(prefix, "%s.attach", transport->name);
800
error = createWithGeneratedName(prefix, transport->shared->attachEventName,
801
createEvent, &transport->attachEvent);
802
if (error != SYS_OK) {
803
closeTransport(transport);
804
return error;
805
}
806
807
*transportPtr = transport;
808
return SYS_OK;
809
}
810
811
812
jint
813
shmemBase_listen(const char *address, SharedMemoryTransport **transportPtr)
814
{
815
int error;
816
817
clearLastError();
818
819
error = createTransport(address, transportPtr);
820
if (error == SYS_OK) {
821
(*transportPtr)->shared->isListening = JNI_TRUE;
822
}
823
return error;
824
}
825
826
827
jint
828
shmemBase_accept(SharedMemoryTransport *transport,
829
long timeout,
830
SharedMemoryConnection **connectionPtr)
831
{
832
jint error;
833
SharedMemoryConnection *connection;
834
835
clearLastError();
836
837
CHECK_ERROR(sysEventWait(NULL, transport->attachEvent, timeout));
838
839
error = createConnection(transport, transport->shared->attachingPID,
840
&connection);
841
if (error != SYS_OK) {
842
/*
843
* Reject the attacher
844
*/
845
transport->shared->isAccepted = JNI_FALSE;
846
sysEventSignal(transport->acceptEvent);
847
848
freeConnection(connection);
849
return error;
850
}
851
852
transport->shared->isAccepted = JNI_TRUE;
853
error = sysEventSignal(transport->acceptEvent);
854
if (error != SYS_OK) {
855
/*
856
* No real point trying to reject it.
857
*/
858
closeConnection(connection);
859
return error;
860
}
861
862
*connectionPtr = connection;
863
return SYS_OK;
864
}
865
866
static jint
867
doAttach(SharedMemoryTransport *transport, long timeout)
868
{
869
transport->shared->attachingPID = sysProcessGetID();
870
CHECK_ERROR(sysEventSignal(transport->attachEvent));
871
CHECK_ERROR(sysEventWait(NULL, transport->acceptEvent, timeout));
872
return SYS_OK;
873
}
874
875
jint
876
shmemBase_attach(const char *addressString, long timeout, SharedMemoryConnection **connectionPtr)
877
{
878
int error;
879
SharedMemoryTransport *transport;
880
jlong acceptingPID;
881
882
clearLastError();
883
884
error = openTransport(addressString, &transport);
885
if (error != SYS_OK) {
886
return error;
887
}
888
889
/* lock transport - no additional event to wait on as no connection yet */
890
error = sysIPMutexEnter(transport->mutex, NULL);
891
if (error != SYS_OK) {
892
setLastError(error);
893
closeTransport(transport);
894
return error;
895
}
896
897
if (transport->shared->isListening) {
898
error = doAttach(transport, timeout);
899
if (error == SYS_OK) {
900
acceptingPID = transport->shared->acceptingPID;
901
}
902
} else {
903
/* Not listening: error */
904
error = SYS_ERR;
905
}
906
907
sysIPMutexExit(transport->mutex);
908
if (error != SYS_OK) {
909
closeTransport(transport);
910
return error;
911
}
912
913
error = openConnection(transport, acceptingPID, connectionPtr);
914
915
closeTransport(transport);
916
917
return error;
918
}
919
920
921
922
923
void
924
shmemBase_closeConnection(SharedMemoryConnection *connection)
925
{
926
clearLastError();
927
closeConnection(connection);
928
}
929
930
void
931
shmemBase_closeTransport(SharedMemoryTransport *transport)
932
{
933
clearLastError();
934
closeTransport(transport);
935
}
936
937
jint
938
shmemBase_sendByte(SharedMemoryConnection *connection, jbyte data)
939
{
940
Stream *stream = &connection->outgoing;
941
SharedStream *shared = stream->shared;
942
int offset;
943
944
clearLastError();
945
946
CHECK_ERROR(enterMutex(stream, connection->shutdown));
947
CHECK_ERROR(waitForSpace(connection, stream));
948
SHMEM_ASSERT(!FULL(stream));
949
offset = shared->writeOffset;
950
shared->buffer[offset] = data;
951
shared->writeOffset = ADD_OFFSET(offset, 1);
952
shared->isFull = (shared->readOffset == shared->writeOffset);
953
954
STREAM_INVARIANT(stream);
955
CHECK_ERROR(leaveMutex(stream));
956
957
CHECK_ERROR(signalData(stream));
958
959
return SYS_OK;
960
}
961
962
jint
963
shmemBase_receiveByte(SharedMemoryConnection *connection, jbyte *data)
964
{
965
Stream *stream = &connection->incoming;
966
SharedStream *shared = stream->shared;
967
int offset;
968
969
clearLastError();
970
971
CHECK_ERROR(enterMutex(stream, connection->shutdown));
972
CHECK_ERROR(waitForData(connection, stream));
973
SHMEM_ASSERT(!EMPTY(stream));
974
offset = shared->readOffset;
975
*data = shared->buffer[offset];
976
shared->readOffset = ADD_OFFSET(offset, 1);
977
shared->isFull = JNI_FALSE;
978
979
STREAM_INVARIANT(stream);
980
CHECK_ERROR(leaveMutex(stream));
981
982
CHECK_ERROR(signalSpace(stream));
983
984
return SYS_OK;
985
}
986
987
static jint
988
sendBytes(SharedMemoryConnection *connection, const void *bytes, jint length)
989
{
990
Stream *stream = &connection->outgoing;
991
SharedStream *shared = stream->shared;
992
jint fragmentStart;
993
jint fragmentLength;
994
jint index = 0;
995
jint maxLength;
996
997
clearLastError();
998
999
CHECK_ERROR(enterMutex(stream, connection->shutdown));
1000
while (index < length) {
1001
CHECK_ERROR(waitForSpace(connection, stream));
1002
SHMEM_ASSERT(!FULL(stream));
1003
1004
fragmentStart = shared->writeOffset;
1005
1006
if (fragmentStart < shared->readOffset) {
1007
maxLength = shared->readOffset - fragmentStart;
1008
} else {
1009
maxLength = SHARED_BUFFER_SIZE - fragmentStart;
1010
}
1011
fragmentLength = MIN(maxLength, length - index);
1012
memcpy(shared->buffer + fragmentStart, (jbyte *)bytes + index, fragmentLength);
1013
shared->writeOffset = ADD_OFFSET(fragmentStart, fragmentLength);
1014
index += fragmentLength;
1015
1016
shared->isFull = (shared->readOffset == shared->writeOffset);
1017
1018
STREAM_INVARIANT(stream);
1019
CHECK_ERROR(signalData(stream));
1020
1021
}
1022
CHECK_ERROR(leaveMutex(stream));
1023
1024
return SYS_OK;
1025
}
1026
1027
1028
/*
1029
* Send packet header followed by data.
1030
*/
1031
jint
1032
shmemBase_sendPacket(SharedMemoryConnection *connection, const jdwpPacket *packet)
1033
{
1034
jint data_length;
1035
1036
clearLastError();
1037
1038
CHECK_ERROR(sendBytes(connection, &packet->type.cmd.id, sizeof(jint)));
1039
CHECK_ERROR(sendBytes(connection, &packet->type.cmd.flags, sizeof(jbyte)));
1040
1041
if (packet->type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
1042
CHECK_ERROR(sendBytes(connection, &packet->type.reply.errorCode, sizeof(jshort)));
1043
} else {
1044
CHECK_ERROR(sendBytes(connection, &packet->type.cmd.cmdSet, sizeof(jbyte)));
1045
CHECK_ERROR(sendBytes(connection, &packet->type.cmd.cmd, sizeof(jbyte)));
1046
}
1047
1048
data_length = packet->type.cmd.len - 11;
1049
SHMEM_GUARANTEE(data_length >= 0);
1050
CHECK_ERROR(sendBytes(connection, &data_length, sizeof(jint)));
1051
1052
if (data_length > 0) {
1053
CHECK_ERROR(sendBytes(connection, packet->type.cmd.data, data_length));
1054
}
1055
1056
return SYS_OK;
1057
}
1058
1059
static jint
1060
receiveBytes(SharedMemoryConnection *connection, void *bytes, jint length)
1061
{
1062
Stream *stream = &connection->incoming;
1063
SharedStream *shared = stream->shared;
1064
jint fragmentStart;
1065
jint fragmentLength;
1066
jint index = 0;
1067
jint maxLength;
1068
1069
clearLastError();
1070
1071
CHECK_ERROR(enterMutex(stream, connection->shutdown));
1072
while (index < length) {
1073
CHECK_ERROR(waitForData(connection, stream));
1074
SHMEM_ASSERT(!EMPTY(stream));
1075
1076
fragmentStart = shared->readOffset;
1077
if (fragmentStart < shared->writeOffset) {
1078
maxLength = shared->writeOffset - fragmentStart;
1079
} else {
1080
maxLength = SHARED_BUFFER_SIZE - fragmentStart;
1081
}
1082
fragmentLength = MIN(maxLength, length - index);
1083
memcpy((jbyte *)bytes + index, shared->buffer + fragmentStart, fragmentLength);
1084
shared->readOffset = ADD_OFFSET(fragmentStart, fragmentLength);
1085
index += fragmentLength;
1086
1087
shared->isFull = JNI_FALSE;
1088
1089
STREAM_INVARIANT(stream);
1090
CHECK_ERROR(signalSpace(stream));
1091
}
1092
CHECK_ERROR(leaveMutex(stream));
1093
1094
return SYS_OK;
1095
}
1096
1097
/*
1098
* Read packet header and insert into packet structure.
1099
* Allocate space for the data and fill it in.
1100
*/
1101
jint
1102
shmemBase_receivePacket(SharedMemoryConnection *connection, jdwpPacket *packet)
1103
{
1104
jint data_length;
1105
jint error;
1106
1107
clearLastError();
1108
1109
CHECK_ERROR(receiveBytes(connection, &packet->type.cmd.id, sizeof(jint)));
1110
CHECK_ERROR(receiveBytes(connection, &packet->type.cmd.flags, sizeof(jbyte)));
1111
1112
if (packet->type.cmd.flags & JDWPTRANSPORT_FLAGS_REPLY) {
1113
CHECK_ERROR(receiveBytes(connection, &packet->type.reply.errorCode, sizeof(jshort)));
1114
} else {
1115
CHECK_ERROR(receiveBytes(connection, &packet->type.cmd.cmdSet, sizeof(jbyte)));
1116
CHECK_ERROR(receiveBytes(connection, &packet->type.cmd.cmd, sizeof(jbyte)));
1117
}
1118
1119
CHECK_ERROR(receiveBytes(connection, &data_length, sizeof(jint)));
1120
1121
if (data_length < 0) {
1122
return SYS_ERR;
1123
} else if (data_length == 0) {
1124
packet->type.cmd.len = 11;
1125
packet->type.cmd.data = NULL;
1126
} else {
1127
packet->type.cmd.len = data_length + 11;
1128
packet->type.cmd.data = (*callback->alloc)(data_length);
1129
if (packet->type.cmd.data == NULL) {
1130
return SYS_ERR;
1131
}
1132
1133
error = receiveBytes(connection, packet->type.cmd.data, data_length);
1134
if (error != SYS_OK) {
1135
(*callback->free)(packet->type.cmd.data);
1136
return error;
1137
}
1138
}
1139
1140
return SYS_OK;
1141
}
1142
1143
jint
1144
shmemBase_name(struct SharedMemoryTransport *transport, char **name)
1145
{
1146
*name = transport->name;
1147
return SYS_OK;
1148
}
1149
1150
jint
1151
shmemBase_getlasterror(char *msg, jint size) {
1152
char *errstr = (char *)sysTlsGet(tlsIndex);
1153
if (errstr != NULL) {
1154
strcpy(msg, errstr);
1155
return SYS_OK;
1156
} else {
1157
return SYS_ERR;
1158
}
1159
}
1160
1161
1162
void
1163
exitTransportWithError(char *message, char *fileName,
1164
char *date, int lineNumber)
1165
{
1166
JNIEnv *env;
1167
jint error;
1168
char buffer[500];
1169
1170
sprintf(buffer, "Shared Memory Transport \"%s\" (%s), line %d: %s\n",
1171
fileName, date, lineNumber, message);
1172
error = (*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_2);
1173
if (error != JNI_OK) {
1174
/*
1175
* We're forced into a direct call to exit()
1176
*/
1177
fprintf(stderr, "%s", buffer);
1178
exit(-1);
1179
} else {
1180
(*env)->FatalError(env, buffer);
1181
}
1182
}
1183
1184