1 /*
  2  * Copyright (c) 2024, 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 
 26 package sun.nio.ch.iouring;
 27 
 28 import java.lang.foreign.*;
 29 import java.lang.invoke.MethodHandle;
 30 import java.nio.ByteBuffer;
 31 import java.nio.charset.StandardCharsets;
 32 import java.util.LinkedList;
 33 import java.util.NoSuchElementException;
 34 import java.util.List;
 35 
 36 import static java.lang.foreign.ValueLayout.JAVA_BYTE;
 37 import static jdk.internal.ffi.generated.iouring.iouring_h.*;
 38 
 39 @SuppressWarnings("restricted")
 40 class Util {
 41 
 42     public static void print(MemorySegment segment, String title) {
 43         print(segment, title, 32);
 44     }
 45 
 46     /**
 47      * Prints to System.out contents of MemorySegment
 48      *
 49      * @param segment
 50      * @param title
 51      * @param wrap Number of bytes to wrap line at
 52      */
 53     public static void print(MemorySegment segment, String title, int wrap) {
 54         long size = segment.byteSize();
 55         long startAddress = segment.address();
 56         System.out.printf("%s, Size: %d bytes, Wrap: %d", title, size, wrap);
 57         for (long offset=0L; offset<size; offset++) {
 58             int b = segment.get(ValueLayout.JAVA_BYTE, offset) & 0xff;
 59             long address = startAddress + offset;
 60             if (offset % wrap == 0) {
 61                 System.out.println("");
 62                 System.out.printf("%08X ", address);
 63             }
 64             System.out.printf("%02X", b);
 65             if (offset % 4 == 3)
 66                 System.out.print(" ");
 67         }
 68         System.out.println("");
 69     }
 70 
 71     public static String sqe_opcode(int code) {
 72         if (code == IORING_OP_ACCEPT())
 73             return "IORING_OP_ACCEPT";
 74         else if (code == IORING_OP_CLOSE())
 75             return "IORING_OP_CLOSE";
 76         else if (code == IORING_OP_SOCKET())
 77             return "IORING_OP_SOCKET";
 78         else if (code == IORING_OP_CONNECT())
 79             return "IORING_OP_CONNECT";
 80         else if (code == IORING_OP_WRITE())
 81             return "IORING_OP_WRITE";
 82         else if (code == IORING_OP_OPENAT())
 83             return "IORING_OP_OPENAT";
 84         else if (code == IORING_OP_READ_FIXED())
 85             return "IORING_OP_READ_FIXED";
 86         else if (code == IORING_OP_WRITE_FIXED())
 87             return "IORING_OP_WRITE_FIXED";
 88         else if (code == IORING_OP_POLL_ADD())
 89             return "IORING_OP_POLL_ADD";
 90         else if (code == IORING_OP_POLL_REMOVE())
 91             return "IORING_OP_POLL_REMOVE";
 92         else if (code == IORING_OP_TIMEOUT())
 93             return "IORING_OP_TIMEOUT";
 94         else if (code == IORING_OP_READ())
 95             return "IORING_OP_READ";
 96         else if (code == IORING_OP_LINK_TIMEOUT())
 97             return "IORING_OP_LINK_TIMEOUT";
 98         else if (code == IORING_OP_NOP())
 99             return "IORING_OP_NOP";
100         else if (code == IORING_OP_MSG_RING())
101             return "IORING_OP_MSG_RING";
102         else return String.format("UNKNOWN(%d)", code);
103     }
104 
105     static MethodHandle locateStdHandle(String name,
106                                         FunctionDescriptor descriptor,
107                                         Linker.Option... options) {
108         try {
109             Linker linker = Linker.nativeLinker();
110             SymbolLookup stdlib = linker.defaultLookup();
111             return linker.downcallHandle(
112                     stdlib.find(name).orElseThrow(),
113                     descriptor,
114                     options
115             );
116         } catch (NoSuchElementException e) {
117             String msg = String.format("Error loading %s from standard lib",
118                 name);
119             throw new RuntimeException(msg);
120         }
121     }
122 
123     static MethodHandle locateHandleFromLib(String libname,
124                                             String symbol,
125                                             FunctionDescriptor descriptor,
126                                             Linker.Option... options) {
127         try {
128             Linker linker = Linker.nativeLinker();
129             SymbolLookup lib = SymbolLookup.libraryLookup(
130                 libname, Arena.global());
131             MethodHandle fn = linker.downcallHandle(
132                 lib.find(symbol).orElseThrow(),
133                 descriptor,
134                 options
135             );
136             return fn;
137         } catch (NoSuchElementException e) {
138             String msg = String.format("Error loading %s from %s",
139                 symbol, libname);
140             throw new RuntimeException(msg);
141         }
142     }
143 
144     public final static ValueLayout INT_POINTER =
145         ValueLayout.ADDRESS.withTargetLayout(
146             ValueLayout.JAVA_INT
147     );
148 
149     private final static ValueLayout POINTER =
150         ValueLayout.ADDRESS.withTargetLayout(
151             MemoryLayout.sequenceLayout(Long.MAX_VALUE, JAVA_BYTE)
152     );
153 
154     private static final MethodHandle strerror_fn = locateStdHandle(
155             "strerror",
156             FunctionDescriptor.of(
157                     POINTER,
158                     ValueLayout.JAVA_INT
159             )
160     );
161     public static String strerror(int errno) {
162         try {
163             MemorySegment result = (MemorySegment) strerror_fn.invokeExact(errno);
164             return result.getString(0, StandardCharsets.UTF_8);
165         } catch (Throwable t) {
166             return "Error: " + errno;
167         }
168     }
169 
170 }