1. 程式人生 > >android下將指定的程序/執行緒繫結到指定的CPU

android下將指定的程序/執行緒繫結到指定的CPU

針對平臺優化的APP,需要根據具體的CPU型號來將一些任務重,佔CPU資源多的執行緒繫結到CPU上處理能力更強的大核上,可參考如下程式碼:

1、將整個程序中的各個執行緒繫結到指定CPU核

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sched.h>
#include <ctype.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <dirent.h>
#include <grp.h>
#include <inttypes.h>
#include <pwd.h>
#include <string.h>
#include <jni.h>
#include <time.h>
#include <poll.h>
#include <errno.h>
#include <fcntl.h>
#include <cutils/log.h>
#include <sys/stat.h>
#include <cutils/properties.h>
JNIEXPORT int JNICALL Java_com_google_vrtoolkit_cardboard_GLSurfaceView2_BindThreadsToCpu45(JNIEnv* env, jobject obj){
    DIR *task_dir;
    struct dirent *tid_dir;
    int pid,tid;
    int ret;
    char filename[64];
 
          ALOGD("BindThreadsToCpu45 : Current platform = rk3399");
        cpu_set_t mask;
        struct sched_param param;
        CPU_ZERO(&mask);
        CPU_SET(4, &mask);
        CPU_SET(5, &mask);
     extern int errno;
        // bind whole processId to cpu 4 & 5
        pid = getpid();
     ret = sched_setaffinity(pid, sizeof(mask), &mask);
        if(ret < 0){
    ALOGE("BindThreadsToCpu45 -> bind process  sched_setaffinity return %d, errno = %d\n",ret,errno);
            return -1;
        }else{
            ALOGD("BindThreadsToCpu45 -> bind process  sched_setaffinity success!");
        }
        // bind all threads before
        sprintf(filename, "/proc/%d/task", pid);
        task_dir = opendir(filename);
        if (!task_dir) ALOGE("opendir failed!");
        while ((tid_dir = readdir(task_dir))) {
            if (!isdigit(tid_dir->d_name[0]))
                continue;
            tid = atoi(tid_dir->d_name);
            ret = sched_setaffinity(tid, sizeof(mask), &mask);
            if(ret < 0){
         ALOGE("BindThreadsToCpu45 -> bind thread %d sched_setaffinity return %d, errno = %d\n",tid,ret,errno);
                return -1;
            }else{
                ALOGD("BindThreadsToCpu45 -> bind thread %d sched_setaffinity success!",tid);
            }
        }
        return 0;
    }

android將執行緒繫結在指定CPU

原文地址:https://blog.csdn.net/lyx2007825/article/details/53885205

linux下可以直接呼叫pthread_setaffinity_np,將當前執行緒繫結在具體的cpu上,而android該API被遮蔽了,需要呼叫sched這個系統API,詳情見下面程式碼:

package nativelibs;
 
public class Affinity {
    static {
        System.loadLibrary("Affinity");
    }
    public static native void bindToCpu(int cpu);
}
void set_cur_thread_affinity(int mask) {
    int err, syscallres;
    pid_t pid = gettid();
    syscallres = syscall(__NR_sched_setaffinity, pid, sizeof(mask), &mask);
    if (syscallres) {
        err = errno;
        LOGE("Error in the syscall setaffinity: mask = %d, err=%d",mask,errno);
    }
    LOGD("tid = %d has setted affinity success",pid);
}

ok,具體的JNI程式碼如下:

#include <jni.h>
#include <android/log.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <sys/syscall.h>
 
#define TAG "Affinity"
#define DEBUG 1
 
#ifndef CPU_ZERO
#define CPU_SETSIZE 1024
#define __NCPUBITS  (8 * sizeof (unsigned long))
typedef struct
{
    unsigned long __bits[CPU_SETSIZE / __NCPUBITS];
} cpu_set_t;
 
#define CPU_SET(cpu, cpusetp) \
  ((cpusetp)->__bits[(cpu)/__NCPUBITS] |= (1UL << ((cpu) % __NCPUBITS)))
#define CPU_ZERO(cpusetp) \
  memset((cpusetp), 0, sizeof(cpu_set_t))
#else
#define CPU_SET(cpu,cpustep) ((void)0)
#define CPU_ZERO(cpu,cpustep) ((void)0)
#endif
 
#ifdef DEBUG
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)
#else
#define LOGD(...) ((void)0)
#define LOGE(...) ((void)0)
#endif
 
void set_cur_thread_affinity(int mask) {
    int err, syscallres;
    pid_t pid = gettid();
    syscallres = syscall(__NR_sched_setaffinity, pid, sizeof(mask), &mask);
    if (syscallres) {
        err = errno;
        LOGE("Error in the syscall setaffinity: mask = %d, err=%d",mask,errno);
    }
    LOGD("tid = %d has setted affinity success",pid);
}
 
static int getCores() {
    return sysconf(_SC_NPROCESSORS_CONF);
}
 
JNIEXPORT int JNICALL Java_nativelibs_Affinity_getCores(JNIEnv *env, jclass type) {
    return getCores();
}
 
JNIEXPORT void JNICALL Java_nativelibs_Affinity_bindToCpu(JNIEnv *env, jclass type, jint cpu) {
    int cores = getCores();
    LOGD("get cpu number = %d\n",cores);
    if (cpu >= cores) {
        LOGE("your set cpu is beyond the cores,exit...");
        return;
    }
 
    cpu_set_t mask;
    CPU_ZERO(&mask);
    CPU_SET(cpu,&mask);
    set_cur_thread_affinity((int)(&mask));
    LOGD("set affinity to %d success",cpu);
}