pstack updated

This commit is contained in:
Remzi Arpaci-Dusseau
2021-08-14 14:39:59 -07:00
parent a140f0bc0f
commit cf38b849dd

View File

@@ -1,70 +1,74 @@
// Persistent stack example of how mmap() naturally creates a software abstraction of persistent memory. // Persistent stack example of how mmap() naturally creates a software abstraction of persistent memory.
// Author: Terence Kelly <tpklly@acm.org> // Author: Terence Kelly
// tpkelly @ { acm.org, cs.princeton.edu, eecs.umich.edu }
// Note: Use 'dd' to make the initial (empty) image, e.g.,
// dd if=/dev/zero of=ps.img bs=32 count=1 // Note: Use 'truncate' to make the initial (empty) backing file,
// makes a 32-byte empty file (the first integer being the size of the stack, // whose size should be a multiple of the system page size:
// the remaining integers being values) //
// prompt> getconf PAGESIZE
#include <assert.h> // 4096
#include <fcntl.h> // prompt> truncate -s 4096 ps.img
#include <stdio.h> //
#include <stdlib.h> // makes a 4096-byte empty file. The first sizeof(size_t) bytes will
#include <string.h> // be interprted as the number of items on the stack; the remainder
#include <unistd.h> // of the file will contain the integers contained in the stack.
#include <sys/mman.h> // Now you can run the program:
#include <sys/stat.h> //
#include <sys/types.h> // prompt> ./pstack 7 13 47 pop
// 47
int open_or_die(const char *path, int oflag) { // prompt> ./pstack pop pop 99
int fd = open(path, oflag); // 13
assert(fd > 0); // 7
return fd; // prompt> ./pstack pop
} // 99
//
int fstat_or_die(int fildes, struct stat *buf) { // Notice that items push'd in one invocation of the program persist
int rc = fstat(fildes, buf); // until the next invocation: The stack is persistent.
assert(rc == 0); //
return rc; // You can use hexdump to examine the contents of the backing file:
} //
// prompt> hexdump ps.img
void *mmap_or_die(void *addr, size_t len, int prot, int flags, int fd, off_t offset) {
void *p = mmap(addr, len, prot, flags, fd, offset); #include <assert.h>
assert(p != MAP_FAILED); #include <fcntl.h>
return p; #include <stdio.h>
} #include <stdlib.h>
#include <string.h>
typedef struct { #include <unistd.h>
size_t n; #include <sys/mman.h>
int stack[]; // zero-length per C99 #include <sys/stat.h>
} pstack_t; #include <sys/types.h>
int main(int argc, char *argv[]) { typedef struct {
int fd, rc; size_t n;
struct stat s; int stack[]; // zero-length per C99
size_t file_size; } pstack_t;
pstack_t *p;
int main(int argc, char *argv[]) {
fd = open_or_die("ps.img", O_RDWR); int fd, rc;
rc = fstat_or_die(fd, &s); struct stat s;
size_t file_size;
file_size = (size_t) s.st_size; pstack_t *p;
assert(file_size % sizeof(int) == 0);
fd = open("ps.img", O_RDWR);
p = mmap_or_die(NULL, file_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); assert(fd > -1);
rc = fstat(fd, &s);
for (int i = 1; i < argc; i++) assert(rc == 0);
if (strcmp(argv[i], "pop") == 0) {
if (p->n > 0) // stack not empty file_size = (size_t) s.st_size;
printf("%d\n", p->stack[--p->n]); assert(file_size >= sizeof(pstack_t) && file_size % sizeof(int) == 0);
else
printf("stack empty\n"); p = (pstack_t *) mmap(NULL, file_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
} else assert(p != MAP_FAILED);
if (sizeof(pstack_t) + p->n * sizeof(int) < file_size) // stack not full
p->stack[p->n++] = atoi(argv[i]); for (int i = 1; i < argc; i++)
else if (strcmp(argv[i], "pop") == 0) {
printf("stack full: %d not added\n", atoi(argv[i])); if (p->n > 0) // stack not empty
printf("%d\n", p->stack[--p->n]);
close(fd); } else { // pop
return 0; if (sizeof(pstack_t) + (1 + p->n) * sizeof(int) <= file_size) // stack not full
} p->stack[p->n++] = atoi(argv[i]);
}
(void) close(fd);
return 0;
}