#include #include #include #include #include HandleSet * hs_init(void) { HandleSet *hs = kzalloc(sizeof *hs, "handles"); hs->refcount = 1; return hs; } HandleSet * hs_copy(HandleSet *from) { HandleSet *hs = hs_init(); assert(from); for (hid_t i = 0; i < HANDLE_MAX; i++) { hs->h[i] = from->h[i]; if (hs->h[i]) { hs->h[i]->refcount++; } } return hs; } void hs_unref(HandleSet *hs) { assert(hs); assert(hs->refcount != 0); hs->refcount--; if (hs->refcount == 0) { for (hid_t i = 0; i < HANDLE_MAX; i++) { hs_close(hs, i); } kfree(hs); } } hid_t hs_findfree(HandleSet *hs, hid_t start) { if (start < 0) start = 0; for (hid_t i = start; i < HANDLE_MAX; i++) { if (hs->h[i] == NULL) { return i; } } return -1; } Handle * hs_get(HandleSet *hs, hid_t id) { if (0 <= id && id < HANDLE_MAX) { return hs->h[id]; } else { return NULL; } } hid_t hs_hinit(HandleSet *hs, enum handle_type type, Handle **hp) { hid_t hid = hs_findfree(hs, 1); if (hid < 0) return -1; hs->h[hid] = handle_init(type); if (hp) *hp = hs->h[hid]; return hid; } hid_t hs_dup(HandleSet *hs, hid_t from, hid_t to, int flags) { Handle *fromh, **toh; if (to < 0 || (flags & DUP_SEARCH)) { to = hs_findfree(hs, to); if (to < 0) return -EMFILE; } else if (to >= HANDLE_MAX) { return -EBADF; } if (to == from) return to; toh = &hs->h[to]; fromh = hs_get(hs, from); if (*toh) handle_close(*toh); *toh = fromh; if (fromh) fromh->refcount++; return to; } Handle * hs_take(HandleSet *hs, hid_t hid) { if (hid < 0 || hid >= HANDLE_MAX) { return NULL; } Handle *h = hs->h[hid]; hs->h[hid] = NULL; return h; } hid_t hs_put(HandleSet *hs, Handle *h) { assert(h); hid_t hid = hs_findfree(hs, 1); if (hid < 0) { handle_close(h); return hid; } hs->h[hid] = h; return hid; }