-struct pshmnode {
- off_t mapp_addr;
- user_size_t map_size; /* XXX unused ? */
- struct pshminfo *pinfo;
- unsigned int pshm_usecount;
-#if DIAGNOSTIC
- unsigned int readcnt;
- unsigned int writecnt;
-#endif
-};
-#define PSHMNODE_NULL (struct pshmnode *)0
-
-
-#define PSHMHASH(pnp) \
- (&pshmhashtbl[(pnp)->pshm_hash & pshmhash])
-
-LIST_HEAD(pshmhashhead, pshmcache) *pshmhashtbl; /* Hash Table */
-u_long pshmhash; /* size of hash table - 1 */
-long pshmnument; /* number of cache entries allocated */
-struct pshmstats pshmstats; /* cache effectiveness statistics */
-
-static int pshm_read (struct fileproc *fp, struct uio *uio,
- int flags, vfs_context_t ctx);
-static int pshm_write (struct fileproc *fp, struct uio *uio,
- int flags, vfs_context_t ctx);
-static int pshm_ioctl (struct fileproc *fp, u_long com,
- caddr_t data, vfs_context_t ctx);
-static int pshm_select (struct fileproc *fp, int which, void *wql, vfs_context_t ctx);
-static int pshm_close(struct pshminfo *pinfo, int dropref);
-static int pshm_closefile (struct fileglob *fg, vfs_context_t ctx);
-
-static int pshm_kqfilter(struct fileproc *fp, struct knote *kn, vfs_context_t ctx);
-
-int pshm_access(struct pshminfo *pinfo, int mode, kauth_cred_t cred, proc_t p);
-static int pshm_cache_add(struct pshminfo *pshmp, struct pshmname *pnp, struct pshmcache *pcp);
-static void pshm_cache_delete(struct pshmcache *pcp);
-#if NOT_USED
-static void pshm_cache_purge(void);
-#endif /* NOT_USED */
-static int pshm_cache_search(struct pshminfo **pshmp, struct pshmname *pnp,
- struct pshmcache **pcache, int addref);
+/*
+ * These handle reference counting pshm_info_t structs using pshm_usecount.
+ */
+static int pshm_ref(pshm_info_t *pinfo);
+static void pshm_deref(pshm_info_t *pinfo);
+#define PSHM_MAXCOUNT UINT_MAX
+
+/*
+ * For every shm_open, we get a new one of these.
+ * The only reason we don't just use pshm_info directly is that
+ * you can query the mapped memory objects via proc_pidinfo to
+ * query the mapped address. Note that even this is a hack. If
+ * you mmap() the same fd multiple times, we only save/report
+ * one address.
+ */
+typedef struct pshmnode {
+ off_t mapp_addr;
+ pshm_info_t *pinfo;
+} pshmnode_t;
+
+
+/* compare function for the red black tree */
+static int
+pshm_compare(pshm_info_t *a, pshm_info_t *b)
+{
+ int cmp = strncmp(a->pshm_hdr.pshm_name, b->pshm_hdr.pshm_name, PSHMNAMLEN + 1);
+
+ if (cmp < 0) {
+ return -1;
+ }
+ if (cmp > 0) {
+ return 1;
+ }
+ return 0;
+}
+
+
+/*
+ * shared memory "paths" are stored in a red black tree for lookup
+ */
+u_long pshmnument; /* count of entries allocated in the red black tree */
+RB_HEAD(pshmhead, internal_pshminfo) pshm_head;
+RB_PROTOTYPE(pshmhead, internal_pshminfo, pshm_links, pshm_compare)
+RB_GENERATE(pshmhead, internal_pshminfo, pshm_links, pshm_compare)
+
+/* lookup, add, remove functions */
+static pshm_info_t *pshm_cache_search(pshm_info_t * look);
+static void pshm_cache_add(pshm_info_t *entry);
+static void pshm_cache_delete(pshm_info_t *entry);
+
+static int pshm_closefile(struct fileglob *fg, vfs_context_t ctx);
+
+static int pshm_access(pshm_info_t *pinfo, int mode, kauth_cred_t cred, proc_t p);
+int pshm_cache_purge_all(proc_t p);
+
+static int pshm_unlink_internal(pshm_info_t *pinfo);