Back to index

numactl  2.0.8~rc4
Defines | Functions | Variables
numactl.c File Reference
#include <getopt.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdarg.h>
#include <ctype.h>
#include "numa.h"
#include "numaif.h"
#include "numaint.h"
#include "util.h"
#include "shm.h"

Go to the source code of this file.

Defines

#define _GNU_SOURCE

Functions

void usage (void)
void usage_msg (char *msg,...)
void show_physcpubind (void)
void show (void)
char * fmt_mem (unsigned long long mem, char *buf)
static void print_distances (int maxnode)
void print_node_cpus (int node)
void hardware (void)
void checkerror (char *s)
void checknuma (void)
void setpolicy (int pol)
void nopolicy (void)
void check_cpubind (int flag)
void noshm (char *opt)
void dontshm (char *opt)
void needshm (char *opt)
void get_short_opts (struct option *o, char *s)
void check_shmbeyond (char *msg)
static struct bitmasknumactl_parse_nodestring (char *s)
int main (int ac, char **av)

Variables

int exitcode
int set_policy = -1
int did_cpubind = 0
int did_strict = 0
int do_shm = 0
int do_dump = 0
int shmattached = 0
char * shmoption

Define Documentation

#define _GNU_SOURCE

Definition at line 17 of file numactl.c.


Function Documentation

void check_cpubind ( int  flag)

Definition at line 326 of file numactl.c.

