📄 gdk_posix.mx
字号:
/* get RSS -- linux only for the moment */ static char MT_mmap_procfile[128] = { 0 }; int fd; if (MT_mmap_procfile[0] == 0) { /* getpid returns pid_t, cast to long to be sure */ sprintf(MT_mmap_procfile, "/proc/%ld/stat", (long) getpid()); } fd = open(MT_mmap_procfile, O_RDONLY); if (fd >= 0) { char buf[1024], *r = buf; size_t i, sz = read(fd, buf, 1024); close(fd); if (sz > 0) { for (i = 0; i < 23; i++) { while (*r && (*r == ' ' || *r == '\t')) r++; while (*r && (*r != ' ' && *r != '\t')) r++; } while (*r && (*r == ' ' || *r == '\t')) r++; return ((size_t) atol(r)) * MT_pagesize(); } } return 0;}char *MT_heapcur(void){ return (char *) sbrk(0);}void*MT_mmap_open(MT_mmap_hdl *hdl, char *path, int mode, off_t off, size_t len, size_t nremaps){ int fd = open(path, O_CREAT | ((mode & MMAP_WRITE) ? O_RDWR : O_RDONLY)); void *ret = (void *) -1L; (void) nremaps; if (fd >= 0) { hdl->mode = mode; hdl->fixed = NULL; hdl->hdl = (void *) (ssize_t) fd; ret = MT_mmap_remap(hdl, off, len); } if (ret != (void *) -1L) { hdl->fixed = ret; fd = MT_mmap_new(path, ret, len, fd, (mode & MMAP_WRITABLE)); if (fd <= 0) hdl->hdl = (void *) 0; /* MT_mmap_new keeps the fd */ } return ret;}void *MT_mmap_remap(MT_mmap_hdl *hdl, off_t off, size_t len){ void *ret; ret = mmap(hdl->fixed, len, ((hdl->mode & MMAP_WRITABLE) ? PROT_WRITE : 0) | PROT_READ, ((hdl->mode & MMAP_COPY) ? (MAP_PRIVATE|MAP_NORESERVE) : MAP_SHARED) | (hdl->fixed ? MAP_FIXED : 0), (int) (ssize_t) hdl->hdl, off); if (ret != (void *) -1L) { if (hdl->mode & MMAP_ADVISE) { (void) MT_madvise(ret, len, hdl->mode & MMAP_ADVISE); } hdl->fixed = (void *) ((char *) ret + len); } return ret;}voidMT_mmap_close(MT_mmap_hdl *hdl){ int fd = (int) (ssize_t) hdl->hdl; if (fd) close(fd); hdl->hdl = NULL;}intMT_munmap(void *p, size_t len){ int ret = munmap(p, len);#ifdef MMAP_DEBUG stream_printf(GDKerr, "munmap(" LLFMT "," LLFMT ",%d) = %d\n", (long long) p, (long long) len, ret);#endif MT_mmap_del(p, len); return ret;}intMT_msync(void *p, size_t len, int mode){ int ret = msync(p, len, (mode & MMAP_SYNC) ? MS_SYNC : ((mode & MMAP_ASYNC) ? MS_ASYNC : MS_INVALIDATE));#ifdef MMAP_DEBUG stream_printf(GDKerr, "msync(" LLFMT "," LLFMT ",%s) = %d\n", (long long) p, (long long) len, (mode & MMAP_SYNC) ? "MS_SYNC" : ((mode & MMAP_ASYNC) ? "MS_ASYNC" : "MS_INVALIDATE"), ret);#endif if (ret < 0) return errno; return ret;}intMT_madvise(void *p, size_t len, int advise){ int ret = posix_madvise(p, len, advise);#ifdef MMAP_DEBUG stream_printf(GDKerr, "posix_madvise(" LLFMT "," LLFMT ",%d) = %d\n", (long long) p, (long long) len, advise, ret);#endif if (MT_fadvise(p, len, advise)) ret = -1; return ret;}struct mallinfoMT_mallinfo(void){ struct mallinfo _ret;#ifdef HAVE_MALLINFO _ret = mallinfo();#else memset(&_ret, 0, sizeof(_ret));#endif if (_ret.uordblks + _ret.fordblks > _ret.arena) { MT_alloc_register(MT_heapbase, _ret.arena, 'H'); } return _ret;}intMT_path_absolute(char *pathname){ return (*pathname == DIR_SEP);}#ifdef WIN32#include <windows.h>#endif#else /* WIN32 native */#ifndef BUFSIZ#define BUFSIZ 1024#endif#undef _errno#undef stat#undef rmdir#undef mkdir#undef NAME_MAX#include <windows.h>#ifdef _MSC_VER#include <io.h>#endif /* _MSC_VER */#define MT_SMALLBLOCK 256voidMT_init_posix(int alloc_map){ MT_heapbase = 0;/* _set_sbh_threshold(MT_SMALLBLOCK);*/#ifdef DEBUG_ALLOC static void MT_alloc_init(void); if (alloc_map) MT_alloc_init();#else (void)alloc_map;#endif MT_mmap_init();}size_tMT_getrss(){#if (_WIN32_WINNT >= 0x0500) MEMORYSTATUSEX state; state.dwLength = sizeof(state); GlobalMemoryStatusEx (&state); return (size_t) (state.ullTotalPhys - state.ullAvailPhys);#else MEMORYSTATUS state; GlobalMemoryStatus (&state); return state.dwTotalPhys - state.dwAvailPhys;#endif}char *MT_heapcur(void){ return (char *) 0;}/* Windows mmap keeps a global list of base addresses for complex (remapped) memory maps * the reason is that each remapped segment needs to be unmapped separately in the end. */typedef struct _remap_t { struct _remap_t * next; char* start; char* end; size_t cnt; void *bases[1]; /* EXTENDS (cnt-1) BEYOND THE END OF THE STRUCT */} remap_t;remap_t *remaps = NULL;static remap_t *remap_find(char* base, int delete) { remap_t *map, *prev=NULL; (void) pthread_mutex_lock(&MT_mmap_lock); for(map=remaps; map; map=map->next) { if (base >= map->start && base < map->end) { if (delete) { if (prev) prev->next = map->next; else remaps = map->next; map->next = NULL; } break; } } (void) pthread_mutex_unlock(&MT_mmap_lock); return map;} void*MT_mmap_open(MT_mmap_hdl *hdl, char *path, int mode, off_t off, size_t len, size_t nremaps){ void *ret = NULL; int mode0 = GENERIC_READ; int mode1 = FILE_SHARE_READ; int mode2 = mode & MMAP_ADVISE; int mode3 = PAGE_READONLY; int mode4 = FILE_MAP_READ; SECURITY_ATTRIBUTES sa; HANDLE h1, h2; remap_t *map; memset(hdl, 0, sizeof(MT_mmap_hdl)); if (mode & MMAP_WRITE) { mode0 |= GENERIC_WRITE; mode1 |= FILE_SHARE_WRITE; } if (mode2 == MMAP_RANDOM || mode2 == MMAP_DONTNEED) { mode2 = FILE_FLAG_RANDOM_ACCESS; } else if (mode2 == MMAP_SEQUENTIAL || mode2 == MMAP_WILLNEED) { mode2 = FILE_FLAG_SEQUENTIAL_SCAN; } else { mode2 = FILE_FLAG_NO_BUFFERING; } if (mode & MMAP_SYNC) { mode2 |= FILE_FLAG_WRITE_THROUGH; } if (mode & MMAP_COPY) { mode3 = PAGE_WRITECOPY; mode4 = FILE_MAP_COPY; } else if (mode & MMAP_WRITE) { mode3 = PAGE_READWRITE; mode4 = FILE_MAP_WRITE; } sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = 0; h1 = CreateFile(path, mode0, mode1, &sa, OPEN_ALWAYS, mode2, NULL); if (h1 == INVALID_HANDLE_VALUE) { GDKsyserror("MT_mmap: CreateFile('%s', %d, %d, &sa, %d, %d, NULL) failed\n", path, mode0, mode1, OPEN_ALWAYS, mode2); return (void *) -1; } h2 = CreateFileMapping(h1, &sa, mode3, (DWORD) ((((gdk_int64) off + (gdk_int64) len) >> 32) & LL_CONSTANT(0xFFFFFFFF)), (DWORD) ((off + len) & LL_CONSTANT(0xFFFFFFFF)), NULL); if (h2 == NULL) { GDKsyserror("MT_mmap: CreateFileMapping(" PTRFMT ", &sa, %d, %d, %u, NULL) failed\n", PTRFMTCAST h1, mode3, (DWORD) ((((gdk_int64) off + (gdk_int64) len) >> 32) & LL_CONSTANT(0xFFFFFFFF)), (DWORD) ((off + len) & LL_CONSTANT(0xFFFFFFFF))); CloseHandle(h1); return (void *) -1; } hdl->hdl = (void *) h2; hdl->mode = mode4; CloseHandle(h1); if (nremaps == 0) { return MT_mmap_remap(hdl, off, len); /* normal mmap(). no further remaps */ } /* for complex mmaps we now make it very likely that the MapViewOfFileEx-es to a predetermined VM address will all succeed */ ret = VirtualAlloc(NULL, len, MEM_RESERVE, PAGE_READWRITE); if (ret == NULL) return (void*) -1; hdl->fixed = ret; /* now we have a VM region that is large enough */ /* ensure exclusive VM access to MapViewOfFile and VirtualAlloc (almost.. malloc() may trigger it -- ignored) */ (void) pthread_mutex_lock(&MT_mmap_lock); hdl->hasLock = 1; /* release the range, so we can MapViewOfFileEx into it later */ VirtualFree(ret, 0, MEM_RELEASE); /* allocate a map record to administer all your bases (they are belong to us!) */ map = malloc(sizeof(remap_t) + sizeof(void *) * nremaps); if (map == NULL) return (void *) -1; hdl->map = (void *) map; map->cnt = 0; map->start = (char *) hdl->fixed; map->end = map->start + len; return ret;}void *MT_mmap_remap(MT_mmap_hdl *hdl, off_t off, size_t len){ remap_t *map = (remap_t*) hdl->map; void *ret; ret = MapViewOfFileEx((HANDLE) hdl->hdl, hdl->mode, (DWORD) ((gdk_int64) off >> 32), (DWORD) off, len, (void *) ((char *) hdl->fixed)); if (ret == NULL) { GDKsyserror("MT_mmap: MapViewOfFileEx(" PTRFMT ", %d, %d, %u, %d, " PTRFMT ") failed\n", PTRFMTCAST hdl->hdl, hdl->mode, (DWORD) ((gdk_int64) off >> 32), (DWORD) off, len, PTRFMTCAST hdl->fixed); return (void *) -1; } if (map) map->bases[map->cnt++] = ret; /* administer new base */ hdl->fixed = (void *) ((char *) ret + len); return ret;}voidMT_mmap_close(MT_mmap_hdl *hdl){ if (hdl->hasLock) { (void) pthread_mutex_unlock(&MT_mmap_lock); } if (hdl->hdl) { CloseHandle((HANDLE) hdl->hdl); hdl->hdl = NULL; }}intMT_munmap(void *p, size_t dummy){ remap_t *map = remap_find(p, TRUE); int ret = 0; (void)dummy; if (map) { /* remapped region; has multiple bases on which we must invoke the Windows API */ size_t i; for(i=0; i<map->cnt; i++) if (UnmapViewOfFile(map->bases[i]) == 0) ret = -1; free(map); } else { /* Windows' UnmapViewOfFile returns success!=0, error== 0, * while Unix's munmap returns success==0, error==-1. */ if (UnmapViewOfFile(p) == 0) ret = -1; } return ret;}intMT_msync(void *p, size_t len, int mode){ remap_t *map = remap_find(p, FALSE); int ret = 0; (void)mode; if (map) { /* remapped region; has multiple bases on which we must invoke the Windows API */ size_t i; for(i=0; i<map->cnt; i++) if (FlushViewOfFile(map->bases[i], 0) == 0) ret = -1; free(map); } else { /* Windows' UnmapViewOfFile returns success!=0, error== 0, * while Unix's munmap returns success==0, error==-1. */ if (FlushViewOfFile(p, len) == 0) ret = -1; } return ret;}intMT_madvise(void *p, size_t len, int advise){ (void)p; (void)len; (void)advise; return 0; /* would -1 be better? */}#ifndef _HEAPOK /* MinGW */#define _HEAPEMPTY (-1)#define _HEAPOK (-2)#define _HEAPBADBEGIN (-3)#define _HEAPBADNODE (-4)#define _HEAPEND (-5)#define _HEAPBADPTR (-6)#endifstruct mallinfoMT_mallinfo(void){ struct mallinfo _ret; _HEAPINFO hinfo; int heapstatus; hinfo._pentry = NULL; memset(&_ret, 0, sizeof(struct mallinfo));/* 64bit: mallinfo uses ints which won't work on 64 bit platforms */ while ((heapstatus = _heapwalk(&hinfo)) == _HEAPOK) { _ret.arena += hinfo._size; if (hinfo._size > MT_SMALLBLOCK) { _ret.smblks++; if (hinfo._useflag == _USEDENTRY) { _ret.usmblks += hinfo._size; MT_alloc_register(hinfo._pentry, hinfo._size, 'H'); } else { _ret.fsmblks += hinfo._size; MT_alloc_register(hinfo._pentry, hinfo._size, 'h'); } } else { _ret.ordblks++; if (hinfo._useflag == _USEDENTRY) { _ret.uordblks += hinfo._size; MT_alloc_register(hinfo._pentry, hinfo._size, 'H'); } else { _ret.fordblks += hinfo._size; MT_alloc_register(hinfo._pentry, hinfo._size, 'h'); } } } if (heapstatus == _HEAPBADPTR || heapstatus == _HEAPBADBEGIN || heapstatus == _HEAPBADNODE) { stream_printf(GDKerr, "mallinfo(): heap is corrupt."); } _heapmin(); return _ret;}intMT_path_absolute(char *pathname){ char *drive_end = strchr(pathname, ':'); char *path_start = strchr(pathname, '\\'); if (path_start == NULL) { return 0; } return (path_start == pathname || drive_end == (path_start - 1));}#ifndef HAVE_FTRUNCATEintftruncate(int fd, off_t size){ HANDLE hfile; unsigned int curpos; if (fd < 0) return -1; hfile = (HANDLE) _get_osfhandle(fd); curpos = SetFilePointer(hfile, 0, NULL, FILE_CURRENT); if (curpos == 0xFFFFFFFF || SetFilePointer(hfile, (LONG) size, NULL, FILE_BEGIN) == 0xFFFFFFFF || !SetEndOfFile(hfile)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -