static void primop_table_ref(long argc) { object o = sp[1]; long i = the_long(2,o); o = *sp++; TYPE_CHECK(TABLE_P(o),1,"table",o); if (i < 0 || i >= TABLE_COUNT(o)) error(MAKE_FIXNUM(i),"index out of range"); *sp = TABLE_ELEMENTS(o)[i*2+1]; }
object make_table(long capacity) { object bindings = make_vector(capacity*2, false_object); long size = sizeof(struct table_heap_structure); object *ve, v; PUSH_GC_PROTECT(bindings); v = make_heap_object(TABLE_TYPE,size); TABLE_COUNT(v) = 0; VECTOR_TAG(bindings) = false_object; /* FIX ME */ TABLE_BINDINGS(v) = bindings; POP_GC_PROTECT(1); return v; }
static void primop_table_get(long argc) { object tbl = *sp++; object key = *sp; object *pBindings; long i, imax; TYPE_CHECK(TABLE_P(tbl),1,"table",tbl); pBindings = TABLE_ELEMENTS(tbl); imax = TABLE_COUNT(tbl); while (imax-- > 0) { if (eq_p(*pBindings++, key)) { *sp = *pBindings; return; } else pBindings++; } *sp = false_object; }
/* * Put a lnode in the table */ static void lsave(lnode_t *lp, struct loinfo *li) { ASSERT(lp->lo_vp); ASSERT(MUTEX_HELD(TABLE_LOCK(lp->lo_vp, li))); #ifdef LODEBUG lo_dprint(4, "lsave lp %p hash %d\n", lp, ltablehash(lp->lo_vp, li)); #endif TABLE_COUNT(lp->lo_vp, li)++; lp->lo_next = TABLE_BUCKET(lp->lo_vp, li); TABLE_BUCKET(lp->lo_vp, li) = lp; if (li->li_refct > (li->li_htsize << lo_resize_threshold)) { TABLE_LOCK_EXIT(lp->lo_vp, li); lgrow(li, li->li_htsize << lo_resize_factor); TABLE_LOCK_ENTER(lp->lo_vp, li); } }
static void primop_table_count(long argc) { object o = *sp; TYPE_CHECK(TABLE_P(o),1,"table",o); *sp = MAKE_FIXNUM(TABLE_COUNT(o)); }
/* * Remove a lnode from the table */ void freelonode(lnode_t *lp) { lnode_t *lt; lnode_t *ltprev = NULL; struct lfsnode *lfs, *nextlfs; struct vfs *vfsp; struct vnode *vp = ltov(lp); struct vnode *realvp = realvp(vp); struct loinfo *li = vtoli(vp->v_vfsp); #ifdef LODEBUG lo_dprint(4, "freelonode lp %p hash %d\n", lp, ltablehash(lp->lo_vp, li)); #endif TABLE_LOCK_ENTER(lp->lo_vp, li); mutex_enter(&vp->v_lock); if (vp->v_count > 1) { vp->v_count--; /* release our hold from vn_rele */ mutex_exit(&vp->v_lock); TABLE_LOCK_EXIT(lp->lo_vp, li); return; } mutex_exit(&vp->v_lock); for (lt = TABLE_BUCKET(lp->lo_vp, li); lt != NULL; ltprev = lt, lt = lt->lo_next) { if (lt == lp) { #ifdef LODEBUG lo_dprint(4, "freeing %p, vfsp %p\n", vp, vp->v_vfsp); #endif atomic_dec_32(&li->li_refct); vfsp = vp->v_vfsp; vn_invalid(vp); if (vfsp != li->li_mountvfs) { mutex_enter(&li->li_lfslock); /* * Check for unused lfs */ lfs = li->li_lfs; while (lfs != NULL) { nextlfs = lfs->lfs_next; if (vfsp == &lfs->lfs_vfs) { lfs_rele(lfs, li); break; } if (lfs->lfs_vfs.vfs_count == 1) { /* * Lfs is idle */ freelfsnode(lfs, li); } lfs = nextlfs; } mutex_exit(&li->li_lfslock); } if (ltprev == NULL) { TABLE_BUCKET(lt->lo_vp, li) = lt->lo_next; } else { ltprev->lo_next = lt->lo_next; } TABLE_COUNT(lt->lo_vp, li)--; TABLE_LOCK_EXIT(lt->lo_vp, li); kmem_cache_free(lnode_cache, lt); vn_free(vp); VN_RELE(realvp); return; } } panic("freelonode"); /*NOTREACHED*/ }