+static void drop_attr_stack(struct attr_stack **stack)
+{
+ while (*stack) {
+ struct attr_stack *elem = *stack;
+ *stack = elem->prev;
+ attr_stack_free(elem);
+ }
+}
+
+/* List of all attr_check structs; access should be surrounded by mutex */
+static struct check_vector {
+ size_t nr;
+ size_t alloc;
+ struct attr_check **checks;
+#ifndef NO_PTHREADS
+ pthread_mutex_t mutex;
+#endif
+} check_vector;
+
+static inline void vector_lock(void)
+{
+#ifndef NO_PTHREADS
+ pthread_mutex_lock(&check_vector.mutex);
+#endif
+}
+
+static inline void vector_unlock(void)
+{
+#ifndef NO_PTHREADS
+ pthread_mutex_unlock(&check_vector.mutex);
+#endif
+}
+
+static void check_vector_add(struct attr_check *c)
+{
+ vector_lock();
+
+ ALLOC_GROW(check_vector.checks,
+ check_vector.nr + 1,
+ check_vector.alloc);
+ check_vector.checks[check_vector.nr++] = c;
+
+ vector_unlock();
+}
+
+static void check_vector_remove(struct attr_check *check)
+{
+ int i;
+
+ vector_lock();
+
+ /* Find entry */
+ for (i = 0; i < check_vector.nr; i++)
+ if (check_vector.checks[i] == check)
+ break;
+
+ if (i >= check_vector.nr)
+ die("BUG: no entry found");
+
+ /* shift entries over */
+ for (; i < check_vector.nr - 1; i++)
+ check_vector.checks[i] = check_vector.checks[i + 1];
+
+ check_vector.nr--;
+
+ vector_unlock();
+}
+
+/* Iterate through all attr_check instances and drop their stacks */
+static void drop_all_attr_stacks(void)
+{
+ int i;
+
+ vector_lock();
+
+ for (i = 0; i < check_vector.nr; i++) {
+ drop_attr_stack(&check_vector.checks[i]->stack);
+ }
+
+ vector_unlock();
+}
+