/** * @brief * reclaim_cpusets() * Given a list of cpusets, attempt to destroy each cpuset named by the list. * If it can be destroyed, unset the bits corresponding to the cpuset's nodes * in the mask (if supplied). This is used to reclaim cpusets that were * supposed to be deleted, but were in fact "stuck", and placed on stucklist. * * @param[in] listp - pointer to cpuset list * @param[in] maskp - pointer to mask bitfield * * @return int * @retval num of cpuset reclaimed success * @retval 0 error * */ int reclaim_cpusets(cpusetlist **listp, Bitfield *maskp) { cpusetlist *set, *next; int count = 0; /* * Walk the list of stuck cpusets, attempting to free each one. Keep * track of the previous and next pointers so the element can be * unlinked and freed. */ for (set = *listp; set != NULL; set = next) { next = set->next; /* Keep track of next pointer. */ /* See if this cpuset can be deleted now. If not, go on. */ if (destroy_cpuset(set->name)) { log_err(0, __func__, "could not destroy cpuset"); continue; } /* * Remove the corresponding bits from the given bitmask, if supplied, * and return the nodes to the nodepool. */ if (maskp != NULL) BITFIELD_CLRM(maskp, &(set->nodes)); BITFIELD_SETM(&nodepool, &(set->nodes)); /* Log that the cpuset was reclaimed. */ (void)sprintf(log_buffer, "stuck cpuset %s reclaimed", set->name); log_event(PBSEVENT_ERROR, PBS_EVENTCLASS_JOB, LOG_INFO, __func__, log_buffer); #ifdef DEBUG (void)sprintf(log_buffer, "nodepool now %s", bitfield2hex(&nodepool)); log_event(PBSEVENT_SYSTEM, PBS_EVENTCLASS_JOB, LOG_INFO, __func__, log_buffer); #endif /* DEBUG */ /* Now free the storage for the cpusetlist element. */ if (remove_from_cpusetlist(listp, NULL, set->name, NULL)) break; count ++; /* Another cpuset reclaimed. */ } /* * Perform a quick sanity check. If there are no cpusets on the supplied * list, then there should be no bits set in the supplied bitfield. Log * an error message if this is not the case. */ if (maskp != NULL && *listp == NULL && !BITFIELD_IS_ZERO(maskp)) log_err(-1, __func__, "NULL cpusetlist but mask not empty!"); return (count); }
static int find_nodemasks(Queue *queue, Resources *rsrcs) { Job *job; Bitfield jobs_using; BITFIELD_CLRALL(&jobs_using); /* * Compute the set of nodes that are both physically available and also * assigned to this queue. */ BITFIELD_CPY(&queue->availmask, &(queue->queuemask)); BITFIELD_ANDM(&queue->availmask, &(queue->rsrcs->availmask)); /* * Compute the set of nodes in use by jobs running on the queue (if * there are any) and remove those nodes from the available node mask. */ if (queue->running) { for (job = queue->jobs; job != NULL; job = job->next) { if (job->state == 'R') BITFIELD_SETM(&jobs_using, &(job->nodemask)); } } /* * Remove the used node bits from the queue's availmask, and add them to * the resources' nodes used bits. */ BITFIELD_CLRM(&queue->availmask, &jobs_using); BITFIELD_SETM(&rsrcs->nodes_used, &jobs_using); return (0); }
int schd_alloc_nodes(int request, Queue *queue, Bitfield *maskp) { char *id = "schd_alloc_nodes"; Bitfield avail; Bitfield mask; Bitfield contig; int remain; int qmsb; int qlsb; int i, n; int count; int found; /* Make certain the nodecount request can be fulfilled. */ if (request <= 0 || request > BITFIELD_NUM_ONES(&(queue->availmask))) return 0; /* * Make a copy of the queue's available bit mask to play with, and clear * the allocated nodes mask. */ BITFIELD_CPY(&avail, &(queue->availmask)); BITFIELD_CLRALL(&mask); /* How many have been found, and how many remain. */ found = 0; remain = request; while (remain > 0) { /* * Find first and last available bit positions in the * queue's available node mask. */ qmsb = BITFIELD_MS_ONE(&avail); qlsb = BITFIELD_LS_ONE(&avail); /* * Starting with the size of the remaining nodes needed to satisfy * this request, look for a set of 'n' contiguous bits in the * available node mask. If that is not found, try the next smallest * contiguous vector, etc. */ for (n = remain; n > 0; n--) { /* * Create a contiguous bitmask of 'n' bits, starting at the * position of the highest bit in the avail mask. */ BITFIELD_CLRALL(&contig); for (i = 0; i < n; i++) BITFIELD_SETB(&contig, qmsb - i); /* * Calculate how many times this contiguous bitmask needs to be * shifted to the right to cover every set of 'n' bits between * the qmsb and qlsb, inclusive. Count the initial configuration * as well (the trailing '+ 1'). */ count = (qmsb + 1 - qlsb) - n + 1; /* * Shift the contiguous mask right one bit at a time, checking * if all the bits in the mask are set in the available mask. */ for (i = 0; i < count; i++) { /* Are all bits in contig also set in the avail mask? */ if (BITFIELD_TSTALLM(&avail, &contig)) { break; } BITFIELD_SHIFTR(&contig); } /* * If the contiguous bits are available, add them to the new job * nodemask, and remove them from the avail mask. Adjust the * remaining node count, and start the next hunt for the remaining * nodes. */ if (i < count) { BITFIELD_SETM(&mask, &contig); BITFIELD_CLRM(&avail, &contig); found += n; remain -= n; break; /* for(n) loop */ } } /* Check for something going wrong. */ if (n == 0) { DBPRT(("%s: couldn't find any contiguous bits (even one!)\n", id)); break; /* while(remain) loop */ } } /* * If no bits remain to be allocated, copy the new mask into the provided * space, and return the number of bits requested. */ if (!remain && (found == request)) { BITFIELD_CPY(maskp, &mask); DBPRT(("%s: mask %s\n", id, schd_format_nodemask(&queue->queuemask, maskp))); return found; } return 0; }