1/*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "rtg_perf_ctrl.h"
17#include "dfx/log/ffrt_log_api.h"
18
19#include <cstdio>
20#include <cstdlib>
21#include <cstring>
22#include <unistd.h>
23#include <sys/types.h>
24#include <sys/ioctl.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27#include <cerrno>
28#include <securec.h>
29
30static int OpenPerfCtrl(void)
31{
32    static bool perfCtrlAvailable = true;
33    int fd = -1;
34
35    if (!perfCtrlAvailable) {
36        return -1;
37    }
38
39    fd = open("/dev/hisi_perf_ctrl", O_RDWR);
40    if (fd < 0) {
41        FFRT_LOGW("open perf_ctrl failed");
42        perfCtrlAvailable = false;
43    }
44
45    return fd;
46}
47
48void SetTaskRtg(pid_t tid, unsigned int grpId)
49{
50    struct RtgGroupTask data = {tid, grpId, 0};
51    int fd = OpenPerfCtrl();
52    if (fd < 0) {
53        return;
54    }
55
56    if (ioctl(fd, PERF_CTRL_SET_TASK_RTG, &data) != 0) {
57        FFRT_LOGW("Error set rtg %d,%u. %s", tid, grpId, strerror(errno));
58        close(fd);
59        return;
60    }
61    close(fd);
62}
63
64void SetRtgStatus(unsigned long long status)
65{
66    int fd = OpenPerfCtrl();
67    if (fd < 0) {
68        return;
69    }
70
71    if (ioctl(fd, PERF_CTRL_SET_FRAME_STATUS, &status) != 0) {
72        FFRT_LOGW("Error set rtg status=%llu. %s", status, strerror(errno));
73        close(fd);
74        return;
75    }
76    close(fd);
77}
78
79void SetRtgQos(int qos) // MHZ
80{
81    int fd = OpenPerfCtrl();
82    if (fd < 0) {
83        return;
84    }
85
86    if (ioctl(fd, PERF_CTRL_SET_FRAME_RATE, &qos) != 0) {
87        FFRT_LOGW("Error set rtg qos=%d. %s", qos, strerror(errno));
88        close(fd);
89        return;
90    }
91    close(fd);
92}
93
94void SetRtgLoadMode(unsigned int grpId, bool utilEnabled, bool freqEnabled)
95{
96    struct RtgLoadMode loadMode;
97
98    memset_s(&loadMode, sizeof(struct RtgLoadMode), 0, sizeof(struct RtgLoadMode));
99    loadMode.grpId = grpId;
100    loadMode.utilEnabled = !!utilEnabled;
101    loadMode.freqEnabled = !!freqEnabled;
102
103    int fd = OpenPerfCtrl();
104    if (fd < 0) {
105        return;
106    }
107
108    if (ioctl(fd, PERF_CTRL_SET_RTG_LOAD_MODE, &loadMode) != 0) {
109        FFRT_LOGW("Error set rtg loadMode %d:%d/%d. %s", loadMode.grpId, loadMode.utilEnabled,
110            loadMode.freqEnabled, strerror(errno));
111        close(fd);
112        return;
113    }
114    close(fd);
115}
116
117void set_task_min_util(pid_t tid, unsigned int util)
118{
119    struct TaskConfig cfg = {tid, util};
120    int fd = OpenPerfCtrl();
121    if (fd < 0) {
122        return;
123    }
124
125    if (ioctl(fd, PERF_CTRL_SET_TASK_MIN_UTIL, &cfg) != 0) {
126        FFRT_LOGW("Error set min util %d,%u. %s", tid, util, strerror(errno));
127        close(fd);
128        return;
129    }
130    close(fd);
131}
132