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 package optkl.ifacemapper;
 26 
 27 
 28 
 29 import java.lang.foreign.GroupLayout;
 30 import java.lang.foreign.MemoryLayout;
 31 import java.lang.foreign.MemorySegment;
 32 import java.lang.foreign.ValueLayout;
 33 import java.lang.invoke.VarHandle;
 34 import java.util.Objects;
 35 
 36 
 37 
 38     /*
 39 
 40 
 41      See backend_ffi_shared/include/shared.h
 42 
 43      Make sure the final static values below match the #defines
 44       // iface buffer bitz
 45       // iface bffa   bitz
 46       // 4a7 1face bffa   b175
 47 
 48 
 49 
 50     struct state{
 51        long magic1; // MAGIC
 52        int bits;
 53        int mode;
 54        void * vendorPtr; // In OpenCL this points to native OpenCL::Buffer
 55        long magic2; // MAGIC
 56     }
 57      */
 58 
 59 public record BufferState(MemorySegment segment, long paddedSize) {
 60     public static final long alignment = ValueLayout.JAVA_LONG.byteSize();
 61     // hat iface buffer bitz
 62     // hat iface bffa   bitz
 63     // 4a7 1face bffa   b175
 64     public static final long MAGIC = 0x4a71facebffab175L;
 65 
 66     public static final int NO_STATE = 0;
 67     public static final int NEW_STATE = 1;
 68     public static final int HOST_OWNED = 2;
 69     public static final int DEVICE_OWNED = 3;
 70     public static final int DEVICE_VALID_HOST_HAS_COPY = 4;
 71     public static String[] stateNames = new String[]{
 72             "NO_STATE",
 73             "NEW_STATE",
 74             "HOST_OWNED",
 75             "DEVICE_OWNED",
 76             "DEVICE_VALID_HOST_HAS_COPY"
 77     };
 78     static final MemoryLayout stateMemoryLayout = MemoryLayout.structLayout(
 79             ValueLayout.JAVA_LONG.withName("magic1"),
 80             ValueLayout.ADDRESS.withName("ptr"),
 81             ValueLayout.JAVA_LONG.withName("length"),
 82             ValueLayout.JAVA_INT.withName("bits"),
 83             ValueLayout.JAVA_INT.withName("state"),
 84             ValueLayout.ADDRESS.withName("vendorPtr"),
 85             ValueLayout.JAVA_LONG.withName("magic2")
 86     ).withName("state");
 87 
 88     static long byteSize() {
 89         return stateMemoryLayout.byteSize();
 90     }
 91 
 92     static final VarHandle magic1 = stateMemoryLayout.varHandle(
 93             MemoryLayout.PathElement.groupElement("magic1")
 94     );
 95     static final VarHandle ptr = stateMemoryLayout.varHandle(
 96             MemoryLayout.PathElement.groupElement("ptr")
 97     );
 98     static final VarHandle length = stateMemoryLayout.varHandle(
 99             MemoryLayout.PathElement.groupElement("length")
100     );
101 
102     static final VarHandle state = stateMemoryLayout.varHandle(
103             MemoryLayout.PathElement.groupElement("state")
104     );
105 
106     static final VarHandle magic2 = stateMemoryLayout.varHandle(
107             MemoryLayout.PathElement.groupElement("magic2")
108     );
109 
110     static final VarHandle vendorPtr = stateMemoryLayout.varHandle(
111             MemoryLayout.PathElement.groupElement("vendorPtr")
112     );
113 
114     public static long getLayoutSizeAfterPadding(GroupLayout layout) {
115         return layout.byteSize() +
116                 ((layout.byteSize() % BufferState.alignment) == 0 ? 0 : BufferState.alignment - (layout.byteSize() % BufferState.alignment));
117     }
118 
119     public static <T> BufferState of(T t) {
120         MappableIface buffer = (MappableIface) Objects.requireNonNull(t);
121         MemorySegment s = MappableIface.getMemorySegment(buffer);
122         return new BufferState(s, s.byteSize() - BufferState.byteSize());
123     }
124     public BufferState setState(int newState) {
125         BufferState.state.set(segment, paddedSize, newState);
126         return this;
127     }
128     public BufferState setPtr(MemorySegment  ptr) {
129         BufferState.ptr.set(segment, paddedSize, ptr);
130         return this;
131     }
132 
133     BufferState setLength(long newLength) {
134         BufferState.length.set(segment, paddedSize, newLength);
135         return this;
136     }
137     BufferState setMagic() {
138         BufferState.magic1.set(segment, paddedSize, MAGIC);
139         BufferState.magic2.set(segment, paddedSize, MAGIC);
140         return this;
141     }
142 
143 
144     public int getState() {
145         return (Integer)BufferState.state.get(segment, paddedSize);
146     }
147     public String getStateString(){
148         return stateNames[getState()];
149     }
150     public MemorySegment getVendorPtr() {
151         return (MemorySegment) BufferState.vendorPtr.get(segment, paddedSize);
152     }
153     public void setVendorPtr(MemorySegment vendorPtr) {
154         BufferState.vendorPtr.set(segment, paddedSize, vendorPtr);
155     }
156 
157     public long magic1() {
158         return (Long) BufferState.magic1.get(segment, paddedSize);
159     }
160 
161     public long magic2() {
162         return (Long) BufferState.magic2.get(segment, paddedSize);
163     }
164 
165     public boolean ok() {
166         return MAGIC == magic1() && MAGIC == magic2();
167     }
168 
169 
170     @Override
171     public String toString() {
172         StringBuilder builder = new StringBuilder();
173         if (ok()) {
174             builder.append("State:ok").append("\n");
175             var vendorPtr = getVendorPtr();
176             builder.append(",").append("VENDOR_PTR:").append(Long.toHexString(vendorPtr.address()));
177             builder.append("\n");
178         } else {
179             builder.append("State: not ok").append("\n");
180         }
181         return builder.toString();
182     }
183 
184 }