+/*
+ * Verify that the given bucket has been sorted correctly.
+ *
+ * Walks through the bucket and verifies that all pids in the
+ * expected_order buffer are in that bucket and in the same
+ * relative order.
+ *
+ * The proc_list_lock must be held by the caller.
+ */
+static int
+memorystatus_verify_sort_order(unsigned int bucket_index, pid_t *expected_order, size_t num_pids)
+{
+ LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
+
+ int error = 0;
+ proc_t p = NULL;
+ size_t i = 0;
+
+ /*
+ * NB: We allow other procs to be mixed in within the expected ones.
+ * We just need the expected procs to be in the right order relative to each other.
+ */
+ p = memorystatus_get_first_proc_locked(&bucket_index, FALSE);
+ while (p) {
+ if (p->p_pid == expected_order[i]) {
+ i++;
+ }
+ if (i == num_pids) {
+ break;
+ }
+ p = memorystatus_get_next_proc_locked(&bucket_index, p, FALSE);
+ }
+ if (i != num_pids) {
+ char buffer[128];
+ size_t len = sizeof(buffer);
+ size_t buffer_idx = 0;
+ os_log_error(OS_LOG_DEFAULT, "memorystatus_verify_sort_order: Processes in bucket %d were not sorted properly\n", bucket_index);
+ for (i = 0; i < num_pids; i++) {
+ int num_written = snprintf(buffer + buffer_idx, len - buffer_idx, "%d,", expected_order[i]);
+ if (num_written <= 0) {
+ break;
+ }
+ if (buffer_idx + (unsigned int) num_written >= len) {
+ break;
+ }
+ buffer_idx += num_written;
+ }
+ os_log_error(OS_LOG_DEFAULT, "memorystatus_verify_sort_order: Expected order [%s]", buffer);
+ memset(buffer, 0, len);
+ buffer_idx = 0;
+ p = memorystatus_get_first_proc_locked(&bucket_index, FALSE);
+ i = 0;
+ os_log_error(OS_LOG_DEFAULT, "memorystatus_verify_sort_order: Actual order:");
+ while (p) {
+ int num_written;
+ if (buffer_idx == 0) {
+ num_written = snprintf(buffer + buffer_idx, len - buffer_idx, "%zu: %d,", i, p->p_pid);
+ } else {
+ num_written = snprintf(buffer + buffer_idx, len - buffer_idx, "%d,", p->p_pid);
+ }
+ if (num_written <= 0) {
+ break;
+ }
+ buffer_idx += (unsigned int) num_written;
+ assert(buffer_idx <= len);
+ if (i % 10 == 0) {
+ os_log_error(OS_LOG_DEFAULT, "memorystatus_verify_sort_order: %s", buffer);
+ buffer_idx = 0;
+ }
+ p = memorystatus_get_next_proc_locked(&bucket_index, p, FALSE);
+ i++;
+ }
+ if (buffer_idx != 0) {
+ os_log_error(OS_LOG_DEFAULT, "memorystatus_verify_sort_order: %s", buffer);
+ }
+ error = EINVAL;
+ }
+ return error;
+}
+