/* doshm.c: description * * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include #include #include #include #include #include #include #include #include #include #include #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_FD 2 #define FUTEX_REQUEUE 3 #define FUTEX_CMP_REQUEUE 4 #define FUTEX_WAKE_OP 5 #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 static inline int futex(int *uaddr, int op, int val, const struct timespec *utime, int *uaddr2, int val3) { return syscall(__NR_futex, uaddr, op, val, utime, uaddr2, val3); } #define MREMAP_MAYMOVE 1 #define SYSERROR(X, Y) \ do { \ if ((long)(X) == -1L) { \ perror(Y); \ exit(1); \ } \ } while(0) void format(void) { fprintf(stderr, "Format: doshm [ ...]\n"); exit(2); } void show_maps(void) { char sysbuf[256]; sprintf(sysbuf, "cat /proc/%d/maps", getpid()); system(sysbuf); } void dosysvshm(int argc, char **argv) { struct shmid_ds ds; void *mem, *mem2; int shmid = -1, tmp; shmid = shmget(IPC_PRIVATE, 1000*1024, IPC_CREAT|0666); SYSERROR(shmid, "shmget"); printf("shmid: %d\n", shmid); mem = shmat(shmid, NULL, 0); SYSERROR(mem, "shmat"); mem2 = shmat(shmid, NULL, 0); SYSERROR(mem, "shmat"); printf("memory: %p\n", mem); show_maps(); // raise(SIGSTOP); tmp = shmctl(shmid, IPC_STAT, &ds); SYSERROR(tmp, "shmctl"); printf("nattch %lu\n", ds.shm_nattch); tmp = shmdt(mem); SYSERROR(tmp, "shmdt"); tmp = shmdt(mem2); SYSERROR(tmp, "shmdt"); tmp = shmctl(shmid, IPC_RMID, NULL); SYSERROR(tmp, "shmctl"); exit(0); } void chardev(int argc, char **argv) { void *mem, *mem2; int fd; fd = open("/dev/workram", O_RDWR, 0600); SYSERROR(fd, "open"); mem = mmap(NULL, 16384, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); SYSERROR(mem, "mmap"); mem2 = mmap(NULL, 16384, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); SYSERROR(mem, "mmap2"); printf("mem: %p\n", mem); printf("mem2: %p\n", mem2); show_maps(); exit(0); } void doposixshm(int argc, char **argv) { size_t size; void *mem, *mem2; int fd, tmp; if (argc != 3) format(); size = atol(argv[2]) * 16384 * 2; #if 1 fd = open(argv[1], O_CREAT | O_TRUNC | O_RDWR, 0600); SYSERROR(fd, "open"); #else fd = shm_open(argv[1], O_CREAT | O_TRUNC | O_RDWR, 0600); SYSERROR(fd, "shm_open"); #endif tmp = ftruncate(fd, size); SYSERROR(tmp, "truncate"); mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); SYSERROR(mem, "mmap"); mem2 = mmap(NULL, size / 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 16384); SYSERROR(mem, "mmap2"); show_maps(); printf("mem: %p\n", mem); printf("mem2: %p\n", mem2); exit(0); } void doshrinkmmap(int argc, char **argv) { size_t size; void *mem, *mem2; int fd, tmp; if (argc != 3) format(); size = atol(argv[2]) * 16384 * 2; fd = open(argv[1], O_CREAT | O_TRUNC | O_RDWR, 0600); SYSERROR(fd, "open"); tmp = ftruncate(fd, size + 16384); SYSERROR(tmp, "truncate"); mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); SYSERROR(mem, "mmap"); mem2 = mmap(NULL, size / 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 16384); SYSERROR(mem, "mmap2"); printf("mem: %p\n", mem); printf("mem2: %p\n", mem2); tmp = ftruncate(fd, size); SYSERROR(tmp, "truncate2"); show_maps(); exit(0); } void doxmmap(int argc, char **argv, const char *file) { unsigned long prot, map; void *mem, *mem2; int fd, perm; argc--; argv++; perm = O_RDWR; prot = PROT_READ | PROT_WRITE; map = MAP_PRIVATE; for (; *argv; argv++) { if (strcmp(*argv, "r") == 0) { perm = O_RDONLY; prot = PROT_READ; continue; } if (strcmp(*argv, "w") == 0) { perm = O_RDWR; prot = PROT_READ | PROT_WRITE; continue; } if (strcmp(*argv, "p") == 0) { map = MAP_PRIVATE; continue; } if (strcmp(*argv, "s") == 0) { map = MAP_SHARED; continue; } } fd = open(file, perm, 0600); SYSERROR(fd, "open"); mem = mmap(NULL, 16384, prot, map, fd, 0); SYSERROR(mem, "mmap"); mem2 = mmap(NULL, 16384, prot, map, fd, 0); SYSERROR(mem, "mmap2"); printf("mem: %p\n", mem); printf("mem2: %p\n", mem2); show_maps(); exit(0); } void doremap(int argc, char **argv) { void *mem, *mem2; mem = mmap(NULL, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0); SYSERROR(mem, "mmap"); mem2 = mremap(mem, 16384, 8192, MREMAP_MAYMOVE); SYSERROR(mem2, "mmap"); printf("mem: %p\n", mem); printf("mem2: %p\n", mem2); show_maps(); exit(0); } void dowait(int argc, char **argv) { int shmid, tmp, *f, n; shmid = shmget(23, 4, IPC_CREAT|0666); SYSERROR(shmid, "shmget"); f = shmat(shmid, NULL, 0); SYSERROR(f, "shmat"); n = *f; printf("WAIT: %p{%x}\n", f, n); tmp = futex(f, FUTEX_WAIT, n, NULL, NULL, 0); SYSERROR(tmp, "futex"); printf("WAITED: %d\n", tmp); tmp = shmdt(f); SYSERROR(tmp, "shmdt"); exit(0); } void dowake(int argc, char **argv) { int shmid, tmp, *f; shmid = shmget(23, 4, IPC_CREAT|0666); SYSERROR(shmid, "shmget"); f = shmat(shmid, NULL, 0); SYSERROR(f, "shmat"); (*f)++; printf("WAKE: %p{%x}\n", f, *f); tmp = futex(f, FUTEX_WAKE, 1, NULL, NULL, 0); SYSERROR(tmp, "futex"); printf("WOKE: %d\n", tmp); tmp = shmdt(f); SYSERROR(tmp, "shmdt"); exit(0); } void badfutex(int argc, char **argv) { int *x; int tmp; x = mmap(NULL, 16384, PROT_READ, MAP_PRIVATE|MAP_ANON, -1, 0); SYSERROR(x, "mmap"); tmp = futex(x, FUTEX_WAIT, 0, NULL, NULL, 0); SYSERROR(tmp, "futex"); exit(0); } /* * allocate a mapping that will be shaved by the mmap alloc shrinker */ void doshave(int argc, char **argv) { void *x; x = mmap(NULL, 16384*16+1, PROT_READ, MAP_PRIVATE|MAP_ANON, -1, 0); SYSERROR(x, "mmap"); exit(0); } int main(int argc, char **argv) { if (argc <= 1) format(); argc--; argv++; printf("Command: %s\n", argv[0]); if (strcmp(argv[0], "sysv") == 0) dosysvshm(argc, argv); if (strcmp(argv[0], "badfutex") == 0) badfutex(argc, argv); if (strcmp(argv[0], "chr") == 0) chardev(argc, argv); if (strcmp(argv[0], "posix") == 0) doposixshm(argc, argv); if (strcmp(argv[0], "remap") == 0) doremap(argc, argv); if (strcmp(argv[0], "shrink") == 0) doshrinkmmap(argc, argv); if (strcmp(argv[0], "file") == 0) { if (argc < 2) format(); argv++; argc--; doxmmap(argc, argv, argv[0]); } if (strcmp(argv[0], "zero") == 0) doxmmap(argc, argv, "/dev/zero"); if (strcmp(argv[0], "null") == 0) doxmmap(argc, argv, "/dev/null"); if (strcmp(argv[0], "mtd") == 0) doxmmap(argc, argv, "/dev/mtd0"); if (strcmp(argv[0], "wait") == 0) dowait(argc, argv); if (strcmp(argv[0], "wake") == 0) dowake(argc, argv); if (strcmp(argv[0], "shave") == 0) doshave(argc, argv); fprintf(stderr, "Unknown command\n"); exit(1); }