about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--string/Makefile2
-rw-r--r--sysdeps/generic/memcpy.c13
-rw-r--r--sysdeps/generic/memmove.c8
-rw-r--r--sysdeps/generic/pagecopy.h74
-rw-r--r--sysdeps/mach/pagecopy.h36
6 files changed, 134 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index ea275a0833..9fb069a143 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 Tue Feb 21 00:10:50 1995  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>
 
+	* string/Makefile (distribute): Add pagecopy.h.
+	* sysdeps/mach/pagecopy.h: New file.
+	* sysdeps/generic/pagecopy.h: New file.
+	* sysdeps/generic/memcpy.c: Include pagecopy.h; call
+ 	PAGE_COPY_FWD_MAYBE first when word aligned.
+	* sysdeps/generic/memmove.c: Likewise.
+
 	* misc/bsd-compat.c (longjmp, setjmp): Functions removed.
 	(getpgrp): Call __getpgid instead of __getpgrp.
 
diff --git a/string/Makefile b/string/Makefile
index a4ba83b465..1fa63c24d2 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -33,7 +33,7 @@ routines	:= strcat strchr strcmp strcoll strcpy strcspn strdup	\
 		   swab strfry memfrob memmem
 
 tests		:= tester testcopy test-ffs
-distribute	:= memcopy.h
+distribute	:= memcopy.h pagecopy.h
 
 
 include ../Rules
diff --git a/sysdeps/generic/memcpy.c b/sysdeps/generic/memcpy.c
index 222d358224..e1a1ade057 100644
--- a/sysdeps/generic/memcpy.c
+++ b/sysdeps/generic/memcpy.c
@@ -21,6 +21,7 @@ Cambridge, MA 02139, USA.  */
 #include <ansidecl.h>
 #include <string.h>
 #include <memcopy.h>
+#include <pagecopy.h>
 
 PTR
 DEFUN(memcpy, (dstpp, srcpp, len),
@@ -38,10 +39,14 @@ DEFUN(memcpy, (dstpp, srcpp, len),
       len -= (-dstp) % OPSIZ;
       BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);
 
-      /* Copy from SRCP to DSTP taking advantage of the known
-	 alignment of DSTP.  Number of bytes remaining is put
-	 in the third argumnet, i.e. in LEN.  This number may
-	 vary from machine to machine.  */
+      /* Copy whole pages from SRCP to DSTP by virtual address manipulation,
+	 as much as possible.  */
+
+      PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);
+
+      /* Copy from SRCP to DSTP taking advantage of the known alignment of
+	 DSTP.  Number of bytes remaining is put in the third argument,
+	 i.e. in LEN.  This number may vary from machine to machine.  */
 
       WORD_COPY_FWD (dstp, srcp, len, len);
 
diff --git a/sysdeps/generic/memmove.c b/sysdeps/generic/memmove.c
index e3016819d9..8ef6f04cbe 100644
--- a/sysdeps/generic/memmove.c
+++ b/sysdeps/generic/memmove.c
@@ -1,6 +1,6 @@
 /* memmove -- copy memory to memory until the specified number of bytes
    has been copied.  Overlap is handled correctly.
-   Copyright (C) 1991 Free Software Foundation, Inc.
+   Copyright (C) 1991, 1995 Free Software Foundation, Inc.
    Contributed by Torbjorn Granlund (tege@sics.se).
 
 The GNU C Library is free software; you can redistribute it and/or
@@ -21,6 +21,7 @@ Cambridge, MA 02139, USA.  */
 #include <ansidecl.h>
 #include <string.h>
 #include <memcopy.h>
+#include <pagecopy.h>
 
 /* All this is so that bcopy.c can #include
    this file after defining some things.  */
