Move blob from compiler/ to util/
[mesa.git] / src / intel / vulkan / anv_allocator.c
index dd967165bbb26dce7d33a779a796f4b431edd1e3..62a527ed235f1b97d7840d13f30e4510b1271dc7 100644 (file)
 #include <unistd.h>
 #include <limits.h>
 #include <assert.h>
-#include <linux/memfd.h>
 #include <sys/mman.h>
 
 #include "anv_private.h"
 
 #include "util/hash_table.h"
 #include "util/simple_mtx.h"
+#include "util/anon_file.h"
 
 #ifdef HAVE_VALGRIND
 #define VG_NOACCESS_READ(__ptr) ({                       \
 #define VG_NOACCESS_WRITE(__ptr, __val) (*(__ptr) = (__val))
 #endif
 
+#ifndef MAP_POPULATE
+#define MAP_POPULATE 0
+#endif
+
 /* Design goals:
  *
  *  - Lock free (except when resizing underlying bos)
@@ -111,14 +115,6 @@ struct anv_mmap_cleanup {
 
 #define ANV_MMAP_CLEANUP_INIT ((struct anv_mmap_cleanup){0})
 
-#ifndef HAVE_MEMFD_CREATE
-static inline int
-memfd_create(const char *name, unsigned int flags)
-{
-   return syscall(SYS_memfd_create, name, flags);
-}
-#endif
-
 static inline uint32_t
 ilog2_round_up(uint32_t value)
 {
@@ -152,20 +148,17 @@ anv_state_table_init(struct anv_state_table *table,
 
    table->device = device;
 
-   table->fd = memfd_create("state table", MFD_CLOEXEC);
-   if (table->fd == -1)
-      return vk_error(VK_ERROR_INITIALIZATION_FAILED);
-
    /* Just make it 2GB up-front.  The Linux kernel won't actually back it
     * with pages until we either map and fault on one of them or we use
     * userptr and send a chunk of it off to the GPU.
     */
-   if (ftruncate(table->fd, BLOCK_POOL_MEMFD_SIZE) == -1) {
+   table->fd = os_create_anonymous_file(BLOCK_POOL_MEMFD_SIZE, "state table");
+   if (table->fd == -1) {
       result = vk_error(VK_ERROR_INITIALIZATION_FAILED);
       goto fail_fd;
    }
 
-   if (!u_vector_init(&table->mmap_cleanups,
+   if (!u_vector_init(&table->cleanups,
                       round_to_power_of_two(sizeof(struct anv_state_table_cleanup)),
                       128)) {
       result = vk_error(VK_ERROR_INITIALIZATION_FAILED);
@@ -179,12 +172,12 @@ anv_state_table_init(struct anv_state_table *table,
    uint32_t initial_size = initial_entries * ANV_STATE_ENTRY_SIZE;
    result = anv_state_table_expand_range(table, initial_size);
    if (result != VK_SUCCESS)
-      goto fail_mmap_cleanups;
+      goto fail_cleanups;
 
    return VK_SUCCESS;
 
- fail_mmap_cleanups:
-   u_vector_finish(&table->mmap_cleanups);
+ fail_cleanups:
+   u_vector_finish(&table->cleanups);
  fail_fd:
    close(table->fd);
 
@@ -195,7 +188,7 @@ static VkResult
 anv_state_table_expand_range(struct anv_state_table *table, uint32_t size)
 {
    void *map;
-   struct anv_mmap_cleanup *cleanup;
+   struct anv_state_table_cleanup *cleanup;
 
    /* Assert that we only ever grow the pool */
    assert(size >= table->state.end);
@@ -204,11 +197,11 @@ anv_state_table_expand_range(struct anv_state_table *table, uint32_t size)
    if (size > BLOCK_POOL_MEMFD_SIZE)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
-   cleanup = u_vector_add(&table->mmap_cleanups);
+   cleanup = u_vector_add(&table->cleanups);
    if (!cleanup)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
-   *cleanup = ANV_MMAP_CLEANUP_INIT;
+   *cleanup = ANV_STATE_TABLE_CLEANUP_INIT;
 
    /* Just leak the old map until we destroy the pool.  We can't munmap it
     * without races or imposing locking on the block allocate fast path. On
@@ -272,12 +265,12 @@ anv_state_table_finish(struct anv_state_table *table)
 {
    struct anv_state_table_cleanup *cleanup;
 
-   u_vector_foreach(cleanup, &table->mmap_cleanups) {
+   u_vector_foreach(cleanup, &table->cleanups) {
       if (cleanup->map)
          munmap(cleanup->map, cleanup->size);
    }
 
-   u_vector_finish(&table->mmap_cleanups);
+   u_vector_finish(&table->cleanups);
 
    close(table->fd);
 }
@@ -446,18 +439,13 @@ anv_block_pool_init(struct anv_block_pool *pool,
    anv_bo_init(pool->bo, 0, 0);
 
    if (!(pool->bo_flags & EXEC_OBJECT_PINNED)) {
-      pool->fd = memfd_create("block pool", MFD_CLOEXEC);
-      if (pool->fd == -1)
-         return vk_error(VK_ERROR_INITIALIZATION_FAILED);
-
       /* Just make it 2GB up-front.  The Linux kernel won't actually back it
        * with pages until we either map and fault on one of them or we use
        * userptr and send a chunk of it off to the GPU.
        */
-      if (ftruncate(pool->fd, BLOCK_POOL_MEMFD_SIZE) == -1) {
-         result = vk_error(VK_ERROR_INITIALIZATION_FAILED);
-         goto fail_fd;
-      }
+      pool->fd = os_create_anonymous_file(BLOCK_POOL_MEMFD_SIZE, "block pool");
+      if (pool->fd == -1)
+         return vk_error(VK_ERROR_INITIALIZATION_FAILED);
    } else {
       pool->fd = -1;
    }
@@ -478,6 +466,11 @@ anv_block_pool_init(struct anv_block_pool *pool,
    if (result != VK_SUCCESS)
       goto fail_mmap_cleanups;
 
+   /* Make the entire pool available in the front of the pool.  If back
+    * allocation needs to use this space, the "ends" will be re-arranged.
+    */
+   pool->state.end = pool->size;
+
    return VK_SUCCESS;
 
  fail_mmap_cleanups:
@@ -493,10 +486,14 @@ void
 anv_block_pool_finish(struct anv_block_pool *pool)
 {
    struct anv_mmap_cleanup *cleanup;
+   const bool use_softpin = !!(pool->bo_flags & EXEC_OBJECT_PINNED);
 
    u_vector_foreach(cleanup, &pool->mmap_cleanups) {
-      if (cleanup->map)
+      if (use_softpin)
+         anv_gem_munmap(cleanup->map, cleanup->size);
+      else
          munmap(cleanup->map, cleanup->size);
+
       if (cleanup->gem_handle)
          anv_gem_close(pool->device, cleanup->gem_handle);
    }