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

Reply via email to