Hi,
I ran into another problem compiling applications under cegcc,
there was this one that couldn't live without mmap().
Here is the cegcc patch for providing [basic] mmap functionality.
I've tested the patch briefly, I attached the test program I used.
Seems to work fine on my device.
Thanks!
Pawel.
--
With best of best regards
Pawel S. Veselov
Index: src/newlib/newlib/libc/include/sys/mman.h
===================================================================
--- src/newlib/newlib/libc/include/sys/mman.h (revision 0)
+++ src/newlib/newlib/libc/include/sys/mman.h (revision 0)
@@ -0,0 +1,48 @@
+/*****************************************************************************
+ *
+ * POSIX memory mapping facilities.
+ *
+ *****************************************************************************/
+#ifndef __sys_mman_h
+#define __sys_mman_h
+
+#include <_ansi.h>
+#include <sys/types.h>
+
+#ifdef _POSIX_MAPPED_FILES
+#undef _POSIX_MAPPED_FILES
+#endif
+#define _POSIX_MAPPED_FILES 1
+
+#ifdef _POSIX_SYNCHRONIZED_IO
+#undef _POSIX_SYNCHRONIZED_IO
+#endif
+#define _POSIX_SYNCHRONIZED_IO 1
+
+void * _EXFUN(mmap, (void *start, size_t length, int prot, int flags,
+ int fd, off_t offset));
+
+int _EXFUN(munmap, (void *start, size_t length));
+
+int _EXFUN(msync, (void *start, size_t length, int flags));
+
+#define PROT_EXEC 0x4
+#define PROT_READ 0x1
+#define PROT_WRITE 0x2
+#define PROT_NONE 0x0
+
+#define MAP_PRIVATE 0x02
+#define MAP_FIXED 0x10
+#define MAP_NORESERVE 0x04000
+#define MAP_ANON MAP_ANONYMOUS
+#define MAP_ANONYMOUS 0x20
+
+#define MS_ASYNC 1
+#define MS_SYNC 4
+#define MS_INVALIDATE 2
+
+#define MAP_FAILED ((void*)-1)
+
+
+#endif /* __sys_mman_h */
+
Index: src/newlib/newlib/libc/sys/wince/Makefile.in
===================================================================
--- src/newlib/newlib/libc/sys/wince/Makefile.in (revision 1170)
+++ src/newlib/newlib/libc/sys/wince/Makefile.in (working copy)
@@ -92,7 +92,7 @@
mingw_SOURCES = _crt_mt.c mthr_thunk.c mthr_ptrs.c pseudo-reloc.c pseudo-reloc_t.c
-lib_a_SOURCES = __eh_continue.S abort.c alloc.c assert.c ceprocess.c cs.c dirent.c dllmain.c dllmaincrtstartup.c dllmaincrtstartup_t.c env.c error.c fifo.c findpath.c fixpath.c fnmatch.c getopt.c getopt1.c getreent.c glob.c group.c ipfcns.c io.c issetugid-stub.c llst.c malloc.c mqueue.c pathconf.c popen.c sclass.c shared.c sig.c sigimp.c spawn.c startup.c startup_thunk.c stat.c system.c termios.c timefcns.c trace.c tzset_hook_r.c uid.c unistd.c utime.c main.c $(net_SOURCES) $(unix_SOURCES) $(celib_SOURCES) $(mingw_SOURCES)
+lib_a_SOURCES = __eh_continue.S abort.c alloc.c assert.c ceprocess.c cs.c dirent.c dllmain.c dllmaincrtstartup.c dllmaincrtstartup_t.c env.c error.c fifo.c findpath.c fixpath.c fnmatch.c getopt.c getopt1.c getreent.c glob.c group.c ipfcns.c io.c issetugid-stub.c llst.c malloc.c mqueue.c pathconf.c popen.c sclass.c shared.c sig.c sigimp.c spawn.c startup.c startup_thunk.c stat.c system.c termios.c timefcns.c trace.c tzset_hook_r.c uid.c unistd.c mman.c utime.c main.c $(net_SOURCES) $(unix_SOURCES) $(celib_SOURCES) $(mingw_SOURCES)
ACLOCAL_AMFLAGS = -I ../../..
@@ -113,7 +113,7 @@
getreent.o glob.o group.o ipfcns.o io.o issetugid-stub.o llst.o \
malloc.o mqueue.o pathconf.o popen.o sclass.o shared.o sig.o sigimp.o \
spawn.o startup.o startup_thunk.o stat.o system.o termios.o timefcns.o \
-trace.o tzset_hook_r.o uid.o unistd.o utime.o main.o ascii2addr.o \
+trace.o tzset_hook_r.o uid.o unistd.o mman.o utime.o main.o ascii2addr.o \
htons.o htonl.o inet_aton.o inet_lnaof.o inet_mkadr.o inet_net.o \
inet_netof.o inet_ntoa.o msnet.o wsdb.o rexec.o wsstrerror.o getcwd.o \
getlogin.o sleep.o usleep.o vfork.o cecopyfile.o cefileattr.o \
Index: src/newlib/newlib/libc/sys/wince/sys/io.h
===================================================================
--- src/newlib/newlib/libc/sys/wince/sys/io.h (revision 1170)
+++ src/newlib/newlib/libc/sys/wince/sys/io.h (working copy)
@@ -30,6 +30,8 @@
SOCKET sock;
};
+ HANDLE mmap;
+
void *cxt;
_DEVOPS devops;
} _fdent_t;
Index: src/newlib/newlib/libc/sys/wince/io.c
===================================================================
--- src/newlib/newlib/libc/sys/wince/io.c (revision 1170)
+++ src/newlib/newlib/libc/sys/wince/io.c (working copy)
@@ -436,6 +436,11 @@
EnterCriticalSection(&critsect);
FDCHECK(fd, &critsect);
+ if (_fdtab[fd].mmap) {
+ /* TODO: should we call munmap() here? */
+ _CloseHandle(_fdtab[fd].mmap);
+ }
+
if (_fdtab[fd].devops == NULL) {
if (_fdtab[fd].type == IO_FILE_TYPE_FILE) {
_CloseHandle(_fdtab[fd].hnd);
Index: src/newlib/newlib/libc/sys/wince/Makefile.am
===================================================================
--- src/newlib/newlib/libc/sys/wince/Makefile.am (revision 1170)
+++ src/newlib/newlib/libc/sys/wince/Makefile.am (working copy)
@@ -20,7 +20,7 @@
getopt.c getopt1.c getreent.c glob.c group.c ipfcns.c io.c issetugid-stub.c llst.c malloc.c \
mqueue.c pathconf.c popen.c sclass.c shared.c sig.c sigimp.c spawn.c \
startup.c startup_thunk.c stat.c system.c termios.c timefcns.c trace.c tzset_hook_r.c \
- uid.c unistd.c utime.c main.c \
+ uid.c unistd.c mman.c utime.c main.c \
$(net_SOURCES) \
$(unix_SOURCES) \
$(celib_SOURCES) \
Index: src/newlib/newlib/libc/sys/wince/mman.c
===================================================================
--- src/newlib/newlib/libc/sys/wince/mman.c (revision 0)
+++ src/newlib/newlib/libc/sys/wince/mman.c (revision 0)
@@ -0,0 +1,289 @@
+
+#include <sys/mman.h>
+#include <sys/io.h>
+#include <errno.h>
+#include "sys/wcetrace.h"
+// TODO: what's the best WCE_XX id for this? Would be lovely to have WCE_MEM
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+static int pageSize = 0;
+static int pageMask;
+static int allocGranularityMask;
+
+static void getPageSize(void);
+
+void getPageSize() {
+
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ pageSize = si.dwPageSize;
+ pageMask = pageSize - 1;
+ allocGranularityMask = si.dwAllocationGranularity - 1;
+ WCETRACE(WCE_MALLOC, "platform page size : %d, mask : %x, allocMask : %x",
+ pageSize, pageMask, allocGranularityMask);
+
+}
+
+void * mmap(void * start, size_t length, int prot, int flags,
+ int fd, off_t offset) {
+
+ if (!pageSize) { getPageSize(); }
+
+ if (flags & MAP_ANONYMOUS) {
+
+ WCETRACE(WCE_MALLOC, "anonymous map for %x bytes at %x, prot=%x,"
+ " flags=%x", length, start, prot, flags);
+
+ // Virtual allocation only
+
+ if (!length || ((int)start & pageMask) || (length & pageMask)) {
+ WCETRACE(WCE_MALLOC,
+ "length is 0, or addres/length are not aligned");
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+ // TODO: Windows MEM_RESERVE doesn't seem to be the same as
+ // POSIX MEM_NORESERVE. Or is it?
+ // MEM_RESERVE: Reserves a range of pages without allocating
+ // physical storage
+ // MEM_NORESERVE: Do not reserve swap space (phys storage) for this
+ // mapping.
+ // What bothers me, is that for windows, it looks like when MEM_RESERVE
+ // is specified, the address is simply "held" and can not be allocated
+ // by anything else. However the statemnt "reserved pages can be
+ // committed" seems to contradict this.
+ // However, MEM_COMMIT says :: allocate phys storage in memory or disk
+ //
+ // I got confused by the windows API doc here, so, I say that
+ // if unix MEM_NORESERVE is not set, then we request for MEM_COMMIT
+ // allocation.
+ int flAllocationType = 0;
+ if (!(flags & MAP_NORESERVE)) {
+ flAllocationType |= MEM_COMMIT;
+ }
+
+ int flProtect = PAGE_NOACCESS;
+ // this is really a hack...
+ switch (prot & (PROT_EXEC | PROT_READ | PROT_WRITE)) {
+ case PROT_WRITE:
+ case (PROT_WRITE | PROT_EXEC):
+ // Can't have write only or write/exec pages
+ // TODO: EINVAL doesn't really suggest the bad
+ // protection mask was specified. Any other alternative
+ // will be to return EACCES
+ WCETRACE(WCE_MALLOC, "Can not map WO or WX pages");
+ errno = EINVAL;
+ return MAP_FAILED;
+ case PROT_READ:
+ flProtect = PAGE_READONLY;
+ break;
+ case PROT_EXEC:
+ flProtect = PAGE_EXECUTE;
+ break;
+ case (PROT_READ | PROT_EXEC):
+ flProtect = PAGE_EXECUTE_READ;
+ break;
+ case (PROT_READ | PROT_EXEC | PROT_WRITE):
+ flProtect = PAGE_EXECUTE_READWRITE;
+ break;
+ case (PROT_READ | PROT_WRITE):
+ flProtect = PAGE_READWRITE;
+ break;
+ }
+
+ WCETRACE(WCE_MALLOC, "VirtualAlloc(%x,%x,%x,%x)",
+ start, length, flAllocationType, flProtect);
+
+ void * mem = VirtualAlloc(start, length, flAllocationType, flProtect);
+
+ if (!mem) {
+ errno = _winerr2errno(GetLastError());
+ WCETRACE(WCE_MALLOC, "VirtualAlloc(): errno=%d, oserr=%d",
+ errno, GetLastError());
+ mem = MAP_FAILED;
+ }
+
+ return mem;
+
+ }
+
+ // file mmap
+ WCETRACE(WCE_MALLOC, "memory map for %x bytes at %x, prot=%x,"
+ " flags=%x on fd %d", length, start, prot, flags, fd);
+
+ if (prot == PROT_NONE) {
+ WCETRACE(WCE_MALLOC, "impossible to create no access mapping");
+ errno = EINVAL; // ?
+ return MAP_FAILED;
+ }
+
+ if (prot & PROT_EXEC) {
+ WCETRACE(WCE_MALLOC, "impossible to execute code on mapped files");
+ errno = EPERM;
+ return MAP_FAILED;
+ }
+
+ if (prot & PROT_WRITE && !(prot & PROT_READ)) {
+ WCETRACE(WCE_MALLOC, "can not create write-only mapping");
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+
+ if (start || !length || (length & pageMask) ||
+ (offset & allocGranularityMask)) {
+
+ WCETRACE(WCE_MALLOC, "start is !0, length is 0, or length is not"
+ " aligned on page boundary, or offset is not aligned on"
+ " alloc boundary");
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+
+ FDCHECK(fd, 0);
+ if (_fdtab[fd].type != IO_FILE_TYPE_FILE) {
+ WCETRACE(WCE_MALLOC, "fd %d is not a file", fd);
+ errno = EINVAL;
+ return MAP_FAILED;
+ }
+
+ if (!_fdtab[fd].mmap) {
+
+ // figure the file size here. We have to do this, unfortunately,
+ // because the MSDN is very unclear on this, having these two
+ // statements next to each other:
+ //
+ // 1. if this parameter (dwMaximumSizeLow) and dwMaximumSizeHigh
+ // are set to zero, the max size of the file-mapping object is
+ // equal to the current size of the file specified by hFile
+ // 2. If dwMaximumSizeLow is set to zero, the function returns
+ // an error indicating an invalid paramter.
+ //
+ // huh??? what if my file mapping is aligned on 32bit boundary,
+ // HELLO???
+
+ int size_high;
+ int size_low = GetFileSize(_fdtab[fd].hnd, &size_high);
+ if (size_low == 0xffffffff && (GetLastError() != NO_ERROR)) {
+ errno = _winerr2errno(GetLastError());
+ WCETRACE(WCE_MALLOC, "Failed to determine file size, "
+ "errno=%d, oserr=%d", errno, GetLastError());
+ return MAP_FAILED;
+ }
+
+ WCETRACE(WCE_MALLOC, "Calling CreateFileMapping(%x, 0, PAGE_RW|COMMIT,"
+ "%x, %x, 0)", _fdtab[fd].hnd, size_high, size_low);
+
+ HANDLE mapHandle = CreateFileMapping(_fdtab[fd].hnd, 0,
+ PAGE_READWRITE | SEC_COMMIT, size_high, size_low, 0);
+
+ if (mapHandle && GetLastError() == ERROR_ALREADY_EXISTS) {
+ CloseHandle(mapHandle);
+ mapHandle = 0;
+ }
+
+ if (!mapHandle) {
+ errno = _winerr2errno(GetLastError());
+ WCETRACE(WCE_MALLOC, "Failed to create file mapping, errno=%d,"
+ " oserr=%d", errno, GetLastError());
+ return MAP_FAILED;
+ }
+
+ _fdtab[fd].mmap = mapHandle;
+
+ }
+
+ int dwDesiredAccess;
+ if (prot & PROT_WRITE) {
+ dwDesiredAccess = FILE_MAP_ALL_ACCESS;
+ } else {
+ dwDesiredAccess = FILE_MAP_READ;
+ }
+
+ // TODO: how about 64 bits? :)
+
+ int dwFileOffsetHigh;
+ int dwFileOffsetLow = offset & 0xffffffff;
+ // TODO, is there a compile time check to replace this with?
+ if (sizeof(off_t) > 32) {
+ dwFileOffsetHigh = (offset >> 32) & 0xffffffff;
+ } else {
+ dwFileOffsetHigh = 0;
+ }
+
+ WCETRACE(WCE_MALLOC, "calling MapViewOfFile(%x, %x, %x, %x, %d)",
+ _fdtab[fd].mmap, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow,
+ length);
+
+ void * mem = MapViewOfFile(_fdtab[fd].mmap, dwDesiredAccess,
+ dwFileOffsetHigh, dwFileOffsetLow, length);
+
+ if (mem) { return mem; }
+
+ errno = _winerr2errno(GetLastError());
+ WCETRACE(WCE_MALLOC, "MapViewOfFile() failed, errno=%d, oserr=%d",
+ errno, GetLastError());
+ return MAP_FAILED;
+
+}
+
+int msync(void * start, size_t length, int flags) {
+ // we don't really support any flags
+
+ WCETRACE(WCE_MALLOC, "msync(%x, %d), flags ignored", start, length);
+
+ if (FlushViewOfFile(start, length)) {
+ return 0;
+ }
+
+ errno = _winerr2errno(GetLastError());
+ WCETRACE(WCE_MALLOC, "FlushViewOfFile(): errno=%d, oserr=%d",
+ errno, GetLastError());
+ return -1;
+
+}
+
+int munmap(void * start, size_t length) {
+
+#define INVAL(x...) { \
+ WCETRACE(WCE_MALLOC, x); \
+ errno = EINVAL; \
+ return -1; }
+
+ WCETRACE(WCE_MALLOC,"unmapping %x bytes at %x", length, start);
+ if (!pageSize) {
+ INVAL("nothing was mmapped yet!");
+ }
+
+ if (!length || ((int)start & pageMask) || (length & pageMask)) {
+ INVAL("bad page alignment");
+ }
+
+ MEMORY_BASIC_INFORMATION mbi;
+ if (!VirtualQuery(start, &mbi, length)) {
+ INVAL("windows has no information about that memory block");
+ }
+
+ if (mbi.State == MEM_FREE) {
+ INVAL("specified region is free memory");
+ }
+
+ if (mbi.Type == MEM_PRIVATE) { // anonymous (?)
+ if (!VirtualFree(start, length, MEM_DECOMMIT)) {
+ errno = _winerr2errno(GetLastError());
+ WCETRACE(WCE_MALLOC, "VirtualFree(): errno=%d, oserr=%d",
+ errno, GetLastError());
+ return -1;
+ }
+ return 0;
+ }
+
+ if (UnmapViewOfFile(start)) { return 0; }
+
+ errno = _winerr2errno(GetLastError());
+ WCETRACE(WCE_MALLOC, "UnmapViewOfFile(): errno=%d, oserr=%d",
+ errno, GetLastError());
+ return -1;
+
+}
Index: src/newlib/ChangeLog.cegcc
===================================================================
--- src/newlib/ChangeLog.cegcc (revision 1170)
+++ src/newlib/ChangeLog.cegcc (working copy)
@@ -1,3 +1,20 @@
+2008-09-02 Pawel Veselov <[EMAIL PROTECTED]>
+ * libc/include/sys/mman.h : New file to declare mman functions
+ * libc/sys/wince/mman.c : New file to implement mman functions.
+ Implemented mmap(), munmap() and msync()
+ * libc/sys/wince/Makefile.in : added mman.c and mman.o
+ * libc/sys/wince/sys/io.h : added mmap handler inside fd structure
+ * libc/sys/wince/io.c : when closing file, close mmap structure
+ * libc/sys/wince/Makefile.am : added mman.c
+
+
+ *
+ * newlib/libc/sys/wince/io.c (fsync, fdatasync) : Implement.
+ * newlib/libc/sys/wince/sys/io.h newlib/libc/sys/wince/io.c
+ newlib/libc/sys/wince/stat.c : Add critical section parameter
+ to FDCHECK to prevent deadlock when FDCHECK returns.
+
+
2008-08-29 Pawel Veselov <[EMAIL PROTECTED]>
* newlib/libc/sys/wince/io.c (fsync, fdatasync) : Implement.
* newlib/libc/sys/wince/sys/io.h newlib/libc/sys/wince/io.c
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wcetrace.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char ** argv) {
WCETRACESET(WCE_ALL);
int block = getpagesize();
printf("page size : %d\n", block);
int fd = open("/tmp/page.bin", O_CREAT|O_RDWR|O_TRUNC, 0666);
if (fd < 0) {
perror("open");
return 1;
}
char * buf = (char*)malloc(block);
if (!buf) {
printf("failed to malloc %d bytes\n", block);
return 1;
}
memset(buf, 0, block);
strcpy(buf, "this is a good test string");
int left = block;
while (left) {
int rc = write(fd, buf + block - left, left);
if (rc < 0) {
perror("write");
return 1;
}
left -= rc;
}
fsync(fd);
close(fd);
printf("block saved to file\n");
fd = open("/tmp/page.bin", O_RDWR);
if (fd < 0) {
perror("open");
return 1;
}
void * mem = mmap(0, block, PROT_READ, MAP_PRIVATE, fd, 0);
if (mem == MAP_FAILED) {
perror("mmap");
return 1;
}
void * anon = mmap(0, block, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if (anon == MAP_FAILED) {
perror("mmap(ANON)");
return 1;
}
memcpy(anon, mem, block);
printf("test string : %s\n", (char*)anon);
if (munmap(anon, block)) {
perror("munmap(ANON)");
}
if (munmap(mem, block)) {
perror("munmap(FILE)");
}
return 0;
}
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Cegcc-devel mailing list
Cegcc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/cegcc-devel