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 <random>
17 #include <csignal>
18 #include <cstdio>
19 #include <cstdlib>
20 #include <unistd.h>
21 #include <cstdint>
22 #include <cstring>
23 #include <cerrno>
24 #include <fcntl.h>
25 #include <cstdbool>
26 #include <sys/ioctl.h>
27 #include <gtest/gtest.h>
28 #include "ffrt_inner.h"
29 #include "dfx/log/ffrt_log_api.h"
30 #include "c/ffrt_flo.h"
31 #include "../common.h"
32 
33 using namespace std;
34 using namespace testing;
35 #ifdef HWTEST_TESTING_EXT_ENABLE
36 using namespace testing::ext;
37 #endif
38 using namespace ffrt;
39 
40 #define IOCTL_SET_FLO_CONFIG	_IOWR('x', 51, struct FloCfg)
41 struct FloCfg {
42     int pid;             // process id
43     int id;              // code part context id (0-32), shouldn't be duplicate
44     unsigned int size;   // this context using how much ddr size set 0x100000(1MB) as default
45     unsigned int port;   // 0 as default I/D cache FLO work on the same time
46     unsigned int offset; // how many ahead used by FLO prefecher
47 #ifndef __OHOS__
48     bool ffrt;
49 #endif
50 };
51 
InitCfg(int ctxId)52 int InitCfg(int ctxId)
53 {
54     int fd;
55     struct FloCfg data;
56 
57     struct FloCfg cfg = {
58         .pid = getpid(),
59         .id = ctxId,
60         .size = 1048576,
61         .port = 0,
62         .offset = 256,
63 #ifndef __OHOS__
64         .ffrt = true,
65 #endif
66     };
67 
68     printf("get para: pid-%d id-%d size-0x%x port-%d offset-%d.\n",
69         cfg.pid, cfg.id, cfg.size, cfg.port, cfg.offset);
70 
71     fd = open("/dev/hisi_perf_ctrl", O_RDWR);
72     if (fd < 0) {
73         printf("open /dev/hisi_perf_ctrl failed.\n");
74         return -1;
75     }
76 
77     if (ioctl(fd, IOCTL_SET_FLO_CONFIG, &cfg) == -1) {
78         printf("Error %d (%s) in IOCTL_SET_FLO_CONFIG\n", errno, strerror(errno));
79         close(fd);
80         return -1;
81     }
82 
83     close(fd);
84     printf("flo cfg finished.\n");
85     return 0;
86 }
87 
88 class FloTest : public testing::Test {
89 protected:
SetUpTestCase()90     static void SetUpTestCase()
91     {
92     }
93 
TearDownTestCase()94     static void TearDownTestCase()
95     {
96     }
97 
SetUp()98     virtual void SetUp()
99     {
100     }
101 
TearDown()102     virtual void TearDown()
103     {
104     }
105 };
106 
HWTEST_F(FloTest, FFRTFloApiSuccess, TestSize.Level1)107 HWTEST_F(FloTest, FFRTFloApiSuccess, TestSize.Level1)
108 {
109     InitCfg(1);
110     ffrt_flo_start(1);
111     ffrt_flo_end(1);
112 }
113 
HWTEST_F(FloTest, FFRTFloTaskWithoutYield, TestSize.Level1)114 HWTEST_F(FloTest, FFRTFloTaskWithoutYield, TestSize.Level1)
115 {
116     InitCfg(2);
117     auto handle = ffrt::submit_h([] {
118         ffrt_flo_start(2);
119         ffrt_flo_end(2);
120     }, {}, {});
121     ffrt::wait({handle});
122 }
123 
HWTEST_F(FloTest, FFRTFloTaskWithYield, TestSize.Level1)124 HWTEST_F(FloTest, FFRTFloTaskWithYield, TestSize.Level1)
125 {
126     InitCfg(3);
127     auto handle = ffrt::submit_h([] {
128         ffrt_flo_start(3);
129         ffrt::this_task::yield();
130         ffrt_flo_end(3);
131     }, {}, {});
132     ffrt::wait({handle});
133 }