Пример #1
0
int
schd_bits2mask(char *string, Bitfield *mask)
  {
  int    i, bit, len;
  Bitfield new_bit;

  BITFIELD_CLRALL(&new_bit);

  len = (int)strlen(string);

  /* Start with the low bit. */
  bit = 0;

  for (i = 0; i < len; i++)
    {
    if (string[len - i - 1] == '1')
      BITFIELD_SETB(&new_bit, bit);
    else if (string[len - i - 1] != '0')
      return (-1);

    ++ bit;
    }

  /* Done.  Copy the new nodemask and return success. */

  BITFIELD_CPY(mask, &new_bit);

  return (0);
  }
Пример #2
0
/*
 * mask_mask is the mask of bits that are in this particular part of the
 * nodemask.  ndmask is the actual nodemask in question.
 *
 * For instance, a mask_mask of: 00000000111111111111111100000000
 * and a nodemask of :   00000000000000111111111100000000
 * generate the output:   ........------XXXXXXXXXX........
 *
 * Note that the storage is static - copy the return before the next call!
 */
char *
schd_format_nodemask(Bitfield *mask_mask, Bitfield *ndmask)
  {
  static char prt_bits[BITFIELD_SIZE + 2];
  Bitfield bit;
  int    idx;

  /* Find the most significant bit in the nodemask. */
  BITFIELD_CLRALL(&bit);
  BITFIELD_SETB(&bit, (BITFIELD_SIZE - 1));

  /* Walk the bits in the nodemask, from MSB to LSB. */

  for (idx = 0; idx < BITFIELD_SIZE; idx ++)
    {
    if (BITFIELD_TSTM(&bit, mask_mask))
      prt_bits[idx] = (BITFIELD_TSTM(ndmask, &bit)) ? 'X' : '-';
    else
      prt_bits[idx] = '.';

    BITFIELD_SHIFTR(&bit);
    }

  /* Null terminate the resulting string. */
  prt_bits[idx] = '\0';

  return (prt_bits);
  }
Пример #3
0
/**
 * @brief
 * 	availnodes() - Fill the supplied bitfield with a set bit for each node on which sufficient
 * 	resources (c.f. mapnodes.h) are configured.  This is the set of nodes that
 * 	are physically available to be allocated -- policy, reserved nodes, etc,
 * 	may reduce the total number of nodes that are usable by jobs.
 *
 * NOTE: Must be called after mapnodes().
 *
 * @param[out] maskp - pointer to Bitfield structure
 *
 * @return	int
 * @retval	0	success
 * @retval	!0	failure
 *
 */
int
availnodes(Bitfield *maskp)
{
	int			node, i, count;
	Bitfield		avail;

	/* This function needs a valid node map in order to find available nodes. */
	if (nodemap == NULL)
		return 1;

	/*
	 * If minimum resource values are not set, default them to reasonable
	 * defaults.
	 */
	if (minnodemem < 0)
		minnodemem = minmem;
	if (minnodecpus < 0)
		minnodecpus = mincpus;
	if (memreserved < 0)
		memreserved = 0;

	(void)sprintf(log_buffer,
		"Minimum node resources: %d cpus, %d MB, %d MB rsvd",
		minnodecpus, minnodemem, memreserved);
	log_err(-1, __func__, log_buffer);

	BITFIELD_CLRALL(&avail);

	/*
	 * Walk through the node map, checking for sufficient resources on each
	 * node, and setting the appropriate bit on the mask for that node if it
	 * is sufficiently endowed.  See mapnodes.h for definition of "sufficient".
	 */
	for (node = 0; node <= maxnodeid; node++) {
		/* Enough CPUs?  If not, skip it. */
		for (count = i = 0; i < MAX_CPUS_PER_NODE; i++)
			if (nodemap[node].cpu[i] >= 0)
				count ++;

		/* Enough memory and cpus?  If not, skip it. */
		if (nodemap[node].memory < minnodemem || count < minnodecpus) {
			(void)sprintf(log_buffer,
				"node %d has only %luMB and %d cpus - cannot use",
				node, nodemap[node].memory, count);
			log_err(-1, __func__, log_buffer);

			continue;
		}

		/* Node has sufficient resources.  Count this node as available. */
		BITFIELD_SETB(&avail, node);
	}

	/* Copy the available mask to the passed-in storage, and return success. */
	BITFIELD_CPY(maskp, &avail);

	return 0;
}
Пример #4
0
int schd_alloc_nodes(int nnodes, Queue *queue, Bitfield *job_mask)
  {
  Bitfield *queue_mask;
  Bitfield *q_avail_mask;
  Bitfield new_bit;
  int candidate;
  int n_found;

  n_found = 0;
  BITFIELD_CLRALL(&new_bit);

  queue_mask   = &(queue->queuemask);
  q_avail_mask = &(queue->availmask);

  candidate = (BITFIELD_SIZE - 1);

  while ((n_found < nnodes) && (candidate >= 0))
    {
    if (BITFIELD_TSTB(queue_mask, candidate))
      {
      if (BITFIELD_TSTB(q_avail_mask, candidate))
        {
        /* available */
        BITFIELD_SETB(&new_bit, candidate);
        ++n_found;
        }
      }

    -- candidate;
    }

  /*
   * If enough nodes were allocated, copy the resultant new nodemask
   * into the supplied area.
   */
  if (nnodes == n_found)
    {
    BITFIELD_CPY(job_mask, &new_bit);
    return nnodes;
    }

  /* Didn't get enough nodes.  Return 0 as an error. */
  return 0;
  }
