#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)
#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)
{
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);
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);
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);
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
{
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);
}
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;
}
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:
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);
}