Kernel/vfs - (minor) commenting only
[tpg/acess2.git] / KernelLand / Kernel / vfs / mmap.c
index 9fe9282..591ae28 100644 (file)
@@ -22,11 +22,15 @@ struct sVFS_MMapPageBlock
        tPAddr  PhysAddrs[MMAP_PAGES_PER_BLOCK];
 };
 
+// === PROTOTYPES ===
+//void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, Uint64 Offset);
+void   *VFS_MMap_Anon(void *Destination, size_t Length, Uint FlagsSet, Uint FlagsMask);
+//int  VFS_MUnmap(void *Addr, size_t Length);
+
 // === CODE ===
 void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD, Uint64 Offset)
 {
-       tVFS_Handle     *h;
-       tVAddr  mapping_dest, mapping_base;
+       tVAddr  mapping_base;
         int    npages, pagenum;
        tVFS_MMapPageBlock      *pb, *prev;
 
@@ -39,40 +43,24 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
        pagenum = Offset / PAGE_SIZE;
 
        mapping_base = (tVAddr)DestHint;
-       mapping_dest = mapping_base & ~(PAGE_SIZE-1);
+       tPage   *mapping_dest = (void*)(mapping_base & ~(PAGE_SIZE-1));
 
-       // TODO: Locate space for the allocation
+       if( DestHint == NULL )
+       {
+               // TODO: Locate space for the allocation
+               LEAVE('n');
+               return NULL;
+       }
 
        // Handle anonymous mappings
        if( Flags & MMAP_MAP_ANONYMOUS )
        {
-               size_t  ofs = 0;
-               LOG("%i pages anonymous to %p", npages, mapping_dest);
-               for( ; npages --; mapping_dest += PAGE_SIZE, ofs += PAGE_SIZE )
-               {
-                       if( MM_GetPhysAddr(mapping_dest) ) {
-                               // TODO: Set flags to COW if needed (well, if shared)
-                               MM_SetFlags(mapping_dest, MM_PFLAG_COW, MM_PFLAG_COW);
-                               LOG("clear from %p, %i bytes", (void*)(mapping_base + ofs),
-                                       PAGE_SIZE - (mapping_base & (PAGE_SIZE-1))
-                                       );
-                               memset( (void*)(mapping_base + ofs), 0, PAGE_SIZE - (mapping_base & (PAGE_SIZE-1)));
-                       }
-                       else {
-                               LOG("New empty page");
-                               // TODO: Map a COW zero page instead
-                               if( !MM_Allocate(mapping_dest) ) {
-                                       // TODO: Error
-                                       Log_Warning("VFS", "VFS_MMap: Anon alloc to %p failed", mapping_dest);
-                               }
-                               memset((void*)mapping_dest, 0, PAGE_SIZE);
-                               LOG("Anon map to %p", mapping_dest);
-                       }
-               }
-               LEAVE_RET('p', (void*)mapping_base);
+               // TODO: Comvert \a Protection into a flag set
+               void    *ret = VFS_MMap_Anon((void*)mapping_base, Length, 0, 0);
+               LEAVE_RET('p', ret);
        }
 
-       h = VFS_GetHandle(FD);
+       tVFS_Handle *h = VFS_GetHandle(FD);
        if( !h || !h->Node )    LEAVE_RET('n', NULL);
 
        LOG("h = %p", h);
@@ -85,7 +73,8 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
                pb = h->Node->MMapInfo, prev = NULL;
                pb && pb->BaseOffset + MMAP_PAGES_PER_BLOCK < pagenum;
                prev = pb, pb = pb->Next
-               );
+               )
+               ;
 
        LOG("pb = %p, pb->BaseOffset = %X", pb, pb ? pb->BaseOffset : 0);
 
