| /** |
| * 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 <errno.h> |
| #include <fcntl.h> |
| #include <pthread.h> |
| #include <sched.h> |
| #include <signal.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <sys/ioctl.h> |
| #include <sys/stat.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| #include "../includes/common.h" |
| |
| #define THREAD_NUM 600 |
| #define DEV "/dev/kgsl-3d0" |
| |
| /* ioctls */ |
| #define KGSL_IOC_TYPE 0x09 |
| |
| /* --- context flags --- */ |
| #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_CONTEXT_PRIORITY_MASK 0x0000F000 |
| #define KGSL_CONTEXT_PRIORITY_SHIFT 12 |
| #define KGSL_CONTEXT_PRIORITY_UNDEF 0 |
| |
| #define KGSL_CONTEXT_IFH_NOP 0x00010000 |
| #define KGSL_CONTEXT_SECURE 0x00020000 |
| |
| #define KGSL_CONTEXT_TYPE_MASK 0x01F00000 |
| #define KGSL_CONTEXT_TYPE_SHIFT 20 |
| #define KGSL_CONTEXT_TYPE_ANY 0 |
| #define KGSL_CONTEXT_TYPE_GL 1 |
| #define KGSL_CONTEXT_TYPE_CL 2 |
| #define KGSL_CONTEXT_TYPE_C2D 3 |
| #define KGSL_CONTEXT_TYPE_RS 4 |
| #define KGSL_CONTEXT_TYPE_UNKNOWN 0x1E |
| |
| #define KGSL_CONTEXT_INVALID 0xffffffff |
| |
| /* |
| * --- command batch flags --- |
| * The bits that are linked to a KGSL_CONTEXT equivalent are either legacy |
| * definitions or bits that are valid for both contexts and cmdbatches. To be |
| * safe the other 8 bits that are still available in the context field should be |
| * omitted here in case we need to share - the other bits are available for |
| * cmdbatch only flags as needed |
| */ |
| #define KGSL_CMDBATCH_MEMLIST 0x00000001 |
| #define KGSL_CMDBATCH_MARKER 0x00000002 |
| #define KGSL_CMDBATCH_SUBMIT_IB_LIST KGSL_CONTEXT_SUBMIT_IB_LIST /* 0x004 */ |
| #define KGSL_CMDBATCH_CTX_SWITCH KGSL_CONTEXT_CTX_SWITCH /* 0x008 */ |
| #define KGSL_CMDBATCH_PROFILING 0x00000010 |
| #define KGSL_CMDBATCH_END_OF_FRAME KGSL_CONTEXT_END_OF_FRAME /* 0x100 */ |
| #define KGSL_CMDBATCH_SYNC KGSL_CONTEXT_SYNC /* 0x400 */ |
| #define KGSL_CMDBATCH_PWR_CONSTRAINT KGSL_CONTEXT_PWR_CONSTRAINT /* 0x800 */ |
| |
| /* create a draw context, which is used to preserve GPU state. |
| * The flags field may contain a mask KGSL_CONTEXT_* values |
| */ |
| 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) |
| |
| void* child_ioctl_0(void* no_use); |
| void* child_ioctl_1(void* no_use); |
| void* child_ioctl_2(void* no_use); |
| |
| int fd; |
| unsigned int kgsl_id; |
| pthread_t thread_id[THREAD_NUM + 1] = {0}; |
| int thread_ret[THREAD_NUM] = {0}; |
| |
| static int set_affinity(int num) { |
| int ret = 0; |
| cpu_set_t mask; |
| CPU_ZERO(&mask); |
| CPU_SET(num, &mask); |
| ret = sched_setaffinity(0, sizeof(cpu_set_t), &mask); |
| return ret; |
| } |
| |
| void* child_ioctl_0(void* no_use) { |
| time_t test_started = start_timer(); |
| struct kgsl_drawctxt_destroy kdd = {0}; |
| kdd.drawctxt_id = kgsl_id; |
| set_affinity(1); |
| |
| while (timer_active(test_started)) { |
| ioctl(fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &kdd); |
| } |
| return NULL; |
| } |
| |
| void* child_ioctl_1(void* no_use) { |
| time_t test_started = start_timer(); |
| struct kgsl_drawctxt_destroy kdd = {0}; |
| kdd.drawctxt_id = kgsl_id; |
| set_affinity(2); |
| |
| while (timer_active(test_started)) { |
| ioctl(fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &kdd); |
| } |
| return NULL; |
| } |
| |
| void* child_ioctl_2(void* no_use) { |
| time_t test_started = start_timer(); |
| struct kgsl_drawctxt_create kdc = {0, 0}; |
| kdc.flags = KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC; |
| set_affinity(3); |
| while (timer_active(test_started)) { |
| ioctl(fd, IOCTL_KGSL_DRAWCTXT_CREATE, &kdc); |
| kgsl_id = kdc.drawctxt_id; |
| } |
| return NULL; |
| } |
| |
| int main() { |
| int i, ret; |
| time_t test_started = start_timer(); |
| struct kgsl_drawctxt_create kdc = {0, 0}; |
| struct kgsl_drawctxt_destroy kdd = {0}; |
| kdc.flags = KGSL_CONTEXT_PREAMBLE | KGSL_CONTEXT_NO_GMEM_ALLOC; |
| |
| /* bind_cpu */ |
| set_affinity(0); |
| |
| /* open dev */ |
| fd = open(DEV, O_RDWR); |
| if (fd == -1) { |
| return 0; |
| } |
| |
| /* create thread */ |
| for (i = 0; i < 150; i = i + 3) { |
| thread_ret[i] = pthread_create(thread_id + i, NULL, child_ioctl_0, NULL); |
| thread_ret[i + 1] = |
| pthread_create(thread_id + i + 1, NULL, child_ioctl_1, NULL); |
| thread_ret[i + 2] = |
| pthread_create(thread_id + i + 2, NULL, child_ioctl_2, NULL); |
| } |
| |
| while (timer_active(test_started)) { |
| ret = ioctl(fd, IOCTL_KGSL_DRAWCTXT_CREATE, &kdc); |
| kgsl_id = kdc.drawctxt_id; |
| } |
| |
| close(fd); |
| |
| return 0; |
| } |