All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ve.pulsar-client-all.3.2.2.7.source-code.netty_io_uring_native.c Maven / Gradle / Ivy

/*
 * Copyright 2020 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
#define _GNU_SOURCE // RTLD_DEFAULT
#include "netty_io_uring.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "syscall.h"
#include "netty_io_uring_linuxsocket.h"
#include 

#include 
#include 
#include 
#include 
#include 

#include 
#include 
// Needed for UDP_SEGMENT
#include 
#include 

// Allow to compile on systems with older kernels.
#ifndef UDP_SEGMENT
#define UDP_SEGMENT 103
#endif

// MSG_FASTOPEN is defined in linux 3.6. We define this here so older kernels can compile.
#ifndef MSG_FASTOPEN
#define MSG_FASTOPEN 0x20000000
#endif

// Add define if NETTY_IO_URING_BUILD_STATIC is defined so it is picked up in netty_jni_util.c
#ifdef NETTY_IO_URING_BUILD_STATIC
#define NETTY_JNI_UTIL_BUILD_STATIC
#endif

#define NATIVE_CLASSNAME "io/netty/incubator/channel/uring/Native"
#define STATICALLY_CLASSNAME "io/netty/incubator/channel/uring/NativeStaticallyReferencedJniMethods"
#define LIBRARYNAME "netty_transport_native_io_uring"

static jclass longArrayClass = NULL;
static char* staticPackagePrefix = NULL;
static int register_unix_called = 0;

static void netty_io_uring_native_JNI_OnUnLoad(JNIEnv* env, const char* packagePrefix) {
    netty_unix_limits_JNI_OnUnLoad(env, packagePrefix);
    netty_unix_errors_JNI_OnUnLoad(env, packagePrefix);
    netty_unix_filedescriptor_JNI_OnUnLoad(env, packagePrefix);
    netty_unix_socket_JNI_OnUnLoad(env, packagePrefix);
    netty_unix_buffer_JNI_OnUnLoad(env, packagePrefix);

    NETTY_JNI_UTIL_UNLOAD_CLASS(env, longArrayClass);
}

static void io_uring_unmap_rings(struct io_uring_sq *sq, struct io_uring_cq *cq) {
    munmap(sq->ring_ptr, sq->ring_sz);
    if (cq->ring_ptr && cq->ring_ptr != sq->ring_ptr) {
        munmap(cq->ring_ptr, cq->ring_sz);
  }
}

static int io_uring_mmap(int fd, struct io_uring_params *p, struct io_uring_sq *sq, struct io_uring_cq *cq) {
    size_t size;
    int ret;

    sq->ring_sz = p->sq_off.array + p->sq_entries * sizeof(unsigned);
    cq->ring_sz = p->cq_off.cqes + p->cq_entries * sizeof(struct io_uring_cqe);

    if ((p->features & IORING_FEAT_SINGLE_MMAP) == 1) {
        if (cq->ring_sz > sq->ring_sz) {
            sq->ring_sz = cq->ring_sz;
        }
        cq->ring_sz = sq->ring_sz;
    }
    sq->ring_ptr = mmap(0, sq->ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQ_RING);
    if (sq->ring_ptr == MAP_FAILED) {
        return -errno;
    }

    if ((p->features & IORING_FEAT_SINGLE_MMAP) == 1) {
        cq->ring_ptr = sq->ring_ptr;
    } else {
        cq->ring_ptr = mmap(0, cq->ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_CQ_RING);
        if (cq->ring_ptr == MAP_FAILED) {
            cq->ring_ptr = NULL;
            ret = -errno;
            goto err;
        }
    }

    sq->khead = sq->ring_ptr + p->sq_off.head;
    sq->ktail = sq->ring_ptr + p->sq_off.tail;
    sq->kring_mask = sq->ring_ptr + p->sq_off.ring_mask;
    sq->kring_entries = sq->ring_ptr + p->sq_off.ring_entries;
    sq->kflags = sq->ring_ptr + p->sq_off.flags;
    sq->kdropped = sq->ring_ptr + p->sq_off.dropped;
    sq->array = sq->ring_ptr + p->sq_off.array;

    size = p->sq_entries * sizeof(struct io_uring_sqe);
    sq->sqes = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQES);
    if (sq->sqes == MAP_FAILED) {
        ret = -errno;
        goto err;
    }

    cq->khead = cq->ring_ptr + p->cq_off.head;
    cq->ktail = cq->ring_ptr + p->cq_off.tail;
    cq->kring_mask = cq->ring_ptr + p->cq_off.ring_mask;
    cq->kring_entries = cq->ring_ptr + p->cq_off.ring_entries;
    cq->koverflow = cq->ring_ptr + p->cq_off.overflow;
    cq->cqes = cq->ring_ptr + p->cq_off.cqes;

    return 0;
err:
    io_uring_unmap_rings(sq, cq);
    return ret;
}

static int setup_io_uring(int ring_fd, struct io_uring *io_uring_ring,
                    struct io_uring_params *p) {
    return io_uring_mmap(ring_fd, p, &io_uring_ring->sq, &io_uring_ring->cq);
}

static jint netty_io_uring_enter(JNIEnv *env, jclass class1, jint ring_fd, jint to_submit,
                                 jint min_complete, jint flags) {
    int result;
    int err;
    do {
        result = sys_io_uring_enter(ring_fd, to_submit, min_complete, flags, NULL);
        if (result >= 0) {
            return result;
        }
    } while ((err = errno) == EINTR);
    return -err;
}

static jstring netty_io_uring_kernel_version(JNIEnv* env, jclass clazz) {
    struct utsname u;
    uname(&u);

    jstring result = (*env)->NewStringUTF(env, u.release);
    return result;
}

static jint netty_epoll_native_blocking_event_fd(JNIEnv* env, jclass clazz) {
    // We use a blocking fd with io_uring FAST_POLL read
    jint eventFD = eventfd(0, EFD_CLOEXEC);

    if (eventFD < 0) {
        netty_unix_errors_throwChannelExceptionErrorNo(env, "eventfd() failed: ", errno);
    }
    return eventFD;
}

static void netty_io_uring_eventFdWrite(JNIEnv* env, jclass clazz, jint fd, jlong value) {
    int result;
    int err;
    do {
        result = eventfd_write(fd, (eventfd_t) value);
        if (result >= 0) {
            return;
        }
    } while ((err = errno) == EINTR);
    netty_unix_errors_throwChannelExceptionErrorNo(env, "eventfd_write(...) failed: ", err);
}

static void netty_io_uring_ring_buffer_exit(JNIEnv *env, jclass clazz,
        jlong submissionQueueArrayAddress, jint submissionQueueRingEntries, jlong submissionQueueRingAddress, jint submissionQueueRingSize,
        jlong completionQueueRingAddress, jint completionQueueRingSize, jint ringFd) {
    munmap((struct io_uring_sqe*) submissionQueueArrayAddress, submissionQueueRingEntries * sizeof(struct io_uring_sqe));
    munmap((void*) submissionQueueRingAddress, submissionQueueRingSize);

    if (((void *) completionQueueRingAddress) && ((void *) completionQueueRingAddress) != ((void *) submissionQueueRingAddress)) {
        munmap((void *)completionQueueRingAddress, completionQueueRingSize);
    }
    close(ringFd);
}

static jboolean netty_io_uring_probe(JNIEnv *env, jclass clazz, jint ring_fd, jintArray ops) {
    jboolean supported = JNI_FALSE;
    jint *opsElements = NULL;
    struct io_uring_probe *probe;
    size_t mallocLen = sizeof(*probe) + 256 * sizeof(struct io_uring_probe_op);
    probe = malloc(mallocLen);
    memset(probe, 0, mallocLen);

    if (sys_io_uring_register(ring_fd, IORING_REGISTER_PROBE, probe, 256) < 0) {
        netty_unix_errors_throwRuntimeExceptionErrorNo(env, "failed to probe via sys_io_uring_register(....) ", errno);
        goto done;
    }

    jsize opsLen = (*env)->GetArrayLength(env, ops);
    opsElements = (*env)->GetIntArrayElements(env, ops, 0);
    int i;
    for (i = 0; i < opsLen; i++) {
        int op = opsElements[i];
        if (op > probe->last_op || (probe->ops[op].flags & IO_URING_OP_SUPPORTED) == 0) {
            goto done;
        }
    }
    // all supported
    supported = JNI_TRUE;
done:
    free(probe);
    if (opsElements != NULL) {
        (*env)->ReleaseIntArrayElements(env, ops, opsElements, JNI_ABORT);
    }
    return supported;
}


static jobjectArray netty_io_uring_setup(JNIEnv *env, jclass clazz, jint entries) {
    struct io_uring_params p;
    memset(&p, 0, sizeof(p));

    jobjectArray array = (*env)->NewObjectArray(env, 2, longArrayClass, NULL);
    if (array == NULL) {
        // This will put an OOME on the stack
        return NULL;
    }
    jlongArray submissionArray = (*env)->NewLongArray(env, 11);
    if (submissionArray == NULL) {
        // This will put an OOME on the stack
        return NULL;

    }
    jlongArray completionArray = (*env)->NewLongArray(env, 9);
    if (completionArray == NULL) {
        // This will put an OOME on the stack
        return NULL;
    }

    int ring_fd = sys_io_uring_setup((int)entries, &p);

    if (ring_fd < 0) {
        if (errno == ENOMEM) {
            netty_unix_errors_throwRuntimeExceptionErrorNo(env,
                "failed to allocate memory for io_uring ring; "
                "try raising memlock limit (see getrlimit(RLIMIT_MEMLOCK, ...) or ulimit -l): ", errno);
        } else {
            netty_unix_errors_throwRuntimeExceptionErrorNo(env, "failed to create io_uring ring fd: ", errno);
        }
        return NULL;
    }
    struct io_uring io_uring_ring;
    int ret = setup_io_uring(ring_fd, &io_uring_ring, &p);

    if (ret != 0) {
        netty_unix_errors_throwRuntimeExceptionErrorNo(env, "failed to mmap io_uring ring buffer: ", ret);
        return NULL;
    }

    jlong submissionArrayElements[] = {
        (jlong)io_uring_ring.sq.khead,
        (jlong)io_uring_ring.sq.ktail,
        (jlong)io_uring_ring.sq.kring_mask,
        (jlong)io_uring_ring.sq.kring_entries,
        (jlong)io_uring_ring.sq.kflags,
        (jlong)io_uring_ring.sq.kdropped,
        (jlong)io_uring_ring.sq.array,
        (jlong)io_uring_ring.sq.sqes,
        (jlong)io_uring_ring.sq.ring_sz,
        (jlong)io_uring_ring.sq.ring_ptr,
        (jlong)ring_fd
    };
    (*env)->SetLongArrayRegion(env, submissionArray, 0, 11, submissionArrayElements);

    jlong completionArrayElements[] = {
        (jlong)io_uring_ring.cq.khead,
        (jlong)io_uring_ring.cq.ktail,
        (jlong)io_uring_ring.cq.kring_mask,
        (jlong)io_uring_ring.cq.kring_entries,
        (jlong)io_uring_ring.cq.koverflow,
        (jlong)io_uring_ring.cq.cqes,
        (jlong)io_uring_ring.cq.ring_sz,
        (jlong)io_uring_ring.cq.ring_ptr,
        (jlong)ring_fd
    };
    (*env)->SetLongArrayRegion(env, completionArray, 0, 9, completionArrayElements);

    (*env)->SetObjectArrayElement(env, array, 0, submissionArray);
    (*env)->SetObjectArrayElement(env, array, 1, completionArray);
    return array;
}

static jint netty_create_file(JNIEnv *env, jclass class, jstring filename) {
    const char *file = (*env)->GetStringUTFChars(env, filename, 0);

    int fd =  open(file, O_RDWR | O_TRUNC | O_CREAT, 0644);
    (*env)->ReleaseStringUTFChars(env, filename, file);
    return fd;
}


static jint netty_io_uring_registerUnix(JNIEnv* env, jclass clazz) {
    register_unix_called = 1;
    return netty_unix_register(env, staticPackagePrefix);
}

static jint netty_io_uring_sockNonblock(JNIEnv* env, jclass clazz) {
    return SOCK_NONBLOCK;
}

static jint netty_io_uring_sockCloexec(JNIEnv* env, jclass clazz) {
    return SOCK_CLOEXEC;
}

static jint netty_io_uring_afInet(JNIEnv* env, jclass clazz) {
    return AF_INET;
}

static jint netty_io_uring_afInet6(JNIEnv* env, jclass clazz) {
    return AF_INET6;
}

static jint netty_io_uring_sizeofSockaddrIn(JNIEnv* env, jclass clazz) {
    return sizeof(struct sockaddr_in);
}

static jint netty_io_uring_sizeofSockaddrIn6(JNIEnv* env, jclass clazz) {
    return sizeof(struct sockaddr_in6);
}

static jint netty_io_uring_sockaddrInOffsetofSinFamily(JNIEnv* env, jclass clazz) {
    return offsetof(struct sockaddr_in, sin_family);
}

static jint netty_io_uring_sockaddrInOffsetofSinPort(JNIEnv* env, jclass clazz) {
    return offsetof(struct sockaddr_in, sin_port);
}

static jint netty_io_uring_sockaddrInOffsetofSinAddr(JNIEnv* env, jclass clazz) {
    return offsetof(struct sockaddr_in, sin_addr);
}

static jint netty_io_uring_inAddressOffsetofSAddr(JNIEnv* env, jclass clazz) {
    return offsetof(struct in_addr, s_addr);
}

static jint netty_io_uring_sockaddrIn6OffsetofSin6Family(JNIEnv* env, jclass clazz) {
    return offsetof(struct sockaddr_in6, sin6_family);
}

static jint netty_io_uring_sockaddrIn6OffsetofSin6Port(JNIEnv* env, jclass clazz) {
    return offsetof(struct sockaddr_in6, sin6_port);
}

static jint netty_io_uring_sockaddrIn6OffsetofSin6Flowinfo(JNIEnv* env, jclass clazz) {
    return offsetof(struct sockaddr_in6, sin6_flowinfo);
}

static jint netty_io_uring_sockaddrIn6OffsetofSin6Addr(JNIEnv* env, jclass clazz) {
    return offsetof(struct sockaddr_in6, sin6_addr);
}

static jint netty_io_uring_sockaddrIn6OffsetofSin6ScopeId(JNIEnv* env, jclass clazz) {
    return offsetof(struct sockaddr_in6, sin6_scope_id);
}

static jint netty_io_uring_in6AddressOffsetofS6Addr(JNIEnv* env, jclass clazz) {
    return offsetof(struct in6_addr, s6_addr);
}

static jint netty_io_uring_sizeofSockaddrStorage(JNIEnv* env, jclass clazz) {
    return sizeof(struct sockaddr_storage);
}

static jint netty_io_uring_sizeofSizeT(JNIEnv* env, jclass clazz) {
    return sizeof(size_t);
}

static jint netty_io_uring_sizeofIovec(JNIEnv* env, jclass clazz) {
    return sizeof(struct iovec);
}

static jint netty_io_uring_iovecOffsetofIovBase(JNIEnv* env, jclass clazz) {
    return offsetof(struct iovec, iov_base);
}

static jint netty_io_uring_iovecOffsetofIovLen(JNIEnv* env, jclass clazz) {
    return offsetof(struct iovec, iov_len);
}

static jint netty_io_uring_sizeofMsghdr(JNIEnv* env, jclass clazz) {
    return sizeof(struct msghdr);
}

static jint netty_io_uring_msghdrOffsetofMsgName(JNIEnv* env, jclass clazz) {
    return offsetof(struct msghdr, msg_name);
}

static jint netty_io_uring_msghdrOffsetofMsgNamelen(JNIEnv* env, jclass clazz) {
    return offsetof(struct msghdr, msg_namelen);
}
static jint netty_io_uring_msghdrOffsetofMsgIov(JNIEnv* env, jclass clazz) {
    return offsetof(struct msghdr, msg_iov);
}
static jint netty_io_uring_msghdrOffsetofMsgIovlen(JNIEnv* env, jclass clazz) {
    return offsetof(struct msghdr, msg_iovlen);
}

static jint netty_io_uring_msghdrOffsetofMsgControl(JNIEnv* env, jclass clazz) {
    return offsetof(struct msghdr, msg_control);
}

static jint netty_io_uring_msghdrOffsetofMsgControllen(JNIEnv* env, jclass clazz) {
    return offsetof(struct msghdr, msg_controllen);
}

static jint netty_io_uring_msghdrOffsetofMsgFlags(JNIEnv* env, jclass clazz) {
    return offsetof(struct msghdr, msg_flags);
}

static jint netty_io_uring_cmsghdrOffsetofCmsgLen(JNIEnv* env, jclass clazz) {
    return offsetof(struct cmsghdr, cmsg_len);
}

static jint netty_io_uring_cmsghdrOffsetofCmsgLevel(JNIEnv* env, jclass clazz) {
    return offsetof(struct cmsghdr, cmsg_level);
}

static jint netty_io_uring_cmsghdrOffsetofCmsgType(JNIEnv* env, jclass clazz) {
    return offsetof(struct cmsghdr, cmsg_type);
}

static jlong netty_io_uring_cmsghdrData(JNIEnv* env, jclass clazz, jlong cmsghdrAddr) {
    return (jlong) CMSG_DATA((struct cmsghdr*) cmsghdrAddr);
}

static jint netty_io_uring_etime(JNIEnv* env, jclass clazz) {
    return ETIME;
}

static jint netty_io_uring_ecanceled(JNIEnv* env, jclass clazz) {
    return ECANCELED;
}

static jint netty_io_uring_pollin(JNIEnv* env, jclass clazz) {
    return POLLIN;
}

static jint netty_io_uring_pollout(JNIEnv* env, jclass clazz) {
    return POLLOUT;
}

static jint netty_io_uring_pollrdhup(JNIEnv* env, jclass clazz) {
    return POLLRDHUP;
}

static jbyte netty_io_uring_ioringOpWritev(JNIEnv* env, jclass clazz) {
    return IORING_OP_WRITEV;
}

static jbyte netty_io_uring_ioringOpPollAdd(JNIEnv* env, jclass clazz) {
    return IORING_OP_POLL_ADD;
}

static jbyte netty_io_uring_ioringOpPollRemove(JNIEnv* env, jclass clazz) {
    return IORING_OP_POLL_REMOVE;
}

static jbyte netty_io_uring_ioringOpTimeout(JNIEnv* env, jclass clazz) {
    return IORING_OP_TIMEOUT;
}

static jbyte netty_io_uring_ioringOpAccept(JNIEnv* env, jclass clazz) {
    return IORING_OP_ACCEPT;
}

static jbyte netty_io_uring_ioringOpRead(JNIEnv* env, jclass clazz) {
    return IORING_OP_READ;
}

static jbyte netty_io_uring_ioringOpWrite(JNIEnv* env, jclass clazz) {
    return IORING_OP_WRITE;
}

static jbyte netty_io_uring_ioringOpRecv(JNIEnv* env, jclass clazz) {
    return IORING_OP_RECV;
}

static jbyte netty_io_uring_ioringOpSend(JNIEnv* env, jclass clazz) {
    return IORING_OP_SEND;
}

static jbyte netty_io_uring_ioringOpConnect(JNIEnv* env, jclass clazz) {
    return IORING_OP_CONNECT;
}

static jbyte netty_io_uring_ioringOpClose(JNIEnv* env, jclass clazz) {
    return IORING_OP_CLOSE;
}

static jbyte netty_io_uring_ioringOpSendmsg(JNIEnv* env, jclass clazz) {
    return IORING_OP_SENDMSG;
}

static jbyte netty_io_uring_ioringOpRecvmsg(JNIEnv* env, jclass clazz) {
    return IORING_OP_RECVMSG;
}

static jint netty_io_uring_ioringEnterGetevents(JNIEnv* env, jclass clazz) {
    return IORING_ENTER_GETEVENTS;
}

static jint netty_io_uring_iosqeAsync(JNIEnv* env, jclass clazz) {
    return IOSQE_ASYNC;
}

static jint netty_io_uring_msgDontwait(JNIEnv* env, jclass clazz) {
    return MSG_DONTWAIT;
}

static jint netty_io_uring_msgFastopen(JNIEnv* env, jclass clazz) {
    return MSG_FASTOPEN;
}

static jint netty_io_uring_cmsgSpace(JNIEnv* env, jclass clazz) {
    return CMSG_SPACE(sizeof(uint16_t));
}

static jint netty_io_uring_cmsgLen(JNIEnv* env, jclass clazz) {
    return CMSG_LEN(sizeof(uint16_t));
}

static jint netty_io_uring_solUdp(JNIEnv* env, jclass clazz) {
    return SOL_UDP;
}

static jint netty_io_uring_udpSegment(JNIEnv* env, jclass clazz) {
    return UDP_SEGMENT;
}

// JNI Method Registration Table Begin
static const JNINativeMethod statically_referenced_fixed_method_table[] = {
  { "sockNonblock", "()I", (void *) netty_io_uring_sockNonblock },
  { "sockCloexec", "()I", (void *) netty_io_uring_sockCloexec },
  { "afInet", "()I", (void *) netty_io_uring_afInet },
  { "afInet6", "()I", (void *) netty_io_uring_afInet6 },
  { "sizeofSockaddrIn", "()I", (void *) netty_io_uring_sizeofSockaddrIn },
  { "sizeofSockaddrIn6", "()I", (void *) netty_io_uring_sizeofSockaddrIn6 },
  { "sockaddrInOffsetofSinFamily", "()I", (void *) netty_io_uring_sockaddrInOffsetofSinFamily },
  { "sockaddrInOffsetofSinPort", "()I", (void *) netty_io_uring_sockaddrInOffsetofSinPort },
  { "sockaddrInOffsetofSinAddr", "()I", (void *) netty_io_uring_sockaddrInOffsetofSinAddr },
  { "inAddressOffsetofSAddr", "()I", (void *) netty_io_uring_inAddressOffsetofSAddr },
  { "sockaddrIn6OffsetofSin6Family", "()I", (void *) netty_io_uring_sockaddrIn6OffsetofSin6Family },
  { "sockaddrIn6OffsetofSin6Port", "()I", (void *) netty_io_uring_sockaddrIn6OffsetofSin6Port },
  { "sockaddrIn6OffsetofSin6Flowinfo", "()I", (void *) netty_io_uring_sockaddrIn6OffsetofSin6Flowinfo },
  { "sockaddrIn6OffsetofSin6Addr", "()I", (void *) netty_io_uring_sockaddrIn6OffsetofSin6Addr },
  { "sockaddrIn6OffsetofSin6ScopeId", "()I", (void *) netty_io_uring_sockaddrIn6OffsetofSin6ScopeId },
  { "in6AddressOffsetofS6Addr", "()I", (void *) netty_io_uring_in6AddressOffsetofS6Addr },
  { "sizeofSockaddrStorage", "()I", (void *) netty_io_uring_sizeofSockaddrStorage },
  { "sizeofSizeT", "()I", (void *) netty_io_uring_sizeofSizeT },
  { "sizeofIovec", "()I", (void *) netty_io_uring_sizeofIovec },
  { "cmsgSpace", "()I", (void *) netty_io_uring_cmsgSpace},
  { "cmsgLen", "()I", (void *) netty_io_uring_cmsgLen},
  { "iovecOffsetofIovBase", "()I", (void *) netty_io_uring_iovecOffsetofIovBase },
  { "iovecOffsetofIovLen", "()I", (void *) netty_io_uring_iovecOffsetofIovLen },
  { "sizeofMsghdr", "()I", (void *) netty_io_uring_sizeofMsghdr },
  { "msghdrOffsetofMsgName", "()I", (void *) netty_io_uring_msghdrOffsetofMsgName },
  { "msghdrOffsetofMsgNamelen", "()I", (void *) netty_io_uring_msghdrOffsetofMsgNamelen },
  { "msghdrOffsetofMsgIov", "()I", (void *) netty_io_uring_msghdrOffsetofMsgIov },
  { "msghdrOffsetofMsgIovlen", "()I", (void *) netty_io_uring_msghdrOffsetofMsgIovlen },
  { "msghdrOffsetofMsgControl", "()I", (void *) netty_io_uring_msghdrOffsetofMsgControl },
  { "msghdrOffsetofMsgControllen", "()I", (void *) netty_io_uring_msghdrOffsetofMsgControllen },
  { "msghdrOffsetofMsgFlags", "()I", (void *) netty_io_uring_msghdrOffsetofMsgFlags },
  { "etime", "()I", (void *) netty_io_uring_etime },
  { "ecanceled", "()I", (void *) netty_io_uring_ecanceled },
  { "pollin", "()I", (void *) netty_io_uring_pollin },
  { "pollout", "()I", (void *) netty_io_uring_pollout },
  { "pollrdhup", "()I", (void *) netty_io_uring_pollrdhup },
  { "ioringOpWritev", "()B", (void *) netty_io_uring_ioringOpWritev },
  { "ioringOpPollAdd", "()B", (void *) netty_io_uring_ioringOpPollAdd },
  { "ioringOpPollRemove", "()B", (void *) netty_io_uring_ioringOpPollRemove },
  { "ioringOpTimeout", "()B", (void *) netty_io_uring_ioringOpTimeout },
  { "ioringOpAccept", "()B", (void *) netty_io_uring_ioringOpAccept },
  { "ioringOpRead", "()B", (void *) netty_io_uring_ioringOpRead },
  { "ioringOpWrite", "()B", (void *) netty_io_uring_ioringOpWrite },
  { "ioringOpRecv", "()B", (void *) netty_io_uring_ioringOpRecv },
  { "ioringOpSend", "()B", (void *) netty_io_uring_ioringOpSend },
  { "ioringOpConnect", "()B", (void *) netty_io_uring_ioringOpConnect },
  { "ioringOpClose", "()B", (void *) netty_io_uring_ioringOpClose },
  { "ioringOpSendmsg", "()B", (void *) netty_io_uring_ioringOpSendmsg },
  { "ioringOpRecvmsg", "()B", (void *) netty_io_uring_ioringOpRecvmsg },
  { "ioringEnterGetevents", "()I", (void *) netty_io_uring_ioringEnterGetevents },
  { "iosqeAsync", "()I", (void *) netty_io_uring_iosqeAsync },
  { "msgDontwait", "()I", (void *) netty_io_uring_msgDontwait },
  { "msgFastopen", "()I", (void *) netty_io_uring_msgFastopen },
  { "solUdp", "()I", (void *) netty_io_uring_solUdp },
  { "udpSegment", "()I", (void *) netty_io_uring_udpSegment },
  { "cmsghdrOffsetofCmsgLen", "()I", (void *) netty_io_uring_cmsghdrOffsetofCmsgLen },
  { "cmsghdrOffsetofCmsgLevel", "()I", (void *) netty_io_uring_cmsghdrOffsetofCmsgLevel },
  { "cmsghdrOffsetofCmsgType", "()I", (void *) netty_io_uring_cmsghdrOffsetofCmsgType },
};
static const jint statically_referenced_fixed_method_table_size = sizeof(statically_referenced_fixed_method_table) / sizeof(statically_referenced_fixed_method_table[0]);

static const JNINativeMethod method_table[] = {
    {"ioUringSetup", "(I)[[J", (void *) netty_io_uring_setup},
    {"ioUringProbe", "(I[I)Z", (void *) netty_io_uring_probe},
    {"ioUringExit", "(JIJIJII)V", (void *) netty_io_uring_ring_buffer_exit},
    {"createFile", "(Ljava/lang/String;)I", (void *) netty_create_file},
    {"ioUringEnter", "(IIII)I", (void *) netty_io_uring_enter},
    {"blockingEventFd", "()I", (void *) netty_epoll_native_blocking_event_fd},
    {"eventFdWrite", "(IJ)V", (void *) netty_io_uring_eventFdWrite },
    {"registerUnix", "()I", (void *) netty_io_uring_registerUnix },
    {"cmsghdrData", "(J)J", (void *) netty_io_uring_cmsghdrData},
    {"kernelVersion", "()Ljava/lang/String;", (void *) netty_io_uring_kernel_version },
};
static const jint method_table_size =
    sizeof(method_table) / sizeof(method_table[0]);
// JNI Method Registration Table End

static jint netty_iouring_native_JNI_OnLoad(JNIEnv* env, const char* packagePrefix) {
    int ret = JNI_ERR;
    int nativeRegistered = 0;
    int staticallyRegistered = 0;
    int linuxsocketOnLoadCalled = 0;

    // We must register the statically referenced methods first!
    if (netty_jni_util_register_natives(env,
            packagePrefix,
            STATICALLY_CLASSNAME,
            statically_referenced_fixed_method_table,
            statically_referenced_fixed_method_table_size) != 0) {
        goto done;
    }
    nativeRegistered = 1;

    if (netty_jni_util_register_natives(env, packagePrefix,
                                       NATIVE_CLASSNAME,
                                       method_table, method_table_size) != 0) {
        goto done;
    }
    staticallyRegistered = 1;

    if (netty_io_uring_linuxsocket_JNI_OnLoad(env, packagePrefix) == JNI_ERR) {
        goto done;
    }
    linuxsocketOnLoadCalled = 1;

    NETTY_JNI_UTIL_LOAD_CLASS(env, longArrayClass, "[J", done);

    if (packagePrefix != NULL) {
        staticPackagePrefix = strdup(packagePrefix);
    }
    ret = NETTY_JNI_UTIL_JNI_VERSION;
done:
    if (ret == JNI_ERR) {
        if (nativeRegistered == 1) {
            netty_jni_util_unregister_natives(env, packagePrefix, NATIVE_CLASSNAME);
        }
        if (staticallyRegistered == 1) {
            netty_jni_util_unregister_natives(env, packagePrefix, STATICALLY_CLASSNAME);
        }
        if (linuxsocketOnLoadCalled == 1) {
            netty_io_uring_linuxsocket_JNI_OnUnLoad(env, packagePrefix);
        }
    }
    return ret;
}

static void netty_iouring_native_JNI_OnUnload(JNIEnv* env) {
    netty_jni_util_unregister_natives(env, staticPackagePrefix, NATIVE_CLASSNAME);
    netty_jni_util_unregister_natives(env, staticPackagePrefix, STATICALLY_CLASSNAME);
    netty_io_uring_native_JNI_OnUnLoad(env, staticPackagePrefix);

    if (register_unix_called == 1) {
        register_unix_called = 0;
        netty_unix_unregister(env, staticPackagePrefix);
    }
    if (staticPackagePrefix != NULL) {
        free((void *) staticPackagePrefix);
        staticPackagePrefix = NULL;
    }
}

// Invoked by the JVM when statically linked
JNIEXPORT jint JNI_OnLoad_netty_transport_native_io_uring(JavaVM* vm, void* reserved) {
    jint ret = netty_jni_util_JNI_OnLoad(vm, reserved, LIBRARYNAME, netty_iouring_native_JNI_OnLoad);
    return ret;
}

// Invoked by the JVM when statically linked
JNIEXPORT void JNI_OnUnload_netty_transport_native_io_uring(JavaVM* vm, void* reserved) {
    netty_jni_util_JNI_OnUnload(vm, reserved, netty_iouring_native_JNI_OnUnload);
}

#ifndef NETTY_IO_URING_BUILD_STATIC
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
    return netty_jni_util_JNI_OnLoad(vm, reserved, LIBRARYNAME, netty_iouring_native_JNI_OnLoad);
}

JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved) {
    netty_jni_util_JNI_OnUnload(vm, reserved, netty_iouring_native_JNI_OnUnload);
}
#endif /* NETTY_IO_URING_BUILD_STATIC */





© 2015 - 2024 Weber Informatics LLC | Privacy Policy