1 /* Copyright (c) 2021-2022 Huawei Device Co., Ltd.
2 * Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15 #define _GNU_SOURCE
16 #include <errno.h>
17 #include <sched.h>
18 #include "syscall.h"
19 #include "atomic.h"
20
21 #ifdef VDSO_GETCPU_SYM
22
23 static void *volatile vdso_func;
24
25 typedef long (*getcpu_f)(unsigned *, unsigned *, void *);
26
getcpu_init(unsigned * cpu,unsigned * node,void * unused)27 static long getcpu_init(unsigned *cpu, unsigned *node, void *unused)
28 {
29 __get_vdso_info();
30 void *p = __get_vdso_addr(VDSO_GETCPU_VER, VDSO_GETCPU_SYM);
31 getcpu_f f = (getcpu_f)p;
32 a_cas_p(&vdso_func, (void *)getcpu_init, p);
33 return f ? f(cpu, node, unused) : -ENOSYS;
34 }
35
36 static void *volatile vdso_func = (void *)getcpu_init;
37
38 #endif
39
sched_getcpu(void)40 int sched_getcpu(void)
41 {
42 int r;
43 unsigned cpu;
44
45 #ifdef VDSO_GETCPU_SYM
46 getcpu_f f = (getcpu_f)vdso_func;
47 if (f) {
48 r = f(&cpu, 0, 0);
49 if (!r) return cpu;
50 if (r != -ENOSYS) return __syscall_ret(r);
51 }
52 #endif
53
54 r = __syscall(SYS_getcpu, &cpu, 0, 0);
55 if (!r) return cpu;
56 return __syscall_ret(r);
57 }
58