1 /**
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define _GNU_SOURCE
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <pthread.h>
21 #include <sched.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <sys/ioctl.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #include "../includes/common.h"
30
31 #define THREAD_NUM 600
32 #define DEV "/dev/kgsl-3d0"
33
34 /* ioctls */
35 #define KGSL_IOC_TYPE 0x09
36
37 /* --- context flags --- */
38 #define KGSL_CONTEXT_SAVE_GMEM 0x00000001
39 #define KGSL_CONTEXT_NO_GMEM_ALLOC 0x00000002
40 /* This is a cmdbatch exclusive flag - use the CMDBATCH equivalent instead */
41 #define KGSL_CONTEXT_SUBMIT_IB_LIST 0x00000004
42 #define KGSL_CONTEXT_CTX_SWITCH 0x00000008
43 #define KGSL_CONTEXT_PREAMBLE 0x00000010
44 #define KGSL_CONTEXT_TRASH_STATE 0x00000020
45 #define KGSL_CONTEXT_PER_CONTEXT_TS 0x00000040
46 #define KGSL_CONTEXT_USER_GENERATED_TS 0x00000080
47 /* This is a cmdbatch exclusive flag - use the CMDBATCH equivalent instead */
48 #define KGSL_CONTEXT_END_OF_FRAME 0x00000100
49 #define KGSL_CONTEXT_NO_FAULT_TOLERANCE 0x00000200
50 /* This is a cmdbatch exclusive flag - use the CMDBATCH equivalent instead */
51 #define KGSL_CONTEXT_SYNC 0x00000400
52 #define KGSL_CONTEXT_PWR_CONSTRAINT 0x00000800
53
54 #define KGSL_CONTEXT_PRIORITY_MASK 0x0000F000
55 #define KGSL_CONTEXT_PRIORITY_SHIFT 12
56 #define KGSL_CONTEXT_PRIORITY_UNDEF 0
57
58 #define KGSL_CONTEXT_IFH_NOP 0x00010000
59 #define KGSL_CONTEXT_SECURE 0x00020000
60
61 #define KGSL_CONTEXT_TYPE_MASK 0x01F00000
62 #define KGSL_CONTEXT_TYPE_SHIFT 20
63 #define KGSL_CONTEXT_TYPE_ANY 0
64 #define KGSL_CONTEXT_TYPE_GL 1
65 #define KGSL_CONTEXT_TYPE_CL 2
66 #define KGSL_CONTEXT_TYPE_C2D 3
67 #define KGSL_CONTEXT_TYPE_RS 4
68 #define KGSL_CONTEXT_TYPE_UNKNOWN 0x1E
69
70 #define KGSL_CONTEXT_INVALID 0xffffffff
71
72 /*
73 * --- command batch flags ---
74 * The bits that are linked to a KGSL_CONTEXT equivalent are either legacy
75 * definitions or bits that are valid for both contexts and cmdbatches. To be
76 * safe the other 8 bits that are still available in the context field should be
77 * omitted here in case we need to share - the other bits are available for
78 * cmdbatch only flags as needed
79 */
80 #define KGSL_CMDBATCH_MEMLIST 0x00000001
81 #define KGSL_CMDBATCH_MARKER 0x00000002
82 #define KGSL_CMDBATCH_SUBMIT_IB_LIST KGSL_CONTEXT_SUBMIT_IB_LIST /* 0x004 */
83 #define KGSL_CMDBATCH_CTX_SWITCH KGSL_CONTEXT_CTX_SWITCH /* 0x008 */
84 #define KGSL_CMDBATCH_PROFILING 0x00000010
85 #define KGSL_CMDBATCH_END_OF_FRAME KGSL_CONTEXT_END_OF_FRAME /* 0x100 */
86 #define KGSL_CMDBATCH_SYNC KGSL_CONTEXT_SYNC /* 0x400 */
87 #define KGSL_CMDBATCH_PWR_CONSTRAINT KGSL_CONTEXT_PWR_CONSTRAINT /* 0x800 */
88
89 /* create a draw context, which is used to preserve GPU state.
90 * The flags field may contain a mask KGSL_CONTEXT_* values
91 */
92 struct kgsl_drawctxt_create {
93 unsigned int flags;
94 unsigned int drawctxt_id; /*output param */
95 };
96
97 #define IOCTL_KGSL_DRAWCTXT_CREATE \
98 _IOWR(KGSL_IOC_TYPE, 0x13, struct kgsl_drawctxt_create)
99
100 /* destroy a draw context */
101 struct kgsl_drawctxt_destroy {
102 unsigned int drawctxt_id;
103 };
104
105 #define IOCTL_KGSL_DRAWCTXT_DESTROY \
106 _IOW(KGSL_IOC_TYPE, 0x14, struct kgsl_drawctxt_destroy)
107
108 void* child_ioctl_0(void* no_use);
109 void* child_ioctl_1(void* no_use);
110 void* child_ioctl_2(void* no_use);
111
112 int fd;
113 unsigned int kgsl_id;
114 pthread_t thread_id[THREAD_NUM + 1] = {0};
115 int thread_ret[THREAD_NUM] = {0};
116
set_affinity(int num)117 static int set_affinity(int num) {
118 int ret = 0;
119 cpu_set_t mask;
120 CPU_ZERO(&mask);
121 CPU_SET(num, &mask);
122 ret = sched_setaffinity(0, sizeof(cpu_set_t), &mask);
123 return ret;
124 }
125
child_ioctl_0(void * no_use)126 void* child_ioctl_0(void* no_use) {
127 int ret = 1;
128 time_t test_started = start_timer();
129 struct kgsl_drawctxt_destroy kdd = {0};
130 kdd.drawctxt_id = kgsl_id;
131 set_affinity(1);
132
133 while (timer_active(test_started)) {
134 ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &kdd);
135 }
136 return NULL;
137 }
138
child_ioctl_1(void * no_use)139 void* child_ioctl_1(void* no_use) {
140 int ret = 1;
141 time_t test_started = start_timer();
142 struct kgsl_drawctxt_destroy kdd = {0};
143 kdd.drawctxt_id = kgsl_id;
144 set_affinity(2);
145
146 while (timer_active(test_started)) {
147 ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &kdd);
148 }
149 return NULL;
150 }
151
child_ioctl_2(void * no_use)152 void* child_ioctl_2(void* no_use) {
153 int ret = 1;
154 time_t test_started = start_timer();
155 struct kgsl_drawctxt_create kdc = {0, 0};
156 kdc.flags = KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC;
157 set_affinity(3);
158 while (timer_active(test_started)) {
159 ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_CREATE, &kdc);
160 kgsl_id = kdc.drawctxt_id;
161 }
162 return NULL;
163 }
164
main()165 int main() {
166 int i, ret;
167 time_t test_started = start_timer();
168 struct kgsl_drawctxt_create kdc = {0, 0};
169 kdc.flags = KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC;
170 struct kgsl_drawctxt_destroy kdd = {0};
171
172 /* bind_cpu */
173 set_affinity(0);
174
175 /* open dev */
176 fd = open(DEV, O_RDWR);
177 if (fd == -1) {
178 return 0;
179 }
180
181 /* create thread */
182 for (i = 0; i < 150; i = i + 3) {
183 thread_ret[i] = pthread_create(thread_id + i, NULL, child_ioctl_0, NULL);
184 thread_ret[i + 1] =
185 pthread_create(thread_id + i + 1, NULL, child_ioctl_1, NULL);
186 thread_ret[i + 2] =
187 pthread_create(thread_id + i + 2, NULL, child_ioctl_2, NULL);
188 }
189
190 while (timer_active(test_started)) {
191 ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_CREATE, &kdc);
192 kgsl_id = kdc.drawctxt_id;
193 }
194
195 close(fd);
196
197 return 0;
198 }
199