grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Optimise memset on i386


From: Colin Watson
Subject: [PATCH] Optimise memset on i386
Date: Wed, 23 Jun 2010 22:38:38 +0100
User-agent: Mutt/1.5.18 (2008-05-17)

I've been working on a project involving fast boot speeds, which are
timed from post-BIOS (this is an axiom of the project and not something
I get to change).  As such I've been working on optimising GRUB, and
have been digging into it with this general debugging pattern (probably
not optimal, I'm just showing it as an example of my approach in case
anyone else is trying to do similar things):

#include <grub/time.h>
#include <grub/env.h>

void
grub_function (void)
{
  char *value, *valueend;

  value = grub_malloc (16384);
  *value = '\0';
  valueend = value;

  grub_snprintf (valueend, 100, "%lld", grub_get_time_ms ());
  valueend = grub_strchr (valueend, '\0');

  /* do slow stuff */

  grub_snprintf (valueend, 100, "%lld", grub_get_time_ms ());
  valueend = grub_strchr (valueend, '\0');

  /* do more slow stuff */

  grub_snprintf (valueend, 100, "%lld", grub_get_time_ms ());
  valueend = grub_strchr (valueend, '\0');
  
  grub_env_set ("identifying_name", value);
  grub_free (value);
}

This seems lightweight enough that it doesn't interfere much with
timings, and the approach of stuffing things into an environment
variable is useful because you can get millisecond-precision timings
even for video initialisation.