Пример #5
0
int
schd_str2mask(char *maskstr, Bitfield *maskp)
  {
  char *id = "str2mask";
  Bitfield nodemask;
  char hex;
  int ndbit = 0, len, dec, hxbit;

  unsigned long long compat;
  char *ptr;
  char     buf[32];

  if (maskstr == NULL)
    return (-1);

  /* Nodemask string must be in the format '0x...'. */
  if ((maskstr[0] != '0') || (tolower(maskstr[1]) != 'x'))
    {

    /* XXX
     * For backwards compatability, if the string will convert
     * into an unsigned long long, then assume this is an old-
     * style decimal nodemask (on 8-128P machines, nodemask is
     * an unsigned long long, and was treated as such).
     *
     * Note that this assumes that sizeof(unsigned long long)
     * is the same as sizeof(unsigned long), which is only the
     * case with the 64-bit SGI compiler ABI.
     */
    compat = strtoul(maskstr, &ptr, 10);

    if (*ptr != '\0')
      return (-1);

    /*
     * String converted to an unsigned long long.  Print it as
     * a hex back into a buffer, and point at that buffer instead.
     * This will cause the newly created hex string to be used.
     */
    (void)sprintf(buf, "0x%llx", compat);

    maskstr = buf;

    (void)sprintf(log_buffer,
                  "converted old-style nodemask %lu to %s", compat, maskstr);

    log_record(PBSEVENT_SYSTEM, PBS_EVENTCLASS_SERVER, id,
               log_buffer);
    }

  /* Zero out the new nodemask struct, and fill it from the maskstr. */
  BITFIELD_CLRALL(&nodemask);

  /* Walk backwards through the hex digits in the string 0x... */
  for (len = (int)strlen(maskstr); len > 2 /* 0x... */; len --)
    {
    hex = maskstr[len - 1];
    /* Make sure it's a hex digit. */

    if (!isxdigit((int)hex))
      return (-1);

    /* If this digit is a '0', it contributes nothing. */
    if (hex != '0')
      {
      /* Convert the hex digit to a decimal int. */
      dec = isdigit((int)hex) ? (hex - '0') :
            (tolower((int)hex) - 'a' + 10);

      for (hxbit = 0; hxbit < 4; hxbit ++)
        {
        if (dec & (1 << hxbit))
          BITFIELD_SETB(&nodemask, ndbit);

        ndbit ++;
        }
      }
    else
      ndbit += 4;

    /* Make sure we haven't walked past the end of the nodemask. */
    if (ndbit > (sizeof(Bitfield) * 8))
      return (-1);
    }

  /* Copy the newly created nodemask into the handed-in one. */
  BITFIELD_CPY(maskp, &nodemask);

  return (0);
  }
Пример #6
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;
  }