@@ -93,14 +82,13 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
        if( !pb || pb->BaseOffset > pagenum )
        {
                void    *old_pb = pb;
-               pb = malloc( sizeof(tVFS_MMapPageBlock) );
+               pb = calloc( 1, sizeof(tVFS_MMapPageBlock) );
                if(!pb) {
                        Mutex_Release( &h->Node->Lock );
                        LEAVE_RET('n', NULL);
                }
                pb->Next = old_pb;
                pb->BaseOffset = pagenum - pagenum % MMAP_PAGES_PER_BLOCK;
-               memset(pb->PhysAddrs, 0, sizeof(pb->PhysAddrs));
                if(prev)
                        prev->Next = pb;
                else
@@ -110,7 +98,7 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
        // - Map (and allocate) pages
        while( npages -- )
        {
-               if( MM_GetPhysAddr(mapping_dest) == 0 )
+               if( MM_GetPhysAddr( mapping_dest ) == 0 )
                {
                        if( pb->PhysAddrs[pagenum - pb->BaseOffset] == 0 )
                        {
@@ -120,7 +108,7 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
                                        // TODO: error
                                }
                                else if( nt->MMap )
-                                       nt->MMap(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, (void*)mapping_dest);
+                                       nt->MMap(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, mapping_dest);
                                else
                                {
                                         int    read_len;
@@ -132,10 +120,12 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
                                                return NULL;
                                        }
                                        // TODO: Clip read length
-                                       read_len = nt->Read(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE, (void*)mapping_dest);
-//                                     if( read_len != PAGE_SIZE ) {
-//                                             memset( (void*)(mapping_dest+read_len), 0, PAGE_SIZE-read_len );
-//                                     }
+                                       read_len = nt->Read(h->Node, pagenum*PAGE_SIZE, PAGE_SIZE,
+                                               mapping_dest, 0);
+                                       // TODO: This was commented out, why?
+                                       if( read_len != PAGE_SIZE ) {
+                                               memset( (char*)mapping_dest + read_len, 0, PAGE_SIZE-read_len );
+                                       }
                                }
                                pb->PhysAddrs[pagenum - pb->BaseOffset] = MM_GetPhysAddr( mapping_dest );
                                MM_SetPageNode( pb->PhysAddrs[pagenum - pb->BaseOffset], h->Node );
@@ -178,7 +168,7 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
                if( Flags & MMAP_MAP_PRIVATE )
                        MM_SetFlags(mapping_dest, MM_PFLAG_COW, MM_PFLAG_COW);
                pagenum ++;
-               mapping_dest += PAGE_SIZE;
+               mapping_dest ++;
 
                // Roll on to next block if needed
                if(pagenum - pb->BaseOffset == MMAP_PAGES_PER_BLOCK)
@@ -194,7 +184,6 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
                                memset(pb->PhysAddrs, 0, sizeof(pb->PhysAddrs));
                                oldpb->Next = pb;
                        }
-                       pagenum = 0;
                }
        }
        
@@ -204,6 +193,74 @@ void *VFS_MMap(void *DestHint, size_t Length, int Protection, int Flags, int FD,
        return (void*)mapping_base;
 }
 
+void *VFS_MMap_Anon(void *Destination, size_t Length, Uint FlagsSet, Uint FlagsMask)
+{
+       size_t  ofs = (tVAddr)Destination & (PAGE_SIZE-1);
+       tPage   *mapping_dest = (void*)( (char*)Destination - ofs );
+       
+       if( ofs > 0 )
+       {
+               size_t  bytes = MIN(PAGE_SIZE - ofs, Length);
+               
+               // Allocate a partial page
+               if( MM_GetPhysAddr(mapping_dest) )
+               {
+                       // Already allocated page, clear the area we're touching
+                       ASSERT( ofs + bytes <= PAGE_SIZE );
+                       
+                       // TODO: Double check that this area isn't already zero
+                       memset( Destination, 0, bytes );
+                       
+                       MM_SetFlags(mapping_dest, FlagsSet, FlagsMask);
+                       
+                       LOG("#1: Clear %i from %p", Length, Destination);
+               }
+               else
+               {
+                       MM_AllocateZero(mapping_dest);
+                       LOG("#1: Allocate for %p", Destination);
+               }
+               mapping_dest ++;
+               Length -= bytes;
+       }
+       while( Length >= PAGE_SIZE )
+       {
+               if( MM_GetPhysAddr( mapping_dest ) )
+               {
+                       // We're allocating entire pages here, so free this page and replace with a COW zero
+                       MM_Deallocate(mapping_dest);
+                       LOG("Replace %p with zero page", mapping_dest);
+               }
+               else
+               {
+                       LOG("Allocate zero at %p", mapping_dest);
+               }
+               MM_AllocateZero(mapping_dest);
+               
+               mapping_dest ++;
+               Length -= PAGE_SIZE;
+       }
+       if( Length > 0 )
+       {
+               ASSERT(Length < PAGE_SIZE);
+               
+               // Tail page
+               if( MM_GetPhysAddr(mapping_dest) )
+               {
+                       // TODO: Don't touch page if already zero
+                       memset( mapping_dest, 0, Length );
+                       LOG("Clear %i in %p", Length, mapping_dest);
+               }
+               else
+               {
+                       MM_AllocateZero(mapping_dest);
+                       LOG("Anon map to %p", mapping_dest);
+               }
+       }
+       
+       return Destination;
+}
+
 int VFS_MUnmap(void *Addr, size_t Length)
 {
        return 0;

UCC git Repository :: git.ucc.asn.au