aboutsummaryrefslogtreecommitdiffstats
path: root/arena.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2001-10-20 02:12:22 +0000
committerH. Peter Anvin <hpa@zytor.com>2001-10-20 02:12:22 +0000
commit50cedb0ff19233273ef33cb5b5e8725025a35024 (patch)
tree25b21afff2ef45d706df0b05f18473516b8911f5 /arena.c
parentf3d637296f1f839d4a95a849a7dbfbb600f563f1 (diff)
downloadlpsm-50cedb0ff19233273ef33cb5b5e8725025a35024.tar.gz
lpsm-50cedb0ff19233273ef33cb5b5e8725025a35024.tar.xz
lpsm-50cedb0ff19233273ef33cb5b5e8725025a35024.zip
Split apart into modules. Create lpsm_zalloc()/lpsm_calloc().
Diffstat (limited to 'arena.c')
-rw-r--r--arena.c242
1 files changed, 114 insertions, 128 deletions
diff --git a/arena.c b/arena.c
index 8026703..f28cb45 100644
--- a/arena.c
+++ b/arena.c
@@ -40,18 +40,12 @@
#include "lpsm.h"
#include "internals.h"
-/* This might end up being a bitmask eventually */
-enum page_status {
- page_clean = 0,
- page_dirty = 1,
-};
-
/*
- * This is the data structure for the object store. Note that only
- * one active object store is supported, due to the need to trap
- * SIGSEGV.
+ * This is the data structure for the persistent memory arena. Note
+ * that only one arena is supported, due to the need to trap SIGSEGV
+ * and address space allocation issues.
*/
-struct ObjStore *lpsm_os_struct;
+struct lpsm_arena *lpsm_memory_info = NULL;
/* Wrappers for read() and write() which retries if incomplete */
static ssize_t lpsm_read(int fd, void *buf, size_t count)
@@ -107,7 +101,6 @@ static ssize_t lpsm_write(int fd, void *buf, size_t count)
*/
static void lpsm_sigsegv(int signal, siginfo_t *siginfo, void *ptr)
{
- struct ObjStore *os = lpsm_os_struct;
void *page;
uintptr_t npage, offset;
char *pageinfo;
@@ -131,13 +124,13 @@ static void lpsm_sigsegv(int signal, siginfo_t *siginfo, void *ptr)
# endif /* __i386__ */
#endif /* __linux__ */
- page = (void *)((uintptr_t)siginfo->si_addr & ~(os->pagesize-1));
- offset = (uintptr_t)page - (uintptr_t)os->arena;
- npage = (offset >> os->pageshift);
- pageinfo = os->pageinfo + npage;
+ page = (void *)((uintptr_t)siginfo->si_addr & ~(PM->pagesize-1));
+ offset = (uintptr_t)page - (uintptr_t)PM->arena;
+ npage = (offset >> PM->pageshift);
+ pageinfo = PM->pageinfo + npage;
if ( signal != SIGSEGV || siginfo->si_code != SEGV_ACCERR ||
- offset >= os->arena_len ) {
+ offset >= PM->arena_len ) {
struct sigaction dfl;
dfl.sa_handler = SIG_DFL;
@@ -157,12 +150,12 @@ static void lpsm_sigsegv(int signal, siginfo_t *siginfo, void *ptr)
return; /* Re-take fault */
}
- mprotect(page, os->pagesize, PROT_READ|PROT_WRITE);
+ mprotect(page, PM->pagesize, PROT_READ|PROT_WRITE);
switch ( (enum page_status) *pageinfo ) {
case page_clean:
*pageinfo = page_dirty; /* Page now dirty */
- os->dirty_count++; /* For accounting purposes */
+ PM->dirty_count++; /* For accounting purposes */
/* Leave page r/w */
break;
@@ -180,15 +173,14 @@ static void lpsm_sigsegv(int signal, siginfo_t *siginfo, void *ptr)
*/
static int lpsm_log_writeback(void)
{
- struct ObjStore *os = lpsm_os_struct;
- struct ObjStore_LogRecord record;
+ struct lpsm_logrecord record;
off_t position, last_commit;
struct flock lockmain;
last_commit = 0; /* Last COMMIT record found */
- position = lseek(os->log_fd, 0, SEEK_SET);
+ position = lseek(PM->log_fd, 0, SEEK_SET);
- while ( lpsm_read(os->log_fd, &record, sizeof(record)) == sizeof(record) ) {
+ while ( lpsm_read(PM->log_fd, &record, sizeof(record)) == sizeof(record) ) {
if ( record.magic != LOGRECORD_MAGIC )
break; /* Bad magic, assume rest of log corrupt */
if ( record.record_type == osrec_commit ) {
@@ -198,7 +190,7 @@ static int lpsm_log_writeback(void)
last_commit = position; /* Found a commit record */
} else if ( record.record_type == osrec_page ) {
/* Advance past current page cluster */
- position = lseek(os->log_fd, record.size, SEEK_CUR);
+ position = lseek(PM->log_fd, record.size, SEEK_CUR);
} else {
return -1; /* Unknown record - unsafe to process */
}
@@ -207,9 +199,9 @@ static int lpsm_log_writeback(void)
/* Now we know where the last commit was. Now we can process
everything up to that point. */
- position = lseek(os->log_fd, 0, SEEK_SET);
+ position = lseek(PM->log_fd, 0, SEEK_SET);
- while ( lpsm_read(os->log_fd, &record, sizeof(record))
+ while ( lpsm_read(PM->log_fd, &record, sizeof(record))
== sizeof(record) && position < last_commit ) {
if ( record.magic != LOGRECORD_MAGIC )
break; /* Bad magic, assume rest of log corrupt */
@@ -226,18 +218,18 @@ static int lpsm_log_writeback(void)
lockmain.l_whence = SEEK_SET;
lockmain.l_start = record.offset;
lockmain.l_len = record.size;
- while ( fcntl(os->main_fd, F_SETLKW, &lockmain) == -1 && errno == EINTR );
+ while ( fcntl(PM->main_fd, F_SETLKW, &lockmain) == -1 && errno == EINTR );
data = mmap(NULL, record.size, PROT_WRITE, MAP_SHARED,
- os->main_fd, record.offset);
+ PM->main_fd, record.offset);
if ( data == MAP_FAILED )
return -1;
- if ( lpsm_read(os->log_fd, data, record.size) != record.size )
+ if ( lpsm_read(PM->log_fd, data, record.size) != record.size )
return -1; /* Badness */
if ( munmap(data, record.size) )
return -1;
lockmain.l_type = F_UNLCK;
- while ( fcntl(os->main_fd, F_SETLKW, &lockmain) == -1 && errno == EINTR );
+ while ( fcntl(PM->main_fd, F_SETLKW, &lockmain) == -1 && errno == EINTR );
position += record.size;
} else {
return -1; /* Unknown record - unsafe to process */
@@ -245,17 +237,17 @@ static int lpsm_log_writeback(void)
}
/* Log successfully recovered. Truncate. */
- fsync(os->main_fd);
- ftruncate(os->log_fd, 0);
+ fsync(PM->main_fd);
+ ftruncate(PM->log_fd, 0);
/* Write initial commit record, for sequence number recovery */
record.magic = LOGRECORD_MAGIC;
record.record_type = osrec_commit;
- record.size = os->fork_seq;
+ record.size = PM->fork_seq;
record.offset = 0x54494d43; /* For debugging */
- if ( lpsm_write(os->log_fd, &record, sizeof(record)) < sizeof(record) )
+ if ( lpsm_write(PM->log_fd, &record, sizeof(record)) < sizeof(record) )
return -1;
- fsync(os->log_fd); /* Indicate log recovery complete */
+ fsync(PM->log_fd); /* Indicate log recovery complete */
return 0;
}
@@ -265,7 +257,6 @@ static int lpsm_log_writeback(void)
*/
static int lpsm_recover_log(void)
{
- struct ObjStore *os = lpsm_os_struct;
struct flock lock;
int rv = 0;
@@ -274,17 +265,17 @@ static int lpsm_recover_log(void)
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
- while ( fcntl(os->log_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
+ while ( fcntl(PM->log_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
/* Do log recovery, and write initial commit record. */
rv = lpsm_log_writeback();
/* Increase the sequence number, since we just wrote a commit. */
- os->fork_seq++;
+ PM->fork_seq++;
/* Unlock file and run. */
lock.l_type = F_UNLCK;
- while ( fcntl(os->log_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
+ while ( fcntl(PM->log_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
return rv;
}
@@ -296,7 +287,6 @@ static int lpsm_recover_log(void)
*/
void *lpsm_arena_init(const char *main_file, const char *log_file, size_t *arena_len)
{
- struct ObjStore *os;
void *arena_ptr;
struct sigaction sigact;
struct flock lock;
@@ -305,30 +295,30 @@ void *lpsm_arena_init(const char *main_file, const char *log_file, size_t *arena
arena_ptr = ARENA_ADDRESS;
- lpsm_os_struct = os = malloc(sizeof(struct ObjStore));
- if ( !os )
+ PM = malloc(sizeof(struct lpsm_arena));
+ if ( !PM )
goto errx0;
- os->fork_seq = 0; /* Initialize sequence counter */
+ PM->fork_seq = 0; /* Initialize sequence counter */
- os->main_fd = open(main_file, O_RDWR|O_CREAT, 0666);
- if ( os->main_fd < 0 )
+ PM->main_fd = open(main_file, O_RDWR|O_CREAT, 0666);
+ if ( PM->main_fd < 0 )
goto errx1;
- os->pagesize = getpagesize();
- if ( os->pagesize & (os->pagesize - 1) )
+ PM->pagesize = getpagesize();
+ if ( PM->pagesize & (PM->pagesize - 1) )
goto errx2; /* WTF -- pagesize not a power of 2? */
- /* Compute log2(os->pagesize) */
- os->pageshift = 0;
- while ( (1 << os->pageshift) < os->pagesize )
- os->pageshift++;
+ /* Compute log2(PM->pagesize) */
+ PM->pageshift = 0;
+ while ( (1 << PM->pageshift) < PM->pagesize )
+ PM->pageshift++;
/*
* Open log file
*/
- os->log_fd = open(log_file, O_RDWR|O_APPEND|O_CREAT, 0666);
- if ( os->log_fd < 0 )
+ PM->log_fd = open(log_file, O_RDWR|O_APPEND|O_CREAT, 0666);
+ if ( PM->log_fd < 0 )
goto errx3;
/* Now, do log recovery if needed */
@@ -340,55 +330,55 @@ void *lpsm_arena_init(const char *main_file, const char *log_file, size_t *arena
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
- while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
- file_len = lseek(os->main_fd, 0, SEEK_END);
+ while ( fcntl(PM->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
+ file_len = lseek(PM->main_fd, 0, SEEK_END);
if ( len < file_len ) {
len = file_len;
}
- len = (len + os->pagesize - 1) & ~(os->pagesize - 1);
+ len = (len + PM->pagesize - 1) & ~(PM->pagesize - 1);
if ( len > file_len ) {
- ftruncate(os->main_fd, len); /* Extend file */
+ ftruncate(PM->main_fd, len); /* Extend file */
}
lock.l_type = F_UNLCK;
- while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
+ while ( fcntl(PM->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
- os->arena = mmap(arena_ptr, len, PROT_READ, MAP_PRIVATE|MAP_FIXED, os->main_fd, 0);
- if ( os->arena == MAP_FAILED )
+ PM->arena = mmap(arena_ptr, len, PROT_READ, MAP_PRIVATE|MAP_FIXED, PM->main_fd, 0);
+ if ( PM->arena == MAP_FAILED )
goto errx3;
- os->arena_len = len;
+ PM->arena_len = len;
if ( *arena_len )
*arena_len = len;
- os->pageinfo = malloc(len >> os->pageshift);
- if ( !os->pageinfo )
+ PM->pageinfo = malloc(len >> PM->pageshift);
+ if ( !PM->pageinfo )
goto errx4;
- file_len = (file_len + os->pagesize - 1) & ~(os->pagesize-1);
- file_pages = file_len >> os->pageshift;
- len_pages = len >> os->pageshift;
+ file_len = (file_len + PM->pagesize - 1) & ~(PM->pagesize-1);
+ file_pages = file_len >> PM->pageshift;
+ len_pages = len >> PM->pageshift;
/* All pages clean at this time */
- memset(os->pageinfo, page_clean, len_pages);
+ memset(PM->pageinfo, page_clean, len_pages);
sigact.sa_sigaction = lpsm_sigsegv;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = SA_RESTART|SA_SIGINFO;
- if ( sigaction(SIGSEGV, &sigact, &os->oldact) )
+ if ( sigaction(SIGSEGV, &sigact, &PM->oldact) )
goto errx5;
- return os->arena;
+ return PM->arena;
errx5:
- munmap(os->pageinfo, len >> os->pageshift);
+ munmap(PM->pageinfo, len >> PM->pageshift);
errx4:
munmap(arena_ptr, len);
errx3:
- if ( os->log_fd >= 0 ) close(os->log_fd);
+ if ( PM->log_fd >= 0 ) close(PM->log_fd);
errx2:
- close(os->main_fd);
+ close(PM->main_fd);
errx1:
- free(os);
+ free(PM);
errx0:
return NULL;
@@ -416,13 +406,12 @@ void *lpsm_arena_init(const char *main_file, const char *log_file, size_t *arena
pid_t lpsm_checkpoint(double gc_factor, enum psmsync wait)
{
static pid_t last_sync = 0;
- struct ObjStore *os = lpsm_os_struct;
pid_t f, w;
char *pi, *epi;
void *page;
- pi = os->pageinfo;
- epi = os->pageinfo + (os->arena_len >> os->pageshift);
+ pi = PM->pageinfo;
+ epi = PM->pageinfo + (PM->arena_len >> PM->pageshift);
if ( last_sync ) {
int status;
@@ -461,11 +450,11 @@ pid_t lpsm_checkpoint(double gc_factor, enum psmsync wait)
/* FIX: We probably want to do something more clever
than memset() here, and perhaps keep around the old dirty
array for a while. */
- mprotect(os->arena, os->arena_len, PROT_READ);
- memset(os->pageinfo, page_clean, os->arena_len >> os->pageshift);
+ mprotect(PM->arena, PM->arena_len, PROT_READ);
+ memset(PM->pageinfo, page_clean, PM->arena_len >> PM->pageshift);
- os->dirty_count = 0; /* No pages dirty */
- os->fork_seq++; /* Increase next sequence number */
+ PM->dirty_count = 0; /* No pages dirty */
+ PM->fork_seq++; /* Increase next sequence number */
if ( wait == PSMSYNC_SYNC ) {
int status;
@@ -482,7 +471,7 @@ pid_t lpsm_checkpoint(double gc_factor, enum psmsync wait)
} else {
/* Child process -- do the actual work of writing back dirty pages */
- struct ObjStore_LogRecord record, last_rec;
+ struct lpsm_logrecord record, last_rec;
struct flock lock;
off_t logsize;
@@ -495,43 +484,43 @@ pid_t lpsm_checkpoint(double gc_factor, enum psmsync wait)
for (;;) {
/* First, lock the entire log file */
lock.l_type = F_WRLCK;
- while ( fcntl(os->log_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
+ while ( fcntl(PM->log_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
/* Make sure we were indeed next in turn */
- lseek(os->log_fd, -(off_t)sizeof(last_rec), SEEK_END);
- if ( lpsm_read(os->log_fd, &last_rec, sizeof(last_rec)) < sizeof(last_rec) ||
+ lseek(PM->log_fd, -(off_t)sizeof(last_rec), SEEK_END);
+ if ( lpsm_read(PM->log_fd, &last_rec, sizeof(last_rec)) < sizeof(last_rec) ||
last_rec.magic != LOGRECORD_MAGIC ) {
/* Something bad happened... */
kill(getppid(), SIGABRT); /* Kill main process */
_exit(99);
}
- if ( last_rec.size+1 == os->fork_seq )
+ if ( last_rec.size+1 == PM->fork_seq )
break; /* It's for us... */
/* Someone else is ahead of us in line. Yield to them. */
lock.l_type = F_UNLCK;
- while ( fcntl(os->log_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
+ while ( fcntl(PM->log_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
sched_yield(); /* Snore... */
}
/* Write dirty pages to log file */
- for ( pi = os->pageinfo ; pi < epi ; pi++ ) {
+ for ( pi = PM->pageinfo ; pi < epi ; pi++ ) {
if ( *pi == page_dirty ) {
- page = (char *)os->arena +
- ((uintptr_t)(pi - os->pageinfo) << os->pageshift);
- record.offset = (char *)page - (char *)os->arena;
+ page = (char *)PM->arena +
+ ((uintptr_t)(pi - PM->pageinfo) << PM->pageshift);
+ record.offset = (char *)page - (char *)PM->arena;
/* Aggregate contiguous pages into a single record */
- record.size = os->pagesize;
+ record.size = PM->pagesize;
while ( pi+1 < epi && pi[1] == page_dirty ) {
pi++;
- record.size += os->pagesize;
+ record.size += PM->pagesize;
}
- if ( lpsm_write(os->log_fd, &record, sizeof(record))
+ if ( lpsm_write(PM->log_fd, &record, sizeof(record))
< sizeof(record) ||
- lpsm_write(os->log_fd, page, record.size) < record.size ) {
+ lpsm_write(PM->log_fd, page, record.size) < record.size ) {
kill(getppid(), SIGABRT); /* Kill main process */
_exit(99);
}
@@ -539,21 +528,21 @@ pid_t lpsm_checkpoint(double gc_factor, enum psmsync wait)
}
/* This might be more efficiently done with fdatasync() */
- fsync(os->log_fd); /* Make sure we have written everything */
+ fsync(PM->log_fd); /* Make sure we have written everything */
/* Write commit record */
record.record_type = osrec_commit;
- record.size = os->fork_seq;
+ record.size = PM->fork_seq;
record.offset = (off_t)0x54494d43;
- if ( lpsm_write(os->log_fd, &record, sizeof(record)) < sizeof(record) ) {
+ if ( lpsm_write(PM->log_fd, &record, sizeof(record)) < sizeof(record) ) {
kill(getppid(), SIGABRT);
_exit(99);
}
- fsync(os->log_fd);
+ fsync(PM->log_fd);
/* Check to see if it's time for garbage collect */
- logsize = lseek(os->log_fd, 0, SEEK_END);
- if ( gc_factor < HUGE_VAL && (double)logsize >= gc_factor*os->arena_len ) {
+ logsize = lseek(PM->log_fd, 0, SEEK_END);
+ if ( gc_factor < HUGE_VAL && (double)logsize >= gc_factor*PM->arena_len ) {
/* Replaying the log isn't the most efficient way to do this.
We could also keep a status bit per page around, and flush
them out of the shadow array. The biggest problem with that
@@ -567,7 +556,7 @@ pid_t lpsm_checkpoint(double gc_factor, enum psmsync wait)
/* Drop lock on log file */
lock.l_type = F_UNLCK;
- while ( fcntl(os->log_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
+ while ( fcntl(PM->log_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
_exit(0); /* Done! */
}
@@ -582,7 +571,6 @@ pid_t lpsm_checkpoint(double gc_factor, enum psmsync wait)
*/
int lpsm_extend(size_t new_size)
{
- struct ObjStore *os = lpsm_os_struct;
struct flock lock;
void *newp, *infop;
off_t file_size;
@@ -591,12 +579,12 @@ int lpsm_extend(size_t new_size)
size_t add_pages, old_pages, new_pages, file_pages;
struct rlimit fsizelimit;
- old_size = os->arena_len;
+ old_size = PM->arena_len;
if ( new_size <= old_size )
return 0; /* No action */
- new_size = (new_size + os->pagesize - 1) & ~(os->pagesize - 1);
+ new_size = (new_size + PM->pagesize - 1) & ~(PM->pagesize - 1);
add_size = new_size - old_size;
/* Make sure we won't run afoul of a set resource limit. */
@@ -609,50 +597,50 @@ int lpsm_extend(size_t new_size)
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
- while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
+ while ( fcntl(PM->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
lock.l_type = F_UNLCK;
- file_size = lseek(os->main_fd, 0, SEEK_END);
+ file_size = lseek(PM->main_fd, 0, SEEK_END);
if ( file_size < new_size )
- ft = ftruncate(os->main_fd, new_size);
+ ft = ftruncate(PM->main_fd, new_size);
else
ft = 0;
if ( ft )
goto reset_size; /* Failure */
- newp = mmap((char*)os->arena + old_size,
+ newp = mmap((char*)PM->arena + old_size,
add_size, PROT_READ,
- MAP_PRIVATE|MAP_FIXED, os->main_fd, old_size);
+ MAP_PRIVATE|MAP_FIXED, PM->main_fd, old_size);
if ( newp == MAP_FAILED )
goto reset_size; /* Failure */
/* Since we specified MAP_FIXED, this should be guaranteed */
- assert( newp == (char*)os->arena + old_size );
+ assert( newp == (char*)PM->arena + old_size );
/* Convert sizes to pages */
- file_size = (file_size + os->pagesize - 1) & ~(os->pagesize-1);
- new_pages = new_size >> os->pageshift;
- old_pages = old_size >> os->pageshift;
- file_pages = file_size >> os->pageshift;
+ file_size = (file_size + PM->pagesize - 1) & ~(PM->pagesize-1);
+ new_pages = new_size >> PM->pageshift;
+ old_pages = old_size >> PM->pageshift;
+ file_pages = file_size >> PM->pageshift;
add_pages = new_pages - old_pages;
- infop = realloc(os->pageinfo, new_pages);
+ infop = realloc(PM->pageinfo, new_pages);
if ( !infop ) {
munmap(newp, add_size);
goto reset_size;
}
- os->arena_len = new_size;
- os->pageinfo = infop;
+ PM->arena_len = new_size;
+ PM->pageinfo = infop;
/* No more failure bailouts, unlock */
- while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
+ while ( fcntl(PM->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
/* Mark new pages clean */
assert(new_pages >= file_pages);
- memset(os->pageinfo + file_pages, page_clean, new_pages-file_pages);
+ memset(PM->pageinfo + file_pages, page_clean, new_pages-file_pages);
return 0;
@@ -660,9 +648,9 @@ int lpsm_extend(size_t new_size)
due to address space limitations. */
reset_size:
/* Restore the original file size */
- ftruncate(os->main_fd, file_size);
+ ftruncate(PM->main_fd, file_size);
/* Drop lock */
- while ( fcntl(os->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
+ while ( fcntl(PM->main_fd, F_SETLKW, &lock) == -1 && errno == EINTR );
return -1;
}
@@ -675,12 +663,10 @@ int lpsm_extend(size_t new_size)
*/
void lpsm_shutdown(void)
{
- struct ObjStore *os = lpsm_os_struct;
-
- munmap(os->arena, os->arena_len);
- free(os->pageinfo);
- sigaction(SIGSEGV, &os->oldact, NULL);
- close(os->log_fd);
- close(os->main_fd);
- free(os);
+ munmap(PM->arena, PM->arena_len);
+ free(PM->pageinfo);
+ sigaction(SIGSEGV, &PM->oldact, NULL);
+ close(PM->log_fd);
+ close(PM->main_fd);
+ free(PM);
}