MTK PerfService (2) - PerfService的落地

MTK PerfService (2) - PerfService的落地

API讲完了之后,我们来看看如何落地。我们先从java层说起。

PerfServiceWrapper

PerfServiceWrapper调用例

我们上面曾经看到过WebView中调用PerfService的例子:

sPerfService = new PerfServiceWrapper(null);
if (sPerfService != null) {
    int minCPU = 2;
    if (maxFreq < 1100000)
        minCPU = 4;
    sPerfHandle = sPerfService.userReg(minCPU, maxFreq);
    if (sPerfHandle != -1) {
        sPerfService.userEnableTimeoutMs(sPerfHandle, 500);
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                sPerfService.userUnreg(sPerfHandle);
            }
        }, 600);
    }
}

我们来看看userReg是如何调用的:

public int userReg(int scn_core, int scn_freq) {
    int handle = -1;
    //log("[userReg] - "+scn_core+", "+scn_freq);
    try {
        init();
        int pid = nativeGetPid();
        int tid = nativeGetTid();
        if (sService != null)
            handle = sService.userReg(scn_core, scn_freq, pid, tid);
    } catch (RemoteException e) {
        loge("ERR: RemoteException in userReg:" + e);
    }
    //log("[userReg] - handle:"+handle);
    return handle;
}

再来看看init是如何做的,通过Context.MTK_PERF_SERVICE来提供服务。

private void init() {
    if (inited == 0) {
        IBinder b = ServiceManager.checkService(Context.MTK_PERF_SERVICE);
        if (b != null) {
            sService = IPerfService.Stub.asInterface(b);
            if (sService != null)
                inited = 1;
            else
                log("ERR: getService() sService is still null..");
        }
    }
}

PerfServiceImpl

我们再看服务中是如何实现的,在/frameworks/base/services/core/java/com/mediatek/perfservice/PerfServiceImpl.java中:

public int userReg(int scn_core, int scn_freq, int pid, int tid) {
    //log("userReg");
    return perfServiceMgr.userReg(scn_core, scn_freq, pid, tid);
}

具体的实现在PerfServiceMgr中,

public int userGetCapability(int cmd) {
    return nativePerfUserGetCapability(cmd);
}

PerfService的落地还是靠JNI:

static int
android_server_PerfUserScnReg(JNIEnv *env, jobject thiz,
                                        jint scn_core, jint scn_freq, jint pid, jint tid)
{
#if defined(MTK_PERFSERVICE_SUPPORT)
    if (!inited)
        init();

    if (perfUserScnReg) {
        return perfUserScnReg(scn_core, scn_freq, pid, tid);
    }

    ALOGE("perfUserScnReg bypassed!");
#endif
    return -1;
}

com_mediatek_perfservice_PerfServiceManager.cpp

最终,终于落地在我们熟悉的Native API上了。定义于frameworks/base/services/core/jni/com_mediatek_perfservice_PerfServiceManager.cpp

#define LIB_FULL_NAME "libperfservice.so"