{
       if (flag)
              usage_msg("cannot do --cpubind on shared memory\n");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void check_shmbeyond ( char *  msg)

Definition at line 365 of file numactl.c.

{
       if (shmoffset >= shmlen) {
              fprintf(stderr,
              "numactl: region offset %#llx beyond its length %#llx at %s\n",
                            shmoffset, shmlen, msg);
              exit(1);
       }
}

Here is the caller graph for this function:

void checkerror ( char *  s)

Definition at line 286 of file numactl.c.

{
       if (errno) {
              perror(s);
              exit(1);
       }
}

Here is the caller graph for this function:

void checknuma ( void  )

Definition at line 294 of file numactl.c.

{
       static int numa = -1;
       if (numa < 0) {
              if (numa_available() < 0)
                     complain("This system does not support NUMA policy");
       }
       numa = 0;
}

Here is the call graph for this function:

void dontshm ( char *  opt)

Definition at line 339 of file numactl.c.

{
       if (shmoption)
              usage_msg("%s shm option is not allowed before %s", shmoption, opt);
}

Here is the call graph for this function:

Here is the caller graph for this function:

char* fmt_mem ( unsigned long long  mem,
char *  buf 
)

Definition at line 177 of file numactl.c.

{
       if (mem == -1L)
              sprintf(buf, "<not available>");
       else
              sprintf(buf, "%Lu MB", mem >> 20);
       return buf;
}

Here is the caller graph for this function:

void get_short_opts ( struct option *  o,
char *  s 
)

Definition at line 351 of file numactl.c.

{
       *s++ = '+';
       while (o->name) {
              if (isprint(o->val)) {
                     *s++ = o->val;
                     if (o->has_arg)
                            *s++ = ':';
              }
              o++;
       }
       *s = '\0';
}

Here is the caller graph for this function:

void hardware ( void  )

Definition at line 227 of file numactl.c.

{
       int i;
       int numnodes=0;
       int prevnode=-1;
       int skip=0;
       int maxnode = numa_max_node();

       for (i=0; i<=maxnode; i++)
              if (numa_bitmask_isbitset(numa_nodes_ptr, i))
                     numnodes++;
       printf("available: %d nodes (", numnodes);
       for (i=0; i<=maxnode; i++) {
              if (numa_bitmask_isbitset(numa_nodes_ptr, i)) {
                     if (prevnode == -1) {
                            printf("%d", i);
                            prevnode=i;
                            continue;
                     }

                     if (i > prevnode + 1) {
                            if (skip) {
                                   printf("%d", prevnode);
                                   skip=0;
                            }
                            printf(",%d", i);
                            prevnode=i;
                            continue;
                     }

                     if (i == prevnode + 1) {
                            if (!skip) {
                                   printf("-");
                                   skip=1;
                            }
                            prevnode=i;
                     }

                     if ((i == maxnode) && skip)
                            printf("%d", prevnode);
              }
       }
       printf(")\n");

       for (i = 0; i <= maxnode; i++) {
              char buf[64];
              long long fr;
              unsigned long long sz = numa_node_size64(i, &fr);
              if (!numa_bitmask_isbitset(numa_nodes_ptr, i))
                     continue;

              printf("node %d cpus:", i);
              print_node_cpus(i);
              printf("node %d size: %s\n", i, fmt_mem(sz, buf));
              printf("node %d free: %s\n", i, fmt_mem(fr, buf));
       }
       print_distances(maxnode);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int main ( int  ac,
char **  av 
)

Definition at line 389 of file numactl.c.

{
       int c, i, nnodes=0;
       long node=-1;
       char *end;
       char shortopts[array_len(opts)*2 + 1];
       struct bitmask *mask = NULL;

       get_short_opts(opts,shortopts);
       while ((c = getopt_long(ac, av, shortopts, opts, NULL)) != -1) {
              switch (c) {
              case 's': /* --show */
                     show();
                     exit(0);
              case 'H': /* --hardware */
                     nopolicy();
                     hardware();
                     exit(0);
              case 'i': /* --interleave */
                     checknuma();
                     mask = numactl_parse_nodestring(optarg);
                     if (!mask) {
                            printf ("<%s> is invalid\n", optarg);
                            usage();
                     }

                     errno = 0;
                     setpolicy(MPOL_INTERLEAVE);
                     if (shmfd >= 0)
                            numa_interleave_memory(shmptr, shmlen, mask);
                     else
                            numa_set_interleave_mask(mask);
                     checkerror("setting interleave mask");
                     break;
              case 'N': /* --cpunodebind */
              case 'c': /* --cpubind */
                     dontshm("-c/--cpubind/--cpunodebind");
                     checknuma();
                     mask = numactl_parse_nodestring(optarg);
                     if (!mask) {
                            printf ("<%s> is invalid\n", optarg);
                            usage();
                     }
                     errno = 0;
                     check_cpubind(do_shm);
                     did_cpubind = 1;
                     numa_run_on_node_mask(mask);
                     checkerror("sched_setaffinity");
                     break;
              case 'C': /* --physcpubind */
              {
                     struct bitmask *cpubuf;
                     dontshm("-C/--physcpubind");
                     cpubuf = numa_parse_cpustring(optarg);
                     if (!cpubuf) {
                            printf ("<%s> is invalid\n", optarg);
                            usage();
                     }
                     errno = 0;
                     check_cpubind(do_shm);
                     did_cpubind = 1;
                     numa_sched_setaffinity(0, cpubuf);
                     checkerror("sched_setaffinity");
                     free(cpubuf);
                     break;
              }
              case 'm': /* --membind */
                     checknuma();
                     setpolicy(MPOL_BIND);
                     mask = numactl_parse_nodestring(optarg);
                     if (!mask) {
                            printf ("<%s> is invalid\n", optarg);
                            usage();
                     }
                     errno = 0;
                     numa_set_bind_policy(1);
                     if (shmfd >= 0) {
                            numa_tonodemask_memory(shmptr, shmlen, mask);
                     } else {
                            numa_set_membind(mask);
                     }
                     numa_set_bind_policy(0);
                     checkerror("setting membind");
                     break;
              case 'p': /* --preferred */
                     checknuma();
                     setpolicy(MPOL_PREFERRED);
                     mask = numactl_parse_nodestring(optarg);
                     if (!mask) {
                            printf ("<%s> is invalid\n", optarg);
                            usage();
                     }
                     for (i=0; i<mask->size; i++) {
                            if (numa_bitmask_isbitset(mask, i)) {
                                   node = i;
                                   nnodes++;
                            }
                     }
                     if (nnodes != 1)
                            usage();
                     numa_bitmask_free(mask);
                     errno = 0;
                     numa_set_bind_policy(0);
                     if (shmfd >= 0)
                            numa_tonode_memory(shmptr, shmlen, node);
                     else
                            numa_set_preferred(node);
                     checkerror("setting preferred node");
                     break;
              case 'l': /* --local */
                     checknuma();
                     setpolicy(MPOL_DEFAULT);
                     errno = 0;
                     if (shmfd >= 0)
                            numa_setlocal_memory(shmptr, shmlen);
                     else
                            numa_set_localalloc();
                     checkerror("local allocation");
                     break;
              case 'S': /* --shm */
                     check_cpubind(did_cpubind);
                     nopolicy();
                     attach_sysvshm(optarg, "--shm");
                     shmattached = 1;
                     break;
              case 'f': /* --file */
                     check_cpubind(did_cpubind);
                     nopolicy();
                     attach_shared(optarg, "--file");
                     shmattached = 1;
                     break;
              case 'L': /* --length */
                     noshm("--length");
                     shmlen = memsize(optarg);
                     break;
              case 'M': /* --shmmode */
                     noshm("--shmmode");
                     shmmode = strtoul(optarg, &end, 8);
                     if (end == optarg || *end)
                            usage();
                     break;
              case 'd': /* --dump */
                     if (shmfd < 0)
                            complain(
                            "Cannot do --dump without shared memory.\n");
                     dump_shm();
                     do_dump = 1;
                     break;
              case 'D': /* --dump-nodes */
                     if (shmfd < 0)
                            complain(
                         "Cannot do --dump-nodes without shared memory.\n");
                     dump_shm_nodes();
                     do_dump = 1;
                     break;
              case 't': /* --strict */
                     did_strict = 1;
                     numa_set_strict(1);
                     break;
              case 'I': /* --shmid */
                     shmid = strtoul(optarg, &end, 0);
                     if (end == optarg || *end)
                            usage();
                     break;

              case 'u': /* --huge */
                     noshm("--huge");
                     shmflags |= SHM_HUGETLB;
                     break;

              case 'o':  /* --offset */
                     noshm("--offset");
                     shmoffset = memsize(optarg);
                     break;               

              case 'T': /* --touch */
                     needshm("--touch");
                     check_shmbeyond("--touch");
                     numa_police_memory(shmptr, shmlen);
                     break;

              case 'V': /* --verify */
                     needshm("--verify");
                     if (set_policy < 0)
                            complain("Need a policy first to verify");
                     check_shmbeyond("--verify");
                     numa_police_memory(shmptr, shmlen);
                     if (!mask)
                            complain("Need a mask to verify");
                     else
                            verify_shm(set_policy, mask);
                     break;

              default:
                     usage();
              }
       }

       av += optind;
       ac -= optind;

       if (shmfd >= 0) {
              if (*av)
                     usage();
              exit(exitcode);
       }

       if (did_strict)
              fprintf(stderr,
                     "numactl: warning. Strict flag for process ignored.\n");

       if (do_dump)
              usage_msg("cannot do --dump|--dump-shm for process");

       if (shmoption)
              usage_msg("shm related option %s for process", shmoption);
       
       if (*av == NULL)
              usage();
       execvp(*av, av);
       complain("execution of `%s': %s\n", av[0], strerror(errno));
       return 0; /* not reached */
}

Here is the call graph for this function:

void needshm ( char *  opt)

Definition at line 345 of file numactl.c.

{
       if (!shmattached)
              usage_msg("%s must be after shared memory specification", opt);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nopolicy ( void  )

Definition at line 313 of file numactl.c.

{
       if (set_policy >= 0)
              usage_msg("specify policy after --shm/--file");
}

Here is the call graph for this function:

Here is the caller graph for this function:

void noshm ( char *  opt)

Definition at line 332 of file numactl.c.

{
       if (shmattached)
              usage_msg("%s must be before shared memory specification", opt);
       shmoption = opt;            
}

Here is the call graph for this function:

Here is the caller graph for this function:

static struct bitmask* numactl_parse_nodestring ( char *  s) [static, read]

Definition at line 375 of file numactl.c.

{
       static char *last;

       if (s[0] == 's' && !strcmp(s, "same")) {
              if (!last)
                     usage_msg("same needs previous node specification");
              s = last;
       } else {
              last = s;
       }
       return numa_parse_nodestring(s);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_distances ( int  maxnode) [static]

Definition at line 186 of file numactl.c.

{
       int i,k;

       if (numa_distance(maxnode,0) == 0) {
              printf("No distance information available.\n");
              return;
       }
       printf("node distances:\n");
       printf("node ");
       for (i = 0; i <= maxnode; i++)
              if (numa_bitmask_isbitset(numa_nodes_ptr, i))
                     printf("% 3d ", i);
       printf("\n");
       for (i = 0; i <= maxnode; i++) {
              if (!numa_bitmask_isbitset(numa_nodes_ptr, i))
                     continue;
              printf("% 3d: ", i);
              for (k = 0; k <= maxnode; k++)
                     if (numa_bitmask_isbitset(numa_nodes_ptr, i) &&
                         numa_bitmask_isbitset(numa_nodes_ptr, k))
                            printf("% 3d ", numa_distance(i,k));
              printf("\n");
       }                    
}

Here is the call graph for this function:

Here is the caller graph for this function:

void print_node_cpus ( int  node)

Definition at line 212 of file numactl.c.

{
       int i, err;
       struct bitmask *cpus;

       cpus = numa_allocate_cpumask();
       err = numa_node_to_cpus(node, cpus);
       if (err >= 0) {
              for (i = 0; i < cpus->size; i++)
                     if (numa_bitmask_isbitset(cpus, i))
                            printf(" %d", i);
       }
       putchar('\n');
}

Here is the call graph for this function:

Here is the caller graph for this function:

void setpolicy ( int  pol)

Definition at line 306 of file numactl.c.

{
       if (set_policy != -1)
              usage_msg("Conflicting policies");
       set_policy = pol;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void show ( void  )

Definition at line 122 of file numactl.c.

{
       unsigned long prefnode;
       struct bitmask *membind, *interleave, *cpubind;
       unsigned long cur;
       int policy;
       int numa_num_nodes = numa_num_possible_nodes();
       
       if (numa_available() < 0) {
              show_physcpubind();
              printf("No NUMA support available on this system.\n");
              exit(1);
       }

       cpubind = numa_get_run_node_mask();

       prefnode = numa_preferred();
       interleave = numa_get_interleave_mask();
       membind = numa_get_membind();
       cur = numa_get_interleave_node();

       policy = 0;
       if (get_mempolicy(&policy, NULL, 0, 0, 0) < 0)
              perror("get_mempolicy");

       printf("policy: %s\n", policy_name(policy));
              
       printf("preferred node: ");
       switch (policy) {
       case MPOL_PREFERRED:
              if (prefnode != -1) {
                     printf("%ld\n", prefnode);
                     break;
              }
              /*FALL THROUGH*/
       case MPOL_DEFAULT:
              printf("current\n");
              break;
       case MPOL_INTERLEAVE:
              printf("%ld (interleave next)\n",cur);
              break;
       case MPOL_BIND:
              printf("%d\n", find_first_bit(&membind, numa_num_nodes));
              break;
       }
       if (policy == MPOL_INTERLEAVE) {
              printmask("interleavemask", interleave);
              printf("interleavenode: %ld\n", cur);
       }
       show_physcpubind();
       printmask("cpubind", cpubind);  // for compatibility
       printmask("nodebind", cpubind);
       printmask("membind", membind);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void show_physcpubind ( void  )

Definition at line 101 of file numactl.c.

{
       int ncpus = numa_num_configured_cpus();
       
       for (;;) {
              struct bitmask *cpubuf;

              cpubuf = numa_bitmask_alloc(ncpus);

              if (numa_sched_getaffinity(0, cpubuf) < 0) {
                     if (errno == EINVAL && ncpus < 1024*1024) {
                            ncpus *= 2;
                            continue;
                     }
                     err("sched_get_affinity");
              }
              printcpumask("physcpubind", cpubuf);
              break;
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void usage ( void  )

Definition at line 60 of file numactl.c.

{
       fprintf(stderr,
              "usage: numactl [--interleave=nodes] [--preferred=node]\n"
              "               [--physcpubind=cpus] [--cpunodebind=nodes]\n"
              "               [--membind=nodes] [--localalloc] command args ...\n"
              "       numactl [--show]\n"
              "       numactl [--hardware]\n"
              "       numactl [--length length] [--offset offset] [--shmmode shmmode]\n"
              "               [--strict]\n"
              "               [--shmid id] --shm shmkeyfile | --file tmpfsfile\n"
              "               [--huge] [--touch] \n"
              "               memory policy | --dump | --dump-nodes\n"
              "\n"
              "memory policy is --interleave, --preferred, --membind, --localalloc\n"
              "nodes is a comma delimited list of node numbers or A-B ranges or all.\n"
              "Instead of a number a node can also be:\n"
              "  netdev:DEV the node connected to network device DEV\n"
              "  file:PATH  the node the block device of path is connected to\n"
              "  ip:HOST    the node of the network device host routes through\n"
              "  block:PATH the node of block device path\n"
              "  pci:[seg:]bus:dev[:func] The node of a PCI device\n"
              "cpus is a comma delimited list of cpu numbers or A-B ranges or all\n"
              "all ranges can be inverted with !\n"
              "all numbers and ranges can be made cpuset-relative with +\n"
              "the old --cpubind argument is deprecated.\n"
              "use --cpunodebind or --physcpubind instead\n"
              "length can have g (GB), m (MB) or k (KB) suffixes\n");
       exit(1);
}
void usage_msg ( char *  msg,
  ... 
)

Definition at line 91 of file numactl.c.

{
       va_list ap;
       va_start(ap,msg);
       fprintf(stderr, "numactl: ");
       vfprintf(stderr, msg, ap);
       putchar('\n');
       usage();
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

int did_cpubind = 0

Definition at line 319 of file numactl.c.

int did_strict = 0

Definition at line 320 of file numactl.c.

int do_dump = 0

Definition at line 322 of file numactl.c.

int do_shm = 0

Definition at line 321 of file numactl.c.

int exitcode

Definition at line 32 of file numactl.c.

int set_policy = -1

Definition at line 304 of file numactl.c.

int shmattached = 0

Definition at line 323 of file numactl.c.

char* shmoption

Definition at line 324 of file numactl.c.