With this approach, one of the most noticeable time sinks is that
setting a graphical video mode (I'm using the VBE backend) takes ages:
1.6 seconds, which is a substantial percentage of this project's total
boot time.  It turns out that most of this is spent initialising
double-buffering: doublebuf_pageflipping_init calls
grub_video_fb_create_render_target_from_pointer twice, and each call
takes a little over 600 milliseconds.  Now,
grub_video_fb_create_render_target_from_pointer is basically just a big
grub_memset to clear framebuffer memory, so this equates to under two
frames per second.  What's going on?

It turns out that write caching is disabled on video memory when GRUB is
running, so we take a cache stall on every single write, and it's
apparently hard to enable caching without implementing MTRRs.  People
who know more about this than I do tell me that this can get
unpleasantly CPU-specific at times, although I still hold out some hope
that it's possible in GRUB.

However, there's a way to substantially speed things up without that.
The naïve implementation of grub_memset writes a byte at a time, and for
that matter on i386 it compiles to a poorly-optimised loop rather than
using REP STOS or similar.  grub_memset is an inner loop practically by
definition, and it's worth optimising.  We can fix both of these
weaknesses by importing the optimised memset from GNU libc: since it
writes four bytes at a time except (sometimes) at the start and end, it
should take about a quarter the number of cache stalls.  And, indeed,
measurement bears this out: instead of taking over 600 milliseconds per
call to grub_video_fb_create_render_target_from_pointer (I think it was
actually 630 or so, though I neglected to write that down), GRUB now
takes about 160 milliseconds per call.  Much better!

The optimised memset is LGPLv2.1 or later, and I've preserved that
notice, but as far as I know this should be fine for use in GRUB; it can
be upgraded to LGPLv3, and that's just GPLv3 with some additional
permissions.  It's already assigned to the FSF due to being in glibc.

2010-06-23  Colin Watson  <address@hidden>

        * conf/any-emu.rmk (kernel_img_SOURCES): Add kern/string.c.
        * conf/common.rmk (grub_mkdevicemap_SOURCES): Likewise.
        (grub_probe_SOURCES): Likewise.
        (grub_fstest_SOURCES): Likewise.
        (grub_script_check_SOURCES): Likewise.
        (grub_editenv_SOURCES): Likewise.
        * conf/mips-qemu-mips.rmk (kernel_img_SOURCES): Likewise.
        * conf/mips-yeeloong.rmk (kernel_img_SOURCES): Likewise.
        * conf/powerpc-ieee1275.rmk (kernel_img_SOURCES): Likewise.
        * conf/sparc64-ieee1275.rmk (kernel_img_SOURCES): Likewise.
        (grub_setup_SOURCES): Likewise.
        * conf/tests.rmk (example_unit_test_SOURCES): Likewise.

        * conf/i386-coreboot.rmk (kernel_img_SOURCES): Add
        kern/i386/string.c.
        * conf/i386-ieee1275.rmk (kernel_img_SOURCES): Likewise.
        * conf/i386-multiboot.rmk (kernel_img_SOURCES): Likewise.
        * conf/i386-pc.rmk (kernel_img_SOURCES): Likewise.
        (grub_setup_SOURCES): Likewise.
        * conf/i386-qemu.rmk (kernel_img_SOURCES): Likewise.
        * conf/x86-efi.rmk (kernel_img_SOURCES): Likewise.

        * kern/i386/string.c: New file.
        * kern/misc.c (grub_memset): Move to ...
        * kern/string.c (grub_memset): ... here.
        * kern/misc.c (memset): Move to ...
        * kern/string.c (memset): ... here.

=== modified file 'conf/any-emu.rmk'
--- conf/any-emu.rmk    2010-06-11 20:31:16 +0000
+++ conf/any-emu.rmk    2010-06-23 16:55:35 +0000
@@ -6,7 +6,7 @@ kernel_img_SOURCES = kern/device.c kern/
        kern/err.c kern/list.c kern/command.c           \
        kern/corecmd.c kern/file.c kern/fs.c kern/main.c kern/misc.c    \
        kern/parser.c kern/partition.c kern/term.c                      \
-       kern/rescue_reader.c kern/rescue_parser.c                       \
+       kern/rescue_reader.c kern/rescue_parser.c kern/string.c         \
                                                                        \
        kern/emu/main.c kern/emu/mm.c kern/emu/misc.c                   \
        kern/emu/getroot.c kern/emu/time.c kern/emu/hostdisk.c          \

=== modified file 'conf/common.rmk'
--- conf/common.rmk     2010-06-21 15:04:30 +0000
+++ conf/common.rmk     2010-06-23 21:04:23 +0000
@@ -7,7 +7,8 @@ sbin_UTILITIES += grub-mkdevicemap
 grub_mkdevicemap_SOURCES = gnulib/progname.c util/grub-mkdevicemap.c \
        util/deviceiter.c \
        util/misc.c kern/emu/misc.c \
-       kern/env.c kern/err.c kern/list.c kern/misc.c kern/emu/mm.c
+       kern/env.c kern/err.c kern/list.c kern/misc.c kern/string.c \
+       kern/emu/mm.c
 
 ifeq ($(target_cpu)-$(platform), sparc64-ieee1275)
 grub_mkdevicemap_SOURCES += util/ieee1275/ofpath.c util/ieee1275/devicemap.c
@@ -27,7 +28,7 @@ util/grub-probe.c_DEPENDENCIES = grub_pr
 grub_probe_SOURCES = gnulib/progname.c util/grub-probe.c       \
        kern/emu/hostdisk.c util/misc.c kern/emu/misc.c kern/emu/getroot.c 
kern/emu/mm.c        \
        kern/device.c kern/disk.c kern/err.c kern/misc.c        \
-       kern/partition.c kern/file.c kern/list.c        \
+       kern/partition.c kern/file.c kern/list.c kern/string.c  \
        \
        fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c         \
        fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c  \
@@ -49,6 +50,7 @@ util/grub-fstest.c_DEPENDENCIES = grub_f
 grub_fstest_SOURCES = gnulib/progname.c util/grub-fstest.c kern/emu/hostfs.c \
        util/misc.c kern/emu/misc.c kern/emu/mm.c       \
        kern/file.c kern/device.c kern/disk.c kern/err.c kern/misc.c    \
+       kern/string.c                                                   \
        disk/host.c disk/loopback.c kern/list.c kern/command.c          \
        lib/arg.c commands/extcmd.c normal/datetime.c normal/misc.c     \
        lib/hexdump.c lib/crc.c commands/blocklist.c commands/ls.c      \
@@ -92,7 +94,7 @@ grub_script_check_SOURCES = gnulib/progn
        util/grub-script-check.c util/misc.c kern/emu/misc.c kern/emu/mm.c \
        script/main.c script/script.c script/function.c script/lexer.c \
        kern/err.c kern/list.c \
-       kern/misc.c kern/env.c grub_script.tab.c \
+       kern/misc.c kern/env.c kern/string.c grub_script.tab.c \
        grub_script.yy.c
 grub_script_check_CFLAGS = $(GNULIB_UTIL_CFLAGS)
 grub_script_check_DEPENDENCIES = grub_script.tab.h
@@ -160,7 +162,7 @@ DISTCLEANFILES += grub_fstest_init.c
 
 # for grub-editenv
 bin_UTILITIES += grub-editenv
-grub_editenv_SOURCES = gnulib/progname.c util/grub-editenv.c lib/envblk.c 
util/misc.c kern/emu/misc.c kern/emu/mm.c kern/misc.c kern/err.c
+grub_editenv_SOURCES = gnulib/progname.c util/grub-editenv.c lib/envblk.c 
util/misc.c kern/emu/misc.c kern/emu/mm.c kern/misc.c kern/err.c kern/string.c
 CLEANFILES += grub-editenv
 
 # Needed for genmk.rb to work

=== modified file 'conf/i386-coreboot.rmk'
--- conf/i386-coreboot.rmk      2010-06-11 20:31:16 +0000
+++ conf/i386-coreboot.rmk      2010-06-23 16:58:20 +0000
@@ -16,7 +16,7 @@ kernel_img_SOURCES = kern/i386/coreboot/
        kern/rescue_parser.c kern/rescue_reader.c \
        kern/time.c kern/list.c  kern/command.c kern/corecmd.c \
        kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \
-       kern/i386/tsc.c kern/i386/pit.c \
+       kern/i386/tsc.c kern/i386/pit.c kern/i386/string.c \
        kern/generic/rtc_get_time_ms.c \
        kern/generic/millisleep.c \
        kern/env.c \

=== modified file 'conf/i386-ieee1275.rmk'
--- conf/i386-ieee1275.rmk      2010-06-11 20:31:16 +0000
+++ conf/i386-ieee1275.rmk      2010-06-23 16:58:48 +0000
@@ -19,6 +19,7 @@ kernel_img_SOURCES = kern/i386/ieee1275/
        kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \
        kern/env.c \
        kern/time.c kern/list.c  kern/command.c kern/corecmd.c \
+       kern/i386/string.c \
        kern/generic/millisleep.c \
        kern/ieee1275/ieee1275.c \
        term/ieee1275/ofconsole.c \

=== modified file 'conf/i386-multiboot.rmk'
--- conf/i386-multiboot.rmk     2010-05-01 12:06:53 +0000
+++ conf/i386-multiboot.rmk     2010-06-23 16:58:56 +0000
@@ -18,7 +18,7 @@ kernel_img_SOURCES = kern/i386/coreboot/
        kern/rescue_parser.c kern/rescue_reader.c \
        kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \
        kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \
-       kern/i386/tsc.c kern/i386/pit.c \
+       kern/i386/tsc.c kern/i386/pit.c kern/i386/string.c \
        kern/generic/rtc_get_time_ms.c \
        kern/generic/millisleep.c \
        kern/env.c \

=== modified file 'conf/i386-pc.rmk'
--- conf/i386-pc.rmk    2010-06-12 11:17:28 +0000
+++ conf/i386-pc.rmk    2010-06-23 21:04:23 +0000
@@ -46,7 +46,7 @@ kernel_img_SOURCES = kern/i386/pc/startu
        kern/time.c kern/list.c kern/command.c kern/corecmd.c \
        kern/$(target_cpu)/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \
        kern/parser.c kern/partition.c \
-       kern/i386/tsc.c kern/i386/pit.c \
+       kern/i386/tsc.c kern/i386/pit.c kern/i386/string.c \
        kern/generic/rtc_get_time_ms.c \
        kern/generic/millisleep.c \
        kern/env.c \
@@ -66,7 +66,7 @@ util/i386/pc/grub-setup.c_DEPENDENCIES =
 grub_setup_SOURCES = gnulib/progname.c util/i386/pc/grub-setup.c       \
        util/misc.c kern/emu/misc.c kern/emu/getroot.c                  \
        kern/emu/hostdisk.c kern/device.c kern/disk.c kern/err.c        \
-       kern/misc.c kern/partition.c kern/file.c                        \
+       kern/misc.c kern/partition.c kern/file.c kern/i386/string.c     \
        kern/emu/mm.c kern/fs.c kern/env.c kern/list.c fs/fshelp.c      \
                                                                        \
        fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c                 \

=== modified file 'conf/i386-qemu.rmk'
--- conf/i386-qemu.rmk  2010-06-11 20:31:16 +0000
+++ conf/i386-qemu.rmk  2010-06-23 16:59:14 +0000
@@ -25,7 +25,7 @@ kernel_img_SOURCES = kern/i386/qemu/star
        kern/rescue_parser.c kern/rescue_reader.c \
        kern/time.c kern/list.c  kern/command.c kern/corecmd.c \
        kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \
-       kern/i386/tsc.c kern/i386/pit.c \
+       kern/i386/tsc.c kern/i386/pit.c kern/i386/string.c \
        kern/generic/rtc_get_time_ms.c \
        kern/generic/millisleep.c \
        kern/env.c \

=== modified file 'conf/mips-qemu-mips.rmk'
--- conf/mips-qemu-mips.rmk     2010-06-11 20:31:16 +0000
+++ conf/mips-qemu-mips.rmk     2010-06-23 16:59:28 +0000
@@ -11,7 +11,7 @@ kernel_img_SOURCES = kern/$(target_cpu)/
        kern/$(target_cpu)/$(target_machine)/init.c             \
        kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c          \
        kern/misc.c kern/mm.c kern/term.c       \
-       kern/rescue_parser.c kern/rescue_reader.c \
+       kern/rescue_parser.c kern/rescue_reader.c kern/string.c \
        kern/list.c  kern/command.c kern/corecmd.c      \
        kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c       
\
        kern/generic/millisleep.c kern/generic/rtc_get_time_ms.c kern/time.c    
\

=== modified file 'conf/mips-yeeloong.rmk'
--- conf/mips-yeeloong.rmk      2010-06-11 20:31:16 +0000
+++ conf/mips-yeeloong.rmk      2010-06-23 16:59:37 +0000
@@ -15,7 +15,7 @@ kernel_img_SOURCES = kern/$(target_cpu)/
        kern/$(target_cpu)/$(target_machine)/init.c             \
        kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c          \
        kern/misc.c kern/mm.c kern/term.c       \
-       kern/rescue_parser.c kern/rescue_reader.c \
+       kern/rescue_parser.c kern/rescue_reader.c kern/string.c \
        kern/list.c  kern/command.c kern/corecmd.c      \
        kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c       
\
        kern/generic/millisleep.c kern/generic/rtc_get_time_ms.c kern/time.c    
\

=== modified file 'conf/powerpc-ieee1275.rmk'
--- conf/powerpc-ieee1275.rmk   2010-06-11 20:31:16 +0000
+++ conf/powerpc-ieee1275.rmk   2010-06-23 16:59:58 +0000
@@ -12,7 +12,7 @@ kernel_img_SOURCES = kern/powerpc/ieee12
        kern/ieee1275/ieee1275.c kern/main.c kern/device.c              \
        kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c          \
        kern/misc.c kern/mm.c kern/term.c       \
-       kern/rescue_parser.c kern/rescue_reader.c \
+       kern/rescue_parser.c kern/rescue_reader.c kern/string.c \
        kern/list.c  kern/command.c kern/corecmd.c      \
        kern/ieee1275/init.c                                            \
        kern/ieee1275/mmap.c                                            \

=== modified file 'conf/sparc64-ieee1275.rmk'
--- conf/sparc64-ieee1275.rmk   2010-06-11 20:31:16 +0000
+++ conf/sparc64-ieee1275.rmk   2010-06-23 17:00:18 +0000
@@ -25,7 +25,7 @@ kernel_img_SOURCES = kern/sparc64/ieee12
        kern/ieee1275/ieee1275.c kern/main.c kern/device.c              \
        kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c          \
        kern/misc.c kern/mm.c kern/term.c                       \
-       kern/rescue_parser.c kern/rescue_reader.c \
+       kern/rescue_parser.c kern/rescue_reader.c kern/string.c \
        kern/list.c  kern/command.c kern/corecmd.c      \
        kern/sparc64/ieee1275/ieee1275.c                                \
        kern/sparc64/ieee1275/init.c                                    \
@@ -48,7 +48,7 @@ util/sparc64/ieee1275/grub-setup.c_DEPEN
 grub_setup_SOURCES = util/sparc64/ieee1275/grub-setup.c                        
\
        util/ieee1275/ofpath.c util/misc.c kern/emu/hostdisk.c          \
        kern/emu/misc.c kern/emu/getroot.c kern/emu/mm.c kern/device.c  \
-       kern/disk.c kern/err.c kern/misc.c                              \
+       kern/disk.c kern/err.c kern/misc.c kern/string.c                \
        kern/partition.c kern/file.c kern/fs.c kern/env.c kern/list.c   \
        fs/fshelp.c                                                     \
                                                                        \

=== modified file 'conf/tests.rmk'
--- conf/tests.rmk      2010-04-30 08:20:41 +0000
+++ conf/tests.rmk      2010-06-23 17:00:25 +0000
@@ -21,7 +21,7 @@ functional_test_mod_LDFLAGS = $(COMMON_L
 
 # Rules for unit tests
 check_UTILITIES += example_unit_test
-example_unit_test_SOURCES = tests/example_unit_test.c kern/list.c kern/misc.c 
tests/lib/test.c tests/lib/unit_test.c
+example_unit_test_SOURCES = tests/example_unit_test.c kern/list.c kern/misc.c 
kern/string.c tests/lib/test.c tests/lib/unit_test.c
 example_unit_test_CFLAGS  = -Wno-format
 
 # Rules for functional tests

=== modified file 'conf/x86-efi.rmk'
--- conf/x86-efi.rmk    2010-06-12 11:17:28 +0000
+++ conf/x86-efi.rmk    2010-06-23 21:04:23 +0000
@@ -26,7 +26,7 @@ kernel_img_SOURCES = kern/$(target_cpu)/
        kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \
        term/efi/console.c disk/efi/efidisk.c \
        kern/time.c kern/list.c  kern/command.c kern/corecmd.c \
-       kern/i386/tsc.c kern/i386/pit.c \
+       kern/i386/tsc.c kern/i386/pit.c kern/i386/string.c \
        kern/generic/rtc_get_time_ms.c \
        kern/generic/millisleep.c
 ifeq ($(target_cpu),x86_64)

=== added file 'kern/i386/string.c'
--- kern/i386/string.c  1970-01-01 00:00:00 +0000
+++ kern/i386/string.c  2010-06-23 17:03:10 +0000
@@ -0,0 +1,96 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010  Free Software 
Foundation, Inc.
+ *
+ *  This optimised memset implementation originates in GNU libc.  Its
+ *  copyright and licensing information follow.
+ *
+ *  Set a block of memory to some byte value.
+ *  For Intel 80x86, x>=3.
+ *  Copyright (C) 1991,1992,1993,1997,1998,2003, 2005 Free Software 
Foundation, Inc.
+ *  This file is part of the GNU C Library.
+ *  Contributed by Torbjorn Granlund (address@hidden).
+ *
+ *  The GNU C Library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 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
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with the GNU C Library; if not, write to the Free
+ *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307 USA.
+ */
+
+#include <grub/misc.h>
+
+#define OPSIZ (sizeof (unsigned long int))
+
+void *
+grub_memset (void *dstpp, int c, grub_size_t len)
+{
+  int d0;
+  unsigned long int dstp = (unsigned long int) dstpp;
+
+  /* This explicit register allocation
+     improves code very much indeed.  */
+  register unsigned long int x asm("ax");
+
+  x = (unsigned char) c;
+
+  /* Clear the direction flag, so filling will move forward.  */
+  asm volatile("cld");
+
+  /* This threshold value is optimal.  */
+  if (len >= 12)
+    {
+      /* Fill X with four copies of the char we want to fill with.  */
+      x |= (x << 8);
+      x |= (x << 16);
+
+      /* Adjust LEN for the bytes handled in the first loop.  */
+      len -= (-dstp) % OPSIZ;
+
+      /* There are at least some bytes to set.
+         No need to test for LEN == 0 in this alignment loop.  */
+
+      /* Fill bytes until DSTP is aligned on a longword boundary.  */
+      asm volatile("rep\n"
+                   "stosb" /* %0, %2, %3 */ :
+                   "=D" (dstp), "=c" (d0) :
+                   "0" (dstp), "1" ((-dstp) % OPSIZ), "a" (x) :
+                   "memory");
+
+      /* Fill longwords.  */
+      asm volatile("rep\n"
+                   "stosl" /* %0, %2, %3 */ :
+                   "=D" (dstp), "=c" (d0) :
+                   "0" (dstp), "1" (len / OPSIZ), "a" (x) :
+                   "memory");
+      len %= OPSIZ;
+    }
+
+  /* Write the last few bytes.  */
+  asm volatile("rep\n"
+               "stosb" /* %0, %2, %3 */ :
+               "=D" (dstp), "=c" (d0) :
+               "0" (dstp), "1" (len), "a" (x) :
+               "memory");
+
+  return dstpp;
+}
+
+#ifndef APPLE_CC
+void *memset (void *s, int c, grub_size_t n)
+  __attribute__ ((alias ("grub_memset")));
+#else
+void *memset (void *s, int c, grub_size_t n)
+{
+  return grub_memset (s, c, n);
+}
+#endif

=== modified file 'kern/misc.c'
--- kern/misc.c 2010-05-28 13:48:45 +0000
+++ kern/misc.c 2010-06-23 17:01:49 +0000
@@ -506,26 +506,6 @@ grub_strndup (const char *s, grub_size_t
   return p;
 }
 
-void *
-grub_memset (void *s, int c, grub_size_t n)
-{
-  unsigned char *p = (unsigned char *) s;
-
-  while (n--)
-    *p++ = (unsigned char) c;
-
-  return s;
-}
-#ifndef APPLE_CC
-void *memset (void *s, int c, grub_size_t n)
-  __attribute__ ((alias ("grub_memset")));
-#else
-void *memset (void *s, int c, grub_size_t n)
-{
-  return grub_memset (s, c, n);
-}
-#endif
-
 grub_size_t
 grub_strlen (const char *s)
 {

=== added file 'kern/string.c'
--- kern/string.c       1970-01-01 00:00:00 +0000
+++ kern/string.c       2010-06-23 17:01:42 +0000
@@ -0,0 +1,42 @@
+/* string.c - definitions of string functions with architecture-specific
+   optimisations */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010  
Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/misc.h>
+
+void *
+grub_memset (void *s, int c, grub_size_t n)
+{
+  unsigned char *p = (unsigned char *) s;
+
+  while (n--)
+    *p++ = (unsigned char) c;
+
+  return s;
+}
+
+#ifndef APPLE_CC
+void *memset (void *s, int c, grub_size_t n)
+  __attribute__ ((alias ("grub_memset")));
+#else
+void *memset (void *s, int c, grub_size_t n)
+{
+  return grub_memset (s, c, n);
+}
+#endif

Thanks,

-- 
Colin Watson                                       address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]