Back to index

numactl  2.0.8~rc4
Defines | Functions | Variables
shm.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.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   1

Functions

long huge_page_size (void)
static void check_region (char *opt)
static key_t sysvkey (char *name)
void attach_sysvshm (char *name, char *opt)
void attach_shared (char *name, char *opt)
static void dumppol (unsigned long long start, unsigned long long end, int pol, struct bitmask *mask)
void dump_shm (void)
static void dumpnode (unsigned long long start, unsigned long long end, int node)
void dump_shm_nodes (void)
static void vwarn (char *ptr, char *fmt,...)
static unsigned interleave_next (unsigned cur, struct bitmask *mask)
void verify_shm (int policy, struct bitmask *nodes)

Variables

int shmfd = -1
long shmid = 0
char * shmptr
unsigned long long shmlen
mode_t shmmode = 0600
unsigned long long shmoffset
int shmflags
static int shm_pagesize

Define Documentation

#define _GNU_SOURCE   1

Definition at line 20 of file shm.c.


Function Documentation

void attach_shared ( char *  name,
char *  opt 
)

Definition at line 133 of file shm.c.

{
       struct stat64 st;

       shmfd = open(name, O_RDONLY);
       if (shmfd < 0) {
              errno = 0;
              if (shmlen == 0)
                      complain("need a --length to create a shared file");
              shmfd = open(name, O_RDWR|O_CREAT, shmmode);
              if (shmfd < 0)
                     nerror("cannot create file %s", name);
       }
       if (fstat64(shmfd, &st) < 0)
              err("shm stat");
       if (shmlen > st.st_size) {
              if (ftruncate64(shmfd, shmlen) < 0) {
                     /* XXX: we could do it by hand, but it would it
                        would be impossible to apply policy then.
                        need to fix that in the kernel. */
                     perror("ftruncate");
              }
       }

       shm_pagesize = st.st_blksize;

       check_region(opt);
       
       /* RED-PEN For shmlen > address space may need to map in pieces.
          Left for some poor 32bit soul. */
       shmptr = mmap64(NULL, shmlen, PROT_READ, MAP_SHARED, shmfd, shmoffset);
       if (shmptr == (char*)-1)
              err("shm mmap");                   

}

Here is the call graph for this function:

Here is the caller graph for this function:

void attach_sysvshm ( char *  name,
char *  opt 
)

Definition at line 98 of file shm.c.

