comparison src/gpu/hsail/vm/gpu_hsail.cpp @ 13819:49db2c1e3bee

added support for co-existing GPU backends (JBS:GRAAL-1)
author Doug Simon <doug.simon@oracle.com>
date Thu, 30 Jan 2014 00:52:33 +0100
parents bfd61161d752
children 35fc64972250
comparison
equal deleted inserted replaced
13818:d2f520f46180 13819:49db2c1e3bee
27 #include "runtime/gpu.hpp" 27 #include "runtime/gpu.hpp"
28 #include "utilities/globalDefinitions.hpp" 28 #include "utilities/globalDefinitions.hpp"
29 #include "utilities/ostream.hpp" 29 #include "utilities/ostream.hpp"
30 #include "memory/allocation.hpp" 30 #include "memory/allocation.hpp"
31 #include "memory/allocation.inline.hpp" 31 #include "memory/allocation.inline.hpp"
32 #include "graal/graalEnv.hpp"
33 #include "graal/graalCompiler.hpp"
34 #include "graal/graalJavaAccess.hpp"
32 #include "hsailKernelArguments.hpp" 35 #include "hsailKernelArguments.hpp"
33 36
34 void * gpu::Hsail::_device_context; 37 // Entry to GPU native method implementation that transitions current thread to '_thread_in_vm'.
38 #define GPU_VMENTRY(result_type, name, signature) \
39 JNIEXPORT result_type JNICALL name signature { \
40 GRAAL_VM_ENTRY_MARK; \
41
42 // Entry to GPU native method implementation that calls a JNI function
43 // and hence cannot transition current thread to '_thread_in_vm'.
44 #define GPU_ENTRY(result_type, name, signature) \
45 JNIEXPORT result_type JNICALL name signature { \
46
47 #define GPU_END }
48
49 #define CC (char*) /*cast a literal from (const char*)*/
50 #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(f))
51
52 #define OBJECT "Ljava/lang/Object;"
53 #define STRING "Ljava/lang/String;"
54 #define HS_INSTALLED_CODE "Lcom/oracle/graal/hotspot/meta/HotSpotInstalledCode;"
55
56 // public native void executeKernel(HotSpotNmethod kernel, int jobSize, int i, int j, Object[] args) throws InvalidInstalledCodeException;
57
58 JNINativeMethod gpu::Hsail::HSAIL_methods[] = {
59 {CC"initialize", CC"()Z", FN_PTR(gpu::Hsail::initialize)},
60 {CC"generateKernel", CC"([B" STRING ")J", FN_PTR(gpu::Hsail::generate_kernel)},
61 {CC"executeKernel0", CC"("HS_INSTALLED_CODE"I["OBJECT")Z", FN_PTR(gpu::Hsail::execute_kernel_void_1d)},
62 };
63
64 void * gpu::Hsail::_device_context = NULL;
35 65
36 gpu::Hsail::okra_create_context_func_t gpu::Hsail::_okra_create_context; 66 gpu::Hsail::okra_create_context_func_t gpu::Hsail::_okra_create_context;
37 gpu::Hsail::okra_create_kernel_func_t gpu::Hsail::_okra_create_kernel; 67 gpu::Hsail::okra_create_kernel_func_t gpu::Hsail::_okra_create_kernel;
38 gpu::Hsail::okra_push_object_func_t gpu::Hsail::_okra_push_object; 68 gpu::Hsail::okra_push_object_func_t gpu::Hsail::_okra_push_object;
39 gpu::Hsail::okra_push_boolean_func_t gpu::Hsail::_okra_push_boolean; 69 gpu::Hsail::okra_push_boolean_func_t gpu::Hsail::_okra_push_boolean;
45 gpu::Hsail::okra_execute_with_range_func_t gpu::Hsail::_okra_execute_with_range; 75 gpu::Hsail::okra_execute_with_range_func_t gpu::Hsail::_okra_execute_with_range;
46 gpu::Hsail::okra_clearargs_func_t gpu::Hsail::_okra_clearargs; 76 gpu::Hsail::okra_clearargs_func_t gpu::Hsail::_okra_clearargs;
47 gpu::Hsail::okra_register_heap_func_t gpu::Hsail::_okra_register_heap; 77 gpu::Hsail::okra_register_heap_func_t gpu::Hsail::_okra_register_heap;
48 78
49 79
50 bool gpu::Hsail::initialize_gpu() {
51 // All the initialization is done in the okra library so
52 // nothing to do here.
53 if (TraceGPUInteraction) {
54 tty->print_cr("[HSAIL] Simulator: initialize_gpu");
55 }
56 return true;
57 }
58
59 unsigned int gpu::Hsail::total_cores() {
60 // This is not important with simulator
61 return 1;
62 }
63
64 void gpu::Hsail::register_heap() { 80 void gpu::Hsail::register_heap() {
65 // After the okra functions are set up and the heap is initialized, register the java heap with HSA 81 // After the okra functions are set up and the heap is initialized, register the java heap with HSA
66 guarantee(Universe::heap() != NULL, "heap should be there by now."); 82 guarantee(Universe::heap() != NULL, "heap should be there by now.");
67 if (TraceGPUInteraction) { 83 if (TraceGPUInteraction) {
68 tty->print_cr("[HSAIL] heap=" PTR_FORMAT, Universe::heap()); 84 tty->print_cr("[HSAIL] heap=" PTR_FORMAT, Universe::heap());
69 tty->print_cr("[HSAIL] base=0x%08x, capacity=%ld", Universe::heap()->base(), Universe::heap()->capacity()); 85 tty->print_cr("[HSAIL] base=0x%08x, capacity=%ld", Universe::heap()->base(), Universe::heap()->capacity());
70 } 86 }
71 _okra_register_heap(Universe::heap()->base(), Universe::heap()->capacity()); 87 _okra_register_heap(Universe::heap()->base(), Universe::heap()->capacity());
72 } 88 }
73 89
74 bool gpu::Hsail::execute_kernel_void_1d(address kernel, int dimX, jobject args, methodHandle& mh) { 90 GPU_VMENTRY(jboolean, gpu::Hsail::execute_kernel_void_1d, (JNIEnv* env, jclass, jobject kernel_handle, jint dimX, jobject args_handle))
75 objArrayOop argsArray = (objArrayOop) JNIHandles::resolve(args); 91
92 ResourceMark rm;
93 jlong nmethodValue = HotSpotInstalledCode::codeBlob(kernel_handle);
94 if (nmethodValue == 0) {
95 SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
96 }
97 nmethod* nm = (nmethod*) (address) nmethodValue;
98 methodHandle mh = nm->method();
99 Symbol* signature = mh->signature();
100
101 void* kernel = (void*) HotSpotInstalledCode::codeStart(kernel_handle);
102 if (kernel == NULL) {
103 SharedRuntime::throw_and_post_jvmti_exception(JavaThread::current(), vmSymbols::com_oracle_graal_api_code_InvalidInstalledCodeException(), NULL);
104 }
105
106 objArrayOop args = (objArrayOop) JNIHandles::resolve(args_handle);
76 107
77 // Reset the kernel arguments 108 // Reset the kernel arguments
78 _okra_clearargs(kernel); 109 _okra_clearargs(kernel);
79 110
80 // This object sets up the kernel arguments 111 // This object sets up the kernel arguments
81 HSAILKernelArguments hka(kernel, mh->signature(), argsArray, mh->is_static()); 112 HSAILKernelArguments hka((address) kernel, mh->signature(), args, mh->is_static());
82 113
83 // Run the kernel 114 // Run the kernel
84 bool success = _okra_execute_with_range(kernel, dimX); 115 return _okra_execute_with_range(kernel, dimX);
85 return success; 116 GPU_END
86 } 117
87 118 GPU_ENTRY(jlong, gpu::Hsail::generate_kernel, (JNIEnv *env, jclass, jbyteArray code_handle, jstring name_handle))
88 void *gpu::Hsail::generate_kernel(unsigned char *code, int code_len, const char *name) { 119 guarantee(_okra_create_kernel != NULL, "[HSAIL] Okra not linked");
89 120 ResourceMark rm;
90 if (_okra_create_kernel == NULL) { 121 jsize name_len = env->GetStringLength(name_handle);
91 // probe linkage and we really need it to work this time 122 jsize code_len = env->GetArrayLength(code_handle);
92 bool success = probe_linkage_internal(true); 123
93 guarantee(success, "[HSAIL] loading okra library"); 124 char* name = NEW_RESOURCE_ARRAY(char, name_len + 1);
94 } 125 unsigned char *code = NEW_RESOURCE_ARRAY(unsigned char, code_len + 1);
95 126
96 gpu::Hsail::register_heap(); 127 code[code_len] = 0;
128 name[name_len] = 0;
129
130 env->GetByteArrayRegion(code_handle, 0, code_len, (jbyte*) code);
131 env->GetStringUTFRegion(name_handle, 0, name_len, name);
132
133 register_heap();
97 134
98 // The kernel entrypoint is always run for the time being 135 // The kernel entrypoint is always run for the time being
99 const char* entryPointName = "&run"; 136 const char* entryPointName = "&run";
100 137
101 _device_context = _okra_create_context(); 138 _device_context = _okra_create_context();
102 139
103 // code is not null terminated, must be a better way to do this 140 return (jlong) _okra_create_kernel(_device_context, code, entryPointName);
104 unsigned char* nullTerminatedCodeBuffer = (unsigned char*) malloc(code_len + 1); 141 GPU_END
105 memcpy(nullTerminatedCodeBuffer, code, code_len);
106 nullTerminatedCodeBuffer[code_len] = 0;
107 void* kernel = _okra_create_kernel(_device_context, nullTerminatedCodeBuffer, entryPointName);
108 free(nullTerminatedCodeBuffer);
109 return kernel;
110 }
111 142
112 #if defined(LINUX) 143 #if defined(LINUX)
113 static const char okra_library_name[] = "libokra_x86_64.so"; 144 static const char okra_library_name[] = "libokra_x86_64.so";
114 #elif defined (_WINDOWS) 145 #elif defined(_WINDOWS)
115 static char const okra_library_name[] = "okra_x86_64.dll"; 146 static char const okra_library_name[] = "okra_x86_64.dll";
116 #else 147 #else
117 static char const okra_library_name[] = ""; 148 static char const okra_library_name[] = NULL;
118 #endif 149 #endif
119
120 #define STD_BUFFER_SIZE 1024
121 150
122 #define STRINGIFY(x) #x 151 #define STRINGIFY(x) #x
123 152
124 #define LOOKUP_OKRA_FUNCTION(name, alias) \ 153 #define LOOKUP_OKRA_FUNCTION(name, alias) \
125 _##alias = \ 154 _##alias = \
126 CAST_TO_FN_PTR(alias##_func_t, os::dll_lookup(handle, STRINGIFY(name))); \ 155 CAST_TO_FN_PTR(alias##_func_t, os::dll_lookup(handle, STRINGIFY(name))); \
127 if (_##alias == NULL) { \ 156 if (_##alias == NULL) { \
128 tty->print_cr("[HSAIL] ***** Error: Failed to lookup %s in %s, wrong version of OKRA?", STRINGIFY(name), okra_library_name); \ 157 tty->print_cr("[HSAIL] ***** Error: Failed to lookup %s in %s, wrong version of OKRA?", STRINGIFY(name), okra_library_name); \
129 return 0; \ 158 return false; \
130 } \ 159 } \
131 160
132 bool gpu::Hsail::probe_linkage() { 161 GPU_ENTRY(jboolean, gpu::Hsail::initialize, (JNIEnv *env, jclass))
133 return probe_linkage_internal(false);
134 }
135
136
137 bool gpu::Hsail::probe_linkage_internal(bool isRequired) {
138 if (okra_library_name == NULL) { 162 if (okra_library_name == NULL) {
139 if (TraceGPUInteraction) { 163 if (TraceGPUInteraction) {
140 tty->print_cr("Unsupported HSAIL platform"); 164 tty->print_cr("Unsupported HSAIL platform");
141 } 165 }
142 return false; 166 return false;
143 } 167 }
144 168
145 // here we know we have a valid okra_library_name to try to load 169 // here we know we have a valid okra_library_name to try to load
146 // the isRequired boolean specifies whether it is an error if the 170 char ebuf[O_BUFLEN];
147 // probe does not find the okra library
148 char *buffer = (char*)malloc(STD_BUFFER_SIZE);
149 if (TraceGPUInteraction) { 171 if (TraceGPUInteraction) {
150 tty->print_cr("[HSAIL] library is %s", okra_library_name); 172 tty->print_cr("[HSAIL] library is %s", okra_library_name);
151 } 173 }
152 void *handle = os::dll_load(okra_library_name, buffer, STD_BUFFER_SIZE); 174 void *handle = os::dll_load(okra_library_name, ebuf, O_BUFLEN);
153 // try alternate location if env variable set 175 // try alternate location if env variable set
154 char *okra_lib_name_from_env_var = getenv("_OKRA_SIM_LIB_PATH_"); 176 char *okra_lib_name_from_env_var = getenv("_OKRA_SIM_LIB_PATH_");
155 if ((handle == NULL) && (okra_lib_name_from_env_var != NULL)) { 177 if ((handle == NULL) && (okra_lib_name_from_env_var != NULL)) {
156 handle = os::dll_load(okra_lib_name_from_env_var, buffer, STD_BUFFER_SIZE); 178 handle = os::dll_load(okra_lib_name_from_env_var, ebuf, O_BUFLEN);
157 if ((handle != NULL) && TraceGPUInteraction) { 179 if ((handle != NULL) && TraceGPUInteraction) {
158 tty->print_cr("[HSAIL] using _OKRA_SIM_LIB_PATH_=%s", getenv("_OKRA_SIM_LIB_PATH_")); 180 tty->print_cr("[HSAIL] using _OKRA_SIM_LIB_PATH_=%s", getenv("_OKRA_SIM_LIB_PATH_"));
159 } 181 }
160 } 182 }
161 free(buffer); 183
162 184 if (handle == NULL) {
163 if ((handle == NULL) && !isRequired) {
164 // return true for now but we will probe again later
165 if (TraceGPUInteraction) {
166 tty->print_cr("[HSAIL] library load not in PATH, waiting for Java to put in tmpdir.");
167 }
168 return true;
169 }
170
171 if ((handle == NULL) && isRequired) {
172 // Unable to dlopen okra 185 // Unable to dlopen okra
173 if (TraceGPUInteraction) { 186 if (TraceGPUInteraction) {
174 tty->print_cr("[HSAIL] library load failed."); 187 tty->print_cr("[HSAIL] library load failed.");
175 } 188 }
176 return false; 189 return false;
177 } 190 }
178 191
192 guarantee(_okra_create_context == NULL, "cannot repeat GPU initialization");
193
179 // at this point we know handle is valid and we can lookup the functions 194 // at this point we know handle is valid and we can lookup the functions
180 LOOKUP_OKRA_FUNCTION(okra_create_context, okra_create_context); 195 LOOKUP_OKRA_FUNCTION(okra_create_context, okra_create_context);
181 LOOKUP_OKRA_FUNCTION(okra_create_kernel, okra_create_kernel); 196 LOOKUP_OKRA_FUNCTION(okra_create_kernel, okra_create_kernel);
182 LOOKUP_OKRA_FUNCTION(okra_push_object, okra_push_object); 197 LOOKUP_OKRA_FUNCTION(okra_push_object, okra_push_object);
183 LOOKUP_OKRA_FUNCTION(okra_push_boolean, okra_push_boolean); 198 LOOKUP_OKRA_FUNCTION(okra_push_boolean, okra_push_boolean);
187 LOOKUP_OKRA_FUNCTION(okra_push_int, okra_push_int); 202 LOOKUP_OKRA_FUNCTION(okra_push_int, okra_push_int);
188 LOOKUP_OKRA_FUNCTION(okra_push_long, okra_push_long); 203 LOOKUP_OKRA_FUNCTION(okra_push_long, okra_push_long);
189 LOOKUP_OKRA_FUNCTION(okra_execute_with_range, okra_execute_with_range); 204 LOOKUP_OKRA_FUNCTION(okra_execute_with_range, okra_execute_with_range);
190 LOOKUP_OKRA_FUNCTION(okra_clearargs, okra_clearargs); 205 LOOKUP_OKRA_FUNCTION(okra_clearargs, okra_clearargs);
191 LOOKUP_OKRA_FUNCTION(okra_register_heap, okra_register_heap); 206 LOOKUP_OKRA_FUNCTION(okra_register_heap, okra_register_heap);
192
193 // if we made it this far, real success 207 // if we made it this far, real success
208
209 gpu::initialized_gpu("Okra");
210
211 return true;
212 GPU_END
213
214 bool gpu::Hsail::register_natives(JNIEnv* env) {
215 jclass klass = env->FindClass("com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend");
216 if (klass == NULL) {
217 if (TraceGPUInteraction) {
218 tty->print_cr("HSAILHotSpotBackend class not found");
219 }
220 return false;
221 }
222 jint status = env->RegisterNatives(klass, HSAIL_methods, sizeof(HSAIL_methods) / sizeof(JNINativeMethod));
223 if (status != JNI_OK) {
224 if (TraceGPUInteraction) {
225 tty->print_cr("Error registering natives for HSAILHotSpotBackend: %d", status);
226 }
227 return false;
228 }
194 return true; 229 return true;
195 } 230 }