blob: 24147deea9ca21572e5da2c1ca75f74faa28f7ff [file] [log] [blame]
Chris Wilson8f3f8622009-09-01 10:09:55 +01001/*
2 * Copyright © 2008-9 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 * Chris Wilson <chris@chris-wilson.co.uk>
26 *
27 */
28
29#define _GNU_SOURCE
30
31#include <unistd.h>
32#include <stdlib.h>
33#include <stdio.h>
34#include <string.h>
35#include <assert.h>
36#include <fcntl.h>
37#include <inttypes.h>
38#include <errno.h>
39#include <sys/stat.h>
40#include <sys/ioctl.h>
41#include <sys/mman.h>
42#include <pthread.h>
43#include "drm.h"
44#include "i915_drm.h"
45#include "drmtest.h"
46
Daniel Vetter2e9e27c2011-10-15 13:46:19 +020047#define OBJECT_SIZE (128*1024) /* restricted to 1MiB alignment on i915 fences */
Chris Wilson8f3f8622009-09-01 10:09:55 +010048
49/* Before introduction of the LRU list for fences, allocation of a fence for a page
50 * fault would use the first inactive fence (i.e. in preference one with no outstanding
51 * GPU activity, or it would wait on the first to finish). Given the choice, it would simply
52 * reuse the fence that had just been allocated for the previous page-fault - the worst choice
53 * when copying between two buffers and thus constantly swapping fences.
54 */
55
56static void *
57bo_create (int fd)
58{
59 struct drm_i915_gem_create create;
60 struct drm_i915_gem_set_tiling tiling;
61 struct drm_i915_gem_set_domain domain;
62 struct drm_i915_gem_mmap_gtt mmap_arg;
63 void *ptr;
64 int handle;
65 int ret;
66
67 memset(&create, 0, sizeof(create));
68 create.size = OBJECT_SIZE;
69 ret = ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create);
70 assert(ret == 0);
71 handle = create.handle;
72
73 memset(&tiling, 0, sizeof(tiling));
74 tiling.handle = handle;
75 tiling.tiling_mode = I915_TILING_X;
76 tiling.stride = 1024;
77 ret = ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &tiling);
78 assert(ret == 0);
79
80 memset(&mmap_arg, 0, sizeof(mmap_arg));
81 mmap_arg.handle = handle;
82
83 /* Get the fake offset back... */
84 ret = ioctl(fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &mmap_arg);
85 assert (ret == 0);
86 ptr = mmap64(0, OBJECT_SIZE, PROT_READ | PROT_WRITE,
87 MAP_SHARED, fd, mmap_arg.offset);
88 assert (ptr != MAP_FAILED);
89
90 /* XXX: mmap_gtt pulls the bo into the GTT read domain. */
91 memset(&domain, 0, sizeof(domain));
92 domain.handle = handle;
93 domain.read_domains = I915_GEM_DOMAIN_GTT;
94 domain.write_domain = I915_GEM_DOMAIN_GTT;
95 ret = ioctl(fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &domain);
96 assert (ret == 0);
97
98 return ptr;
99}
100
101static void *
102bo_copy (void *_arg)
103{
104 int fd = *(int *)_arg;
Daniel Vetter2e9e27c2011-10-15 13:46:19 +0200105 int n;
Chris Wilson8f3f8622009-09-01 10:09:55 +0100106 char *a, *b;
107
108 a = bo_create (fd);
109 b = bo_create (fd);
110
Daniel Vetter2e9e27c2011-10-15 13:46:19 +0200111 for (n = 0; n < 1000; n++) {
112 memcpy (a, b, OBJECT_SIZE);
Alan Coopersmith00751592012-01-06 15:45:28 -0800113 sched_yield ();
Chris Wilson8f3f8622009-09-01 10:09:55 +0100114 }
115
116 return NULL;
117}
118
119int
120main(int argc, char **argv)
121{
122 drm_i915_getparam_t gp;
123 pthread_t threads[32];
124 int n, num_fences;
125 int fd, ret;
126
127 fd = drm_open_any();
128
129 gp.param = I915_PARAM_NUM_FENCES_AVAIL;
130 gp.value = &num_fences;
131 ret = ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp);
132 assert (ret == 0);
133
134 printf ("creating %d threads\n", num_fences);
135 assert (num_fences < sizeof (threads) / sizeof (threads[0]));
136
137 for (n = 0; n < num_fences; n++)
138 pthread_create (&threads[n], NULL, bo_copy, &fd);
139
140 for (n = 0; n < num_fences; n++)
141 pthread_join (threads[n], NULL);
142
143 close(fd);
144
145 return 0;
146}