/* sshare_distribute_own_slots() */ int sshare_distribute_own_slots(struct tree_ *t, uint32_t slots) { struct tree_node_ *n; link_t *stack; struct share_acct *sacct; uint32_t avail; int tried; int first; stack = make_link(); /* This must be emptied after every scheduling * cycle. There could be still some leafs * if not all jobs got dispatched. */ while (pop_link(t->leafs)) ; avail = slots; sort_tree_by_deviate(t); zero_out_sent(t); tried = 0; /* only after sort get the first child */ n = t->root->child; first = 0; znovu: /* Iterate at each tree level but * don't traverse branches without * tokens. */ while (n) { sacct = n->data; /* all is a dummy share account the * tree is populated with real ones. */ if (sacct->options & SACCT_USER_ALL) { n = n->right; continue; } /* enqueue as we want to traverse * the tree by priority */ if (n->child) enqueue_link(stack, n); /* Enforce the ownership/guarantee at the * first level of the tree. */ if (first == 0) { if (sacct->numRUN > sacct->shares) sacct->sent = 0; else sacct->sent = sacct->shares - sacct->numRUN; } else { avail = avail - compute_slots(n, slots, avail); } assert(avail >= 0); /* As we traverse in priority order * the leafs are also sorted */ if (n->child == NULL) enqueue_link(t->leafs, n); n = n->right; } ++first; n = pop_link(stack); if (n) { /* tokens come from the parent */ sacct = n->data; avail = slots = sacct->sent; n = n->child; goto znovu; } if (avail > 0 && tried == 0) { ++tried; n = t->root->child; goto znovu; } fin_link(stack); return 0; }
/* sshare_distribute_slots() */ int sshare_distribute_slots(struct tree_ *t, uint32_t slots) { struct tree_node_ *n; link_t *stack; struct share_acct *sacct; uint32_t avail; int tried; int last; int prev_last; int x; int total_slots; stack = make_link(); /* This must be emptied after every scheduling * cycle. There could be still some leafs * if not all jobs got dispatched. */ while (pop_link(t->leafs)) ; avail = total_slots = slots; sort_tree_by_deviate(t); zero_out_sent(t); tried = 0; last = prev_last = 0; /* only after sort get the first child */ n = t->root->child; znovu: /* Iterate at each tree level but * don't traverse branches without * tokens. */ while (n) { sacct = n->data; /* all is a dummy share account the * tree is populated with real ones. */ if (sacct->options & SACCT_USER_ALL) { n = n->right; continue; } /* enqueue as we want to traverse * the tree by priority */ if (n->child) enqueue_link(stack, n); avail = avail - compute_slots(n, slots, avail); assert(avail >= 0); n = n->right; } n = pop_link(stack); if (n) { /* tokens come from the parent */ sacct = n->data; avail = slots = sacct->avail; n = n->child; goto znovu; } x = get_distrib(t); last = total_slots - x; if (last > 0 && prev_last != last && tried < 1000) { ++tried; prev_last = last; avail = last; slots = last; n = t->root->child; goto znovu; } if (tried >= 1000 || last < 0) { ls_syslog(LOG_ERR, "\ %s: tried %d >= 1000 total_slots %d last %d prev_last %d", __func__, tried, total_slots, last, prev_last); }