1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * memtoy: segment.c - manage memory segments 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * create/destroy/map/unmap - anonymous, file and SysV shmem segments 5f08c3bdfSopenharmony_ci * touch [read or write] - ranges of segments 6f08c3bdfSopenharmony_ci * mbind - ranges of segments 7f08c3bdfSopenharmony_ci * show mappings or locations of segment pages 8f08c3bdfSopenharmony_ci */ 9f08c3bdfSopenharmony_ci/* 10f08c3bdfSopenharmony_ci * Copyright (c) 2005 Hewlett-Packard, Inc 11f08c3bdfSopenharmony_ci * All rights reserved. 12f08c3bdfSopenharmony_ci */ 13f08c3bdfSopenharmony_ci 14f08c3bdfSopenharmony_ci/* 15f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or modify 16f08c3bdfSopenharmony_ci * it under the terms of the GNU General Public License as published by 17f08c3bdfSopenharmony_ci * the Free Software Foundation; either version 2 of the License, or 18f08c3bdfSopenharmony_ci * (at your option) any later version. 19f08c3bdfSopenharmony_ci * 20f08c3bdfSopenharmony_ci * This program is distributed in the hope that it will be useful, 21f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 22f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23f08c3bdfSopenharmony_ci * GNU General Public License for more details. 24f08c3bdfSopenharmony_ci * 25f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 26f08c3bdfSopenharmony_ci * along with this program; if not, write to the Free Software 27f08c3bdfSopenharmony_ci * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 28f08c3bdfSopenharmony_ci */ 29f08c3bdfSopenharmony_ci 30f08c3bdfSopenharmony_ci#include "config.h" 31f08c3bdfSopenharmony_ci 32f08c3bdfSopenharmony_ci#ifdef HAVE_NUMA_V2 33f08c3bdfSopenharmony_ci 34f08c3bdfSopenharmony_ci#include <sys/types.h> 35f08c3bdfSopenharmony_ci#include <sys/ipc.h> 36f08c3bdfSopenharmony_ci#include <sys/mman.h> 37f08c3bdfSopenharmony_ci#include <sys/shm.h> 38f08c3bdfSopenharmony_ci#include <sys/stat.h> 39f08c3bdfSopenharmony_ci#include <sys/time.h> 40f08c3bdfSopenharmony_ci#include <errno.h> 41f08c3bdfSopenharmony_ci#include <fcntl.h> 42f08c3bdfSopenharmony_ci#include <libgen.h> 43f08c3bdfSopenharmony_ci#include <numa.h> 44f08c3bdfSopenharmony_ci#include <numaif.h> 45f08c3bdfSopenharmony_ci#include <stdarg.h> 46f08c3bdfSopenharmony_ci#include <stdlib.h> 47f08c3bdfSopenharmony_ci#include <stdio.h> 48f08c3bdfSopenharmony_ci#include <string.h> 49f08c3bdfSopenharmony_ci#include <unistd.h> 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci#include "memtoy.h" 52f08c3bdfSopenharmony_ci#include "segment.h" 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_cistruct segment { 55f08c3bdfSopenharmony_ci char *seg_name; 56f08c3bdfSopenharmony_ci void *seg_start; 57f08c3bdfSopenharmony_ci size_t seg_length; 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci off_t seg_offset; /* memory mapped files */ 60f08c3bdfSopenharmony_ci char *seg_path; /* " " " */ 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_ci seg_type_t seg_type; 63f08c3bdfSopenharmony_ci int seg_slot; 64f08c3bdfSopenharmony_ci int seg_flags; /* shared|private */ 65f08c3bdfSopenharmony_ci int seg_prot; 66f08c3bdfSopenharmony_ci int seg_fd; /* saved file descriptor */ 67f08c3bdfSopenharmony_ci int seg_shmid; 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci}; 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_ci#define MAX_SEGMENTS 63 /* arbitrary max */ 72f08c3bdfSopenharmony_ci#define SEG_FD_NONE (-1) 73f08c3bdfSopenharmony_ci#define SHM_ID_NONE (-1) 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ci#define SEG_ERR (0) 76f08c3bdfSopenharmony_ci#define SEG_OK (1) 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci#define SEG_OFFSET(SEGP, ADDR) ((char *)(ADDR) - (char *)(SEGP->seg_start)) 79f08c3bdfSopenharmony_ci 80f08c3bdfSopenharmony_ci/* 81f08c3bdfSopenharmony_ci * ========================================================================= 82f08c3bdfSopenharmony_ci */ 83f08c3bdfSopenharmony_civoid segment_init(struct global_context *gcp) 84f08c3bdfSopenharmony_ci{ 85f08c3bdfSopenharmony_ci /* 86f08c3bdfSopenharmony_ci * one extra slot to terminate the list 87f08c3bdfSopenharmony_ci */ 88f08c3bdfSopenharmony_ci gcp->seglist = calloc(MAX_SEGMENTS + 1, sizeof(segment_t *)); 89f08c3bdfSopenharmony_ci if (!gcp->seglist) 90f08c3bdfSopenharmony_ci die(4, "%s: can't alloc segment table\n", gcp->program_name); 91f08c3bdfSopenharmony_ci gcp->seg_avail = NULL; 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci} 94f08c3bdfSopenharmony_ci 95f08c3bdfSopenharmony_cistatic segment_t *new_segment(void) 96f08c3bdfSopenharmony_ci{ 97f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 98f08c3bdfSopenharmony_ci segment_t *segp = (segment_t *) calloc(1, sizeof(segment_t)); 99f08c3bdfSopenharmony_ci 100f08c3bdfSopenharmony_ci if (segp == NULL) 101f08c3bdfSopenharmony_ci fprintf(stderr, "%s: failed to allocate segment\n", 102f08c3bdfSopenharmony_ci gcp->program_name); 103f08c3bdfSopenharmony_ci return segp; 104f08c3bdfSopenharmony_ci} 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci/* 107f08c3bdfSopenharmony_ci * get_seg_slot() -- allocate a segment table slot for a new segment 108f08c3bdfSopenharmony_ci */ 109f08c3bdfSopenharmony_cistatic segment_t *get_seg_slot(void) 110f08c3bdfSopenharmony_ci{ 111f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 112f08c3bdfSopenharmony_ci segment_t *segp, **segpp; 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci /* 115f08c3bdfSopenharmony_ci * consume saved slot, if any 116f08c3bdfSopenharmony_ci */ 117f08c3bdfSopenharmony_ci segp = gcp->seg_avail; 118f08c3bdfSopenharmony_ci if (segp != NULL) { 119f08c3bdfSopenharmony_ci gcp->seg_avail = NULL; 120f08c3bdfSopenharmony_ci return segp; 121f08c3bdfSopenharmony_ci } 122f08c3bdfSopenharmony_ci 123f08c3bdfSopenharmony_ci /* 124f08c3bdfSopenharmony_ci * simple linear scan for first available slot 125f08c3bdfSopenharmony_ci */ 126f08c3bdfSopenharmony_ci for (segpp = gcp->seglist; (segp = *segpp); ++segpp) { 127f08c3bdfSopenharmony_ci if (segp->seg_type == SEGT_NONE) 128f08c3bdfSopenharmony_ci return segp; 129f08c3bdfSopenharmony_ci } 130f08c3bdfSopenharmony_ci 131f08c3bdfSopenharmony_ci if (segpp < &gcp->seglist[MAX_SEGMENTS]) { 132f08c3bdfSopenharmony_ci /* 133f08c3bdfSopenharmony_ci * previously unused slot 134f08c3bdfSopenharmony_ci */ 135f08c3bdfSopenharmony_ci *segpp = segp = new_segment(); 136f08c3bdfSopenharmony_ci segp->seg_slot = segpp - gcp->seglist; 137f08c3bdfSopenharmony_ci return segp; 138f08c3bdfSopenharmony_ci } 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci fprintf(stderr, "%s: segment table full\n", gcp->program_name); 141f08c3bdfSopenharmony_ci return NULL; 142f08c3bdfSopenharmony_ci} 143f08c3bdfSopenharmony_ci 144f08c3bdfSopenharmony_cistatic void unmap_segment(segment_t * segp) 145f08c3bdfSopenharmony_ci{ 146f08c3bdfSopenharmony_ci 147f08c3bdfSopenharmony_ci if (segp->seg_start == MAP_FAILED) 148f08c3bdfSopenharmony_ci return; /* already unmapped */ 149f08c3bdfSopenharmony_ci 150f08c3bdfSopenharmony_ci switch (segp->seg_type) { 151f08c3bdfSopenharmony_ci case SEGT_ANON: 152f08c3bdfSopenharmony_ci case SEGT_FILE: 153f08c3bdfSopenharmony_ci munmap(segp->seg_start, segp->seg_length); 154f08c3bdfSopenharmony_ci break; 155f08c3bdfSopenharmony_ci 156f08c3bdfSopenharmony_ci case SEGT_SHM: 157f08c3bdfSopenharmony_ci shmdt(segp->seg_start); 158f08c3bdfSopenharmony_ci break; 159f08c3bdfSopenharmony_ci 160f08c3bdfSopenharmony_ci default: 161f08c3bdfSopenharmony_ci // shouldn't happen? 162f08c3bdfSopenharmony_ci break; 163f08c3bdfSopenharmony_ci } 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_ci segp->seg_start = MAP_FAILED; 166f08c3bdfSopenharmony_ci} 167f08c3bdfSopenharmony_ci 168f08c3bdfSopenharmony_ci/* 169f08c3bdfSopenharmony_ci * free up a segment table slot, freeing any string storage 170f08c3bdfSopenharmony_ci * and removing shm segment, if necessary 171f08c3bdfSopenharmony_ci * clear out the segment, but preserve slot # 172f08c3bdfSopenharmony_ci */ 173f08c3bdfSopenharmony_cistatic void free_seg_slot(segment_t * segp) 174f08c3bdfSopenharmony_ci{ 175f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 176f08c3bdfSopenharmony_ci int slot = segp->seg_slot; 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_ci if (segp->seg_name != NULL) 179f08c3bdfSopenharmony_ci free(segp->seg_name); 180f08c3bdfSopenharmony_ci 181f08c3bdfSopenharmony_ci if (segp->seg_path != NULL) 182f08c3bdfSopenharmony_ci free(segp->seg_path); 183f08c3bdfSopenharmony_ci 184f08c3bdfSopenharmony_ci if (segp->seg_type == SEGT_FILE && segp->seg_fd != SEG_FD_NONE) 185f08c3bdfSopenharmony_ci close(segp->seg_fd); 186f08c3bdfSopenharmony_ci 187f08c3bdfSopenharmony_ci if (segp->seg_type == SEGT_SHM && segp->seg_shmid != SHM_ID_NONE) 188f08c3bdfSopenharmony_ci shmctl(segp->seg_shmid, IPC_RMID, NULL); 189f08c3bdfSopenharmony_ci 190f08c3bdfSopenharmony_ci (void)memset(segp, 0, sizeof(*segp)); 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_ci segp->seg_slot = slot; 193f08c3bdfSopenharmony_ci if (gcp->seg_avail == NULL) 194f08c3bdfSopenharmony_ci gcp->seg_avail = segp; 195f08c3bdfSopenharmony_ci 196f08c3bdfSopenharmony_ci} 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci/* 199f08c3bdfSopenharmony_ci * called from memtoy "at exit" cleanup(). 200f08c3bdfSopenharmony_ci * primarily to remove any shm segments created. 201f08c3bdfSopenharmony_ci */ 202f08c3bdfSopenharmony_civoid segment_cleanup(struct global_context *gcp) 203f08c3bdfSopenharmony_ci{ 204f08c3bdfSopenharmony_ci segment_t *segp, **segpp; 205f08c3bdfSopenharmony_ci 206f08c3bdfSopenharmony_ci segpp = gcp->seglist; 207f08c3bdfSopenharmony_ci if (segpp == NULL) 208f08c3bdfSopenharmony_ci return; 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ci for (; (segp = *segpp); ++segpp) { 211f08c3bdfSopenharmony_ci if (segp->seg_type != SEGT_SHM) { 212f08c3bdfSopenharmony_ci continue; 213f08c3bdfSopenharmony_ci } 214f08c3bdfSopenharmony_ci free_seg_slot(segp); /* to remove shared mem */ 215f08c3bdfSopenharmony_ci } 216f08c3bdfSopenharmony_ci} 217f08c3bdfSopenharmony_ci 218f08c3bdfSopenharmony_cistatic size_t round_up_to_pagesize(size_t size) 219f08c3bdfSopenharmony_ci{ 220f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 221f08c3bdfSopenharmony_ci size_t pagemask = gcp->pagesize - 1; 222f08c3bdfSopenharmony_ci 223f08c3bdfSopenharmony_ci return ((size + pagemask) & ~pagemask); 224f08c3bdfSopenharmony_ci 225f08c3bdfSopenharmony_ci} 226f08c3bdfSopenharmony_ci 227f08c3bdfSopenharmony_cistatic size_t round_down_to_pagesize(size_t size) 228f08c3bdfSopenharmony_ci{ 229f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 230f08c3bdfSopenharmony_ci size_t pagemask = gcp->pagesize - 1; 231f08c3bdfSopenharmony_ci 232f08c3bdfSopenharmony_ci return (size & ~pagemask); 233f08c3bdfSopenharmony_ci 234f08c3bdfSopenharmony_ci} 235f08c3bdfSopenharmony_ci 236f08c3bdfSopenharmony_ci/* 237f08c3bdfSopenharmony_ci * get_node() -- fetch numa node id of page at vaddr 238f08c3bdfSopenharmony_ci * [from Ray Bryant's [SGI] memory migration tests] 239f08c3bdfSopenharmony_ci */ 240f08c3bdfSopenharmony_cistatic int get_node(void *vaddr) 241f08c3bdfSopenharmony_ci{ 242f08c3bdfSopenharmony_ci int rc, node; 243f08c3bdfSopenharmony_ci 244f08c3bdfSopenharmony_ci rc = get_mempolicy(&node, NULL, 0, vaddr, MPOL_F_NODE | MPOL_F_ADDR); 245f08c3bdfSopenharmony_ci if (rc) 246f08c3bdfSopenharmony_ci return -1; 247f08c3bdfSopenharmony_ci 248f08c3bdfSopenharmony_ci return node; 249f08c3bdfSopenharmony_ci} 250f08c3bdfSopenharmony_ci 251f08c3bdfSopenharmony_ci/* 252f08c3bdfSopenharmony_ci * ========================================================================= 253f08c3bdfSopenharmony_ci */ 254f08c3bdfSopenharmony_cistatic int map_anon_segment(segment_t * segp) 255f08c3bdfSopenharmony_ci{ 256f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 257f08c3bdfSopenharmony_ci 258f08c3bdfSopenharmony_ci char *memp; 259f08c3bdfSopenharmony_ci int flags = segp->seg_flags; 260f08c3bdfSopenharmony_ci 261f08c3bdfSopenharmony_ci if (!flags) 262f08c3bdfSopenharmony_ci flags = MAP_PRIVATE; /* default */ 263f08c3bdfSopenharmony_ci 264f08c3bdfSopenharmony_ci memp = (char *)mmap(0, segp->seg_length, segp->seg_prot, flags | MAP_ANONYMOUS, 0, /* fd -- ignored */ 265f08c3bdfSopenharmony_ci 0); /* offset -- ignored */ 266f08c3bdfSopenharmony_ci 267f08c3bdfSopenharmony_ci if (memp == MAP_FAILED) { 268f08c3bdfSopenharmony_ci int err = errno; 269f08c3bdfSopenharmony_ci fprintf(stderr, "%s: anonymous mmap failed - %s\n", 270f08c3bdfSopenharmony_ci __FUNCTION__, strerror(err)); 271f08c3bdfSopenharmony_ci return SEG_ERR; 272f08c3bdfSopenharmony_ci } 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci vprint("%s: mmap()ed anon seg %s at 0x%lx-0x%lx\n", 275f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_name, 276f08c3bdfSopenharmony_ci memp, memp + segp->seg_length - 1); 277f08c3bdfSopenharmony_ci 278f08c3bdfSopenharmony_ci segp->seg_start = memp; 279f08c3bdfSopenharmony_ci 280f08c3bdfSopenharmony_ci return SEG_OK; 281f08c3bdfSopenharmony_ci} 282f08c3bdfSopenharmony_ci 283f08c3bdfSopenharmony_ci/* 284f08c3bdfSopenharmony_ci * open_file() -- open and validate file when registering a file segment. 285f08c3bdfSopenharmony_ci * remember fd in segment struct. 286f08c3bdfSopenharmony_ci */ 287f08c3bdfSopenharmony_cistatic int open_file(segment_t * segp) 288f08c3bdfSopenharmony_ci{ 289f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 290f08c3bdfSopenharmony_ci 291f08c3bdfSopenharmony_ci struct stat stbuf; 292f08c3bdfSopenharmony_ci int fd, flags; 293f08c3bdfSopenharmony_ci 294f08c3bdfSopenharmony_ci if (stat(segp->seg_path, &stbuf) < 0) { 295f08c3bdfSopenharmony_ci int err = errno; 296f08c3bdfSopenharmony_ci fprintf(stderr, "%s: can't stat %s - %s\n", 297f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_path, strerror(err)); 298f08c3bdfSopenharmony_ci free_seg_slot(segp); 299f08c3bdfSopenharmony_ci return SEG_ERR; 300f08c3bdfSopenharmony_ci } 301f08c3bdfSopenharmony_ci 302f08c3bdfSopenharmony_ci /* 303f08c3bdfSopenharmony_ci * TODO: for now, just regular files. later? 304f08c3bdfSopenharmony_ci */ 305f08c3bdfSopenharmony_ci if (!S_ISREG(stbuf.st_mode)) { 306f08c3bdfSopenharmony_ci fprintf(stderr, "%s: %s - is not a regular file\n", 307f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_path); 308f08c3bdfSopenharmony_ci free_seg_slot(segp); 309f08c3bdfSopenharmony_ci return SEG_ERR; 310f08c3bdfSopenharmony_ci } 311f08c3bdfSopenharmony_ci 312f08c3bdfSopenharmony_ci /* 313f08c3bdfSopenharmony_ci * Open file with maximal privileges; adjust segment mapping 314f08c3bdfSopenharmony_ci * protections if permissions don't allow full R/W access. 315f08c3bdfSopenharmony_ci */ 316f08c3bdfSopenharmony_ci if (!access(segp->seg_path, R_OK | W_OK)) 317f08c3bdfSopenharmony_ci flags = O_RDWR; 318f08c3bdfSopenharmony_ci else if (!access(segp->seg_path, R_OK)) { 319f08c3bdfSopenharmony_ci flags = O_RDONLY; 320f08c3bdfSopenharmony_ci segp->seg_prot &= ~PROT_WRITE; 321f08c3bdfSopenharmony_ci } else if (!access(segp->seg_path, W_OK)) { 322f08c3bdfSopenharmony_ci flags = O_WRONLY; 323f08c3bdfSopenharmony_ci segp->seg_prot &= ~PROT_READ; 324f08c3bdfSopenharmony_ci } else { 325f08c3bdfSopenharmony_ci fprintf(stderr, "%s: can't access %s\n", 326f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_path); 327f08c3bdfSopenharmony_ci free_seg_slot(segp); 328f08c3bdfSopenharmony_ci return SEG_ERR; 329f08c3bdfSopenharmony_ci } 330f08c3bdfSopenharmony_ci 331f08c3bdfSopenharmony_ci fd = open(segp->seg_path, flags); 332f08c3bdfSopenharmony_ci if (fd < 0) { 333f08c3bdfSopenharmony_ci int err = errno; 334f08c3bdfSopenharmony_ci fprintf(stderr, "%s: can't open %s - %s\n", 335f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_path, strerror(err)); 336f08c3bdfSopenharmony_ci free_seg_slot(segp); 337f08c3bdfSopenharmony_ci return SEG_ERR; 338f08c3bdfSopenharmony_ci } 339f08c3bdfSopenharmony_ci 340f08c3bdfSopenharmony_ci segp->seg_fd = fd; 341f08c3bdfSopenharmony_ci return SEG_OK; 342f08c3bdfSopenharmony_ci} 343f08c3bdfSopenharmony_ci 344f08c3bdfSopenharmony_ci/* 345f08c3bdfSopenharmony_ci * re-fetch file size at map time -- just in case it's changed 346f08c3bdfSopenharmony_ci */ 347f08c3bdfSopenharmony_cistatic size_t file_size(int fd) 348f08c3bdfSopenharmony_ci{ 349f08c3bdfSopenharmony_ci struct stat stbuf; 350f08c3bdfSopenharmony_ci 351f08c3bdfSopenharmony_ci if (fstat(fd, &stbuf) != 0) { 352f08c3bdfSopenharmony_ci return BOGUS_SIZE; 353f08c3bdfSopenharmony_ci } 354f08c3bdfSopenharmony_ci 355f08c3bdfSopenharmony_ci return stbuf.st_size; 356f08c3bdfSopenharmony_ci} 357f08c3bdfSopenharmony_ci 358f08c3bdfSopenharmony_ci/* 359f08c3bdfSopenharmony_ci * map_file_segment() -- map a [range of a] registered file segment. 360f08c3bdfSopenharmony_ci */ 361f08c3bdfSopenharmony_cistatic int map_file_segment(segment_t * segp) 362f08c3bdfSopenharmony_ci{ 363f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 364f08c3bdfSopenharmony_ci 365f08c3bdfSopenharmony_ci char *memp; 366f08c3bdfSopenharmony_ci size_t size; 367f08c3bdfSopenharmony_ci int fd; 368f08c3bdfSopenharmony_ci int flags = segp->seg_flags; 369f08c3bdfSopenharmony_ci 370f08c3bdfSopenharmony_ci if (!flags) 371f08c3bdfSopenharmony_ci flags = MAP_PRIVATE; /* default */ 372f08c3bdfSopenharmony_ci 373f08c3bdfSopenharmony_ci if ((fd = segp->seg_fd) == SEG_FD_NONE) { 374f08c3bdfSopenharmony_ci fprintf(stderr, "%s: file %s not open\n", 375f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_path); 376f08c3bdfSopenharmony_ci return SEG_ERR; 377f08c3bdfSopenharmony_ci } 378f08c3bdfSopenharmony_ci 379f08c3bdfSopenharmony_ci size = file_size(fd); 380f08c3bdfSopenharmony_ci 381f08c3bdfSopenharmony_ci /* 382f08c3bdfSopenharmony_ci * page align offset/length; verify fit in file 383f08c3bdfSopenharmony_ci */ 384f08c3bdfSopenharmony_ci segp->seg_offset = round_down_to_pagesize(segp->seg_offset); 385f08c3bdfSopenharmony_ci if (segp->seg_offset > size) { 386f08c3bdfSopenharmony_ci fprintf(stderr, "%s: offset 0x%lx beyond end of file %s\n", 387f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_offset, segp->seg_path); 388f08c3bdfSopenharmony_ci return SEG_ERR; 389f08c3bdfSopenharmony_ci } 390f08c3bdfSopenharmony_ci 391f08c3bdfSopenharmony_ci if (segp->seg_length == 0) 392f08c3bdfSopenharmony_ci segp->seg_length = round_up_to_pagesize(size) - 393f08c3bdfSopenharmony_ci segp->seg_offset; 394f08c3bdfSopenharmony_ci else 395f08c3bdfSopenharmony_ci segp->seg_length = round_up_to_pagesize(segp->seg_length); 396f08c3bdfSopenharmony_ci 397f08c3bdfSopenharmony_ci memp = (char *)mmap(0, segp->seg_length, 398f08c3bdfSopenharmony_ci segp->seg_prot, flags, fd, segp->seg_offset); 399f08c3bdfSopenharmony_ci 400f08c3bdfSopenharmony_ci if (memp == MAP_FAILED) { 401f08c3bdfSopenharmony_ci int err = errno; 402f08c3bdfSopenharmony_ci fprintf(stderr, "%s: mmap of %s failed - %s\n", 403f08c3bdfSopenharmony_ci __FUNCTION__, segp->seg_path, strerror(err)); 404f08c3bdfSopenharmony_ci return SEG_ERR; 405f08c3bdfSopenharmony_ci } 406f08c3bdfSopenharmony_ci 407f08c3bdfSopenharmony_ci vprint("%s: mmap()ed file seg %s at 0x%lx-0x%lx\n", 408f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_name, 409f08c3bdfSopenharmony_ci memp, memp + segp->seg_length - 1); 410f08c3bdfSopenharmony_ci 411f08c3bdfSopenharmony_ci segp->seg_start = memp; 412f08c3bdfSopenharmony_ci 413f08c3bdfSopenharmony_ci return SEG_OK; 414f08c3bdfSopenharmony_ci} 415f08c3bdfSopenharmony_ci 416f08c3bdfSopenharmony_ci/* 417f08c3bdfSopenharmony_ci * get_shm_segment() -- create [shmget] a new shared memory segment 418f08c3bdfSopenharmony_ci */ 419f08c3bdfSopenharmony_cistatic int get_shm_segment(segment_t * segp) 420f08c3bdfSopenharmony_ci{ 421f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 422f08c3bdfSopenharmony_ci 423f08c3bdfSopenharmony_ci int shmid; 424f08c3bdfSopenharmony_ci 425f08c3bdfSopenharmony_ci shmid = shmget(IPC_PRIVATE, segp->seg_length, SHM_R | SHM_W); 426f08c3bdfSopenharmony_ci if (shmid == -1) { 427f08c3bdfSopenharmony_ci int err = errno; 428f08c3bdfSopenharmony_ci fprintf(stderr, "%s: failed to get shm segment %s - %s\n", 429f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_name, strerror(err)); 430f08c3bdfSopenharmony_ci free_seg_slot(segp); 431f08c3bdfSopenharmony_ci return SEG_ERR; 432f08c3bdfSopenharmony_ci } 433f08c3bdfSopenharmony_ci 434f08c3bdfSopenharmony_ci segp->seg_shmid = shmid; 435f08c3bdfSopenharmony_ci vprint("%s: shm seg %s id: %d\n", 436f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_name, segp->seg_shmid); 437f08c3bdfSopenharmony_ci return SEG_OK; 438f08c3bdfSopenharmony_ci} 439f08c3bdfSopenharmony_ci 440f08c3bdfSopenharmony_ci/* 441f08c3bdfSopenharmony_ci * map_shm_segment() -- attach [shmat] a shared memory segment 442f08c3bdfSopenharmony_ci */ 443f08c3bdfSopenharmony_cistatic int map_shm_segment(segment_t * segp) 444f08c3bdfSopenharmony_ci{ 445f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 446f08c3bdfSopenharmony_ci 447f08c3bdfSopenharmony_ci segp->seg_start = shmat(segp->seg_shmid, NULL, 0); 448f08c3bdfSopenharmony_ci if (segp->seg_start == MAP_FAILED) { 449f08c3bdfSopenharmony_ci int err = errno; 450f08c3bdfSopenharmony_ci fprintf(stderr, "%s: failed to attach shm segment %s: %s\n", 451f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_name, strerror(err)); 452f08c3bdfSopenharmony_ci return SEG_ERR; 453f08c3bdfSopenharmony_ci } 454f08c3bdfSopenharmony_ci 455f08c3bdfSopenharmony_ci vprint("%s: mmap()ed shm seg %s at 0x%lx-0x%lx\n", 456f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_name, 457f08c3bdfSopenharmony_ci segp->seg_start, segp->seg_start + segp->seg_length - 1); 458f08c3bdfSopenharmony_ci 459f08c3bdfSopenharmony_ci return SEG_OK; 460f08c3bdfSopenharmony_ci} 461f08c3bdfSopenharmony_ci 462f08c3bdfSopenharmony_ci/* 463f08c3bdfSopenharmony_ci * ========================================================================= 464f08c3bdfSopenharmony_ci * segment API 465f08c3bdfSopenharmony_ci */ 466f08c3bdfSopenharmony_ci/* 467f08c3bdfSopenharmony_ci * segment_get(name) - lookup named segment 468f08c3bdfSopenharmony_ciTODO: move to segment private functions? 469f08c3bdfSopenharmony_ci */ 470f08c3bdfSopenharmony_cisegment_t *segment_get(char *name) 471f08c3bdfSopenharmony_ci{ 472f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 473f08c3bdfSopenharmony_ci segment_t *segp, **segpp; 474f08c3bdfSopenharmony_ci 475f08c3bdfSopenharmony_ci for (segpp = gcp->seglist; (segp = *segpp); ++segpp) { 476f08c3bdfSopenharmony_ci if (segp->seg_type == SEGT_NONE) { 477f08c3bdfSopenharmony_ci if (gcp->seg_avail == NULL) 478f08c3bdfSopenharmony_ci gcp->seg_avail = *segpp; 479f08c3bdfSopenharmony_ci continue; 480f08c3bdfSopenharmony_ci } 481f08c3bdfSopenharmony_ci if (!strcmp(name, segp->seg_name)) 482f08c3bdfSopenharmony_ci return segp; 483f08c3bdfSopenharmony_ci } 484f08c3bdfSopenharmony_ci 485f08c3bdfSopenharmony_ci if (gcp->seg_avail == NULL && segpp < &gcp->seglist[MAX_SEGMENTS]) { 486f08c3bdfSopenharmony_ci /* 487f08c3bdfSopenharmony_ci * prealloc an available segment 488f08c3bdfSopenharmony_ci */ 489f08c3bdfSopenharmony_ci *segpp = segp = new_segment(); 490f08c3bdfSopenharmony_ci if (segp != NULL) { 491f08c3bdfSopenharmony_ci segp->seg_slot = segpp - gcp->seglist; 492f08c3bdfSopenharmony_ci gcp->seg_avail = segp; 493f08c3bdfSopenharmony_ci } 494f08c3bdfSopenharmony_ci } 495f08c3bdfSopenharmony_ci 496f08c3bdfSopenharmony_ci return NULL; 497f08c3bdfSopenharmony_ci} 498f08c3bdfSopenharmony_ci 499f08c3bdfSopenharmony_ci/* 500f08c3bdfSopenharmony_ci * segment_register: register an anon, file or shm segment based on args. 501f08c3bdfSopenharmony_ci * for anon and shm, 'name' = segment name. 502f08c3bdfSopenharmony_ci * for file, 'name' = path name; segment name = basename(path) 503f08c3bdfSopenharmony_ci * 504f08c3bdfSopenharmony_ci * returns: !0 on success; 0 on failure 505f08c3bdfSopenharmony_ci */ 506f08c3bdfSopenharmony_ciint segment_register(seg_type_t type, char *name, range_t * range, int flags) 507f08c3bdfSopenharmony_ci{ 508f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 509f08c3bdfSopenharmony_ci segment_t *segp; 510f08c3bdfSopenharmony_ci char *path; 511f08c3bdfSopenharmony_ci 512f08c3bdfSopenharmony_ci segp = segment_get(basename(name)); /* ensure unique name */ 513f08c3bdfSopenharmony_ci if (segp != NULL) { 514f08c3bdfSopenharmony_ci fprintf(stderr, "%s: segment %s already exists\n", 515f08c3bdfSopenharmony_ci gcp->program_name, segp->seg_name); 516f08c3bdfSopenharmony_ci return SEG_ERR; 517f08c3bdfSopenharmony_ci } 518f08c3bdfSopenharmony_ci 519f08c3bdfSopenharmony_ci segp = get_seg_slot(); 520f08c3bdfSopenharmony_ci if (segp == NULL) 521f08c3bdfSopenharmony_ci return SEG_ERR; 522f08c3bdfSopenharmony_ci 523f08c3bdfSopenharmony_ci path = strdup(name); /* save a copy */ 524f08c3bdfSopenharmony_ci segp->seg_name = strdup(basename(name)); 525f08c3bdfSopenharmony_ci segp->seg_start = MAP_FAILED; 526f08c3bdfSopenharmony_ci segp->seg_length = round_up_to_pagesize(range->length); 527f08c3bdfSopenharmony_ci segp->seg_offset = round_down_to_pagesize(range->offset); 528f08c3bdfSopenharmony_ci segp->seg_type = type; 529f08c3bdfSopenharmony_ci segp->seg_flags = flags; /* possibly 0 */ 530f08c3bdfSopenharmony_ci segp->seg_prot = PROT_READ | PROT_WRITE; /* default */ 531f08c3bdfSopenharmony_ci segp->seg_fd = SEG_FD_NONE; 532f08c3bdfSopenharmony_ci segp->seg_shmid = SHM_ID_NONE; 533f08c3bdfSopenharmony_ci 534f08c3bdfSopenharmony_ci switch (type) { 535f08c3bdfSopenharmony_ci case SEGT_ANON: 536f08c3bdfSopenharmony_ci free(path); 537f08c3bdfSopenharmony_ci break; 538f08c3bdfSopenharmony_ci 539f08c3bdfSopenharmony_ci case SEGT_FILE: 540f08c3bdfSopenharmony_ci segp->seg_path = path; 541f08c3bdfSopenharmony_ci return open_file(segp); 542f08c3bdfSopenharmony_ci break; 543f08c3bdfSopenharmony_ci 544f08c3bdfSopenharmony_ci case SEGT_SHM: 545f08c3bdfSopenharmony_ci free(path); 546f08c3bdfSopenharmony_ci return get_shm_segment(segp); 547f08c3bdfSopenharmony_ci break; 548f08c3bdfSopenharmony_ci 549f08c3bdfSopenharmony_ci default: 550f08c3bdfSopenharmony_ci free(path); 551f08c3bdfSopenharmony_ci } 552f08c3bdfSopenharmony_ci return SEG_OK; 553f08c3bdfSopenharmony_ci} 554f08c3bdfSopenharmony_ci 555f08c3bdfSopenharmony_cistatic char *segment_header = 556f08c3bdfSopenharmony_ci " _____address______ ____length____ ____offset____ prot share name\n"; 557f08c3bdfSopenharmony_ci 558f08c3bdfSopenharmony_cistatic char seg_type[] = { '.', 'a', 'f', 's' }; 559f08c3bdfSopenharmony_ci 560f08c3bdfSopenharmony_cistatic int show_one_segment(segment_t * segp, bool header) 561f08c3bdfSopenharmony_ci{ 562f08c3bdfSopenharmony_ci char *protection, *share, *name; 563f08c3bdfSopenharmony_ci 564f08c3bdfSopenharmony_ci switch (segp->seg_prot & (PROT_READ | PROT_WRITE)) { 565f08c3bdfSopenharmony_ci case PROT_READ | PROT_WRITE: 566f08c3bdfSopenharmony_ci protection = "rw"; 567f08c3bdfSopenharmony_ci break; 568f08c3bdfSopenharmony_ci 569f08c3bdfSopenharmony_ci case PROT_READ: 570f08c3bdfSopenharmony_ci protection = "r-"; 571f08c3bdfSopenharmony_ci break; 572f08c3bdfSopenharmony_ci 573f08c3bdfSopenharmony_ci case PROT_WRITE: 574f08c3bdfSopenharmony_ci protection = "-w"; 575f08c3bdfSopenharmony_ci break; 576f08c3bdfSopenharmony_ci 577f08c3bdfSopenharmony_ci default: 578f08c3bdfSopenharmony_ci protection = "--"; 579f08c3bdfSopenharmony_ci break; 580f08c3bdfSopenharmony_ci } 581f08c3bdfSopenharmony_ci 582f08c3bdfSopenharmony_ci if (segp->seg_flags) 583f08c3bdfSopenharmony_ci share = (segp->seg_flags & MAP_SHARED) ? "shared " : "private"; 584f08c3bdfSopenharmony_ci else 585f08c3bdfSopenharmony_ci share = "default"; 586f08c3bdfSopenharmony_ci 587f08c3bdfSopenharmony_ci name = (segp->seg_type == SEGT_FILE) ? segp->seg_path : segp->seg_name; 588f08c3bdfSopenharmony_ci 589f08c3bdfSopenharmony_ci if (header) 590f08c3bdfSopenharmony_ci puts(segment_header); 591f08c3bdfSopenharmony_ci 592f08c3bdfSopenharmony_ci if (segp->seg_start != MAP_FAILED) { 593f08c3bdfSopenharmony_ci printf("%c 0x%p 0x%012zx 0x%012lx %s %s %s\n", 594f08c3bdfSopenharmony_ci seg_type[segp->seg_type], 595f08c3bdfSopenharmony_ci segp->seg_start, 596f08c3bdfSopenharmony_ci segp->seg_length, 597f08c3bdfSopenharmony_ci segp->seg_offset, protection, share, name); 598f08c3bdfSopenharmony_ci } else { 599f08c3bdfSopenharmony_ci printf("%c *** not-mapped *** 0x%012zx 0x%012lx %s %s %s\n", 600f08c3bdfSopenharmony_ci seg_type[segp->seg_type], 601f08c3bdfSopenharmony_ci segp->seg_length, 602f08c3bdfSopenharmony_ci segp->seg_offset, protection, share, name); 603f08c3bdfSopenharmony_ci } 604f08c3bdfSopenharmony_ci 605f08c3bdfSopenharmony_ci return SEG_OK; 606f08c3bdfSopenharmony_ci} 607f08c3bdfSopenharmony_ci 608f08c3bdfSopenharmony_ci/* 609f08c3bdfSopenharmony_ci * segment_show() -- show specified segment, or all, if none specified. 610f08c3bdfSopenharmony_ci */ 611f08c3bdfSopenharmony_ciint segment_show(char *name) 612f08c3bdfSopenharmony_ci{ 613f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 614f08c3bdfSopenharmony_ci segment_t *segp, **segpp; 615f08c3bdfSopenharmony_ci bool header; 616f08c3bdfSopenharmony_ci 617f08c3bdfSopenharmony_ci if (name != NULL) { 618f08c3bdfSopenharmony_ci segp = segment_get(name); 619f08c3bdfSopenharmony_ci if (segp == NULL) { 620f08c3bdfSopenharmony_ci fprintf(stderr, "%s: no such segment: %s\n", 621f08c3bdfSopenharmony_ci gcp->program_name, name); 622f08c3bdfSopenharmony_ci return SEG_ERR; 623f08c3bdfSopenharmony_ci } 624f08c3bdfSopenharmony_ci show_one_segment(segp, false); 625f08c3bdfSopenharmony_ci return SEG_OK; 626f08c3bdfSopenharmony_ci } 627f08c3bdfSopenharmony_ci 628f08c3bdfSopenharmony_ci /* 629f08c3bdfSopenharmony_ci * show all 630f08c3bdfSopenharmony_ci */ 631f08c3bdfSopenharmony_ci header = true; 632f08c3bdfSopenharmony_ci for (segpp = gcp->seglist; (segp = *segpp); ++segpp) { 633f08c3bdfSopenharmony_ci if (segp->seg_type != SEGT_NONE) { 634f08c3bdfSopenharmony_ci show_one_segment(segp, header); 635f08c3bdfSopenharmony_ci header = false; /* first time only */ 636f08c3bdfSopenharmony_ci } 637f08c3bdfSopenharmony_ci } 638f08c3bdfSopenharmony_ci 639f08c3bdfSopenharmony_ci return SEG_OK; 640f08c3bdfSopenharmony_ci 641f08c3bdfSopenharmony_ci} 642f08c3bdfSopenharmony_ci 643f08c3bdfSopenharmony_ci/* 644f08c3bdfSopenharmony_ci * segment_remove() - remove the specified segment, if exists. 645f08c3bdfSopenharmony_ci */ 646f08c3bdfSopenharmony_ciint segment_remove(char *name) 647f08c3bdfSopenharmony_ci{ 648f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 649f08c3bdfSopenharmony_ci segment_t *segp; 650f08c3bdfSopenharmony_ci 651f08c3bdfSopenharmony_ci segp = segment_get(name); 652f08c3bdfSopenharmony_ci if (segp == NULL) { 653f08c3bdfSopenharmony_ci fprintf(stderr, "%s: no such segment: %s\n", 654f08c3bdfSopenharmony_ci gcp->program_name, name); 655f08c3bdfSopenharmony_ci return SEG_ERR; 656f08c3bdfSopenharmony_ci } 657f08c3bdfSopenharmony_ci 658f08c3bdfSopenharmony_ci unmap_segment(segp); 659f08c3bdfSopenharmony_ci 660f08c3bdfSopenharmony_ci free_seg_slot(segp); 661f08c3bdfSopenharmony_ci 662f08c3bdfSopenharmony_ci return SEG_OK; 663f08c3bdfSopenharmony_ci} 664f08c3bdfSopenharmony_ci 665f08c3bdfSopenharmony_ci/* 666f08c3bdfSopenharmony_ci * segment_touch() - "touch" [read or write] each page of specified range 667f08c3bdfSopenharmony_ci * -- from offset to offset+length -- to fault in or to 668f08c3bdfSopenharmony_ci * test protection. 669f08c3bdfSopenharmony_ci * NOTE: offset is relative to start of mapping, not start of file! 670f08c3bdfSopenharmony_ci */ 671f08c3bdfSopenharmony_ciint segment_touch(char *name, range_t * range, int rw) 672f08c3bdfSopenharmony_ci{ 673f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 674f08c3bdfSopenharmony_ci segment_t *segp; 675f08c3bdfSopenharmony_ci off_t offset; 676f08c3bdfSopenharmony_ci size_t length, maxlength; 677f08c3bdfSopenharmony_ci unsigned long *memp; 678f08c3bdfSopenharmony_ci struct timeval t_start, t_end; 679f08c3bdfSopenharmony_ci 680f08c3bdfSopenharmony_ci segp = segment_get(name); 681f08c3bdfSopenharmony_ci if (segp == NULL) { 682f08c3bdfSopenharmony_ci fprintf(stderr, "%s: no such segment: %s\n", 683f08c3bdfSopenharmony_ci gcp->program_name, name); 684f08c3bdfSopenharmony_ci return SEG_ERR; 685f08c3bdfSopenharmony_ci } 686f08c3bdfSopenharmony_ci 687f08c3bdfSopenharmony_ci offset = round_down_to_pagesize(range->offset); 688f08c3bdfSopenharmony_ci if (offset >= segp->seg_length) { 689f08c3bdfSopenharmony_ci fprintf(stderr, "%s: offset %ld is past end of segment %s\n", 690f08c3bdfSopenharmony_ci gcp->program_name, offset, name); 691f08c3bdfSopenharmony_ci return SEG_ERR; 692f08c3bdfSopenharmony_ci } 693f08c3bdfSopenharmony_ci 694f08c3bdfSopenharmony_ci memp = (unsigned long *)(segp->seg_start + offset); 695f08c3bdfSopenharmony_ci maxlength = segp->seg_length - offset; 696f08c3bdfSopenharmony_ci 697f08c3bdfSopenharmony_ci length = range->length; 698f08c3bdfSopenharmony_ci if (length) 699f08c3bdfSopenharmony_ci length = round_up_to_pagesize(length); 700f08c3bdfSopenharmony_ci 701f08c3bdfSopenharmony_ci /* 702f08c3bdfSopenharmony_ci * note: we silently truncate to max length [end of segment] 703f08c3bdfSopenharmony_ci */ 704f08c3bdfSopenharmony_ci if (length == 0 || length > maxlength) 705f08c3bdfSopenharmony_ci length = maxlength; 706f08c3bdfSopenharmony_ci 707f08c3bdfSopenharmony_ci gettimeofday(&t_start, NULL); 708f08c3bdfSopenharmony_ci touch_memory(rw, memp, length); 709f08c3bdfSopenharmony_ci gettimeofday(&t_end, NULL); 710f08c3bdfSopenharmony_ci printf("%s: touched %d pages in %6.3f secs\n", 711f08c3bdfSopenharmony_ci gcp->program_name, length / gcp->pagesize, 712f08c3bdfSopenharmony_ci (float)(tv_diff_usec(&t_start, &t_end)) / 1000000.0); 713f08c3bdfSopenharmony_ci 714f08c3bdfSopenharmony_ci return SEG_OK; 715f08c3bdfSopenharmony_ci} 716f08c3bdfSopenharmony_ci 717f08c3bdfSopenharmony_ci/* 718f08c3bdfSopenharmony_ci * segment_unmap() - unmap the specified segment, if any, from seg_start 719f08c3bdfSopenharmony_ci * to seg_start+seg_lenth. Leave the segment in the 720f08c3bdfSopenharmony_ci * table; 721f08c3bdfSopenharmony_ci */ 722f08c3bdfSopenharmony_ciint segment_unmap(char *name) 723f08c3bdfSopenharmony_ci{ 724f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 725f08c3bdfSopenharmony_ci segment_t *segp; 726f08c3bdfSopenharmony_ci 727f08c3bdfSopenharmony_ci segp = segment_get(name); 728f08c3bdfSopenharmony_ci if (segp == NULL) { 729f08c3bdfSopenharmony_ci fprintf(stderr, "%s: no such segment: %s\n", 730f08c3bdfSopenharmony_ci gcp->program_name, name); 731f08c3bdfSopenharmony_ci return SEG_ERR; 732f08c3bdfSopenharmony_ci } 733f08c3bdfSopenharmony_ci 734f08c3bdfSopenharmony_ci if (segp->seg_start == MAP_FAILED) 735f08c3bdfSopenharmony_ci return SEG_OK; /* silent success */ 736f08c3bdfSopenharmony_ci 737f08c3bdfSopenharmony_ci switch (segp->seg_type) { 738f08c3bdfSopenharmony_ci case SEGT_ANON: 739f08c3bdfSopenharmony_ci case SEGT_FILE: 740f08c3bdfSopenharmony_ci munmap(segp->seg_start, segp->seg_length); 741f08c3bdfSopenharmony_ci break; 742f08c3bdfSopenharmony_ci 743f08c3bdfSopenharmony_ci case SEGT_SHM: 744f08c3bdfSopenharmony_ci //TODO: shmdt()... 745f08c3bdfSopenharmony_ci break; 746f08c3bdfSopenharmony_ci /* Handle default to get rid of -Wswitch-enum */ 747f08c3bdfSopenharmony_ci default: 748f08c3bdfSopenharmony_ci break; 749f08c3bdfSopenharmony_ci } 750f08c3bdfSopenharmony_ci 751f08c3bdfSopenharmony_ci segp->seg_start = MAP_FAILED; 752f08c3bdfSopenharmony_ci 753f08c3bdfSopenharmony_ci return SEG_OK; 754f08c3bdfSopenharmony_ci} 755f08c3bdfSopenharmony_ci 756f08c3bdfSopenharmony_ci/* 757f08c3bdfSopenharmony_ci * segment_map() -- [re] map() a previously unmapped segment 758f08c3bdfSopenharmony_ci * no-op if already mapped. 759f08c3bdfSopenharmony_ci * range only applies to mapped file. 760f08c3bdfSopenharmony_ci */ 761f08c3bdfSopenharmony_ciint segment_map(char *name, range_t * range, int flags) 762f08c3bdfSopenharmony_ci{ 763f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 764f08c3bdfSopenharmony_ci segment_t *segp; 765f08c3bdfSopenharmony_ci 766f08c3bdfSopenharmony_ci segp = segment_get(name); 767f08c3bdfSopenharmony_ci if (segp == NULL) { 768f08c3bdfSopenharmony_ci fprintf(stderr, "%s: no such segment: %s\n", 769f08c3bdfSopenharmony_ci gcp->program_name, name); 770f08c3bdfSopenharmony_ci return SEG_ERR; 771f08c3bdfSopenharmony_ci } 772f08c3bdfSopenharmony_ci 773f08c3bdfSopenharmony_ci if (segp->seg_start != MAP_FAILED) { 774f08c3bdfSopenharmony_ci fprintf(stderr, "%s: segment %s already mapped\n", 775f08c3bdfSopenharmony_ci gcp->program_name, name); 776f08c3bdfSopenharmony_ci return SEG_OK; /* treat as success */ 777f08c3bdfSopenharmony_ci } 778f08c3bdfSopenharmony_ci 779f08c3bdfSopenharmony_ci if (flags != 0) 780f08c3bdfSopenharmony_ci segp->seg_flags = flags; 781f08c3bdfSopenharmony_ci 782f08c3bdfSopenharmony_ci switch (segp->seg_type) { 783f08c3bdfSopenharmony_ci case SEGT_ANON: 784f08c3bdfSopenharmony_ci return map_anon_segment(segp); 785f08c3bdfSopenharmony_ci break; 786f08c3bdfSopenharmony_ci 787f08c3bdfSopenharmony_ci case SEGT_FILE: 788f08c3bdfSopenharmony_ci if (range != NULL) { 789f08c3bdfSopenharmony_ci segp->seg_offset = range->offset; 790f08c3bdfSopenharmony_ci segp->seg_length = range->length; 791f08c3bdfSopenharmony_ci } 792f08c3bdfSopenharmony_ci return map_file_segment(segp); 793f08c3bdfSopenharmony_ci break; 794f08c3bdfSopenharmony_ci 795f08c3bdfSopenharmony_ci case SEGT_SHM: 796f08c3bdfSopenharmony_ci return map_shm_segment(segp); 797f08c3bdfSopenharmony_ci break; 798f08c3bdfSopenharmony_ci /* Handle default to get rid of -Wswitch-enum */ 799f08c3bdfSopenharmony_ci default: 800f08c3bdfSopenharmony_ci break; 801f08c3bdfSopenharmony_ci } 802f08c3bdfSopenharmony_ci 803f08c3bdfSopenharmony_ci return SEG_ERR; /* unrecognized segment type -- shouldn't happen */ 804f08c3bdfSopenharmony_ci 805f08c3bdfSopenharmony_ci} 806f08c3bdfSopenharmony_ci 807f08c3bdfSopenharmony_ci/* 808f08c3bdfSopenharmony_ci * segment_mbind() - set memory policy for a range of specified segment 809f08c3bdfSopenharmony_ci * 810f08c3bdfSopenharmony_ci * NOTE: offset is relative to start of mapping, not start of file 811f08c3bdfSopenharmony_ci */ 812f08c3bdfSopenharmony_ciint 813f08c3bdfSopenharmony_cisegment_mbind(char *name, range_t * range, int policy, 814f08c3bdfSopenharmony_ci nodemask_t * nodemask, int flags) 815f08c3bdfSopenharmony_ci{ 816f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 817f08c3bdfSopenharmony_ci segment_t *segp; 818f08c3bdfSopenharmony_ci char *start; 819f08c3bdfSopenharmony_ci off_t offset; 820f08c3bdfSopenharmony_ci size_t length, maxlength; 821f08c3bdfSopenharmony_ci int ret; 822f08c3bdfSopenharmony_ci 823f08c3bdfSopenharmony_ci segp = segment_get(name); 824f08c3bdfSopenharmony_ci if (segp == NULL) { 825f08c3bdfSopenharmony_ci fprintf(stderr, "%s: no such segment: %s\n", 826f08c3bdfSopenharmony_ci gcp->program_name, name); 827f08c3bdfSopenharmony_ci return SEG_ERR; 828f08c3bdfSopenharmony_ci } 829f08c3bdfSopenharmony_ci 830f08c3bdfSopenharmony_ci if (segp->seg_start == MAP_FAILED) { 831f08c3bdfSopenharmony_ci fprintf(stderr, "%s: segment %s not mapped\n", 832f08c3bdfSopenharmony_ci gcp->program_name, name); 833f08c3bdfSopenharmony_ci return SEG_ERR; 834f08c3bdfSopenharmony_ci } 835f08c3bdfSopenharmony_ci 836f08c3bdfSopenharmony_ci offset = round_down_to_pagesize(range->offset); 837f08c3bdfSopenharmony_ci if (offset >= segp->seg_length) { 838f08c3bdfSopenharmony_ci fprintf(stderr, "%s: offset %ld is past end of segment %s\n", 839f08c3bdfSopenharmony_ci gcp->program_name, offset, name); 840f08c3bdfSopenharmony_ci return SEG_ERR; 841f08c3bdfSopenharmony_ci } 842f08c3bdfSopenharmony_ci 843f08c3bdfSopenharmony_ci start = segp->seg_start + offset; 844f08c3bdfSopenharmony_ci maxlength = segp->seg_length - offset; 845f08c3bdfSopenharmony_ci 846f08c3bdfSopenharmony_ci length = range->length; 847f08c3bdfSopenharmony_ci if (length) 848f08c3bdfSopenharmony_ci length = round_up_to_pagesize(length); 849f08c3bdfSopenharmony_ci 850f08c3bdfSopenharmony_ci /* 851f08c3bdfSopenharmony_ci * note: we silently truncate to max length [end of segment] 852f08c3bdfSopenharmony_ci */ 853f08c3bdfSopenharmony_ci if (length == 0 || length > maxlength) 854f08c3bdfSopenharmony_ci length = maxlength; 855f08c3bdfSopenharmony_ci 856f08c3bdfSopenharmony_ci ret = mbind(segp->seg_start + offset, length, policy, nodemask->n, 857f08c3bdfSopenharmony_ci NUMA_NUM_NODES, flags); 858f08c3bdfSopenharmony_ci 859f08c3bdfSopenharmony_ci if (ret == -1) { 860f08c3bdfSopenharmony_ci int err = errno; 861f08c3bdfSopenharmony_ci fprintf(stderr, "%s: mbind() of segment %s failed - %s\n", 862f08c3bdfSopenharmony_ci gcp->program_name, name, strerror(err)); 863f08c3bdfSopenharmony_ci return SEG_ERR; 864f08c3bdfSopenharmony_ci } 865f08c3bdfSopenharmony_ci 866f08c3bdfSopenharmony_ci return SEG_OK; 867f08c3bdfSopenharmony_ci} 868f08c3bdfSopenharmony_ci 869f08c3bdfSopenharmony_ci/* 870f08c3bdfSopenharmony_ci * segment_location() - report node location of specified range of segment 871f08c3bdfSopenharmony_ci * 872f08c3bdfSopenharmony_ci * NOTE: offset is relative to start of mapping, not start of file 873f08c3bdfSopenharmony_ci */ 874f08c3bdfSopenharmony_ci#define PG_PER_LINE 8 875f08c3bdfSopenharmony_ci#define PPL_MASK (PG_PER_LINE - 1) 876f08c3bdfSopenharmony_ciint segment_location(char *name, range_t * range) 877f08c3bdfSopenharmony_ci{ 878f08c3bdfSopenharmony_ci glctx_t *gcp = &glctx; 879f08c3bdfSopenharmony_ci segment_t *segp; 880f08c3bdfSopenharmony_ci char *apage, *end; 881f08c3bdfSopenharmony_ci off_t offset; 882f08c3bdfSopenharmony_ci size_t length, maxlength; 883f08c3bdfSopenharmony_ci int pgid, i; 884f08c3bdfSopenharmony_ci bool need_nl; 885f08c3bdfSopenharmony_ci 886f08c3bdfSopenharmony_ci segp = segment_get(name); 887f08c3bdfSopenharmony_ci if (segp == NULL) { 888f08c3bdfSopenharmony_ci fprintf(stderr, "%s: no such segment: %s\n", 889f08c3bdfSopenharmony_ci gcp->program_name, name); 890f08c3bdfSopenharmony_ci return SEG_ERR; 891f08c3bdfSopenharmony_ci } 892f08c3bdfSopenharmony_ci 893f08c3bdfSopenharmony_ci if (segp->seg_start == MAP_FAILED) { 894f08c3bdfSopenharmony_ci fprintf(stderr, "%s: segment %s not mapped\n", 895f08c3bdfSopenharmony_ci gcp->program_name, name); 896f08c3bdfSopenharmony_ci return SEG_ERR; 897f08c3bdfSopenharmony_ci } 898f08c3bdfSopenharmony_ci 899f08c3bdfSopenharmony_ci offset = round_down_to_pagesize(range->offset); 900f08c3bdfSopenharmony_ci if (offset >= segp->seg_length) { 901f08c3bdfSopenharmony_ci fprintf(stderr, "%s: offset %ld is past end of segment %s\n", 902f08c3bdfSopenharmony_ci gcp->program_name, offset, name); 903f08c3bdfSopenharmony_ci return SEG_ERR; 904f08c3bdfSopenharmony_ci } 905f08c3bdfSopenharmony_ci 906f08c3bdfSopenharmony_ci apage = segp->seg_start + offset; 907f08c3bdfSopenharmony_ci maxlength = segp->seg_length - offset; 908f08c3bdfSopenharmony_ci 909f08c3bdfSopenharmony_ci length = range->length; 910f08c3bdfSopenharmony_ci if (length) 911f08c3bdfSopenharmony_ci length = round_up_to_pagesize(length); 912f08c3bdfSopenharmony_ci 913f08c3bdfSopenharmony_ci /* 914f08c3bdfSopenharmony_ci * note: we silently truncate to max length [end of segment] 915f08c3bdfSopenharmony_ci */ 916f08c3bdfSopenharmony_ci if (length == 0 || length > maxlength) 917f08c3bdfSopenharmony_ci length = maxlength; 918f08c3bdfSopenharmony_ci 919f08c3bdfSopenharmony_ci end = apage + length; 920f08c3bdfSopenharmony_ci pgid = offset / gcp->pagesize; 921f08c3bdfSopenharmony_ci 922f08c3bdfSopenharmony_ci show_one_segment(segp, false); /* show mapping, no header */ 923f08c3bdfSopenharmony_ci 924f08c3bdfSopenharmony_ci printf("page offset "); 925f08c3bdfSopenharmony_ci for (i = 0; i < PG_PER_LINE; ++i) 926f08c3bdfSopenharmony_ci printf(" +%02d", i); 927f08c3bdfSopenharmony_ci printf("\n"); 928f08c3bdfSopenharmony_ci if (pgid & PPL_MASK) { 929f08c3bdfSopenharmony_ci /* 930f08c3bdfSopenharmony_ci * start partial line 931f08c3bdfSopenharmony_ci */ 932f08c3bdfSopenharmony_ci int pgid2 = pgid & ~PPL_MASK; 933f08c3bdfSopenharmony_ci printf("%12x: ", pgid2); 934f08c3bdfSopenharmony_ci while (pgid2 < pgid) { 935f08c3bdfSopenharmony_ci printf(" "); 936f08c3bdfSopenharmony_ci ++pgid2; 937f08c3bdfSopenharmony_ci } 938f08c3bdfSopenharmony_ci need_nl = true; 939f08c3bdfSopenharmony_ci } else 940f08c3bdfSopenharmony_ci need_nl = false; 941f08c3bdfSopenharmony_ci 942f08c3bdfSopenharmony_ci for (; apage < end; apage += gcp->pagesize, ++pgid) { 943f08c3bdfSopenharmony_ci int node; 944f08c3bdfSopenharmony_ci 945f08c3bdfSopenharmony_ci node = get_node(apage); 946f08c3bdfSopenharmony_ci if (node < 0) { 947f08c3bdfSopenharmony_ci fprintf(stderr, "\n%s: " 948f08c3bdfSopenharmony_ci "failed to get node for segment %s, offset 0x%x\n", 949f08c3bdfSopenharmony_ci gcp->program_name, name, SEG_OFFSET(segp, 950f08c3bdfSopenharmony_ci apage)); 951f08c3bdfSopenharmony_ci return SEG_ERR; 952f08c3bdfSopenharmony_ci } 953f08c3bdfSopenharmony_ci 954f08c3bdfSopenharmony_ci if ((pgid & PPL_MASK) == 0) { 955f08c3bdfSopenharmony_ci if (need_nl) 956f08c3bdfSopenharmony_ci printf("\n"); 957f08c3bdfSopenharmony_ci printf("%12x: ", pgid); /* start a new line */ 958f08c3bdfSopenharmony_ci need_nl = true; 959f08c3bdfSopenharmony_ci } 960f08c3bdfSopenharmony_ci printf(" %3d", node); 961f08c3bdfSopenharmony_ci 962f08c3bdfSopenharmony_ci if (signalled(gcp)) { 963f08c3bdfSopenharmony_ci reset_signal(); 964f08c3bdfSopenharmony_ci break; 965f08c3bdfSopenharmony_ci } 966f08c3bdfSopenharmony_ci } 967f08c3bdfSopenharmony_ci printf("\n"); 968f08c3bdfSopenharmony_ci 969f08c3bdfSopenharmony_ci return SEG_OK; 970f08c3bdfSopenharmony_ci} 971f08c3bdfSopenharmony_ci#endif 972