drm_gem_names.c revision 282199
1235783Skib/*- 2235783Skib * Copyright (c) 2011 The FreeBSD Foundation 3235783Skib * All rights reserved. 4235783Skib * 5235783Skib * This software was developed by Konstantin Belousov under sponsorship from 6235783Skib * the FreeBSD Foundation. 7235783Skib * 8235783Skib * Redistribution and use in source and binary forms, with or without 9235783Skib * modification, are permitted provided that the following conditions 10235783Skib * are met: 11235783Skib * 1. Redistributions of source code must retain the above copyright 12235783Skib * notice, this list of conditions and the following disclaimer. 13235783Skib * 2. Redistributions in binary form must reproduce the above copyright 14235783Skib * notice, this list of conditions and the following disclaimer in the 15235783Skib * documentation and/or other materials provided with the distribution. 16235783Skib * 17235783Skib * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18235783Skib * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19235783Skib * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20235783Skib * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21235783Skib * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22235783Skib * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23235783Skib * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24235783Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25235783Skib * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26235783Skib * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27235783Skib * SUCH DAMAGE. 28235783Skib */ 29235783Skib 30235783Skib#include <sys/cdefs.h> 31235783Skib__FBSDID("$FreeBSD: stable/10/sys/dev/drm2/drm_gem_names.c 282199 2015-04-28 19:35:05Z dumbbell $"); 32235783Skib 33235783Skib#include <sys/param.h> 34235783Skib#include <sys/systm.h> 35235783Skib#include <sys/kernel.h> 36235783Skib#include <sys/limits.h> 37235783Skib#include <sys/malloc.h> 38235783Skib 39235783Skib#include <dev/drm2/drm_gem_names.h> 40235783Skib 41235783SkibMALLOC_DEFINE(M_GEM_NAMES, "gem_name", "Hash headers for the gem names"); 42235783Skib 43235783Skibstatic void drm_gem_names_delete_name(struct drm_gem_names *names, 44235783Skib struct drm_gem_name *np); 45235783Skib 46235783Skibvoid 47235783Skibdrm_gem_names_init(struct drm_gem_names *names) 48235783Skib{ 49235783Skib 50235783Skib names->unr = new_unrhdr(1, INT_MAX, NULL); /* XXXKIB */ 51235783Skib names->names_hash = hashinit(1000 /* XXXKIB */, M_GEM_NAMES, 52235783Skib &names->hash_mask); 53235783Skib mtx_init(&names->lock, "drmnames", NULL, MTX_DEF); 54235783Skib} 55235783Skib 56235783Skibvoid 57235783Skibdrm_gem_names_fini(struct drm_gem_names *names) 58235783Skib{ 59235783Skib struct drm_gem_name *np; 60235783Skib int i; 61235783Skib 62235783Skib mtx_lock(&names->lock); 63235783Skib for (i = 0; i <= names->hash_mask; i++) { 64235783Skib while ((np = LIST_FIRST(&names->names_hash[i])) != NULL) { 65235783Skib drm_gem_names_delete_name(names, np); 66235783Skib mtx_lock(&names->lock); 67235783Skib } 68235783Skib } 69235783Skib mtx_unlock(&names->lock); 70235783Skib mtx_destroy(&names->lock); 71235783Skib hashdestroy(names->names_hash, M_GEM_NAMES, names->hash_mask); 72235783Skib delete_unrhdr(names->unr); 73235783Skib} 74235783Skib 75235783Skibstatic struct drm_gem_names_head * 76235783Skibgem_name_hash_index(struct drm_gem_names *names, int name) 77235783Skib{ 78235783Skib 79235783Skib return (&names->names_hash[name & names->hash_mask]); 80235783Skib} 81235783Skib 82235783Skibvoid * 83235783Skibdrm_gem_name_ref(struct drm_gem_names *names, uint32_t name, 84235783Skib void (*ref)(void *)) 85235783Skib{ 86235783Skib struct drm_gem_name *n; 87235783Skib 88235783Skib mtx_lock(&names->lock); 89235783Skib LIST_FOREACH(n, gem_name_hash_index(names, name), link) { 90235783Skib if (n->name == name) { 91235783Skib if (ref != NULL) 92235783Skib ref(n->ptr); 93235783Skib mtx_unlock(&names->lock); 94235783Skib return (n->ptr); 95235783Skib } 96235783Skib } 97235783Skib mtx_unlock(&names->lock); 98235783Skib return (NULL); 99235783Skib} 100235783Skib 101235783Skibstruct drm_gem_ptr_match_arg { 102235783Skib uint32_t res; 103235783Skib void *ptr; 104235783Skib}; 105235783Skib 106235783Skibstatic int 107235783Skibdrm_gem_ptr_match(uint32_t name, void *ptr, void *arg) 108235783Skib{ 109235783Skib struct drm_gem_ptr_match_arg *a; 110235783Skib 111235783Skib a = arg; 112235783Skib if (ptr == a->ptr) { 113235783Skib a->res = name; 114235783Skib return (1); 115235783Skib } else 116235783Skib return (0); 117235783Skib} 118235783Skib 119235783Skibuint32_t 120235783Skibdrm_gem_find_name(struct drm_gem_names *names, void *ptr) 121235783Skib{ 122235783Skib struct drm_gem_ptr_match_arg arg; 123235783Skib 124235783Skib arg.res = 0; 125235783Skib arg.ptr = ptr; 126235783Skib drm_gem_names_foreach(names, drm_gem_ptr_match, &arg); 127235783Skib return (arg.res); 128235783Skib} 129235783Skib 130271816Sdumbbellvoid * 131271816Sdumbbelldrm_gem_find_ptr(struct drm_gem_names *names, uint32_t name) 132271816Sdumbbell{ 133271816Sdumbbell struct drm_gem_name *n; 134271816Sdumbbell void *res; 135271816Sdumbbell 136271816Sdumbbell mtx_lock(&names->lock); 137271816Sdumbbell LIST_FOREACH(n, gem_name_hash_index(names, name), link) { 138271816Sdumbbell if (n->name == name) { 139271816Sdumbbell res = n->ptr; 140271816Sdumbbell mtx_unlock(&names->lock); 141271816Sdumbbell return (res); 142271816Sdumbbell } 143271816Sdumbbell } 144271816Sdumbbell mtx_unlock(&names->lock); 145271816Sdumbbell return (NULL); 146271816Sdumbbell} 147271816Sdumbbell 148235783Skibint 149235783Skibdrm_gem_name_create(struct drm_gem_names *names, void *p, uint32_t *name) 150235783Skib{ 151235783Skib struct drm_gem_name *np; 152235783Skib 153235783Skib if (*name != 0) { 154282199Sdumbbell return (-EALREADY); 155235783Skib } 156254838Sdumbbell 157254838Sdumbbell np = malloc(sizeof(struct drm_gem_name), M_GEM_NAMES, M_WAITOK); 158254838Sdumbbell mtx_lock(&names->lock); 159235783Skib np->name = alloc_unr(names->unr); 160235783Skib if (np->name == -1) { 161235783Skib mtx_unlock(&names->lock); 162235783Skib free(np, M_GEM_NAMES); 163282199Sdumbbell return (-ENOMEM); 164235783Skib } 165235783Skib *name = np->name; 166235783Skib np->ptr = p; 167235783Skib LIST_INSERT_HEAD(gem_name_hash_index(names, np->name), np, link); 168235783Skib mtx_unlock(&names->lock); 169235783Skib return (0); 170235783Skib} 171235783Skib 172235783Skibstatic void 173235783Skibdrm_gem_names_delete_name(struct drm_gem_names *names, struct drm_gem_name *np) 174235783Skib{ 175235783Skib 176235783Skib mtx_assert(&names->lock, MA_OWNED); 177235783Skib LIST_REMOVE(np, link); 178235783Skib mtx_unlock(&names->lock); 179235783Skib free_unr(names->unr, np->name); 180235783Skib free(np, M_GEM_NAMES); 181235783Skib} 182235783Skib 183235783Skibvoid * 184235783Skibdrm_gem_names_remove(struct drm_gem_names *names, uint32_t name) 185235783Skib{ 186235783Skib struct drm_gem_name *n; 187235783Skib void *res; 188235783Skib 189235783Skib mtx_lock(&names->lock); 190235783Skib LIST_FOREACH(n, gem_name_hash_index(names, name), link) { 191235783Skib if (n->name == name) { 192235783Skib res = n->ptr; 193235783Skib drm_gem_names_delete_name(names, n); 194235783Skib return (res); 195235783Skib } 196235783Skib } 197235783Skib mtx_unlock(&names->lock); 198235783Skib return (NULL); 199235783Skib} 200235783Skib 201235783Skibvoid 202235783Skibdrm_gem_names_foreach(struct drm_gem_names *names, 203235783Skib int (*f)(uint32_t, void *, void *), void *arg) 204235783Skib{ 205235783Skib struct drm_gem_name *np; 206235783Skib struct drm_gem_name marker; 207235783Skib int i, fres; 208235783Skib 209235783Skib bzero(&marker, sizeof(marker)); 210235783Skib marker.name = -1; 211235783Skib mtx_lock(&names->lock); 212235783Skib for (i = 0; i <= names->hash_mask; i++) { 213235783Skib for (np = LIST_FIRST(&names->names_hash[i]); np != NULL; ) { 214235783Skib if (np->name == -1) { 215235783Skib np = LIST_NEXT(np, link); 216235783Skib continue; 217235783Skib } 218235783Skib LIST_INSERT_AFTER(np, &marker, link); 219235783Skib mtx_unlock(&names->lock); 220235783Skib fres = f(np->name, np->ptr, arg); 221235783Skib mtx_lock(&names->lock); 222235783Skib np = LIST_NEXT(&marker, link); 223235783Skib LIST_REMOVE(&marker, link); 224235783Skib if (fres) 225235783Skib break; 226235783Skib } 227235783Skib } 228235783Skib mtx_unlock(&names->lock); 229235783Skib} 230