#ifndef _VM_OBJECT_
#define _VM_OBJECT_
#include <sys/queue.h>
#include <sys/_blockcount.h>
#include <sys/_lock.h>
#include <sys/_mutex.h>
#include <sys/_pctrie.h>
#include <sys/_rwlock.h>
#include <sys/_domainset.h>
#include <vm/_vm_radix.h>
#ifndef VM_PAGE_HAVE_PGLIST
TAILQ_HEAD(pglist, vm_page);
#define VM_PAGE_HAVE_PGLIST
#endif
struct vm_object {
struct rwlock lock;
TAILQ_ENTRY(vm_object) object_list;
LIST_HEAD(, vm_object) shadow_head;
LIST_ENTRY(vm_object) shadow_list;
struct vm_radix rtree;
vm_pindex_t size;
struct domainset_ref domain;
volatile int generation;
int cleangeneration;
volatile u_int ref_count;
int shadow_count;
vm_memattr_t memattr;
objtype_t type;
u_short pg_color;
u_int flags;
blockcount_t paging_in_progress;
blockcount_t busy;
int resident_page_count;
struct vm_object *backing_object;
vm_ooffset_t backing_object_offset;
TAILQ_ENTRY(vm_object) pager_object_list;
LIST_HEAD(, vm_reserv) rvq;
void *handle;
union {
struct {
off_t vnp_size;
vm_ooffset_t writemappings;
} vnp;
struct {
TAILQ_HEAD(, vm_page) devp_pglist;
const struct cdev_pager_ops *ops;
void *handle;
} devp;
struct {
TAILQ_HEAD(, vm_page) sgp_pglist;
} sgp;
struct {
void *swp_priv;
struct pctrie swp_blks;
vm_ooffset_t writemappings;
} swp;
struct {
const struct phys_pager_ops *ops;
union {
void *data_ptr;
uintptr_t data_val;
};
void *phys_priv;
} phys;
} un_pager;
struct ucred *cred;
void *umtx_data;
};
#define OBJ_FICTITIOUS 0x00000001
#define OBJ_UNMANAGED 0x00000002
#define OBJ_POPULATE 0x00000004
#define OBJ_DEAD 0x00000008
#define OBJ_ANON 0x00000010
#define OBJ_UMTXDEAD 0x00000020
#define OBJ_SIZEVNLOCK 0x00000040
#define OBJ_PG_DTOR 0x00000080
#define OBJ_SHADOWLIST 0x00000100
#define OBJ_SWAP 0x00000200
#define OBJ_SPLIT 0x00000400
#define OBJ_COLLAPSING 0x00000800
#define OBJ_COLORED 0x00001000
#define OBJ_ONEMAPPING 0x00002000
#define OBJ_PAGERPRIV1 0x00004000
#define OBJ_PAGERPRIV2 0x00008000
#define OBJ_SYSVSHM 0x00010000
#define OBJ_POSIXSHM 0x00020000
#define IDX_TO_OFF(idx) (((vm_ooffset_t)(idx)) << PAGE_SHIFT)
#define OFF_TO_IDX(off) ((vm_pindex_t)(((vm_ooffset_t)(off)) >> PAGE_SHIFT))
#define OBJ_MAX_SIZE (OFF_TO_IDX(UINT64_MAX) + 1)
#ifdef _KERNEL
#define OBJPC_SYNC 0x1
#define OBJPC_INVAL 0x2
#define OBJPC_NOSYNC 0x4
#define OBJPR_CLEANONLY 0x1
#define OBJPR_NOTMAPPED 0x2
#define OBJPR_VALIDONLY 0x4
#define OBJCO_CHARGED 0x1
#define OBJCO_NO_CHARGE 0x2
TAILQ_HEAD(object_q, vm_object);
extern struct object_q vm_object_list;
extern struct mtx vm_object_list_mtx;
extern struct vm_object kernel_object_store;
#define kernel_object (&kernel_object_store)
#define VM_OBJECT_ASSERT_LOCKED(object) \
rw_assert(&(object)->lock, RA_LOCKED)
#define VM_OBJECT_ASSERT_RLOCKED(object) \
rw_assert(&(object)->lock, RA_RLOCKED)
#define VM_OBJECT_ASSERT_WLOCKED(object) \
rw_assert(&(object)->lock, RA_WLOCKED)
#define VM_OBJECT_ASSERT_UNLOCKED(object) \
rw_assert(&(object)->lock, RA_UNLOCKED)
#define VM_OBJECT_LOCK_DOWNGRADE(object) \
rw_downgrade(&(object)->lock)
#define VM_OBJECT_RLOCK(object) \
rw_rlock(&(object)->lock)
#define VM_OBJECT_RUNLOCK(object) \
rw_runlock(&(object)->lock)
#define VM_OBJECT_SLEEP(object, wchan, pri, wmesg, timo) \
rw_sleep((wchan), &(object)->lock, (pri), (wmesg), (timo))
#define VM_OBJECT_TRYRLOCK(object) \
rw_try_rlock(&(object)->lock)
#define VM_OBJECT_TRYWLOCK(object) \
rw_try_wlock(&(object)->lock)
#define VM_OBJECT_TRYUPGRADE(object) \
rw_try_upgrade(&(object)->lock)
#define VM_OBJECT_WLOCK(object) \
rw_wlock(&(object)->lock)
#define VM_OBJECT_WOWNED(object) \
rw_wowned(&(object)->lock)
#define VM_OBJECT_WUNLOCK(object) \
rw_wunlock(&(object)->lock)
#define VM_OBJECT_UNLOCK(object) \
rw_unlock(&(object)->lock)
#define VM_OBJECT_DROP(object) \
lock_class_rw.lc_unlock(&(object)->lock.lock_object)
#define VM_OBJECT_PICKUP(object, state) \
lock_class_rw.lc_lock(&(object)->lock.lock_object, (state))
#define VM_OBJECT_ASSERT_PAGING(object) \
KASSERT(blockcount_read(&(object)->paging_in_progress) != 0, \
("vm_object %p is not paging", object))
#define VM_OBJECT_ASSERT_REFERENCE(object) \
KASSERT((object)->reference_count != 0, \
("vm_object %p is not referenced", object))
struct vnode;
static __inline void
vm_object_set_flag(vm_object_t object, u_int bits)
{
object->flags |= bits;
}
static __inline void
vm_object_color(vm_object_t object, u_short color)
{
if ((object->flags & OBJ_COLORED) == 0) {
object->pg_color = color;
vm_object_set_flag(object, OBJ_COLORED);
}
}
static __inline bool
vm_object_reserv(vm_object_t object)
{
if (object != NULL &&
(object->flags & (OBJ_COLORED | OBJ_FICTITIOUS)) == OBJ_COLORED) {
return (true);
}
return (false);
}
void vm_object_clear_flag(vm_object_t object, u_short bits);
void vm_object_pip_add(vm_object_t object, short i);
void vm_object_pip_wakeup(vm_object_t object);
void vm_object_pip_wakeupn(vm_object_t object, short i);
void vm_object_pip_wait(vm_object_t object, const char *waitid);
void vm_object_pip_wait_unlocked(vm_object_t object, const char *waitid);
void vm_object_busy(vm_object_t object);
void vm_object_unbusy(vm_object_t object);
void vm_object_busy_wait(vm_object_t object, const char *wmesg);
static inline bool
vm_object_busied(vm_object_t object)
{
return (blockcount_read(&object->busy) != 0);
}
#define VM_OBJECT_ASSERT_BUSY(object) MPASS(vm_object_busied((object)))
void umtx_shm_object_init(vm_object_t object);
void umtx_shm_object_terminated(vm_object_t object);
extern int umtx_shm_vnobj_persistent;
vm_object_t vm_object_allocate (objtype_t, vm_pindex_t);
vm_object_t vm_object_allocate_anon(vm_pindex_t, vm_object_t, struct ucred *);
vm_object_t vm_object_allocate_dyn(objtype_t, vm_pindex_t, u_short);
boolean_t vm_object_coalesce(vm_object_t, vm_ooffset_t, vm_size_t, vm_size_t,
int);
void vm_object_collapse (vm_object_t);
void vm_object_deallocate (vm_object_t);
void vm_object_destroy (vm_object_t);
void vm_object_terminate (vm_object_t);
void vm_object_set_writeable_dirty (vm_object_t);
void vm_object_set_writeable_dirty_(vm_object_t object);
bool vm_object_mightbedirty(vm_object_t object);
bool vm_object_mightbedirty_(vm_object_t object);
void vm_object_init (void);
int vm_object_kvme_type(vm_object_t object, struct vnode **vpp);
void vm_object_madvise(vm_object_t, vm_pindex_t, vm_pindex_t, int);
boolean_t vm_object_page_clean(vm_object_t object, vm_ooffset_t start,
vm_ooffset_t end, int flags);
void vm_object_page_noreuse(vm_object_t object, vm_pindex_t start,
vm_pindex_t end);
void vm_object_page_remove(vm_object_t object, vm_pindex_t start,
vm_pindex_t end, int options);
boolean_t vm_object_populate(vm_object_t, vm_pindex_t, vm_pindex_t);
void vm_object_prepare_buf_pages(vm_object_t object, vm_page_t *ma_dst,
int count, int *rbehind, int *rahead, vm_page_t *ma_src);
void vm_object_print(long addr, boolean_t have_addr, long count, char *modif);
void vm_object_reference (vm_object_t);
void vm_object_reference_locked(vm_object_t);
int vm_object_set_memattr(vm_object_t object, vm_memattr_t memattr);
void vm_object_shadow(vm_object_t *, vm_ooffset_t *, vm_size_t, struct ucred *,
bool);
void vm_object_split(vm_map_entry_t);
boolean_t vm_object_sync(vm_object_t, vm_ooffset_t, vm_size_t, boolean_t,
boolean_t);
void vm_object_unwire(vm_object_t object, vm_ooffset_t offset,
vm_size_t length, uint8_t queue);
struct vnode *vm_object_vnode(vm_object_t object);
bool vm_object_is_active(vm_object_t obj);
#endif
#endif