{
       struct shmid_ds s;
       key_t key = sysvkey(name);
       
       shmfd = shmget(key, shmlen, shmflags);
       if (shmfd < 0 && errno == ENOENT) {
              if (shmlen == 0)
                     complain(
                     "need a --length to create a sysv shared memory segment");
              fprintf(stderr,
         "numactl: Creating shared memory segment %s id %ld mode %04o length %.fMB\n",
                     name, shmid, shmmode, ((double)shmlen) / (1024*1024) );
              shmfd = shmget(key, shmlen, IPC_CREAT|shmmode|shmflags);
              if (shmfd < 0)
                     nerror("cannot create shared memory segment");
       }

       if (shmlen == 0) {
              if (shmctl(shmfd, IPC_STAT, &s) < 0)
                     err("shmctl IPC_STAT");
              shmlen = s.shm_segsz;
       }

       shmptr = shmat(shmfd, NULL, SHM_RDONLY);
       if (shmptr == (void*)-1)
              err("shmat");
       shmptr += shmoffset;

       shm_pagesize = (shmflags & SHM_HUGETLB) ? huge_page_size() : getpagesize();

       check_region(opt);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void check_region ( char *  opt) [static]

Definition at line 64 of file shm.c.

{
       if (((unsigned long)shmptr % shm_pagesize) || (shmlen % shm_pagesize)) {
              fprintf(stderr, "numactl: policy region not page aligned\n");
              exit(1);
       }
       if (!shmlen) {
              fprintf(stderr,
              "numactl: policy region length not specified before %s\n",
                     opt);
              exit(1);
       }
}

Here is the caller graph for this function:

void dump_shm ( void  )

Definition at line 182 of file shm.c.

{
       struct bitmask *nodes, *prevnodes;
       int prevpol = -1, pol;
       unsigned long long c, start;

       start = 0;
       if (shmlen == 0) {
              printf("nothing to dump\n");
              return;
       }

       nodes = numa_allocate_nodemask();
       prevnodes = numa_allocate_nodemask();

       for (c = 0; c < shmlen; c += shm_pagesize) {
              if (get_mempolicy(&pol, nodes->maskp, nodes->size, c+shmptr,
                                          MPOL_F_ADDR) < 0)
                     err("get_mempolicy on shm");
              if (pol == prevpol)
                     continue;
              if (prevpol != -1)
                     dumppol(start, c, prevpol, prevnodes);
              prevnodes = nodes;
              prevpol = pol;
              start = c;
       }
       dumppol(start, c, prevpol, prevnodes);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void dump_shm_nodes ( void  )

Definition at line 218 of file shm.c.

{
       int prevnode = -1, node;
       unsigned long long c, start;

       start = 0;
       if (shmlen == 0) {
              printf("nothing to dump\n");
              return;
       }

       for (c = 0; c < shmlen; c += shm_pagesize) {
              if (get_mempolicy(&node, NULL, 0, c+shmptr,
                                          MPOL_F_ADDR|MPOL_F_NODE) < 0)
                     err("get_mempolicy on shm");
              if (node == prevnode)
                     continue;
              if (prevnode != -1)
                     dumpnode(start, c, prevnode);
              prevnode = node;
              start = c;
       }
       dumpnode(start, c, prevnode);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dumpnode ( unsigned long long  start,
unsigned long long  end,
int  node 
) [static]

Definition at line 212 of file shm.c.

{
       printf("%016Lx-%016Lx: %d\n", shmoffset+start, shmoffset+end, node);
}

Here is the caller graph for this function:

static void dumppol ( unsigned long long  start,
unsigned long long  end,
int  pol,
struct bitmask mask 
) [static]

Definition at line 170 of file shm.c.

{
       if (pol == MPOL_DEFAULT)
              return;
       printf("%016Lx-%016Lx: %s ",
              shmoffset+start,
              shmoffset+end,
              policy_name(pol));
       printmask("", mask);
}

Here is the call graph for this function:

Here is the caller graph for this function:

long huge_page_size ( void  )

Definition at line 47 of file shm.c.

{
       size_t len = 0;
       char *line = NULL;
       FILE *f = fopen("/proc/meminfo", "r");
       if (f != NULL) {
              while (getdelim(&line, &len, '\n', f) > 0) {
                     int ps;
                     if (sscanf(line, "Hugepagesize: %d kB", &ps) == 1)
                            return ps * 1024;
              }
              free(line);
              fclose(f);
       }
       return getpagesize();
}

Here is the caller graph for this function:

static unsigned interleave_next ( unsigned  cur,
struct bitmask mask 
) [static]

Definition at line 254 of file shm.c.

{
       int numa_num_nodes = numa_num_possible_nodes();

       ++cur;
       while (!numa_bitmask_isbitset(mask, cur)) {
              cur = (cur+1) % numa_num_nodes;
       }
       return cur;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static key_t sysvkey ( char *  name) [static]

Definition at line 78 of file shm.c.

{
       int fd;
       key_t key = ftok(name, shmid);
       if (key >= 0)
              return key;

       fprintf(stderr, "numactl: Creating shm key file %s mode %04o\n",
              name, shmmode);
       fd = creat(name, shmmode);
       if (fd < 0)
              nerror("cannot create key for shm %s\n", name);  
       key = ftok(name, shmid);
       if (key < 0)
              nerror("cannot get key for newly created shm key file %s",
                     name);
       return key;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void verify_shm ( int  policy,
struct bitmask nodes 
)

Definition at line 266 of file shm.c.

{
       char *p;
       int ilnode, node;
       int pol2;
       struct bitmask *nodes2;

       nodes2 = numa_allocate_nodemask();
       
       if (policy == MPOL_INTERLEAVE) {
              if (get_mempolicy(&ilnode, NULL, 0, shmptr,
                                   MPOL_F_ADDR|MPOL_F_NODE)
                  < 0)
                     err("get_mempolicy");
       }
       
       for (p = shmptr; p - (char *)shmptr < shmlen; p += shm_pagesize) {
              if (get_mempolicy(&pol2, nodes2->maskp, nodes2->size, p,
                                                 MPOL_F_ADDR) < 0)
                     err("get_mempolicy");
              if (pol2 != policy) {
                     vwarn(p, "wrong policy %s, expected %s\n",
                           policy_name(pol2), policy_name(policy));
                     return;
              }
              if (memcmp(nodes2, nodes, numa_bitmask_nbytes(nodes))) {
                     vwarn(p, "mismatched node mask\n");
                     printmask("expected", nodes);
                     printmask("real", nodes2);
              }

              if (get_mempolicy(&node, NULL, 0, p, MPOL_F_ADDR|MPOL_F_NODE) < 0)
                     err("get_mempolicy");

              switch (policy) {
              case MPOL_INTERLEAVE:
                     if (node < 0 || !numa_bitmask_isbitset(nodes2, node))
                            vwarn(p, "interleave node out of range %d\n", node);
                     if (node != ilnode) {
                            vwarn(p, "expected interleave node %d, got %d\n",
                                 ilnode,node);
                            return;
                     }
                     ilnode = interleave_next(ilnode, nodes2);
                     break;
              case MPOL_PREFERRED:
              case MPOL_BIND:
                     if (!numa_bitmask_isbitset(nodes2, node)) {
                            vwarn(p, "unexpected node %d\n", node);
                            printmask("expected", nodes2);
                     }      
                     break;

              case MPOL_DEFAULT:
                     break;
                     
              }
       }
              
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void vwarn ( char *  ptr,
char *  fmt,
  ... 
) [static]

Definition at line 243 of file shm.c.

{
       va_list ap;
       unsigned long off = (unsigned long)ptr - (unsigned long)shmptr;
       va_start(ap,fmt);
       printf("numactl verify %lx(%lx): ",  (unsigned long)ptr, off);
       vprintf(fmt, ap);
       va_end(ap);
       exitcode = 1;
}

Here is the caller graph for this function:


Variable Documentation

int shm_pagesize [static]

Definition at line 45 of file shm.c.

int shmfd = -1

Definition at line 38 of file shm.c.

int shmflags

Definition at line 44 of file shm.c.

long shmid = 0

Definition at line 39 of file shm.c.

unsigned long long shmlen

Definition at line 41 of file shm.c.

mode_t shmmode = 0600

Definition at line 42 of file shm.c.

unsigned long long shmoffset

Definition at line 43 of file shm.c.

char* shmptr

Definition at line 40 of file shm.c.