#ifndef _IPC_IMPL_H
#define _IPC_IMPL_H
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/mutex.h>
#include <sys/ipc_rctl.h>
#include <sys/project.h>
#include <sys/zone.h>
#include <sys/sysmacros.h>
#include <sys/avl.h>
#include <sys/id_space.h>
#include <sys/cred.h>
#include <sys/list.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef uint64_t ipc_time_t;
#define IPC_SET64 13
#define IPC_STAT64 14
#if defined(_SYSCALL32)
struct ipc_perm32 {
uid32_t uid;
gid32_t gid;
uid32_t cuid;
gid32_t cgid;
mode32_t mode;
uint32_t seq;
key32_t key;
int32_t pad[4];
};
#endif
typedef struct ipc_perm64 {
uid_t ipcx_uid;
gid_t ipcx_gid;
uid_t ipcx_cuid;
gid_t ipcx_cgid;
mode_t ipcx_mode;
key_t ipcx_key;
projid_t ipcx_projid;
zoneid_t ipcx_zoneid;
} ipc_perm64_t;
struct shmid_ds64 {
ipc_perm64_t shmx_perm;
pid_t shmx_lpid;
pid_t shmx_cpid;
uint64_t shmx_segsz;
uint64_t shmx_nattch;
uint64_t shmx_cnattch;
uint64_t shmx_lkcnt;
ipc_time_t shmx_atime;
ipc_time_t shmx_dtime;
ipc_time_t shmx_ctime;
};
struct semid_ds64 {
ipc_perm64_t semx_perm;
ushort_t semx_nsems;
ushort_t _semx_pad[3];
ipc_time_t semx_otime;
ipc_time_t semx_ctime;
};
struct msqid_ds64 {
ipc_perm64_t msgx_perm;
uint64_t msgx_cbytes;
uint64_t msgx_qnum;
uint64_t msgx_qbytes;
pid_t msgx_lspid;
pid_t msgx_lrpid;
ipc_time_t msgx_stime;
ipc_time_t msgx_rtime;
ipc_time_t msgx_ctime;
};
#ifdef _KERNEL
#define IPC_FREE(x) (((x)->ipc_mode & IPC_ALLOC) == 0)
#define IPC_SEQ_BITS 7
#define IPC_SEQ_MASK ((1 << IPC_SEQ_BITS) - 1)
#define IPC_SEQ_SHIFT (31 - IPC_SEQ_BITS)
#define IPC_INDEX_MASK ((1 << IPC_SEQ_SHIFT) - 1)
#define IPC_SEQ(x) ((unsigned int)(x) >> IPC_SEQ_SHIFT)
#define IPC_INDEX(x) ((unsigned int)(x) & IPC_INDEX_MASK)
#define IPC_IDS_MIN (PAGESIZE / 64)
#define IPC_IDS_MAX (1 << IPC_SEQ_SHIFT)
#define IPC_ID_INVAL UINT_MAX
#define IPC_PROJ_USAGE(p, s) \
(*(rctl_qty_t *)(((char *)&p->ipc_proj->kpj_data.kpd_ipc) + \
s->ipcs_rctlofs))
#define IPC_ZONE_USAGE(p, s) \
(*(rctl_qty_t *)(((char *)&p->ipc_zone_ref.zref_zone->zone_ipc) + \
s->ipcs_rctlofs))
#define IPC_LOCKED(s, o) \
MUTEX_HELD(&s->ipcs_table[IPC_INDEX(o->ipc_id)].ipct_lock)
typedef struct kipc_perm {
avl_node_t ipc_avl;
list_node_t ipc_list;
uint_t ipc_ref;
uid_t ipc_uid;
gid_t ipc_gid;
uid_t ipc_cuid;
gid_t ipc_cgid;
mode_t ipc_mode;
key_t ipc_key;
kproject_t *ipc_proj;
uint_t ipc_id;
zoneid_t ipc_zoneid;
zone_ref_t ipc_zone_ref;
} kipc_perm_t;
typedef struct ipc_slot {
kmutex_t ipct_lock;
kipc_perm_t *ipct_data;
uint_t ipct_seq;
struct ipc_slot *ipct_chain;
char ipct_pad[64 - sizeof (kmutex_t) - 3 * sizeof (void *)];
} ipc_slot_t;
typedef void(ipc_func_t)(kipc_perm_t *);
typedef struct ipc_service {
kmutex_t ipcs_lock;
avl_tree_t ipcs_keys;
ipc_slot_t *ipcs_table;
uint_t ipcs_tabsz;
uint_t ipcs_count;
rctl_hndl_t ipcs_proj_rctl;
rctl_hndl_t ipcs_zone_rctl;
size_t ipcs_rctlofs;
id_space_t *ipcs_ids;
size_t ipcs_ssize;
ipc_func_t *ipcs_dtor;
ipc_func_t *ipcs_rmid;
list_t ipcs_usedids;
int ipcs_atype;
} ipc_service_t;
int ipcperm_access(kipc_perm_t *, int, cred_t *);
int ipcperm_set(ipc_service_t *, struct cred *, kipc_perm_t *,
struct ipc_perm *, model_t);
void ipcperm_stat(struct ipc_perm *, kipc_perm_t *, model_t);
int ipcperm_set64(ipc_service_t *, struct cred *, kipc_perm_t *,
ipc_perm64_t *);
void ipcperm_stat64(ipc_perm64_t *, kipc_perm_t *);
ipc_service_t *ipcs_create(const char *, rctl_hndl_t, rctl_hndl_t, size_t,
ipc_func_t *, ipc_func_t *, int, size_t);
void ipcs_destroy(ipc_service_t *);
void ipcs_lock(ipc_service_t *);
void ipcs_unlock(ipc_service_t *);
kmutex_t *ipc_lock(ipc_service_t *, int);
kmutex_t *ipc_relock(ipc_service_t *, int, kmutex_t *);
kmutex_t *ipc_lookup(ipc_service_t *, int, kipc_perm_t **);
void ipc_hold(ipc_service_t *, kipc_perm_t *);
void ipc_rele(ipc_service_t *, kipc_perm_t *);
void ipc_rele_locked(ipc_service_t *, kipc_perm_t *);
int ipc_get(ipc_service_t *, key_t, int, kipc_perm_t **, kmutex_t **);
int ipc_commit_begin(ipc_service_t *, key_t, int, kipc_perm_t *);
kmutex_t *ipc_commit_end(ipc_service_t *, kipc_perm_t *);
void ipc_cleanup(ipc_service_t *, kipc_perm_t *);
int ipc_rmid(ipc_service_t *, int, cred_t *);
int ipc_ids(ipc_service_t *, int *, uint_t, uint_t *);
void ipc_remove_zone(ipc_service_t *, zoneid_t);
#else
int msgctl64(int, int, struct msqid_ds64 *);
int semctl64(int, int, int, ...);
int shmctl64(int, int, struct shmid_ds64 *);
#endif
#ifdef __cplusplus
}
#endif
#endif