annotate src/se/native/com/oracle/dio/dio_event_queue.cpp @ 251:4045c31c14f9

8136841: Segmentation fault if GPIO input pin is litened Summary: Reorder listener assigment and start notification calls, javanotify is guarded against uninitialized variables. Reviewed-by: alkonsta
author snazarki
date Tue, 22 Sep 2015 18:40:20 +0300
parents 2c0af8cb3202
children 4299ff23b184
rev   line source
duke@0 1 /*
duke@0 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
duke@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 4 *
duke@0 5 * This code is free software; you can redistribute it and/or modify it
duke@0 6 * under the terms of the GNU General Public License version 2 only, as
duke@0 7 * published by the Free Software Foundation. Oracle designates this
duke@0 8 * particular file as subject to the "Classpath" exception as provided
duke@0 9 * by Oracle in the LICENSE file that accompanied this code.
duke@0 10 *
duke@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@0 15 * accompanied this code).
duke@0 16 *
duke@0 17 * You should have received a copy of the GNU General Public License version
duke@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 20 *
duke@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
duke@0 22 * or visit www.oracle.com if you need additional information or have any
duke@0 23 * questions.
duke@0 24 */
duke@0 25
duke@0 26 #include "dio_event_queue.h"
duke@0 27 #include <string.h>
duke@0 28
snazarki@177 29 /* Entities required for sending notifications */
snazarki@177 30 static jobject eventBuffer = NULL;
duke@0 31
duke@0 32 extern "C" {
duke@0 33
snazarki@177 34 JNIEXPORT void JNICALL Java_com_oracle_dio_impl_EventQueue_setNativeEntries
snazarki@208 35 (JNIEnv* env, jobject this_obj, jobject buffer) {
snazarki@177 36 if (eventBuffer) {
snazarki@177 37 env->DeleteGlobalRef(eventBuffer);
jld@38 38 }
snazarki@177 39 eventBuffer = env->NewGlobalRef(buffer);
duke@0 40 }
duke@0 41
duke@0 42 } /* extern "C */
duke@0 43
duke@0 44 /*
duke@0 45 * Puts an event to the provided NIO buffer and sends a notification to the
duke@0 46 * EventQueue object that handles the buffer. See the implementation
duke@0 47 * of the com.oracle.dio.impl.EventQueue class for details.
duke@0 48 */
duke@0 49 void event_queue_put_native_event
snazarki@177 50 (JavaVM* cachedJVM, const char* device_type, const char *payload, int payload_size) {
duke@0 51 JNIEnv* env;
snazarki@251 52 if (NULL == eventBuffer) {
snazarki@251 53 JAVACALL_REPORT_ERROR(JC_DIO, "Event queue is not initialized properly");
snazarki@251 54 return;
snazarki@251 55 }
snazarki@251 56 cachedJVM->AttachCurrentThread((void **)&env, NULL);
duke@0 57
snazarki@177 58 jclass bufferClass = env->GetObjectClass(eventBuffer);
jld@38 59 jmethodID notifyID = bufferClass ? env->GetMethodID(bufferClass, "notify", "()V") :
jld@38 60 NULL;
jld@38 61 jmethodID limitID = notifyID ? env->GetMethodID(bufferClass, "limit", "()I") :
jld@38 62 NULL;
jld@38 63 jmethodID setLimitID = limitID ? env->GetMethodID(bufferClass, "limit", "(I)Ljava/nio/Buffer;") :
jld@38 64 NULL;
duke@0 65
snazarki@177 66 const int device_type_len = strlen(device_type) + 1;
jld@38 67 if (setLimitID) {
snazarki@177 68 env->MonitorEnter(eventBuffer);
duke@0 69
jld@38 70 if (env->ExceptionCheck() != JNI_TRUE) {
jld@38 71 // check enough space in direct buffer
snazarki@177 72 jlong capacity = env->GetDirectBufferCapacity(eventBuffer);
snazarki@177 73 jint limit = env->CallIntMethod(eventBuffer, limitID);
duke@0 74
snazarki@177 75 jint newLimit = limit + device_type_len + payload_size + 2;
duke@0 76
jld@38 77 if (newLimit < capacity) {
snazarki@177 78 jbyte* buf = (jbyte*)env->GetDirectBufferAddress(eventBuffer);
duke@0 79
jld@38 80 buf += limit;
jld@14 81
snazarki@177 82 memcpy(buf, device_type, device_type_len);
snazarki@177 83 buf += device_type_len;
duke@0 84
jld@38 85 // payload
jld@38 86 *buf++ = (jbyte)((payload_size & 0xFF00) >> 8); // high byte
jld@38 87 *buf++ = (jbyte)(payload_size & 0xFF); // then low byte
jld@38 88 memcpy(buf, payload, payload_size);
duke@0 89
snazarki@177 90 env->CallObjectMethod(eventBuffer, setLimitID, newLimit);
jld@38 91 }
snazarki@212 92 env->CallVoidMethod(eventBuffer, notifyID);
jld@38 93 }
snazarki@212 94 env->MonitorExit(eventBuffer);
duke@0 95 }
duke@0 96 cachedJVM->DetachCurrentThread();
duke@0 97 }