static void init()
{
#if defined(MTK_PERFSERVICE_SUPPORT)
    void handle, func;

    // only enter once
    inited = true;

    handle = dlopen(LIB_FULL_NAME, RTLD_NOW);
    if (handle == NULL) {
        ALOGE("Can't load library: %s", dlerror());
        return;
    }

...

    func = dlsym(handle, "perfUserScnReg");
    perfUserScnReg = reinterpret_cast<user_reg>(func);

    if (perfUserScnReg == NULL) {
        ALOGE("perfUserScnReg error: %s", dlerror());
        perfUserScnReg = NULL;
        dlclose(handle);
        return;
    }

超时的处理

超时并不是在libperfservice.so中实现的,直接在java层就搞定了:

public void userEnableTimeout(int handle, int timeout) {
    mHandler.stopCheckUserTimer(handle);
    nativePerfUserScnEnable(handle);

    Message msg = mHandler.obtainMessage();
    msg.what = PerfServiceThreadHandler.MESSAGE_USER_ENABLE_TIMEOUT;
    msg.arg1 = handle;
    msg.arg2 = timeout;
    msg.sendToTarget();
}

public void userEnableTimeoutMs(int handle, int timeout_ms) {
    mHandler.stopCheckUserTimer(handle);
    nativePerfUserScnEnable(handle);

    Message msg = mHandler.obtainMessage();
    msg.what = PerfServiceThreadHandler.MESSAGE_USER_ENABLE_TIMEOUT_MS;
    msg.arg1 = handle;
    msg.arg2 = timeout_ms;
    msg.sendToTarget();
}

Native API的调用方式

请注意,com_mediatek_perfservice_PerfServiceManager.cpp是调用libperfservice.so,而我们使用libperfservicenative.so.
所以我们也要做一些事情才可以调用

函数原型定义

我们先把可能用到的Native API的原型定义一下,这些函数方便后面调用。

static int  (*perfUserScnReg)(int, int) = nullptr;
static int  (*perfUserScnRegBigLittle)(int, int, int, int) = nullptr;
static void (*perfUserScnUnreg)(int) = nullptr;
static int  (*perfUserGetCapability)(int) = nullptr;
static int  (*perfUserRegScn)(void) = nullptr;
static void (*perfUserRegScnConfig)(int, int, int, int, int, int) = nullptr;
static void (*perfUserUnregScn)(int) = nullptr;
static void (*perfUserScnEnable)(int) = nullptr;
static void (*perfUserScnDisable)(int) = nullptr;
static void (*perfUserScnEnableTimeout)(int, int) = nullptr;
static void (*perfUserScnEnableTimeoutMs)(int, int) = nullptr;

然后再用typedef定义一些类型吧:

typedef int  (*user_reg)(int, int);
typedef int  (*user_reg_big_little)(int, int, int, int);
typedef void (*user_unreg)(int);
typedef int  (*user_get_capability)(int);
typedef int  (*user_reg_scn)(void);
typedef void (*user_reg_scn_config)(int, int, int, int, int, int);
typedef void (*user_unreg_scn)(int);
typedef void (*user_enable)(int);
typedef void (*user_disable)(int);
typedef void (*user_enable_timeout)(int, int);
typedef void (*user_enable_timeout_ms)(int, int);

引入libperfservicenative.so

 #define PERF_SERVICE_NATIVE_LIB "libperfservicenative.so"

    void handle, func;

    handle = dlopen(PERF_SERVICE_NATIVE_LIB, RTLD_NOW);
    if (handle == nullptr) {
        ALOGE("Can't load library: %s", dlerror());
        return;
    }

加载符号

    func = dlsym(handle, "PerfServiceNative_userReg");
    perfUserScnReg = reinterpret_cast<user_reg>(func);

    if (perfUserScnReg == nullptr) {
        ALOGE("perfUserScnReg error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userRegBigLittle");
    perfUserScnRegBigLittle = reinterpret_cast<user_reg_big_little>(func);

    if (perfUserScnRegBigLittle == nullptr) {
        ALOGE("perfUserScnRegBigLittle error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userUnreg");
    perfUserScnUnreg = reinterpret_cast<user_unreg>(func);

    if (perfUserScnUnreg == nullptr) {
        ALOGE("perfUserScnUnreg error: %s", dlerror());
        dlclose(handle);
        return;
    }
...

终于可以调用了

下面终于可以正式干活了:

老的API,开8个核!

    int handle;

    init();
    handle = perfUserScnReg(4,0);
    perfUserScnEnable(handle);

    //Do job!

    perfUserScnDisable(handle);
    perfUserScnUnreg(handle);

新的API:

    int handle2;
    handle2 = perfUserRegScn();
    perfUserRegScnConfig(handle2,CMD_SET_CPU_CORE_MIN,4,0,0,0);
    perfUserRegScnConfig(handle2,CMD_SET_CPU_FREQ_MIN,1469000,0,0,0);
    perfUserRegScnConfig(handle2,CMD_SET_CPU_FREQ_MAX,1469000,0,0,0);
    perfUserScnEnable(handle2);

    //Do job!

    perfUserScnDisable(handle2);
    perfUserUnregScn(handle2);

Native调用的完整例子

Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES += libdl liblog
LOCAL_C_INCLUDES += $(MTK_PATH_SOURCE)/hardware/perfservice/perfservicenative/

LOCAL_SRC_FILES := native_perf.cc
LOCAL_MODULE := nativeperf
include $(BUILD_EXECUTABLE)

native_perf.cc

#include <dlfcn.h>
#include <android/log.h>
#include "PerfServiceNative.h"

#define PERF_SERVICE_NATIVE_LIB "libperfservicenative.so"

#define  ALOGE(...)  __android_log_print(ANDROID_LOG_ERROR,"TestPerfNative",__VA_ARGS__)

static int  (*perfUserScnReg)(int, int) = nullptr;
static int  (*perfUserScnRegBigLittle)(int, int, int, int) = nullptr;
static void (*perfUserScnUnreg)(int) = nullptr;
static int  (*perfUserGetCapability)(int) = nullptr;
static int  (*perfUserRegScn)(void) = nullptr;
static void (*perfUserRegScnConfig)(int, int, int, int, int, int) = nullptr;
static void (*perfUserUnregScn)(int) = nullptr;
static void (*perfUserScnEnable)(int) = nullptr;
static void (*perfUserScnDisable)(int) = nullptr;
static void (*perfUserScnEnableTimeout)(int, int) = nullptr;
static void (*perfUserScnEnableTimeoutMs)(int, int) = nullptr;

typedef int  (*user_reg)(int, int);
typedef int  (*user_reg_big_little)(int, int, int, int);
typedef void (*user_unreg)(int);
typedef int  (*user_get_capability)(int);
typedef int  (*user_reg_scn)(void);
typedef void (*user_reg_scn_config)(int, int, int, int, int, int);
typedef void (*user_unreg_scn)(int);
typedef void (*user_enable)(int);
typedef void (*user_disable)(int);
typedef void (*user_enable_timeout)(int, int);
typedef void (*user_enable_timeout_ms)(int, int);

static void init()
{
    void *handle, *func;

    handle = dlopen(PERF_SERVICE_NATIVE_LIB, RTLD_NOW);
    if (handle == nullptr) {
        ALOGE("Can't load library: %s", dlerror());
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userReg");
    perfUserScnReg = reinterpret_cast<user_reg>(func);

    if (perfUserScnReg == nullptr) {
        ALOGE("perfUserScnReg error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userRegBigLittle");
    perfUserScnRegBigLittle = reinterpret_cast<user_reg_big_little>(func);

    if (perfUserScnRegBigLittle == nullptr) {
        ALOGE("perfUserScnRegBigLittle error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userUnreg");
    perfUserScnUnreg = reinterpret_cast<user_unreg>(func);

    if (perfUserScnUnreg == nullptr) {
        ALOGE("perfUserScnUnreg error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userGetCapability");
    perfUserGetCapability = reinterpret_cast<user_get_capability>(func);

    if (perfUserGetCapability == nullptr) {
        ALOGE("perfUserGetCapability error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userRegScn");
    perfUserRegScn = reinterpret_cast<user_reg_scn>(func);

    if (perfUserRegScn == nullptr) {
        ALOGE("perfUserRegScn error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userRegScnConfig");
    perfUserRegScnConfig = reinterpret_cast<user_reg_scn_config>(func);

    if (perfUserRegScnConfig == nullptr) {
        ALOGE("perfUserRegScnConfig error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userUnregScn");
    perfUserUnregScn = reinterpret_cast<user_unreg_scn>(func);

    if (perfUserUnregScn == nullptr) {
        ALOGE("perfUserUnregScn error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userEnable");
    perfUserScnEnable = reinterpret_cast<user_enable>(func);

    if (perfUserScnEnable == nullptr) {
        ALOGE("perfUserScnEnable error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userDisable");
    perfUserScnDisable = reinterpret_cast<user_disable>(func);

    if (perfUserScnDisable == nullptr) {
        ALOGE("perfUserScnDisable error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userEnableTimeout");
    perfUserScnEnableTimeout = reinterpret_cast<user_enable_timeout>(func);

    if (perfUserScnEnableTimeout == nullptr) {
        ALOGE("perfUserScnEnableTimeout error: %s", dlerror());
        dlclose(handle);
        return;
    }

    func = dlsym(handle, "PerfServiceNative_userEnableTimeoutMs");
    perfUserScnEnableTimeoutMs = reinterpret_cast<user_enable_timeout_ms>(func);

    if (perfUserScnEnableTimeoutMs == nullptr) {
        ALOGE("perfUserScnEnableTimeoutMs error: %s", dlerror());
        dlclose(handle);
        return;
    }
};

int main()
{
    int handle;

    init();
    handle = perfUserScnReg(4,0);
    perfUserScnEnable(handle);

    //Do job!

    perfUserScnDisable(handle);
    perfUserScnUnreg(handle);

    int handle2;
    handle2 = perfUserRegScn();
    perfUserRegScnConfig(handle2,CMD_SET_CPU_CORE_MIN,4,0,0,0);
    perfUserRegScnConfig(handle2,CMD_SET_CPU_FREQ_MIN,1469000,0,0,0);
    perfUserRegScnConfig(handle2,CMD_SET_CPU_FREQ_MAX,1469000,0,0,0);
    perfUserScnEnable(handle2);

    //Do job!

    perfUserScnDisable(handle2);
    perfUserUnregScn(handle2);
}
时间: 2024-12-02 08:56:28

MTK PerfService (2) - PerfService的落地的相关文章

在MTK芯片上如何控制CPU的核数和频率-MTK PerfService

在MTK芯片上如何控制CPU的核数和频率-MTK PerfService 一句话:PerfService就是用来调整CPU/GPU资源的.对于老的API,可以更简单地讲就是调CPU核数和CPU频率的. PerfService简介 kernel中实现了两个driver,一个负责控制开关CPU的核数,叫做hot-plug驱动,另一个负责调整CPU的频率,叫做DVFS驱动. kernel中的driver会根据系统的负载情况下,自动调整使用几个CPU和调整CPU频率.如果负载高了,提高频率,或者多开几个

专访 | 今日头条李磊:程序员如何跻身AI大潮,应用如何落地

李磊博士是今日头条人工智能实验室(Toutiao AI Lab)总监,原百度美国深度学习实验室"少帅科学家",师从数据挖掘领域权威Christos Faloutsos教授,主要研究领域为深度学习.概率模型与推理.自然语言理解,以及时间序列分析.在国际顶级学术会议发表学术论文30余篇,拥有三项美国发明专利. 今日头条科学家.人工智能实验室总监 李磊 近日,这位研究出身,如今又投身工业界的博士接受了CSDN的专访,采访中李磊分享了他对当下人工智能过热的一些看法,并结合自身的求学与从业经历,

B2B公司的“2”或将指落地合作

据说,清朝在与沙俄边界交易的时候,有两种翻译中介:一种是专门做中介但不会外语的肢体翻译中介:另一种则是从头到尾把事情全部沟通好的语言翻译中介.当然前一种是最早的交易群体,因为刚开始接触的时候,双方交易大多是通过肢体语言去表达,而最初的翻译也只是肢体语言做的比较好的,但也只能让双方把货物放一起比较之后,就自己闪人,剩下的肢体语言自然是由买卖双方去做:渐渐的,中俄商人就感觉这样很不方便,于是开始寻找能够通晓双方语言的翻译中介,慢慢的依靠肢体语言进行信息提供的中介就失去了原有的饭碗,而通晓双方语言的中

清华裴丹分享AIOps落地路线图,看智能运维如何落地生根

大家上午好,非常荣幸,能有这个机会,跟这么多的运维人一起交流智能运维.最近这两年运维里面有一个很火的一个词叫做AIOps(智能运维),并且有一小部分人一往无前的投入到AIOps中去了, 但是更多的人都还在持观望态度,因为大家内心中还存在一个无法回避的问题:AIOps到底在自己的场景下怎么落地?所以今天我要跟大家分享我认为的AIOps落地应该遵循的路线图.既有技术路线图,也有战略路线图.这虽然不是唯一的一个路线图,但这是我今后十年会不断努力.专注和迭代的一个方向,希望为那些对AIOps感兴趣的朋友

保证有效落地 东软又成车联网领域的先行者

出门打车用软件,购物付款用软件,看病挂号用软件-- 今天我们所处的时代正在经历一场社会形态的深刻变革,软件.互联网.大数据.人工智能已经走进我们的日常生活,改变着每一个人的学习.工作和生活,我们已经进入了数字社会时代. 在充满无限想象的未来,我们能做什么?如何创造我们的商业?如何改变我们的世界?又如何适应数字社会的生存? 东软有一个口号叫"软件是一种态度".即:软件是用来创造社会价值,创造用户价值,让技术价值得以体现. 比如在今年东软解决方案论坛上,东软就与客户.合作伙伴一起携手,以创

宽带不宽?网络带宽成云计算落地的最大制约

云计算从概念走向了落地,成为企业在寻求数据中心转型之路时的最好选择,但当企业摩拳擦掌,准备大规模部署云计算时,却发现,这对于现在的网络性能来说,还面临着超乎想象的挑战.众所周知,云计算可能会大幅度增加互联网流量,由此引发的服务中断.网络延迟等问题会严重制约云计算的发展. 虽然从表面上看来,云服务使用方式简单.轻巧.方便,但是背后却消耗着大量的网络带宽.不得不承认,网络带宽的难以保障,成为了制约云计算发展的"隐形杀手". 云计算走向落地 足够高的.可靠的.低成本的.容易获取的带宽资源,是

DockOne微信分享(一四二):容器云在万达的落地经验

本文讲的是DockOne微信分享(一四二):容器云在万达的落地经验[编者的话]容器生态是现在非常火热的技术生态之一,个人认为它主要囊括着四个方面的技术栈:一是容器核心技术栈(包括 Docker.rkt 及第三方公司自主研发的容器 Engine 等):二是容器基础技术栈(包括容器网络.存储.安全及服务发现等):三是容器编排技术栈(包括 Mesos/Marathon.Swarm.Kubernetes 及 OpenShift 等):四是容器应用技术栈(主要包括 CI/CD.监控.日志及微服务框架等).

DockOne微信分享(一一零):Docker在沪江落地的实践

本文讲的是DockOne微信分享(一一零):Docker在沪江落地的实践[编者的话]容器化是很多公司技术层向往又惧怕的一项热门技术,它的高效性,封装性能给开发.运维带来许多便利,但其本身也需要较强的技术能力去控制,否则会变成一个无法落地的概念.沪江作为教育界的独角兽,随着业务的增长,在开发.测试.运维上的成本增加日益显著.经过我们一年的探索,终于使Docker技术在沪江落地,不但成功的降低了成本,并吸引了其他部门的关注与试用,取得良好的成效. [上海站|3天烧脑式微服务架构训练营]培训内容包括:

全国首家阿里巴巴大数据学院落地贵州,计划三年内培养25000名人才

近日,贵州理工学院与阿里云宣布联合共建"阿里巴巴·贵州理工大数据学院",促进高校.科研院所.企业科技教育资源共享,创立高校与科研院所.行业.企业联合培养人才的新机制.据悉,此次合作也是贵州省人民政府与阿里巴巴战略合作的重要落地项目之一.     今年8月,贵州省同阿里巴巴集团签署深化全面合作协议,计划在大数据人才培养.技术研发.创新创业.智慧城市等多个新领域展开合作,推动贵州成为"数据之都".其中,大数据人才培养是合作的重要基础之一,当时即提出要在三年内为贵州培养2