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 
30 #define THREAD_NUM 600
31 #define DEV "/dev/kgsl-3d0"
32 
33 /* ioctls */
34 #define KGSL_IOC_TYPE 0x09
35 
36 /* --- context flags --- */
37 #define KGSL_CONTEXT_SAVE_GMEM 0x00000001
38 #define KGSL_CONTEXT_NO_GMEM_ALLOC 0x00000002
39 /* This is a cmdbatch exclusive flag - use the CMDBATCH equivalent instead */
40 #define KGSL_CONTEXT_SUBMIT_IB_LIST 0x00000004
41 #define KGSL_CONTEXT_CTX_SWITCH 0x00000008
42 #define KGSL_CONTEXT_PREAMBLE 0x00000010
43 #define KGSL_CONTEXT_TRASH_STATE 0x00000020
44 #define KGSL_CONTEXT_PER_CONTEXT_TS 0x00000040
45 #define KGSL_CONTEXT_USER_GENERATED_TS 0x00000080
46 /* This is a cmdbatch exclusive flag - use the CMDBATCH equivalent instead */
47 #define KGSL_CONTEXT_END_OF_FRAME 0x00000100
48 #define KGSL_CONTEXT_NO_FAULT_TOLERANCE 0x00000200
49 /* This is a cmdbatch exclusive flag - use the CMDBATCH equivalent instead */
50 #define KGSL_CONTEXT_SYNC 0x00000400
51 #define KGSL_CONTEXT_PWR_CONSTRAINT 0x00000800
52 
53 #define KGSL_CONTEXT_PRIORITY_MASK 0x0000F000
54 #define KGSL_CONTEXT_PRIORITY_SHIFT 12
55 #define KGSL_CONTEXT_PRIORITY_UNDEF 0
56 
57 #define KGSL_CONTEXT_IFH_NOP 0x00010000
58 #define KGSL_CONTEXT_SECURE 0x00020000
59 
60 #define KGSL_CONTEXT_TYPE_MASK 0x01F00000
61 #define KGSL_CONTEXT_TYPE_SHIFT 20
62 #define KGSL_CONTEXT_TYPE_ANY 0
63 #define KGSL_CONTEXT_TYPE_GL 1
64 #define KGSL_CONTEXT_TYPE_CL 2
65 #define KGSL_CONTEXT_TYPE_C2D 3
66 #define KGSL_CONTEXT_TYPE_RS 4
67 #define KGSL_CONTEXT_TYPE_UNKNOWN 0x1E
68 
69 #define KGSL_CONTEXT_INVALID 0xffffffff
70 
71 /*
72  * --- command batch flags ---
73  * The bits that are linked to a KGSL_CONTEXT equivalent are either legacy
74  * definitions or bits that are valid for both contexts and cmdbatches.  To be
75  * safe the other 8 bits that are still available in the context field should be
76  * omitted here in case we need to share - the other bits are available for
77  * cmdbatch only flags as needed
78  */
79 #define KGSL_CMDBATCH_MEMLIST 0x00000001
80 #define KGSL_CMDBATCH_MARKER 0x00000002
81 #define KGSL_CMDBATCH_SUBMIT_IB_LIST KGSL_CONTEXT_SUBMIT_IB_LIST /* 0x004 */
82 #define KGSL_CMDBATCH_CTX_SWITCH KGSL_CONTEXT_CTX_SWITCH         /* 0x008 */
83 #define KGSL_CMDBATCH_PROFILING 0x00000010
84 #define KGSL_CMDBATCH_END_OF_FRAME KGSL_CONTEXT_END_OF_FRAME     /* 0x100 */
85 #define KGSL_CMDBATCH_SYNC KGSL_CONTEXT_SYNC                     /* 0x400 */
86 #define KGSL_CMDBATCH_PWR_CONSTRAINT KGSL_CONTEXT_PWR_CONSTRAINT /* 0x800 */
87 
88 /* create a draw context, which is used to preserve GPU state.
89  * The flags field may contain a mask KGSL_CONTEXT_*  values
90  */
91 struct kgsl_drawctxt_create {
92   unsigned int flags;
93   unsigned int drawctxt_id; /*output param */
94 };
95 
96 #define IOCTL_KGSL_DRAWCTXT_CREATE \
97   _IOWR(KGSL_IOC_TYPE, 0x13, struct kgsl_drawctxt_create)
98 
99 /* destroy a draw context */
100 struct kgsl_drawctxt_destroy {
101   unsigned int drawctxt_id;
102 };
103 
104 #define IOCTL_KGSL_DRAWCTXT_DESTROY \
105   _IOW(KGSL_IOC_TYPE, 0x14, struct kgsl_drawctxt_destroy)
106 
107 void* child_ioctl_0(void* no_use);
108 void* child_ioctl_1(void* no_use);
109 void* child_ioctl_2(void* no_use);
110 
111 int fd;
112 unsigned int kgsl_id;
113 pthread_t thread_id[THREAD_NUM + 1] = {0};
114 int thread_ret[THREAD_NUM] = {0};
115 
set_affinity(int num)116 static int set_affinity(int num) {
117   int ret = 0;
118   cpu_set_t mask;
119   CPU_ZERO(&mask);
120   CPU_SET(num, &mask);
121   ret = sched_setaffinity(0, sizeof(cpu_set_t), &mask);
122   return ret;
123 }
124 
child_ioctl_0(void * no_use)125 void* child_ioctl_0(void* no_use) {
126   int ret = 1;
127   struct kgsl_drawctxt_destroy kdd = {0};
128   kdd.drawctxt_id = kgsl_id;
129   set_affinity(1);
130 
131   while (1) {
132     ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &kdd);
133   }
134 }
135 
child_ioctl_1(void * no_use)136 void* child_ioctl_1(void* no_use) {
137   int ret = 1;
138   struct kgsl_drawctxt_destroy kdd = {0};
139   kdd.drawctxt_id = kgsl_id;
140   set_affinity(2);
141 
142   while (1) {
143     ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &kdd);
144   }
145 }
146 
child_ioctl_2(void * no_use)147 void* child_ioctl_2(void* no_use) {
148   int ret = 1;
149   struct kgsl_drawctxt_create kdc = {0, 0};
150   kdc.flags = KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC;
151   set_affinity(3);
152   while (1) {
153     ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_CREATE, &kdc);
154     kgsl_id = kdc.drawctxt_id;
155   }
156 }
157 
main()158 int main() {
159   int i, ret;
160   struct kgsl_drawctxt_create kdc = {0, 0};
161   kdc.flags = KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC;
162   struct kgsl_drawctxt_destroy kdd = {0};
163 
164   /* bind_cpu */
165   set_affinity(0);
166 
167   /* open dev */
168   fd = open(DEV, O_RDWR);
169   if (fd == -1) {
170     return 0;
171   }
172 
173   /* create thread */
174   for (i = 0; i < 150; i = i + 3) {
175     thread_ret[i] = pthread_create(thread_id + i, NULL, child_ioctl_0, NULL);
176     thread_ret[i + 1] =
177         pthread_create(thread_id + i + 1, NULL, child_ioctl_1, NULL);
178     thread_ret[i + 2] =
179         pthread_create(thread_id + i + 2, NULL, child_ioctl_2, NULL);
180   }
181 
182   while (1) {
183     ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_CREATE, &kdc);
184     kgsl_id = kdc.drawctxt_id;
185   }
186 }
187