arm_compute v17.12
[platform/upstream/armcl.git] / src / runtime / IScheduler.cpp
1 /*
2  * Copyright (c) 2016, 2017 ARM Limited.
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in all
14  * copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24 #include "arm_compute/runtime/IScheduler.h"
25
26 #include <array>
27 #include <cstdlib>
28 #include <cstring>
29 #include <fcntl.h>
30 #include <sched.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34
35 namespace
36 {
37 unsigned int get_cpu_impl()
38 {
39 #ifndef BARE_METAL
40     int fd = open("/proc/cpuinfo", 0); // NOLINT
41     std::array<char, 1200> buff{ {} };
42     char *pos     = nullptr;
43     char *end     = nullptr;
44     bool  foundid = false;
45
46     int cpu = sched_getcpu();
47
48     if(fd == -1)
49     {
50         return 0;
51     }
52
53     int charsread = read(fd, buff.data(), 1200);
54     pos           = buff.data();
55     end           = buff.data() + charsread;
56
57     close(fd);
58
59     /* So, to date I've encountered two formats for /proc/cpuinfo.
60      *
61      * One of them just lists processor : n  for each processor (with no
62      * other info), then at the end lists part information for the current
63      * CPU.
64      *
65      * The other has an entire clause (including part number info) for each
66      * CPU in the system, with "processor : n" headers.
67      *
68      * We can cope with either of these formats by waiting to see
69      * "processor: n" (where n = our CPU ID), and then looking for the next
70      * "CPU part" field.
71      */
72     while(pos < end)
73     {
74         if(foundid && strncmp(pos, "CPU part", 8) == 0)
75         {
76             /* Found part number */
77             pos += 11;
78
79             for(char *ch = pos; ch < end; ch++)
80             {
81                 if(*ch == '\n')
82                 {
83                     *ch = '\0';
84                     break;
85                 }
86             }
87
88             return strtoul(pos, nullptr, 0);
89         }
90
91         if(strncmp(pos, "processor", 9) == 0)
92         {
93             /* Found processor ID, see if it's ours. */
94             pos += 11;
95
96             for(char *ch = pos; ch < end; ch++)
97             {
98                 if(*ch == '\n')
99                 {
100                     *ch = '\0';
101                     break;
102                 }
103             }
104
105             int num = strtol(pos, nullptr, 0);
106
107             if(num == cpu)
108             {
109                 foundid = true;
110             }
111         }
112
113         while(pos < end)
114         {
115             char ch = *pos++;
116             if(ch == '\n' || ch == '\0')
117             {
118                 break;
119             }
120         }
121     }
122 #endif /* BARE_METAL */
123
124     return 0;
125 }
126 } // namespace
127
128 namespace arm_compute
129 {
130 IScheduler::IScheduler()
131 {
132     switch(get_cpu_impl())
133     {
134         case 0xd0f:
135             _info.CPU = CPUTarget::A55_DOT;
136             break;
137         case 0xd03:
138             _info.CPU = CPUTarget::A53;
139             break;
140         default:
141 #ifdef __arm__
142             _info.CPU = CPUTarget::ARMV7;
143 #elif __aarch64__
144             _info.CPU = CPUTarget::ARMV8;
145 #else  /* __arm__ || __aarch64__ */
146             _info.CPU = CPUTarget::INTRINSICS;
147 #endif /* __arm__ || __aarch64__ */
148             break;
149     }
150
151     _info.L1_size = 31000;
152     _info.L2_size = 500000;
153 }
154
155 void IScheduler::set_target(CPUTarget target)
156 {
157     _info.CPU = target;
158 }
159
160 CPUInfo IScheduler::cpu_info() const
161 {
162     return _info;
163 }
164 } // namespace arm_compute