/** * Copyright 2013, Landz and its contributors. All rights reserved. * * Licensed 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 * * http://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. */ package z.znr; import z.evil.Intrinsics; import z.znr.invoke.linux.x64.NativeLibrary; import java.lang.invoke.MethodHandle; import static jnr.x86asm.Asm.*; import static z.znr.MethodHandles.asm; import static z.util.Unsafes.*; import static z.util.Throwables.*; import static z.offheap.zmalloc.Allocator.*; /** * Functions from LibC */ public class LibC { static { NativeLibrary.loadLibrary("c"); Intrinsics.warmup();//TODO:? } //getpid private static final MethodHandle mh_getpid = asm(int.class, a -> a.jmp(imm(NativeLibrary.findSymbolAddress("getpid"))) ); public static int getpid() { try { return (int) mh_getpid.invokeExact(); } catch (Throwable t) { throw new RuntimeException(t); } } //gettimeofday private static final MethodHandle mh_gettimeofday = asm( int.class, long.class, // param regs are %rdi, %rsi, %rdx, %rcx, %r8 and %r9 a -> { a.mov(rdi, rdx); a.jmp(imm(NativeLibrary.findSymbolAddress("gettimeofday"))); } ); public static int gettimeofday(Timeval timeval) { try { long addrBuffer = timeval.addrBuffer(); int rt = (int)mh_gettimeofday.invokeExact(addrBuffer); UNSAFE.putLong(timeval,Timeval.offset_tv_sec, UNSAFE.getLong(addrBuffer)); UNSAFE.putLong(timeval,Timeval.offset_tv_usec, UNSAFE.getLong(addrBuffer+8)); return rt; } catch (Throwable t) { // t.printStackTrace(); return -1; } } //TODO: use landz.buffer in the future? public static final class Timeval { long tv_sec, tv_usec; private final long buffer; public Timeval() { buffer = allocate(16); } public long addrBuffer() { return buffer; } static final long offset_tv_sec; static final long offset_tv_usec; static { offset_tv_sec = uncheckTo(()-> UNSAFE.objectFieldOffset (Timeval.class.getDeclaredField("tv_sec")) ); offset_tv_usec = uncheckTo(()-> UNSAFE.objectFieldOffset (Timeval.class.getDeclaredField("tv_usec")) ); } @Override public void finalize() { if (buffer!=0L) free(buffer); // System.out.println("buffer freed!"); } } //sched_getaffinity private static final MethodHandle mh_sched_getaffinity = asm( int.class, int.class, long.class, long.class, a -> {// param regs are %rdi, %rsi, %rdx, %rcx, %r8 and %r9 a.mov(rdi, rdx);//pid a.mov(rsi, rcx);//cpusetsize a.mov(rdx, r8);//*mask a.jmp(imm(NativeLibrary.findSymbolAddress("sched_getaffinity"))); } ); public static int getAffinity(int pid, Cpuset mask) { try { return (int)mh_sched_getaffinity.invokeExact( pid, Cpuset.SIZE_CPUSET_TYPE, mask.addrBuffer()); } catch (Throwable t) { // t.printStackTrace(); return -1; } } //sched_setaffinity /** * fixme: tested via {@link Affinity#bindTo} */ private static final MethodHandle mh_sched_setaffinity = asm( int.class, int.class, long.class, long.class, a -> {// param regs are %rdi, %rsi, %rdx, %rcx, %r8 and %r9 a.mov(rdi, rdx);//pid a.mov(rsi, rcx);//cpusetsize a.mov(rdx, r8);//*mask a.jmp(imm(NativeLibrary.findSymbolAddress("sched_setaffinity"))); } ); public static int setAffinity(int pid, Cpuset mask) { try { return (int)mh_sched_setaffinity.invokeExact( pid, Cpuset.SIZE_CPUSET_TYPE, mask.addrBuffer()); } catch (Throwable t) { // t.printStackTrace(); return -1; } } /** * now only support machine <= 64 cpus. * see more {@link Affinity.Topology} */ public static final class Cpuset { public static final long SIZE_CPUSET_TYPE = 8; private final long buffer; public Cpuset(long mask) { buffer = allocate(SIZE_CPUSET_TYPE); UNSAFE.putLong(buffer,mask); } public Cpuset() { buffer = allocate(SIZE_CPUSET_TYPE); UNSAFE.putLong(buffer,0L); } public long getMask() { return UNSAFE.getLong(buffer); } public long addrBuffer() { return buffer; } @Override public void finalize() { if (buffer!=0L) free(buffer); } } }