@@ -55,6 +56,11 @@ DEFUN(memmove, (a1, a2, len),
 	  len -= (-dstp) % OPSIZ;
 	  BYTE_COPY_FWD (dstp, srcp, (-dstp) % OPSIZ);
 
+	  /* Copy whole pages from SRCP to DSTP by virtual address
+	     manipulation, as much as possible.  */
+
+	  PAGE_COPY_FWD_MAYBE (dstp, srcp, len, len);
+
 	  /* Copy from SRCP to DSTP taking advantage of the known
 	     alignment of DSTP.  Number of bytes remaining is put
 	     in the third argumnet, i.e. in LEN.  This number may
diff --git a/sysdeps/generic/pagecopy.h b/sysdeps/generic/pagecopy.h
new file mode 100644
index 0000000000..07202a3119
--- /dev/null
+++ b/sysdeps/generic/pagecopy.h
@@ -0,0 +1,74 @@
+/* Macros for copying by pages; used in memcpy, memmove.  Generic macros.
+Copyright (C) 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+/* This file defines the macro:
+
+   PAGE_COPY_FWD_MAYBE (dstp, srcp, nbytes_left, nbytes)
+
+   which is invoked like WORD_COPY_FWD et al.  The pointers should be at
+   least word aligned.  This will check if virtual copying by pages can and
+   should be done and do it if so.
+
+   System-specific pagecopy.h files should define these macros and then
+   #include this file:
+
+   PAGE_COPY_THRESHOLD
+   -- Minimum size for which virtual copying by pages is worthwhile.
+
+   PAGE_SIZE
+   -- Size of a page.
+
+   PAGE_COPY_FWD (dstp, srcp, nbytes_left, nbytes)
+   -- Macro to perform the virtual copy operation.
+   The pointers will be aligned to PAGE_SIZE bytes.
+*/
+
+
+#if PAGE_COPY_THRESHOLD
+
+#define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes)		      \
+  do									      \
+    {									      \
+      if ((nbytes) >= PAGE_COPY_THRESHOLD &&				      \
+	  PAGE_OFFSET (dstp) == PAGE_OFFSET (srcp))			      \
+	{								      \
+	  /* The amount to copy is past the threshold for copying	      \
+	     pages virtually with kernel VM operations, and the		      \
+	     source and destination addresses have the same alignment.  */    \
+	  size_t nbytes_before = PAGE_OFFSET (PAGE_SIZE - PAGE_OFFSET (dstp));\
+	  if (nbytes_before != 0)					      \
+	    {								      \
+	      /* First copy the words before the first page boundary.  */     \
+	      WORD_COPY_FWD (dstp, srcp, nbytes_left, nbytes_before);	      \
+	      nbytes_before -= nbytes_left;				      \
+	      nbytes -= nbytes_before;					      \
+	    }								      \
+	  if (nbytes_before == 0)					      \
+	    PAGE_COPY_FWD (dstp, srcp, nbytes_left, nbytes);		      \
+	}								      \
+    } while (0)
+
+/* The page size is always a power of two, so we can avoid modulo division.  */
+#define PAGE_OFFSET(n)	((n) & (PAGE_SIZE - 1))
+
+#else
+
+#define PAGE_COPY_FWD_MAYBE(dstp, srcp, nbytes_left, nbytes) /* nada */
+
+#endif
diff --git a/sysdeps/mach/pagecopy.h b/sysdeps/mach/pagecopy.h
new file mode 100644
index 0000000000..e75c064f06
--- /dev/null
+++ b/sysdeps/mach/pagecopy.h
@@ -0,0 +1,36 @@
+/* Macros for copying by pages; used in memcpy, memmove.  Mach version.
+Copyright (C) 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#include <mach.h>
+
+/* Threshold at which vm_copy is more efficient than well-optimized copying
+   by words.  This parameter should be tuned as necessary.  */
+#define PAGE_THRESHOLD		(2 * PAGE_SIZE)	/* XXX ? */
+
+#define PAGE_SIZE		__vm_page_size
+#define PAGE_COPY_FWD(dstp, srcp, nbytes_left, nbytes)			      \
+  ((nbytes_left) = ((nbytes) -						      \
+		    (__vm_copy (__mach_task_self (),			      \
+				(vm_address_t) srcp, trunc_page (nbytes),     \
+				(vm_address_t) dstp) == KERN_SUCCESS	      \
+		     ? trunc_page (nbytes)				      \
+		     : 0)))
+
+/* Get the generic macro.  */
+#include_next <pagecopy.h>