📄 mem.c
字号:
/** mem.h** Simple and Virtual Memory Manager unix/palm** Nicholas Christopoulos** This program is distributed under the terms of the GPL v2.0 or later* Download the GNU Public License (GPL) from www.gnu.org*/#include "sys.h"#include "pmem.h"#include "panic.h"#if defined(_PalmOS)#define ID_SmBa 0x536D4261#define ID_DATA 0x44415441#define ID_UFST 0x55465354#endif#if defined(_PalmOS)static FileHand log_dev; /* logfile file handle */#elsestatic int log_dev; /* logfile file handle */static char log_name[256]; /* LOGFILE filename */#endif#if defined(ENABLE_VMM)#if defined(_PalmOS)static LocalID vm_lid;static FileHand vm_dev; /* VM swap file handle */static FileHand vm_index; /* VM index file handle */#elsestatic int vm_dev; /* VM swap file handle */static int vm_index; /* VM index file handle */static char vm_name[256]; /* VM swap filename */static char vm_idxname[256]; /* VM index filename */#endifstatic int vm_init_count; /* VM initialization check *//** VMM node*/struct vm_node_s { void *ptr; /* pointer to local memory (only locked chunks had pointer!=NULL) */ dword offset; /* offset in file */ word size; /* block size */ word status; /* low byte = lock counter, high byte = [bit 7=deleted] */ };typedef struct vm_node_s vm_node;static int vm_index_page_size; /* VMM index page size (see vm_init(), index page size = 10% of free memory */static vm_node *vm_table; /* VMM index page */static int vm_count; /* VMM number of nodes */static word vm_bank; /* VMM current index-page number (this one is loaded into memory @'vm_table') */static dword vm_fsize; /* VMM data-file size; speed optimization */#endif // ENABLE_VMM/* ERROR MESSAGES */void err_outofmem() SEC(TRASH);void err_outofmem() { panic("OUT OF MEMORY"); }void err_tmpalloc(dword size) SEC(TRASH);void err_tmpalloc(dword size) { panic("tmp_alloc: size=%ld\n", size); }void err_tmpfree() SEC(TRASH);void err_tmpfree() { panic("tmp_free: Cannot recover handle"); } void err_tmprealloc1() SEC(TRASH);void err_tmprealloc1() { panic("tmp_realloc: Cannot recover handle"); }void err_tmprealloc2(dword size) SEC(TRASH);void err_tmprealloc2(dword size) { panic("tmp_realloc: Cannot resize memory to %ld", size); }void err_memalloc1(dword size) SEC(TRASH);void err_memalloc1(dword size) { panic("mem_alloc: size=%ld\n", size); }void err_memrealloc1() SEC(TRASH);void err_memrealloc1() { panic("mem_realloc: Invalid handle"); }void err_memrealloc2(dword size) SEC(TRASH);void err_memrealloc2(dword size) { panic("mem_realloc: Cannot resize memory to %ld", size); }void err_lock() SEC(TRASH);void err_lock() { panic("mem_lock:MemLckErr"); }void err_memunlock() SEC(TRASH);void err_memunlock() { panic("mem_unlock:MemHandleErr"); }void err_memfree() SEC(TRASH);void err_memfree() { panic("mem_free:MemHandleErr"); }void err_mlistadd() SEC(TRASH);void err_mlistadd() { panic("mlist_add: OUT OF MEMORY"); }void err_tlistadd() SEC(TRASH);void err_tlistadd() { panic("tmplist_add: OUT OF MEMORY"); }/** Allocate local memory*/#if defined(_PalmOS)void *tmp_alloc(dword size){ void *ptr; MemHandle hdl; if ( size < 0 ) err_tmpalloc(size); hdl = MemHandleNew(size); if ( hdl == 0 ) err_tmpalloc(size); ptr = MemHandleLock(hdl); return ptr;}#elsevoid *tmp_allocX(dword size, const char *file, int line){ void *ptr; MemHandle hdl; if ( size < 0 ) err_tmpalloc(size); hdl = MemHandleNewX(size, file, line); if ( hdl == 0 ) err_tmpalloc(size); ptr = MemHandleLock(hdl); return ptr;}#endif/** Free local memory*/#if defined(_PalmOS)void tmp_free(void *ptr){ MemHandle hdl; if ( ptr == NULL ) err_tmpfree(); MemPtrSize(ptr); // check hdl = MemPtrRecoverHandle(ptr); if ( hdl == 0 ) err_tmpfree(); MemHandleUnlock(hdl); MemHandleFree(hdl);}#elsevoid tmp_freeX(void *ptr, const char *file, int line){ MemHandle hdl; if ( ptr == NULL ) err_tmpfree(); hdl = MemPtrRecoverHandleX(ptr, file, line); if ( hdl == 0 ) err_tmpfree(); MemHandleUnlockX(hdl, file, line); MemHandleFreeX(hdl, file, line);}#endif/** Reallocate the size of a memory chunk*/void *tmp_realloc(void *ptr, dword size){ MemHandle hdl; MemPtrSize(ptr); // check hdl = MemPtrRecoverHandle(ptr); if ( hdl == 0 ) err_tmprealloc1(); MemHandleUnlock(hdl); #if defined(_PalmOS) // memory defrag MemHeapCompact(0); #endif if ( MemHandleResize(hdl, size) ) err_tmprealloc2(size); return MemHandleLock(hdl);}/** Allocate a memory handle (a memory block on "storage area")*/#if defined(_UnixOS)mem_t mem_allocX(dword size, const char *file, int line)#elsemem_t mem_alloc(dword size)#endif{ mem_t h = 0; if ( size < 0 ) err_memalloc1(size); #if defined(_UnixOS) h = MemHandleNewX(size, file, line); #else h = MemHandleNew(size); #endif if ( h == 0 ) err_outofmem(); return h;}/** lock a memory handle (moves the memory block to dynamic RAM)*/void* mem_lock(mem_t h){ void *p; if ( h <= 0 ) err_lock(); p = MemHandleLock(h); if ( p == NULL ) err_lock(); return p;}/** unlock a memory handle*/void mem_unlock(mem_t h){ if ( h <= 0 ) err_memunlock(); MemHandleUnlock(h);}/** Reallocate the size of a memory chunk*/mem_t mem_realloc(mem_t hdl, dword new_size){ if ( hdl == 0 ) err_memrealloc1(); if ( MemHandleResize(hdl, new_size) ) err_memrealloc2(new_size); return hdl;}/** free a memory block from storage RAM*/void mem_free(mem_t h){ if ( h <= 0 ) err_memfree(); MemHandleFree(h);}/** creates a memory block in storage RAM for string 'text'*/mem_t mem_new_text(const char *text){ mem_t h; int l; char *p; l = strlen(text) + 1; h = mem_alloc(l); p = (char *) mem_lock(h); strcpy(p, text); mem_unlock(h); return h;}#if defined(ENABLE_MEMLIST)/** dynamic single-linked list in storage RAM** list initialization*/void mlist_init(mlist_t*lst){ lst->head = lst->tail = NULL; lst->count = 0;}void mlist_clear(mlist_t*lst){ mnode_t *cur, *pre; cur = lst->head; while ( cur ) { pre = cur; cur = cur->next; mem_free(pre->data); MemPtrFree(pre); } mlist_init(lst);}mnode_t *mlist_add(mlist_t* lst, mem_t h){ mnode_t *np; np = (mnode_t *) MemPtrNew(sizeof(mnode_t)); if ( !np ) err_mlistadd(); np->data = h; np->next = NULL; if ( lst->head ) ( lst->tail->next = np, lst->tail = np ); else lst->head = lst->tail = np; lst->count ++; return np;}#endif // ENABLE_MEMLIST#if defined(ENABLE_TMPLIST)/** dynamic single-linked list in dynamic RAM*/void tmplist_init(tmplist_t*lst){ lst->head = lst->tail = NULL; lst->count = 0;}void tmplist_clear(tmplist_t*lst){ tmpnode_t *cur, *pre; cur = lst->head; while ( cur ) { pre = cur; cur = cur->next; tmp_free(pre->data); tmp_free(pre); } tmplist_init(lst);}tmpnode_t *tmplist_add(tmplist_t* lst, void *data, int size){ tmpnode_t *np; np = (tmpnode_t *) MemPtrNew(sizeof(tmpnode_t)); if ( !np ) err_tlistadd(); np->data = tmp_alloc(size); memcpy(np->data, data, size); np->next = NULL; if ( lst->head ) ( lst->tail->next = np, lst->tail = np ); else lst->head = lst->tail = np; lst->count ++; return np;}#endif // ENABLE_TMPLIST/* -----------------------------------------------------------------------------------------------------------------------** LOGFILE**///void lwrite(const char *buf){ #if defined(_PalmOS) Err ferr; #endif //////// // open #if defined(_PalmOS) log_dev = FileOpen(0, "SB.LOG", ID_UFST, ID_SmBa, fileModeAppend, &ferr); if ( ferr != 0 ) panic("LOG: Error on creating log-file"); #else #if defined(_Win32) sprintf(log_name, "c:\sb.log"); #else /* a real OS */ sprintf(log_name, "/tmp/sb.log"); #endif log_dev = open(log_name, O_RDWR); lseek(log_dev, 0, SEEK_END); if ( log_dev == -1 ) log_dev = open(log_name, O_CREAT | O_RDWR); if ( log_dev == -1 ) panic("LOG: Error on creating log file"); #endif /////////// // write #if defined(_PalmOS) FileWrite(log_dev, (char *) buf, strlen(buf), 1, &ferr); if ( ferr ) { if ( ferr != fileErrEOF ) panic("LOG: write failed (ERR:%d)", ferr); } #else if ( write(log_dev, buf, strlen(buf)) == -1 ) panic("LOG: write failed"); #endif /// close #if defined(_PalmOS) FileClose(log_dev); #else close(log_dev); #endif}//void lprintf(const char *fmt, ...){ va_list ap; char *buf; buf = tmp_alloc(256); va_start(ap, fmt); #if defined(_PalmOS) StrVPrintF(buf, fmt, ap); #else vsprintf(buf, fmt, ap); #endif va_end(ap); lwrite(buf); tmp_free(buf);}//void lg(const char *fmt, ...){ va_list ap; char *buf;// #if defined(_PalmOS)// ULong dts;// DateTimeType cur_date;// #else// struct tm tms;// time_t now;// #endif buf = tmp_alloc(256); ///////////// // time/date// #if defined(_PalmOS)// dts = TimGetSeconds();// TimSecondsToDateTime(dts, &cur_date);// StrPrintF(buf, // "%02d/%02d %02d:%02d:%02d: ", // /* cur_date.year, */ cur_date.month, cur_date.day, // cur_date.hour, cur_date.minute, cur_date.second);// #else// time(&now);// tms = *localtime(&now);// sprintf(buf, // "%02d/%02d %02d:%02d:%02d: ", // /* tms.tm_year+1900, */ tms.tm_mon+1, tms.tm_mday,// tms.tm_hour, tms.tm_min, tms.tm_sec);// #endif// logwrite(buf); lwrite("--- "); va_start(ap, fmt); #if defined(_PalmOS) StrVPrintF(buf, fmt, ap); #else vsprintf(buf, fmt, ap); #endif va_end(ap); strcat(buf, "\n"); lwrite(buf); tmp_free(buf);}/* -----------------------------------------------------------------------------------------------------------------------** VIRTUAL MEMORY** VMM works like DBMS** Its has a table of vm_node (vm_index file) witch keeps information about each allocated handle* There is loaded (into the memory) only a part of this index of 'vmm_index_page_size' nodes witch located at vm_table* Each block of vmm_index_page_size nodes is called bank.*/#if defined(ENABLE_VMM)/** initialize*/void vm_init(){ #if defined(_PalmOS) dword dwfre, dwmax; Err ferr; #endif if ( vm_init_count ) vm_init_count ++; else { #if defined(_PalmOS) vm_lid = DmFindDatabase(0, "SB.SWP"); if ( vm_lid ) { FileDelete(0, "SB.SWP"); FileDelete(0, "SBIDX.SWP"); } vm_dev = FileOpen(0, "SB.SWP", ID_DATA, ID_SmBa, fileModeReadWrite | fileModeTemporary, &ferr); vm_index = FileOpen(0, "SBIDX.SWP", ID_DATA, ID_SmBa, fileModeReadWrite | fileModeTemporary, &ferr); if ( ferr != 0 ) panic("VMM: Error on creating swap file"); #else #if defined(_Win32) sprintf(vm_name, "c:\sb%d.swp", 1); sprintf(vm_idxname, "c:\sb%di.swp", 1); #else /* a real OS */ sprintf(vm_name, "/tmp/sb%d.swp", getpid()); sprintf(vm_idxname, "/tmp/sb%di.swp", getpid()); #endif remove(vm_name); remove(vm_idxname); vm_dev = open(vm_name, O_CREAT | O_RDWR | O_EXCL); vm_index = open(vm_idxname, O_CREAT | O_RDWR | O_EXCL); if ( vm_dev < 0 ) panic("VMM: Error on creating swap file"); #endif // #if defined(_PalmOS) MemHeapFreeBytes(0, &dwfre, &dwmax); vm_index_page_size = ((dwmax/10)/sizeof(vm_node)); // 10% of free memory #else vm_index_page_size = (65536/sizeof(vm_node)); // 64KB #endif vm_table = (vm_node *) tmp_alloc(sizeof(vm_node) * vm_index_page_size); vm_bank = 0; vm_count = 0; vm_fsize = 0; vm_init_count ++; }}/** Switch bank */void vm_swbank(int bank){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -