Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/cuda/CudaCommon.cpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 2013, 2019 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include "CudaCommon.hpp"
24
#include "java/com_ibm_cuda_Cuda.h"
25
#include "java/com_ibm_cuda_Cuda_Cleaner.h"
26
27
/**
28
* Unless there is an outstanding exception, create and throw a CudaException.
29
*
30
* @param[in] env the JNI interface pointer
31
* @param[in] error the CUDA error code to be included in the exception
32
*/
33
void
34
throwCudaException(JNIEnv * env, int32_t error)
35
{
36
J9VMThread * thread = (J9VMThread *)env;
37
38
Trc_cuda_throwCudaException_entry(thread, error);
39
40
J9JavaVM * javaVM = thread->javaVM;
41
J9CudaGlobals * globals = javaVM->cudaGlobals;
42
43
Assert_cuda_true(NULL != globals);
44
Assert_cuda_true(NULL != globals->exception_init);
45
46
if (env->ExceptionCheck()) {
47
Trc_cuda_throwCudaException_suppressed(thread);
48
} else {
49
jobject exception = env->NewObject(globals->exceptionClass, globals->exception_init, error);
50
51
if (NULL != exception) {
52
env->Throw((jthrowable)exception);
53
}
54
}
55
56
Trc_cuda_throwCudaException_exit(thread);
57
}
58
59
/**
60
* Allocate a block of pinned host memory. Transfers between pinned memory and
61
* devices avoids the intermediate copy via a pinned buffer local to the device
62
* driver.
63
*
64
* Class: com.ibm.cuda.Cuda
65
* Method: allocatePinnedBuffer
66
* Signature: (J)J
67
*
68
* @param[in] env the JNI interface pointer
69
* @param[in] (unused) the class pointer
70
* @param[in] byteCount the number of bytes requested
71
* @return a pointer to the pinned block of storage
72
*/
73
jlong JNICALL
74
Java_com_ibm_cuda_Cuda_allocatePinnedBuffer
75
(JNIEnv * env, jclass, jlong byteCount)
76
{
77
J9VMThread * thread = (J9VMThread *)env;
78
79
Trc_cuda_allocatePinnedBuffer_entry(thread, byteCount);
80
81
void * address = NULL;
82
int32_t error = J9CUDA_ERROR_NO_DEVICE;
83
#ifdef OMR_OPT_CUDA
84
PORT_ACCESS_FROM_ENV(env);
85
error = j9cuda_hostAlloc((size_t)byteCount, J9CUDA_HOST_ALLOC_DEFAULT, &address);
86
#endif /* OMR_OPT_CUDA */
87
88
if (0 != error) {
89
throwCudaException(env, error);
90
}
91
92
Trc_cuda_allocatePinnedBuffer_exit(thread, address);
93
94
return (jlong)address;
95
}
96
97
/**
98
* Return the number of devices visible to this process.
99
*
100
* Class: com.ibm.cuda.Cuda
101
* Method: getDeviceCount
102
* Signature: ()I
103
*
104
* @param[in] env the JNI interface pointer
105
* @param[in] (unused) the class pointer
106
* @return the number of devices visible to this process
107
*/
108
jint JNICALL
109
Java_com_ibm_cuda_Cuda_getDeviceCount
110
(JNIEnv * env, jclass)
111
{
112
J9VMThread * thread = (J9VMThread *)env;
113
114
Trc_cuda_getDeviceCount_entry(thread);
115
116
uint32_t count = 0;
117
#ifdef OMR_OPT_CUDA
118
PORT_ACCESS_FROM_ENV(env);
119
int32_t error = j9cuda_deviceGetCount(&count);
120
121
if (0 != error) {
122
throwCudaException(env, error);
123
}
124
#endif /* OMR_OPT_CUDA */
125
126
Trc_cuda_getDeviceCount_exit(thread, count);
127
128
return (jint)count;
129
}
130
131
/**
132
* Return the version number of the device driver.
133
*
134
* Class: com.ibm.cuda.Cuda
135
* Method: getDriverVersion
136
* Signature: ()I
137
*
138
* @param[in] env the JNI interface pointer
139
* @param[in] (unused) the class pointer
140
* @return the driver version number
141
*/
142
jint JNICALL
143
Java_com_ibm_cuda_Cuda_getDriverVersion
144
(JNIEnv * env, jclass)
145
{
146
J9VMThread * thread = (J9VMThread *)env;
147
148
Trc_cuda_getDriverVersion_entry(thread);
149
150
uint32_t version = 0;
151
int32_t error = J9CUDA_ERROR_NO_DEVICE;
152
#ifdef OMR_OPT_CUDA
153
PORT_ACCESS_FROM_ENV(env);
154
error = j9cuda_driverGetVersion(&version);
155
#endif /* OMR_OPT_CUDA */
156
157
if (0 != error) {
158
throwCudaException(env, error);
159
}
160
161
Trc_cuda_getDriverVersion_exit(thread, version);
162
163
return (jint)version;
164
}
165
166
/**
167
* Return a string describing the given error code.
168
*
169
* Class: com.ibm.cuda.Cuda
170
* Method: getErrorMessage
171
* Signature: (I)Ljava/lang/String;
172
*
173
* @param[in] env the JNI interface pointer
174
* @param[in] (unused) the class pointer
175
* @param[in] code the error code
176
* @return a string describing the error
177
*/
178
jstring JNICALL
179
Java_com_ibm_cuda_Cuda_getErrorMessage
180
(JNIEnv * env, jclass, jint code)
181
{
182
J9VMThread * thread = (J9VMThread *)env;
183
184
Trc_cuda_getErrorMessage_entry(thread, code);
185
186
const char * message = NULL;
187
#ifdef OMR_OPT_CUDA
188
PORT_ACCESS_FROM_ENV(env);
189
message = j9cuda_getErrorString(code);
190
#else /* OMR_OPT_CUDA */
191
/* Without CUDA support from OMR, these are the only error codes in use. */
192
switch (code) {
193
case J9CUDA_NO_ERROR:
194
message = "no error";
195
break;
196
case J9CUDA_ERROR_MEMORY_ALLOCATION:
197
message = "memory allocation failed";
198
break;
199
case J9CUDA_ERROR_NO_DEVICE:
200
message = "no CUDA-capable device is detected";
201
break;
202
default:
203
break;
204
}
205
#endif /* OMR_OPT_CUDA */
206
207
Trc_cuda_getErrorMessage_exit(thread, (NULL == message) ? "(null)" : message);
208
209
return (NULL == message) ? NULL : env->NewStringUTF(message);
210
}
211
212
/**
213
* Return the version number of the CUDA runtime.
214
*
215
* Class: com.ibm.cuda.Cuda
216
* Method: getRuntimeVersion
217
* Signature: ()I
218
*
219
* @param[in] env the JNI interface pointer
220
* @param[in] (unused) the class pointer
221
* @return the runtime version number
222
*/
223
jint JNICALL
224
Java_com_ibm_cuda_Cuda_getRuntimeVersion
225
(JNIEnv * env, jclass)
226
{
227
J9VMThread * thread = (J9VMThread *)env;
228
229
Trc_cuda_getRuntimeVersion_entry(thread);
230
231
uint32_t version = 0;
232
int32_t error = J9CUDA_ERROR_NO_DEVICE;
233
#ifdef OMR_OPT_CUDA
234
PORT_ACCESS_FROM_ENV(env);
235
error = j9cuda_runtimeGetVersion(&version);
236
#endif /* OMR_OPT_CUDA */
237
238
if (0 != error) {
239
throwCudaException(env, error);
240
}
241
242
Trc_cuda_getRuntimeVersion_exit(thread, version);
243
244
return (jint)version;
245
}
246
247
/**
248
* Perform initialization required by native code.
249
*
250
* Class: com.ibm.cuda.Cuda
251
* Method: initialize
252
* Signature: (Ljava/lang/Class;Ljava/lang/reflect/Method;)I
253
*
254
* @param[in] env the JNI interface pointer
255
* @param[in] (unused) the class pointer
256
* @param[in] exceptionClass the class pointer for CudaException
257
* @param[in] runMethod the method handle for Runnable.run()
258
* @return a CUDA error code
259
*/
260
jint JNICALL
261
Java_com_ibm_cuda_Cuda_initialize
262
(JNIEnv * env, jclass, jclass exceptionClass, jobject runMethod)
263
{
264
jint result = 0;
265
J9CudaGlobals * globals = NULL;
266
J9VMThread * thread = (J9VMThread *)env;
267
J9JavaVM * javaVM = thread->javaVM;
268
269
UT_MODULE_LOADED(J9_UTINTERFACE_FROM_VM(javaVM));
270
271
Trc_cuda_initialize_entry(thread);
272
273
Assert_cuda_true(NULL != exceptionClass);
274
Assert_cuda_true(NULL != runMethod);
275
276
PORT_ACCESS_FROM_JAVAVM(javaVM);
277
278
globals = (J9CudaGlobals *)J9CUDA_ALLOCATE_MEMORY(sizeof(J9CudaGlobals));
279
280
if (NULL == globals) {
281
Trc_cuda_initialize_fail(thread, "allocate globals");
282
result = J9CUDA_ERROR_MEMORY_ALLOCATION;
283
goto done;
284
}
285
286
memset(globals, 0, sizeof(J9CudaGlobals));
287
288
// Cache handles for classes and methods we use.
289
290
globals->exceptionClass = (jclass)env->NewGlobalRef(exceptionClass);
291
292
if (NULL == globals->exceptionClass) {
293
Trc_cuda_initialize_fail(thread, "create NewGlobalRef for CudaException");
294
result = J9CUDA_ERROR_MEMORY_ALLOCATION;
295
goto error1;
296
}
297
298
globals->exception_init = env->GetMethodID(globals->exceptionClass, "<init>", "(I)V");
299
300
if (NULL == globals->exception_init) {
301
Trc_cuda_initialize_fail(thread, "find CudaException constructor");
302
result = J9CUDA_ERROR_INITIALIZATION_ERROR;
303
goto error2;
304
}
305
306
globals->runnable_run = env->FromReflectedMethod(runMethod);
307
308
if (NULL == globals->runnable_run) {
309
Trc_cuda_initialize_fail(thread, "get method handle");
310
result = J9CUDA_ERROR_INITIALIZATION_ERROR;
311
312
error2:
313
env->DeleteGlobalRef(globals->exceptionClass);
314
315
error1:
316
J9CUDA_FREE_MEMORY(globals);
317
globals = NULL;
318
}
319
320
javaVM->cudaGlobals = globals;
321
322
done:
323
Trc_cuda_initialize_exit(thread, result);
324
325
return result;
326
}
327
328
#ifdef OMR_OPT_CUDA
329
330
/**
331
* Wrap the given native host buffer in a direct NIO byte buffer.
332
*
333
* Class: com.ibm.cuda.Cuda
334
* Method: wrapDirectBuffer
335
* Signature: (JJ)Ljava/nio/ByteBuffer;
336
*
337
* @param[in] env the JNI interface pointer
338
* @param[in] (unused) the class pointer
339
* @param[in] buffer the buffer pointer
340
* @param[in] capacity the buffer size in bytes
341
* @return a direct byte buffer
342
*/
343
jobject JNICALL
344
Java_com_ibm_cuda_Cuda_wrapDirectBuffer
345
(JNIEnv * env, jclass, jlong buffer, jlong capacity)
346
{
347
J9VMThread * thread = (J9VMThread *)env;
348
349
Trc_cuda_wrapDirectBuffer_entry(thread, (uintptr_t)buffer, capacity);
350
351
jobject wrapper = env->NewDirectByteBuffer((void *)(uintptr_t)buffer, capacity);
352
353
Trc_cuda_wrapDirectBuffer_exit(thread, wrapper);
354
355
return wrapper;
356
}
357
358
/**
359
* Release a block of pinned host memory.
360
*
361
* Class: com.ibm.cuda.Cuda.Cleaner
362
* Method: releasePinnedBuffer
363
* Signature: (J)V
364
*
365
* @param[in] env the JNI interface pointer
366
* @param[in] (unused) the class pointer
367
* @param[in] address the buffer pointer
368
*/
369
void JNICALL
370
Java_com_ibm_cuda_Cuda_00024Cleaner_releasePinnedBuffer
371
(JNIEnv * env, jclass, jlong address)
372
{
373
J9VMThread * thread = (J9VMThread *)env;
374
375
Trc_cuda_releasePinnedBuffer_entry(thread, (uintptr_t)address);
376
377
PORT_ACCESS_FROM_ENV(env);
378
379
int32_t error = j9cuda_hostFree((void *)(uintptr_t)address);
380
381
if (0 != error) {
382
throwCudaException(env, error);
383
}
384
385
Trc_cuda_releasePinnedBuffer_exit(thread);
386
}
387
388
#endif /* OMR_OPT_CUDA */
389
390
/**
391
* Called immediately before our shared library is unloaded: Release resources we allocated.
392
*/
393
void JNICALL
394
JNI_OnUnload(JavaVM * jvm, void *)
395
{
396
J9JavaVM * javaVM = (J9JavaVM *)jvm;
397
J9CudaGlobals * globals = javaVM->cudaGlobals;
398
399
PORT_ACCESS_FROM_JAVAVM(javaVM);
400
401
if (NULL != globals) {
402
if (NULL != globals->exceptionClass) {
403
JNIEnv * env = NULL;
404
405
/*
406
* It's not serious if we can't get the JNIEnv - we're likely shutting down anyway.
407
*/
408
if (JNI_OK == jvm->GetEnv((void **)&env, JNI_VERSION_1_2)) {
409
env->DeleteGlobalRef(globals->exceptionClass);
410
}
411
}
412
413
J9CUDA_FREE_MEMORY(globals);
414
javaVM->cudaGlobals = NULL;
415
}
416
417
UT_MODULE_UNLOADED(J9_UTINTERFACE_FROM_VM(javaVM));
418
}
419
420