-struct mbuf_tag_id_entry {
- SLIST_ENTRY(mbuf_tag_id_entry) next;
- mbuf_tag_id_t id;
- char string[];
-};
-
-#define MBUF_TAG_ID_ENTRY_SIZE(__str) \
- ((size_t)&(((struct mbuf_tag_id_entry*)0)->string[0]) + \
- strlen(__str) + 1)
-
-#define MTAG_FIRST_ID 1000
-static mbuf_tag_id_t mtag_id_next = MTAG_FIRST_ID;
-static SLIST_HEAD(,mbuf_tag_id_entry) mtag_id_list = {NULL};
-static lck_mtx_t *mtag_id_lock = NULL;
-
-__private_extern__ void
-mbuf_tag_id_first_last(
- mbuf_tag_id_t * first,
- mbuf_tag_id_t * last)
-{
- *first = MTAG_FIRST_ID;
- *last = mtag_id_next - 1;
-}
-
-__private_extern__ errno_t
-mbuf_tag_id_find_internal(
- const char *string,
- mbuf_tag_id_t *out_id,
- int create)
-{
- struct mbuf_tag_id_entry *entry = NULL;
-
-
- *out_id = 0;
-
- if (string == NULL || out_id == NULL) {
- return EINVAL;
- }
-
- /* Don't bother allocating the lock if we're only doing a lookup */
- if (create == 0 && mtag_id_lock == NULL)
- return ENOENT;
-
- /* Allocate lock if necessary */
- if (mtag_id_lock == NULL) {
- lck_grp_attr_t *grp_attrib = NULL;
- lck_attr_t *lck_attrb = NULL;
- lck_grp_t *lck_group = NULL;
- lck_mtx_t *new_lock = NULL;
-
- grp_attrib = lck_grp_attr_alloc_init();
- lck_group = lck_grp_alloc_init("mbuf_tag_allocate_id", grp_attrib);
- lck_grp_attr_free(grp_attrib);
- lck_attrb = lck_attr_alloc_init();
-
- new_lock = lck_mtx_alloc_init(lck_group, lck_attrb);
- if (!OSCompareAndSwap((UInt32)0, (UInt32)new_lock, (UInt32*)&mtag_id_lock)) {
- /*
- * If the atomic swap fails, someone else has already
- * done this work. We can free the stuff we allocated.
- */
- lck_mtx_free(new_lock, lck_group);
- lck_grp_free(lck_group);
- }
- lck_attr_free(lck_attrb);
- }
-
- /* Look for an existing entry */
- lck_mtx_lock(mtag_id_lock);
- SLIST_FOREACH(entry, &mtag_id_list, next) {
- if (strncmp(string, entry->string, strlen(string) + 1) == 0) {
- break;
- }
- }
-
- if (entry == NULL) {
- if (create == 0) {
- lck_mtx_unlock(mtag_id_lock);
- return ENOENT;
- }
-
- entry = kalloc(MBUF_TAG_ID_ENTRY_SIZE(string));
- if (entry == NULL) {
- lck_mtx_unlock(mtag_id_lock);
- return ENOMEM;
- }
-
- strlcpy(entry->string, string, strlen(string)+1);
- entry->id = mtag_id_next;
- mtag_id_next++;
- SLIST_INSERT_HEAD(&mtag_id_list, entry, next);
- }
- lck_mtx_unlock(mtag_id_lock);
-
- *out_id = entry->id;
-
- return 0;
-}