void hash_insert(struct locked_hash_table *table, unsigned long key, void *value) { pthread_rwlock_wrlock(&table->lock); drmHashInsert(table->table, key, value); pthread_rwlock_unlock(&table->lock); }
drm_public int drm_tegra_bo_get_name(struct drm_tegra_bo *bo, uint32_t *name) { if (!bo || !name) return -EINVAL; if (!bo->name) { struct drm_gem_flink args; int err; memset(&args, 0, sizeof(args)); args.handle = bo->handle; err = drmIoctl(bo->drm->fd, DRM_IOCTL_GEM_FLINK, &args); if (err < 0) { VDBG_BO(bo, "err %d strerror(%s)\n", err, strerror(-err)); return -errno; } pthread_mutex_lock(&table_lock); drmHashInsert(bo->drm->name_table, args.name, bo); bo->name = args.name; pthread_mutex_unlock(&table_lock); } *name = bo->name; DBG_BO(bo, "\n"); return 0; }
/* allocate a new buffer object, call w/ table_lock held */ static struct etna_bo * bo_from_handle(struct etna_device *dev, uint32_t size, uint32_t handle) { unsigned int i; struct etna_bo *bo = calloc(sizeof(*bo), 1); if (!bo) { struct drm_gem_close req = { .handle = handle, }; drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req); return NULL; } for (i = 0; i < ARRAY_SIZE(bo->list); i++) list_inithead(&bo->list[i]); bo->dev = etna_device_ref(dev); bo->size = size; bo->handle = handle; atomic_set(&bo->refcnt, 1); /* add ourselves to the handle table: */ drmHashInsert(dev->handle_table, handle, bo); return bo; }
/* allocate a new buffer object, call w/ table_lock held */ static struct omap_bo * bo_from_handle(struct omap_device *dev, uint32_t handle) { struct omap_bo *bo = calloc(sizeof(*bo), 1); if (!bo) { struct drm_gem_close req = { .handle = handle, }; drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req); return NULL; } bo->dev = omap_device_ref(dev); bo->handle = handle; atomic_set(&bo->refcnt, 1); /* add ourselves to the handle table: */ drmHashInsert(dev->handle_table, handle, bo); return bo; }
drm_public int drm_tegra_bo_wrap(struct drm_tegra_bo **bop, struct drm_tegra *drm, uint32_t handle, uint32_t flags, uint32_t size) { struct drm_tegra_bo *bo; int err = 0; if (!drm || !bop) return -EINVAL; pthread_mutex_lock(&table_lock); /* check handle table to see if BO is already open */ bo = lookup_bo(drm->handle_table, handle); if (bo) goto unlock; bo = calloc(1, sizeof(*bo)); if (!bo) { err = -ENOMEM; goto unlock; } DRMINITLISTHEAD(&bo->push_list); DRMINITLISTHEAD(&bo->bo_list); atomic_set(&bo->ref, 1); bo->handle = handle; bo->flags = flags; bo->size = size; bo->drm = drm; VG_BO_ALLOC(bo); /* add ourselves into the handle table */ drmHashInsert(drm->handle_table, handle, bo); DBG_BO(bo, "success\n"); unlock: pthread_mutex_unlock(&table_lock); *bop = bo; return err; }
struct fd_device * fd_device_new(int fd) { struct fd_device *dev = NULL; int key = fd; pthread_mutex_lock(&table_lock); if (!dev_table) dev_table = drmHashCreate(); if (drmHashLookup(dev_table, key, (void **)&dev)) { dev = fd_device_new_impl(fd); if (dev) drmHashInsert(dev_table, key, dev); } else { dev = fd_device_ref(dev); } pthread_mutex_unlock(&table_lock); return dev; }
drm_public struct omap_device * omap_device_new(int fd) { struct omap_device *dev = NULL; pthread_mutex_lock(&table_lock); if (!dev_table) dev_table = drmHashCreate(); if (drmHashLookup(dev_table, fd, (void **)&dev)) { /* not found, create new device */ dev = omap_device_new_impl(fd); drmHashInsert(dev_table, fd, dev); } else { /* found, just incr refcnt */ dev = omap_device_ref(dev); } pthread_mutex_unlock(&table_lock); return dev; }
/* allocate a new buffer object, call w/ table_lock held */ static struct fd_bo * bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle) { struct fd_bo *bo; bo = dev->funcs->bo_from_handle(dev, size, handle); if (!bo) { struct drm_gem_close req = { .handle = handle, }; drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req); return NULL; } bo->dev = fd_device_ref(dev); bo->size = size; bo->handle = handle; atomic_set(&bo->refcnt, 1); list_inithead(&bo->list); /* add ourself into the handle table: */ drmHashInsert(dev->handle_table, handle, bo); return bo; }
/* set buffer name, and add to table, call w/ table_lock held: */ static void set_name(struct etna_bo *bo, uint32_t name) { bo->name = name; /* add ourself into the handle table: */ drmHashInsert(bo->dev->handle_table, name, bo); }
int getDRIDrawableInfoLocked(void *drawHash, Display *display, int screen, Drawable draw, unsigned lockFlags, int drmFD, drm_context_t drmContext, drmAddress sarea, Bool updateInfo, drawableInfo **info, unsigned long infoSize) { drawableInfo *drawInfo; void *res; drm_drawable_t drmDraw=0; volatile drm_sarea_t *pSarea = (drm_sarea_t *) sarea; drm_clip_rect_t *clipFront, *clipBack; int ret; if (drmHashLookup(drawHash, (unsigned long) draw, &res)) { /* * The drawable is unknown to us. Create it and put it in the * hash table. */ DRM_UNLOCK(drmFD, &pSarea->lock, drmContext); if (!uniDRICreateDrawable(display, screen, draw, &drmDraw)) { DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags); return 1; } DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags); drawInfo = (drawableInfo *) malloc(infoSize); if (!drawInfo) return 1; drawInfo->drmDraw = drmDraw; drawInfo->stamp = 0; drawInfo->clipFront = 0; drawInfo->clipBack = 0; drmHashInsert( drawHash, (unsigned long) draw, drawInfo); } else { drawInfo = res; } drawInfo->touched = FALSE; while (!drawInfo->clipFront || drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) { /* * The drawable has been touched since we last got info about it. * obtain new info from the X server. */ drawInfo->touched = TRUE; if (updateInfo || !drawInfo->clipFront) { DRM_UNLOCK(drmFD, &pSarea->lock, drmContext); ret = uniDRIGetDrawableInfo(display, screen, draw, &drawInfo->index, &drawInfo->stamp, &drawInfo->x, &drawInfo->y, &drawInfo->w, &drawInfo->h, &drawInfo->numClipFront, &clipFront, &drawInfo->backX, &drawInfo->backY, &drawInfo->numClipBack, &clipBack); DRM_LIGHT_LOCK(drmFD, &pSarea->lock, drmContext); /* * Error. Probably the drawable is destroyed. Return error and old values. */ if (!ret) { free(drawInfo); drawInfo = NULL; drmHashDelete(drawHash, (unsigned long) draw); DRM_UNLOCK(drmFD, &pSarea->lock, drmContext); uniDRIDestroyDrawable( display, screen, draw); DRM_LOCK(drmFD, &pSarea->lock, drmContext, lockFlags); return 1; } if (drawInfo->stamp != drawStamp(pSarea, drawInfo->index)) { /* * The info is already outdated. Sigh. Have another go. */ XFree(clipFront); XFree(clipBack); continue; } if (drawInfo->clipFront) XFree(drawInfo->clipFront); drawInfo->clipFront = clipFront; if (drawInfo->clipBack) XFree(drawInfo->clipBack); drawInfo->clipBack = clipBack; } else { if (!drawInfo->clipFront) drawInfo->clipFront = (drm_clip_rect_t *) ~0UL; drawInfo->stamp = drawStamp(pSarea, drawInfo->index); } } *info = drawInfo; return 0; }
drm_public int drm_tegra_bo_from_dmabuf(struct drm_tegra_bo **bop, struct drm_tegra *drm, int fd, uint32_t flags) { struct drm_tegra_bo *dup; struct drm_tegra_bo *bo; uint32_t handle; uint32_t size; int err; if (!drm || !bop) return -EINVAL; pthread_mutex_lock(&table_lock); bo = calloc(1, sizeof(*bo)); if (!bo) { err = -ENOMEM; goto unlock; } err = drmPrimeFDToHandle(drm->fd, fd, &handle); if (err) { free(bo); bo = NULL; goto unlock; } /* check handle table to see if BO is already open */ dup = lookup_bo(drm->handle_table, handle); if (dup) { DBG_BO(dup, "success reused\n"); free(bo); bo = dup; goto unlock; } errno = 0; /* lseek() to get bo size */ size = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_CUR); /* store lseek() error number */ err = -errno; atomic_set(&bo->ref, 1); bo->handle = handle; bo->flags = flags; bo->size = size; bo->drm = drm; VG_BO_ALLOC(bo); /* add ourself into the handle table: */ drmHashInsert(drm->handle_table, handle, bo); /* handle lseek() error */ if (err) { VDBG_BO(bo, "lseek failed %d (%s)\n", err, strerror(-err)); drm_tegra_bo_free(bo); bo = NULL; } else { DBG_BO(bo, "success\n"); } unlock: pthread_mutex_unlock(&table_lock); *bop = bo; return err; }
drm_public int drm_tegra_bo_from_name(struct drm_tegra_bo **bop, struct drm_tegra *drm, uint32_t name, uint32_t flags) { struct drm_gem_open args; struct drm_tegra_bo *dup; struct drm_tegra_bo *bo; int err = 0; if (!drm || !name || !bop) return -EINVAL; pthread_mutex_lock(&table_lock); /* check name table first, to see if BO is already open */ bo = lookup_bo(drm->name_table, name); if (bo) goto unlock; bo = calloc(1, sizeof(*bo)); if (!bo) { err = -ENOMEM; goto unlock; } memset(&args, 0, sizeof(args)); args.name = name; err = drmIoctl(drm->fd, DRM_IOCTL_GEM_OPEN, &args); if (err < 0) { VDBG_DRM(drm, "failed name 0x%08X err %d strerror(%s)\n", name, err, strerror(-err)); err = -errno; free(bo); bo = NULL; goto unlock; } /* check handle table second, to see if BO is already open */ dup = lookup_bo(drm->handle_table, args.handle); if (dup) { VDBG_BO(dup, "success reused name 0x%08X\n", name); free(bo); bo = dup; goto unlock; } drmHashInsert(drm->name_table, name, bo); atomic_set(&bo->ref, 1); bo->name = name; bo->handle = args.handle; bo->flags = flags; bo->size = args.size; bo->drm = drm; DBG_BO(bo, "success\n"); VG_BO_ALLOC(bo); unlock: pthread_mutex_unlock(&table_lock); *bop = bo; return err; }
drm_public int drm_tegra_bo_new(struct drm_tegra_bo **bop, struct drm_tegra *drm, uint32_t flags, uint32_t size) { struct drm_tegra_gem_create args; struct drm_tegra_bo *bo; int err; if (!drm || size == 0 || !bop) return -EINVAL; pthread_mutex_lock(&table_lock); bo = drm_tegra_bo_cache_alloc(drm, &size, flags); pthread_mutex_unlock(&table_lock); if (bo) { DBG_BO(bo, "success from cache\n"); goto out; } bo = calloc(1, sizeof(*bo)); if (!bo) return -ENOMEM; DRMINITLISTHEAD(&bo->push_list); DRMINITLISTHEAD(&bo->bo_list); atomic_set(&bo->ref, 1); bo->reuse = true; bo->flags = flags; bo->size = size; bo->drm = drm; memset(&args, 0, sizeof(args)); args.flags = flags; args.size = size; #ifndef NDEBUG if (drm->debug_bo_front_guard) { bo->offset += 4096; args.size += 4096; } if (drm->debug_bo_back_guard) args.size += 4096; #endif err = drmCommandWriteRead(drm->fd, DRM_TEGRA_GEM_CREATE, &args, sizeof(args)); if (err < 0) { VDBG_DRM(drm, "failed size %u bytes flags 0x%08X err %d (%s)\n", size, flags, err, strerror(-err)); free(bo); return err; } bo->handle = args.handle; DBG_BO(bo, "success new\n"); VG_BO_ALLOC(bo); #ifndef NDEBUG if (drm->debug_bo) { bo->debug_size = align(bo->size, 4096); drm->debug_bos_total_size += bo->debug_size; drm->debug_bos_allocated++; } #endif drm_tegra_bo_setup_guards(bo); DBG_BO_STATS(drm); pthread_mutex_lock(&table_lock); /* add ourselves into the handle table */ drmHashInsert(drm->handle_table, args.handle, bo); pthread_mutex_unlock(&table_lock); out: *bop = bo; return 0; }
int main(void) { HashTablePtr table; unsigned long i; int ret = 0; printf("\n***** 256 consecutive integers ****\n"); table = drmHashCreate(); for (i = 0; i < 256; i++) drmHashInsert(table, i, (void *)(i << 16 | i)); for (i = 0; i < 256; i++) ret |= check_table(table, i, (void *)(i << 16 | i)); compute_dist(table); drmHashDestroy(table); printf("\n***** 1024 consecutive integers ****\n"); table = drmHashCreate(); for (i = 0; i < 1024; i++) drmHashInsert(table, i, (void *)(i << 16 | i)); for (i = 0; i < 1024; i++) ret |= check_table(table, i, (void *)(i << 16 | i)); compute_dist(table); drmHashDestroy(table); printf("\n***** 1024 consecutive page addresses (4k pages) ****\n"); table = drmHashCreate(); for (i = 0; i < 1024; i++) drmHashInsert(table, i*4096, (void *)(i << 16 | i)); for (i = 0; i < 1024; i++) ret |= check_table(table, i*4096, (void *)(i << 16 | i)); compute_dist(table); drmHashDestroy(table); printf("\n***** 1024 random integers ****\n"); table = drmHashCreate(); srandom(0xbeefbeef); for (i = 0; i < 1024; i++) drmHashInsert(table, random(), (void *)(i << 16 | i)); srandom(0xbeefbeef); for (i = 0; i < 1024; i++) ret |= check_table(table, random(), (void *)(i << 16 | i)); srandom(0xbeefbeef); for (i = 0; i < 1024; i++) ret |= check_table(table, random(), (void *)(i << 16 | i)); compute_dist(table); drmHashDestroy(table); printf("\n***** 5000 random integers ****\n"); table = drmHashCreate(); srandom(0xbeefbeef); for (i = 0; i < 5000; i++) drmHashInsert(table, random(), (void *)(i << 16 | i)); srandom(0xbeefbeef); for (i = 0; i < 5000; i++) ret |= check_table(table, random(), (void *)(i << 16 | i)); srandom(0xbeefbeef); for (i = 0; i < 5000; i++) ret |= check_table(table, random(), (void *)(i << 16 | i)); compute_dist(table); drmHashDestroy(table); return ret; }