[openrtm-commit:02675] r964 - in trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src: RTMExamples_scripts jp/go/aist/rtm/RTC jp/go/aist/rtm/RTC/executionContext jp/go/aist/rtm/RTC/util

openrtm @ openrtm.org openrtm @ openrtm.org
2017年 7月 13日 (木) 10:57:06 JST


Author: t-katami
Date: 2017-07-13 10:57:06 +0900 (Thu, 13 Jul 2017)
New Revision: 964

Added:
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/CPUAffinityLinux.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/CPUAffinityWindows.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/ICPUAffinity.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/util/Kernel32.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/util/Libc.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/util/cpu_set_t.java
Modified:
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/RTMExamples_scripts/search_classpath.func
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/Manager.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/RTObject_impl.java
   trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/executionContext/PeriodicExecutionContext.java
Log:
[incompat,->RELENG_1_2] CPU affinity setting has been added. refs #3713

Modified: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/RTMExamples_scripts/search_classpath.func
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/RTMExamples_scripts/search_classpath.func	2017-07-11 08:31:38 UTC (rev 963)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/RTMExamples_scripts/search_classpath.func	2017-07-13 01:57:06 UTC (rev 964)
@@ -1,7 +1,9 @@
 get_classpath()
 {
   FILE1=`ls ${RTM_JAVA_ROOT}/jar/OpenRTM*`
-  FILE2=`ls ${RTM_JAVA_ROOT}/jar/commons-cli*`
-  CLASSPATH=.:$FILE1:$FILE2
+  FILE2=`ls ${RTM_JAVA_ROOT}/lib/commons-cli*`
+  FILE3=`ls ${RTM_JAVA_ROOT}/lib/jna-?.?.?.jar`
+  FILE4=`ls ${RTM_JAVA_ROOT}/lib/jna-platform-*.jar`
+  CLASSPATH=.:$FILE1:$FILE2:$FILE3:$FILE4:${RTM_JAVA_ROOT}/bin
   echo ${CLASSPATH}
 }

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/CPUAffinityLinux.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/CPUAffinityLinux.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/CPUAffinityLinux.java	2017-07-13 01:57:06 UTC (rev 964)
@@ -0,0 +1,127 @@
+package jp.go.aist.rtm.RTC;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+
+import com.sun.jna.Platform;
+
+import jp.go.aist.rtm.RTC.util.cpu_set_t;
+import jp.go.aist.rtm.RTC.util.Libc;
+import jp.go.aist.rtm.RTC.log.Logbuf;
+
+
+  /**
+   * {@.ja CPU affinity Class For Linux }
+   * {@.en CPU affinity Class For Linux }
+   *
+   */
+public class CPUAffinityLinux implements ICPUAffinity {
+
+    /**
+     * {@.ja コンストラクタ}
+     * {@.en Constructor}
+     *
+     *
+     */
+    public CPUAffinityLinux(){
+        rtcout = new Logbuf("CPUAffinityLinux");
+    }
+    
+    /**
+     * {@.ja プロセスのCPUアフィニティを設定}
+     * {@.en Setting the CPU affinity of a process}
+     * 
+     * <p>
+     * @param cpu_set
+     *   {@.ja CPU番号のリスト(ビット表現)}
+     *   {@.en The list in which the number of the CPU is stocked}
+     * 
+     * @return 
+     *   {@.ja 結果(成功:true,失敗:false)}
+     *   {@.en Setup result (Successful:true, Failed:false)}
+     */
+    @Override
+    public boolean setProcessAffinity(BitSet cpu_set){
+        rtcout.println(Logbuf.DEBUG, "setProcessAffinity");
+        rtcout.println(Logbuf.DEBUG, "cpu_set:" + cpu_set.isEmpty());
+        final Libc lib = Libc.INSTANCE;
+        final int pid = lib.getpid();
+        rtcout.println(Logbuf.DEBUG, "pid:" + pid);
+        final cpu_set_t cpuset = new cpu_set_t();
+        final int size = cpu_set_t.SIZE_OF_CPU_SET_T;
+        rtcout.println(Logbuf.DEBUG, "size:" + size);
+        final long[] bits = cpu_set.toLongArray();
+        for (int i = 0; i < bits.length; i++) {
+            rtcout.println(Logbuf.DEBUG, "bit[" + i + "]:"+bits[i]);
+            rtcout.println(Logbuf.DEBUG, "Platform64:"+Platform.is64Bit());
+            if (Platform.is64Bit()) {
+                cpuset.__bits[i].setValue(bits[i]);
+            } else {
+                cpuset.__bits[i * 2].setValue(bits[i] & 0xFFFFFFFFL);
+                cpuset.__bits[i * 2 + 1].setValue((bits[i] >>> 32) & 0xFFFFFFFFL);
+            }
+        }
+
+        if (lib.sched_setaffinity(pid, size, cpuset) != 0) {
+            rtcout.println(Logbuf.DEBUG, "false");
+            return false;
+        }
+        else{
+            rtcout.println(Logbuf.DEBUG, "true");
+            return true;
+        }
+    }
+    /**
+     * {@.ja スレッドのCPUアフィニティを設定}
+     * {@.en Setting the CPU affinity of a process}
+     * 
+     * <p>
+     * @param cpu_set
+     *   {@.ja CPU番号のリスト}
+     *   {@.en The list in which the number of the CPU is stocked}
+     * 
+     * @return 
+     *   {@.ja 結果(成功:true,失敗:false)}
+     *   {@.en Setup result (Successful:true, Failed:false)}
+     */
+    @Override
+    public boolean setThreadAffinity(ArrayList<Integer> cpu_num_list){
+        final int SYS_gettid = Platform.is64Bit() ? 186 : 224;
+
+        BitSet cpu_set = new BitSet();
+        cpu_set.clear();
+
+        for(int ic=0;ic<cpu_num_list.size();++ic){
+            int num = cpu_num_list.get(ic).intValue();
+            cpu_set.set(num);
+        }
+        final Libc lib = Libc.INSTANCE;
+        int tid = lib.syscall(SYS_gettid);
+        rtcout.println(Logbuf.DEBUG, "tid:" + tid);
+
+        final cpu_set_t cpuset = new cpu_set_t();
+        final int size = cpu_set_t.SIZE_OF_CPU_SET_T;
+        final long[] bits = cpu_set.toLongArray();
+        for (int ic = 0; ic < bits.length; ic++) {
+            if (Platform.is64Bit()) {
+                cpuset.__bits[ic].setValue(bits[ic]);
+            } else {
+                cpuset.__bits[ic * 2].setValue(bits[ic] & 0xFFFFFFFFL);
+                cpuset.__bits[ic * 2 + 1].setValue((bits[ic] >>> 32) & 0xFFFFFFFFL);
+            }
+        }
+
+
+        if (lib.sched_setaffinity(tid, size, cpuset) != 0) {
+            return false;
+        }
+        else{
+            return true;
+        }
+    }
+    /**
+     * {@.ja Logging用フォーマットオブジェクト}
+     * {@.en Format object for Logging}
+     */
+    protected Logbuf rtcout;
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/CPUAffinityWindows.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/CPUAffinityWindows.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/CPUAffinityWindows.java	2017-07-13 01:57:06 UTC (rev 964)
@@ -0,0 +1,148 @@
+package jp.go.aist.rtm.RTC;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+
+import com.sun.jna.Platform;
+import com.sun.jna.platform.win32.WinDef;
+import com.sun.jna.ptr.LongByReference;
+
+import jp.go.aist.rtm.RTC.util.cpu_set_t;
+import jp.go.aist.rtm.RTC.util.Kernel32;
+import jp.go.aist.rtm.RTC.log.Logbuf;
+
+  /**
+   * {@.ja CPU affinity Class For Windows }
+   * {@.en CPU affinity Class For Windows }
+   *
+   */
+public class CPUAffinityWindows implements ICPUAffinity {
+
+    /**
+     * {@.ja コンストラクタ}
+     * {@.en Constructor}
+     *
+     *
+     */
+    public CPUAffinityWindows(){
+        rtcout = new Logbuf("CPUAffinityWindows");
+    }
+    
+    /**
+     * {@.ja プロセスのCPUアフィニティを設定}
+     * {@.en Setting the CPU affinity of a process}
+     * 
+     * <p>
+     * @param cpu_set
+     *   {@.ja CPU番号のリスト(ビット表現)}
+     *   {@.en The list in which the number of the CPU is stocked}
+     * 
+     * @return 
+     *   {@.ja 結果(成功:true,失敗:false)}
+     *   {@.en Setup result (Successful:true, Failed:false)}
+     */
+    @Override
+    public boolean setProcessAffinity(BitSet cpu_set){
+        rtcout.println(Logbuf.DEBUG, "setProcessAffinity");
+        rtcout.println(Logbuf.DEBUG, "cpu_set:" + cpu_set.isEmpty());
+        final int pid = Kernel32.INSTANCE.GetCurrentProcess();
+        rtcout.println(Logbuf.DEBUG, "pid:" + pid);
+        //System.out.println("pid:" + Kernel32.INSTANCE.GetCurrentProcessId());
+
+        //PROCESS_QUERY_INFORMATION(0x400) 
+        //PROCESS_SET_INFORMATION(0x200)
+        Kernel32.INSTANCE.OpenProcess(0x0600, false, pid);
+
+        WinDef.DWORD aff;
+        long[] longs = cpu_set.toLongArray();
+        switch (longs.length) {
+            case 0:
+                aff = new WinDef.DWORD(0);
+                break;
+            case 1:
+                aff = new WinDef.DWORD(longs[0]);
+                break;
+            default:
+                aff = new WinDef.DWORD(longs[0]);
+                rtcout.println(Logbuf.DEBUG, "Windows API does not support "
+                               + "more than 64 CPUs for thread affinity");
+        }
+
+        Kernel32.INSTANCE.SetProcessAffinityMask(pid, aff);
+        final LongByReference cpuset1 = new LongByReference(0);
+        final LongByReference cpuset2 = new LongByReference(0);
+        int result = Kernel32.INSTANCE.GetProcessAffinityMask(pid,
+                                    cpuset1,
+                                    cpuset2);
+        long[] longs_temp = new long[1];
+        longs_temp[0] = cpuset1.getValue();
+        if (BitSet.valueOf(longs_temp) != cpu_set) {
+            rtcout.println(Logbuf.DEBUG, "false");
+            return false;
+        }
+        else{
+            rtcout.println(Logbuf.DEBUG, "true");
+            return true;
+        }
+    }
+    /**
+     * {@.ja スレッドのCPUアフィニティを設定}
+     * {@.en Setting the CPU affinity of a process}
+     * 
+     * <p>
+     * @param cpu_set
+     *   {@.ja CPU番号のリスト}
+     *   {@.en The list in which the number of the CPU is stocked}
+     * 
+     * @return 
+     *   {@.ja 結果(成功:true,失敗:false)}
+     *   {@.en Setup result (Successful:true, Failed:false)}
+     */
+    @Override
+    public boolean setThreadAffinity(ArrayList<Integer> cpu_num_list){
+        rtcout.println(Logbuf.DEBUG, "setThreadAffinity");
+
+        BitSet cpu_set = new BitSet();
+        cpu_set.clear();
+
+        for(int ic=0;ic<cpu_num_list.size();++ic){
+            int num = cpu_num_list.get(ic).intValue();
+            cpu_set.set(num);
+        }
+        rtcout.println(Logbuf.DEBUG, "cpu_set:" + cpu_set.isEmpty());
+
+        final int pid = Kernel32.INSTANCE.GetCurrentThread();
+        rtcout.println(Logbuf.DEBUG, "pid:" + pid);
+        //System.out.println("pid:" + Kernel32.INSTANCE.GetCurrentThreadId());
+
+        WinDef.DWORD aff;
+        long[] longs = cpu_set.toLongArray();
+        switch (longs.length) {
+            case 0:
+                aff = new WinDef.DWORD(0);
+                break;
+            case 1:
+                aff = new WinDef.DWORD(longs[0]);
+                break;
+            default:
+                aff = new WinDef.DWORD(longs[0]);
+                rtcout.println(Logbuf.DEBUG, "Windows API does not support "
+                               + "more than 64 CPUs for thread affinity");
+        }
+
+        WinDef.DWORD result = Kernel32.INSTANCE.SetThreadAffinityMask(pid, aff);
+        if (result != aff) {
+            rtcout.println(Logbuf.DEBUG, "false");
+            return false;
+        }
+        else{
+            rtcout.println(Logbuf.DEBUG, "true");
+            return true;
+        }
+    }
+    /**
+     * {@.ja Logging用フォーマットオブジェクト}
+     * {@.en Format object for Logging}
+     */
+    protected Logbuf rtcout;
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/ICPUAffinity.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/ICPUAffinity.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/ICPUAffinity.java	2017-07-13 01:57:06 UTC (rev 964)
@@ -0,0 +1,43 @@
+package jp.go.aist.rtm.RTC;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.lang.Integer;
+
+  /**
+   * {@.ja CPU affinity用インターフェイス}
+   * {@.en Interface for CPU affinity}
+   *
+   *
+   */
+public interface ICPUAffinity {
+    /**
+     * {@.ja プロセスのCPUアフィニティを設定}
+     * {@.en Setting the CPU affinity of a process}
+     * 
+     * <p>
+     * @param cpu_set
+     *   {@.ja CPU番号のリスト(ビット表現)}
+     *   {@.en The list in which the number of the CPU is stocked}
+     * 
+     * @return 
+     *   {@.ja 結果(成功:true,失敗:false)}
+     *   {@.en Setup result (Successful:true, Failed:false)}
+     */
+    public boolean setProcessAffinity(BitSet cpu_set);
+
+    /**
+     * {@.ja スレッドのCPUアフィニティを設定}
+     * {@.en Setting the CPU affinity of a process}
+     * 
+     * <p>
+     * @param cpu_set
+     *   {@.ja CPU番号のリスト}
+     *   {@.en The list in which the number of the CPU is stocked}
+     * 
+     * @return 
+     *   {@.ja 結果(成功:true,失敗:false)}
+     *   {@.en Setup result (Successful:true, Failed:false)}
+     */
+    public boolean setThreadAffinity(ArrayList<Integer> cpu_num_list);
+}

Modified: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/Manager.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/Manager.java	2017-07-11 08:31:38 UTC (rev 963)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/Manager.java	2017-07-13 01:57:06 UTC (rev 964)
@@ -11,6 +11,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.BitSet;
 import java.util.Iterator;
 import java.util.Vector;
 import java.util.logging.FileHandler;
@@ -1873,6 +1874,7 @@
             "exec_cxt.activation_timeout",
             "exec_cxt.deactivation_timeout",
             "exec_cxt.reset_timeout",
+            "exec_cxt.cpu_affinity",
             "logger.enable",
             "logger.log_level",
             "naming.enable",
@@ -3774,9 +3776,47 @@
         PeriodicExecutionContext.PeriodicExecutionContextInit(this);
         ExtTrigExecutionContext.ExtTrigExecutionContextInit(this);
         OpenHRPExecutionContext.OpenHRPExecutionContextInit(this);
-        
+        initCpuAffinity();
         return true;
     }
+    /**
+     * {@.ja スレッドの CPU affinity マスクを設定・取得する}
+     * {@.en et  and get a thread's CPU affinity mask}
+     *
+     */
+    protected void initCpuAffinity() {
+        rtcout.println(Logbuf.TRACE, "initCpuAffinity()");
+        Properties node = m_config.findNode("manager.cpu_affinity");
+        if (node == null) {
+            return;
+        }
+        String affinity_str = m_config.getProperty("manager.cpu_affinity");
+
+        rtcout.println(Logbuf.DEBUG, "CPU affinity property: "+ affinity_str);
+
+        String[] tmp = affinity_str.split(",");
+        String osname = System.getProperty("os.name").toLowerCase();
+        rtcout.println(Logbuf.DEBUG, "os.name: "+ osname);
+        ICPUAffinity CPUAffinity;
+        if(osname.startsWith("windows")){
+            CPUAffinity = new CPUAffinityWindows();
+        }
+        else{
+            CPUAffinity = new CPUAffinityLinux();
+        }
+
+        ArrayList<Integer> cpu_num = new ArrayList<Integer>();
+        BitSet cpu_set = new BitSet();
+        cpu_set.clear();
+
+        rtcout.println(Logbuf.DEBUG, "cpu_num: ");
+        for(int ic=0;ic<tmp.length;++ic){
+            int num = Integer.parseInt(tmp[ic]);
+            rtcout.println(Logbuf.DEBUG, "    " + num);
+            cpu_set.set(num);
+        }
+        CPUAffinity.setProcessAffinity(cpu_set);
+    }
     
     /**
      * {@.ja PeriodicECSharedComposite の初期化。}

Modified: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/RTObject_impl.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/RTObject_impl.java	2017-07-11 08:31:38 UTC (rev 963)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/RTObject_impl.java	2017-07-13 01:57:06 UTC (rev 964)
@@ -6452,6 +6452,7 @@
             "activation_timeout",
             "deactivation_timeout",
             "reset_timeout",
+            "cpu_affinity",
             ""
           };
         Properties node = m_properties.findNode("exec_cxt");
@@ -6627,65 +6628,134 @@
      * {@.en creating, initializing and binding context}
      */
     protected ReturnCode_t createContexts(ArrayList<Properties> ec_args){
-         ReturnCode_t ret = ReturnCode_t.RTC_OK;
-         Set<String> avail_ec
-           = ExecutionContextFactory.instance().getIdentifiers();
-         for (int ic=0; ic < ec_args.size(); ++ic) {
-             String ec_type = ec_args.get(ic).getProperty("type");
-             String ec_name = ec_args.get(ic).getProperty("name");
-             ExecutionContextBase ec = null;
-             // if EC's name exists, find existing EC in the factory.
-             if (!(ec_name.length()<1) &&
-                 findExistingEC(ec_args.get(ic), ec) == ReturnCode_t.RTC_OK) { 
-                 rtcout.println(Logbuf.DEBUG, "EC: type="
-                                        + ec_type
-                                        + ", name="
-                                        + ec_name
-                                        + " already exists.");
-             }
-             // If EC's name is empty or no existing EC, create new EC.
-             else { // If EC's name is empty or no existing EC, create new EC.
-                 boolean find_flag = false;
-                 Iterator it = avail_ec.iterator();
-                 while (it.hasNext()) {
-                     if(it.next().equals(ec_type)){
-                         find_flag= true;
-                         break;
-                     }
-                 }
-                 if (!find_flag) {
-                     rtcout.println(Logbuf.WARN, "EC: "
-                                        + ec_type
-                                        + " is not available.");
-                     rtcout.println(Logbuf.DEBUG, "Available ECs: "
-                                        + avail_ec.toString());
-                     continue;
-                 }
-                 ExecutionContextFactory<ExecutionContextBase,String> factory 
-                                        = ExecutionContextFactory.instance();
-                 ec = factory.createObject(ec_type);
+        ReturnCode_t ret = ReturnCode_t.RTC_OK;
+        Set<String> avail_ec
+            = ExecutionContextFactory.instance().getIdentifiers();
+        for (int ic=0; ic < ec_args.size(); ++ic) {
+            String ec_type = ec_args.get(ic).getProperty("type");
+            String ec_name = ec_args.get(ic).getProperty("name");
+            ExecutionContextBase ec = null;
+            // if EC's name exists, find existing EC in the factory.
+            if (!(ec_name.length()<1) &&
+                findExistingEC(ec_args.get(ic), ec) == ReturnCode_t.RTC_OK) { 
+                rtcout.println(Logbuf.DEBUG, "EC: type="
+                                             + ec_type
+                                             + ", name="
+                                             + ec_name
+                                             + " already exists.");
+            }
+            // If EC's name is empty or no existing EC, create new EC.
+            else { // If EC's name is empty or no existing EC, create new EC.
+                boolean find_flag = false;
+                Iterator it = avail_ec.iterator();
+                while (it.hasNext()) {
+                    if(it.next().equals(ec_type)){
+                        find_flag= true;
+                        break;
+                    }
+                }
+                if (!find_flag) {
+                    rtcout.println(Logbuf.WARN, "EC: "
+                                       + ec_type
+                                       + " is not available.");
+                    rtcout.println(Logbuf.DEBUG, "Available ECs: "
+                                       + avail_ec.toString());
+                    continue;
+                }
+                ExecutionContextFactory<ExecutionContextBase,String> factory 
+                                       = ExecutionContextFactory.instance();
+                ec = factory.createObject(ec_type);
 
-             }
+            }
      
-             // EC factory available but creation failed. Resource full?
-             if (ec == null) {
-                 rtcout.println(Logbuf.ERROR, "EC ("
-                                        + ec_type
-                                        + ") creation failed.");
-                 rtcout.println(Logbuf.DEBUG, "Available EC list: "
+            // EC factory available but creation failed. Resource full?
+            if (ec == null) {
+                rtcout.println(Logbuf.ERROR, "EC ("
+                                      + ec_type
+                                       + ") creation failed.");
+                rtcout.println(Logbuf.DEBUG, "Available EC list: "
                                         + avail_ec.toString());
-                 ret = ReturnCode_t.RTC_ERROR;
-                 continue;
-             }
-             rtcout.println(Logbuf.DEBUG, "EC ("
-                                        + ec_type
-                                        + ") created.");
+                ret = ReturnCode_t.RTC_ERROR;
+                continue;
+            }
+            rtcout.println(Logbuf.DEBUG, "EC ("
+                                       + ec_type
+                                       + ") created.");
      
-             ec.init(ec_args.get(ic));
-             m_eclist.add(ec);
-             ec.bindComponent(this);
-         }
-         return ret;
+            ec.init(ec_args.get(ic));
+            m_eclist.add(ec);
+            ec.bindComponent(this);
+        }
+        if (m_eclist.size() == 0) {
+            Properties default_prop = new Properties();
+            default_prop.setDefaults(DefaultConfiguration.default_config);
+            ExecutionContextBase ec = null;
+
+            String ec_type = 
+                        default_prop.getProperty("exec_cxt.periodic.type");
+            Iterator it = avail_ec.iterator();
+            while (it.hasNext()) {
+                if(it.next().equals(ec_type)){
+                    rtcout.println(Logbuf.WARN, "EC: "
+                                       + ec_type
+                                       + " is not available.");
+                    rtcout.println(Logbuf.DEBUG, "Available ECs: "
+                                       + it.toString());
+                    return ReturnCode_t.RTC_ERROR;
+                }
+            }
+            ExecutionContextFactory<ExecutionContextBase,String> factory 
+                                       = ExecutionContextFactory.instance();
+            ec = factory.createObject(ec_type);
+            if (ec == null) {
+                rtcout.println(Logbuf.ERROR, "EC ("
+                                       + ec_type
+                                       + ") creation failed.");
+                rtcout.println(Logbuf.DEBUG, "Available EC list: "
+                                       + avail_ec.toString());
+                return ReturnCode_t.RTC_ERROR;
+            }
+            Properties default_opts = new Properties();
+            Properties prop = default_prop.findNode("exec_cxt.exec_cxt");
+            if (prop == null) {
+                rtcout.println(Logbuf.WARN, "No default EC options found.");
+                return ReturnCode_t.RTC_ERROR;
+            }
+            default_opts.merge(prop);
+            final String inherited_opts[] =
+              {
+                "sync_transition",
+                "sync_activation",
+                "sync_deactivation",
+                "sync_reset",
+                "transition_timeout",
+                "activation_timeout",
+                "deactivation_timeout",
+                "reset_timeout",
+                "cpu_affinity",
+                ""
+              };
+            Properties node = m_properties.findNode("exec_cxt");
+            if (node == null) {
+                rtcout.println(Logbuf.WARN, "No exec_cxt option found.");
+                return ReturnCode_t.RTC_ERROR;
+            }
+            rtcout.println(Logbuf.DEBUG, "Copying inherited EC options.");
+            for (int ic=0; inherited_opts[ic].length()<1; ++ic) {
+                if (node.findNode(inherited_opts[ic]) != null) {
+                    rtcout.println(Logbuf.PARANOID, "Option "
+                                            + inherited_opts[ic]
+                                            + " exists.");
+                    default_opts.setProperty(inherited_opts[ic], 
+                                        node.getProperty(inherited_opts[ic]));
+                }
+            }
+            ec.init(default_opts);
+            m_eclist.add(ec);
+            ec.bindComponent(this);
+        }
+
+        return ret;
     }
     /**
      * {@.ja マネージャオブジェクト}

Modified: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/executionContext/PeriodicExecutionContext.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/executionContext/PeriodicExecutionContext.java	2017-07-11 08:31:38 UTC (rev 963)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/executionContext/PeriodicExecutionContext.java	2017-07-13 01:57:06 UTC (rev 964)
@@ -1,8 +1,12 @@
 package jp.go.aist.rtm.RTC.executionContext;
 
+import java.util.ArrayList;
 import java.util.Vector;
 
 import jp.go.aist.rtm.RTC.Manager;
+import jp.go.aist.rtm.RTC.ICPUAffinity;
+import jp.go.aist.rtm.RTC.CPUAffinityLinux;
+import jp.go.aist.rtm.RTC.CPUAffinityWindows;
 import jp.go.aist.rtm.RTC.ObjectCreator;
 import jp.go.aist.rtm.RTC.ObjectDestructor;
 import jp.go.aist.rtm.RTC.RTObjectStateMachine;
@@ -136,6 +140,19 @@
         int count = 0 ;
         rtcout.println(Logbuf.TRACE, "PeriodicExecutionContext.svc()");
 
+        if(m_cpu.size()>0) {
+            ICPUAffinity CPUAffinity;
+            String osname = System.getProperty("os.name").toLowerCase();
+            rtcout.println(Logbuf.DEBUG, "os.name: "+ osname);
+            if(osname.startsWith("windows")){
+                CPUAffinity = new CPUAffinityWindows();
+            }
+            else{
+                CPUAffinity = new CPUAffinityLinux();
+            }
+            CPUAffinity.setThreadAffinity(m_cpu);
+        }
+
         do {
             invokeWorkerPreDo();
             synchronized (m_workerthread.mutex_) {
@@ -155,9 +172,12 @@
             if(count > 1000){
                 TimeValue t1_w = t1;
                 TimeValue period_w = period;
-                rtcout.println(Logbuf.PARANOID, "Period:    " + period.getSec() + " [s]");
-                rtcout.println(Logbuf.PARANOID, "Execution: " + t1_w.minus(t0).getSec() + " [s]");
-                rtcout.println(Logbuf.PARANOID, "Sleep:     " + period_w.minus(t1_w).getSec() + " [s]");
+                rtcout.println(Logbuf.PARANOID, "Period:    " 
+                               + period.getSec() + " [s]");
+                rtcout.println(Logbuf.PARANOID, "Execution: " 
+                               + t1_w.minus(t0).getSec() + " [s]");
+                rtcout.println(Logbuf.PARANOID, "Sleep:     " 
+                               + period_w.minus(t1_w).getSec() + " [s]");
             }
             TimeValue delta = t1.minus(t0);
             if( !m_nowait && period.toDouble() > delta.toDouble())
@@ -1540,6 +1560,7 @@
     protected boolean m_nowait;
     protected Thread m_thread = null;
     protected boolean ticked_;
+    protected ArrayList<Integer> m_cpu = new ArrayList<Integer>();
 
     /**
      * <p>このExecutionContextを生成するFactoryクラスを
@@ -1661,6 +1682,10 @@
                 + ", Timeout = "+m_resetTimeout.toDouble());
         // Setting given Properties to EC's profile::properties
         setProperties(props);
+     
+        setCpuAffinity(props);
+        rtcout.println(Logbuf.DEBUG, "init() done");
+
     }
 
 
@@ -1955,4 +1980,31 @@
     public void invokeWorkerPreDo()   { m_worker.invokeWorkerPreDo(); }
     public void invokeWorkerDo()      { m_worker.invokeWorkerDo(); }
     public void invokeWorkerPostDo()  { m_worker.invokeWorkerPostDo(); }
+
+    /**
+     * {@.ja  終了処理用コールバック関数。}
+     * {@.en Callback function to finalize}
+     * 
+     */
+    public void setCpuAffinity(Properties props){
+        rtcout.println(Logbuf.TRACE, "setCpuAffinity()");
+        String affinity_str = props.getProperty("cpu_affinity");
+
+        if(!affinity_str.isEmpty()) {
+            rtcout.println(Logbuf.DEBUG, "CPU affinity property: " 
+                                         + affinity_str);
+            String[] tmp = affinity_str.split(",");
+            m_cpu.clear();
+            for (int ic=0; ic < tmp.length; ++ic) {
+                try {
+                    m_cpu.add(Integer.parseInt(tmp[ic]));
+                    rtcout.println(Logbuf.DEBUG, "CPU affinity int value: "
+                                                 + tmp[ic]
+                                                 + " add.");
+                }
+                catch(Exception ex){
+                }
+            }
+        }
+    }
 }

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/util/Kernel32.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/util/Kernel32.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/util/Kernel32.java	2017-07-13 01:57:06 UTC (rev 964)
@@ -0,0 +1,59 @@
+package jp.go.aist.rtm.RTC.util;
+import com.sun.jna.Library;
+import com.sun.jna.platform.win32.WinNT;
+import com.sun.jna.platform.win32.WinDef;
+
+
+import com.sun.jna.Native;
+import com.sun.jna.Pointer;
+import com.sun.jna.PointerType;
+import com.sun.jna.win32.StdCallLibrary;
+import com.sun.jna.win32.W32APIOptions;
+
+
+/**
+ * {@.ja Kernel32 クラス}
+ * {@.en Kernel32 class}
+ * <p>
+ * {@.ja WindowsAPIラッパクラス
+ * JNAを使用してWindowsAPIを呼び出す}
+ * {@.en WindowsAPI wrappers class
+ * Calls windowsAPI via JNA.}
+ *
+ */
+public interface Kernel32 extends Library,StdCallLibrary, WinNT {
+    Kernel32 INSTANCE = (Kernel32)Native.loadLibrary("kernel32" , 
+                                                     Kernel32.class);
+
+    int GetProcessAffinityMask(
+        final int pid, 
+        final PointerType lpProcessAffinityMask, 
+        final PointerType lpSystemAffinityMask
+    );
+    WinDef.DWORD SetThreadAffinityMask(
+        final int pid, 
+        final WinDef.DWORD lpProcessAffinityMask
+    );
+
+    boolean SetProcessAffinityMask(
+        final int pid, 
+        final WinDef.DWORD dwProcessAffinityMask
+    );
+
+    int GetCurrentThread();
+
+    int GetCurrentProcess();
+
+    int GetCurrentThreadId();
+
+    int GetCurrentProcessId();
+
+    HANDLE OpenProcess(
+        int dwDesiredAccess,  // アクセスフラグ
+        boolean bInheritHandle,    // ハンドルの継承オプション
+        int dwProcessId       // プロセス識別子
+    );
+    boolean CloseHandle(
+        HANDLE hObject                // オブジェクトのハンドル
+    );
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/util/Libc.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/util/Libc.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/util/Libc.java	2017-07-13 01:57:06 UTC (rev 964)
@@ -0,0 +1,21 @@
+package jp.go.aist.rtm.RTC.util;
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+
+
+  /**
+   * {@.ja LinuxのCライブラリ用インターフェイス}
+   * {@.en Interface for C library}
+   *
+   *
+   */
+public interface Libc extends Library {
+    Libc INSTANCE = (Libc) Native.loadLibrary("libc", Libc.class);
+
+    int getpid();
+    int sched_setaffinity(final int pid,
+                          final int cpusetsize,
+                          final cpu_set_t cpuset);
+    int syscall(int number, Object... args);
+
+}

Added: trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/util/cpu_set_t.java
===================================================================
--- trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/util/cpu_set_t.java	                        (rev 0)
+++ trunk/OpenRTM-aist-Java/jp.go.aist.rtm.RTC/src/jp/go/aist/rtm/RTC/util/cpu_set_t.java	2017-07-13 01:57:06 UTC (rev 964)
@@ -0,0 +1,65 @@
+package jp.go.aist.rtm.RTC.util;
+import com.sun.jna.Library;
+import com.sun.jna.Structure;
+import com.sun.jna.NativeLong;
+
+import java.util.Arrays;
+import java.util.List;
+
+  /**
+   * {@.ja cpu_set_t構造体}
+   * {@.en cpu_set_t structure}
+   *
+   *
+   */
+public class cpu_set_t extends Structure {
+    static final int __CPU_SETSIZE = 1024;
+    static final int __NCPUBITS = 8 * NativeLong.SIZE;
+    public static final int SIZE_OF_CPU_SET_T = (__CPU_SETSIZE / __NCPUBITS) * NativeLong.SIZE;
+    static List<String> FIELD_ORDER = Arrays.asList("__bits");
+    public NativeLong[] __bits = new NativeLong[__CPU_SETSIZE / __NCPUBITS];
+
+    public cpu_set_t() {
+        for (int i = 0; i < __bits.length; i++) {
+            __bits[i] = new NativeLong(0);
+        }
+    }
+
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static void __CPU_ZERO(cpu_set_t cpuset) {
+        for (NativeLong bits : cpuset.__bits) {
+            bits.setValue(0l);
+        }
+    }
+
+    public static int __CPUELT(int cpu) {
+        return cpu / __NCPUBITS;
+    }
+
+    public static long __CPUMASK(int cpu) {
+        return 1l << (cpu % __NCPUBITS);
+    }
+
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static void __CPU_SET(int cpu, cpu_set_t cpuset) {
+        cpuset.__bits[__CPUELT(cpu)].setValue(
+                cpuset.__bits[__CPUELT(cpu)].longValue() | __CPUMASK(cpu));
+    }
+
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static void __CPU_CLR(int cpu, cpu_set_t cpuset) {
+        cpuset.__bits[__CPUELT(cpu)].setValue(
+                cpuset.__bits[__CPUELT(cpu)].longValue() & ~__CPUMASK(cpu));
+    }
+
+    @SuppressWarnings({"UnusedDeclaration"})
+    public static boolean __CPU_ISSET(int cpu, cpu_set_t cpuset) {
+        return (cpuset.__bits[__CPUELT(cpu)].longValue() & __CPUMASK(cpu)) != 0;
+    }
+
+    @Override
+    protected List getFieldOrder() {
+        return FIELD_ORDER;
+    }
+}
+



More information about the openrtm-commit mailing list