emacs-diffs
[Top][All Lists]
Advanced

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

feature/android 265435fdf8b: Update Android port


From: Po Lu
Subject: feature/android 265435fdf8b: Update Android port
Date: Fri, 17 Feb 2023 22:54:55 -0500 (EST)

branch: feature/android
commit 265435fdf8b39b564fefda2f0dd40f2668c3f607
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Update Android port
    
    * configure.ac: Check for madvise.
    * lisp/international/fontset.el (script-representative-chars):
    Improve detection of CJK fonts.
    * src/pdumper.c (dump_discard_mem): Use madvise if possible.
    * src/sfnt.c (sfnt_map_glyf_table, sfnt_unmap_glyf_table): New
    functions.
    * src/sfnt.h (struct sfnt_glyf_table): New field.
    * src/sfntfont.c (struct sfnt_font_info, sfntfont_open)
    (sfntfont_close, sfntfont_detect_sigbus): Allow mmapping fonts
    if possible.
    * src/sfntfont.h: Update prototypes.
    * src/sysdep.c (handle_sigbus, init_sigbus, init_signals):
    Initialize SIGBUS correctly.
---
 configure.ac                  |   4 +-
 lisp/international/fontset.el |   5 +-
 src/pdumper.c                 |   4 +-
 src/sfnt.c                    |  90 +++++++++++++++++++++++++++++++
 src/sfnt.h                    |   9 ++++
 src/sfntfont.c                | 121 ++++++++++++++++++++++++++++++++++++++++--
 src/sfntfont.h                |   9 ++++
 src/sysdep.c                  |  43 ++++++++++++++-
 8 files changed, 276 insertions(+), 9 deletions(-)

diff --git a/configure.ac b/configure.ac
index a4a16ec8062..dc6a81d9f4a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5722,8 +5722,8 @@ if test "$with_unexec" = yes && test "$opsys" = "haiku"; 
then
 Please use the portable dumper instead.])
 fi
 
-# Dump loading
-AC_CHECK_FUNCS([posix_madvise])
+# Dump loading.  Android lacks posix_madvise.
+AC_CHECK_FUNCS([posix_madvise madvise])
 
 dnl Cannot use AC_CHECK_FUNCS
 AC_CACHE_CHECK([for __builtin_frame_address],
diff --git a/lisp/international/fontset.el b/lisp/international/fontset.el
index 8fa67d99477..a60ce4c4df6 100644
--- a/lisp/international/fontset.el
+++ b/lisp/international/fontset.el
@@ -200,7 +200,10 @@
        (symbol . [#x201C #x2200 #x2500])
        (braille #x2800)
        (ideographic-description #x2FF0)
-       (cjk-misc #x300E #xff0c)
+        ;; Noto Sans Phags Pa is broken and reuses the CJK misc code
+        ;; points for some of its own characters.  Add one actual CJK
+        ;; character to prevent finding such broken fonts.
+       (cjk-misc #x300E #xff0c #x300a #xff09 #x5b50)
        (kana #x304B)
        (bopomofo #x3105)
        (kanbun #x319D)
diff --git a/src/pdumper.c b/src/pdumper.c
index baa33c4f647..645661060c1 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -4747,7 +4747,9 @@ dump_discard_mem (void *mem, size_t size)
 # ifdef HAVE_POSIX_MADVISE
       /* Discard COWed pages.  */
       (void) posix_madvise (mem, size, POSIX_MADV_DONTNEED);
-# endif
+# elif defined HAVE_MADVISE
+      (void) madvise (mem, size, MADV_DONTNEED);
+#endif
       /* Release the commit charge for the mapping.  */
       (void) mprotect (mem, size, PROT_NONE);
 #endif
diff --git a/src/sfnt.c b/src/sfnt.c
index b6f4a48ea8b..06985c74a57 100644
--- a/src/sfnt.c
+++ b/src/sfnt.c
@@ -34,6 +34,11 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 
USA.  */
 #include <string.h>
 #include <unistd.h>
 #include <setjmp.h>
+#include <errno.h>
+
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+#endif
 
 #if defined __GNUC__ && !defined __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
@@ -1584,6 +1589,91 @@ sfnt_read_glyf_table (int fd, struct 
sfnt_offset_subtable *subtable)
   return glyf;
 }
 
+#if defined HAVE_MMAP && !defined TEST
+
+/* Map a glyph table from the given font FD.  Use the table directory
+   specified in SUBTABLE.  The glyph data is not byte-swapped.
+
+   Value is the glyf table upon success, else NULL.
+   A mapped glyf table must be unmapped using `sfnt_unmap_glyf_table'.
+   The caller must correctly handle bus errors in between glyf->table
+   and glyf->size.  */
+
+struct sfnt_glyf_table *
+sfnt_map_glyf_table (int fd, struct sfnt_offset_subtable *subtable)
+{
+  struct sfnt_table_directory *directory;
+  struct sfnt_glyf_table *glyf;
+  void *glyphs;
+  size_t offset, page, map_offset;
+
+  /* Find the table in the directory.  */
+
+  directory = sfnt_find_table (subtable, SFNT_TABLE_GLYF);
+
+  if (!directory)
+    return NULL;
+
+  /* Now try to map the glyph data.  Make sure offset is a multiple of
+     the page size.  */
+
+  page = getpagesize ();
+  offset = directory->offset & ~(page - 1);
+
+  /* Figure out how much larger the mapping should be.  */
+  map_offset = directory->offset - offset;
+
+  /* Do the mmap.  */
+  glyphs = mmap (NULL, directory->length + map_offset,
+                PROT_READ, MAP_PRIVATE, fd, offset);
+
+  if (glyphs == MAP_FAILED)
+    {
+      fprintf (stderr, "sfnt_map_glyf_table: mmap: %s\n",
+              strerror (errno));
+
+      return NULL;
+    }
+
+  /* An observation is that glyphs tend to be accessed in sequential
+     order and immediately after the font's glyph table is loaded.  */
+
+#ifdef HAVE_POSIX_MADVISE
+  posix_madvise (glyphs, directory->length,
+                POSIX_MADV_WILLNEED);
+#elif defined HAVE_MADVISE
+  madvise (glyphs, directory->length, MADV_WILLNEED);
+#endif
+
+  /* Allocate the glyf table.  */
+  glyf = xmalloc (sizeof *glyf);
+  glyf->size = directory->length;
+  glyf->glyphs = (unsigned char *) glyphs + map_offset;
+  glyf->start = glyphs;
+  return glyf;
+}
+
+/* Unmap the mmap'ed glyf table GLYF, then free its associated data.
+   Value is 0 upon success, else 1, in which case GLYF is still freed
+   all the same.  */
+
+int
+sfnt_unmap_glyf_table (struct sfnt_glyf_table *glyf)
+{
+  int rc;
+  size_t size;
+
+  /* Calculate the size of the mapping.  */
+  size = glyf->size + (glyf->glyphs - glyf->start);
+
+  rc = munmap (glyf->start, size);
+  xfree (glyf);
+
+  return rc != 0;
+}
+
+#endif /* HAVE_MMAP */
+
 /* Read the simple glyph outline from the glyph GLYPH from the
    specified glyf table at the given offset.  Set GLYPH->simple to a
    non-NULL value upon success, else set it to NULL.  */
diff --git a/src/sfnt.h b/src/sfnt.h
index 40c77ee123f..4bf46b62397 100644
--- a/src/sfnt.h
+++ b/src/sfnt.h
@@ -524,6 +524,10 @@ struct sfnt_glyf_table
 
   /* Pointer to possibly unaligned glyph data.  */
   unsigned char *glyphs;
+
+  /* Pointer to the start of the mapping.
+     Only initialized if this table was mmapped.  */
+  unsigned char *start;
 };
 
 struct sfnt_simple_glyph
@@ -951,6 +955,11 @@ extern struct sfnt_loca_table_short 
*sfnt_read_loca_table_short (PROTOTYPE);
 extern struct sfnt_loca_table_long *sfnt_read_loca_table_long (PROTOTYPE);
 extern struct sfnt_maxp_table *sfnt_read_maxp_table (PROTOTYPE);
 extern struct sfnt_glyf_table *sfnt_read_glyf_table (PROTOTYPE);
+
+#ifdef HAVE_MMAP
+extern struct sfnt_glyf_table *sfnt_map_glyf_table (PROTOTYPE);
+extern int sfnt_unmap_glyf_table (struct sfnt_glyf_table *);
+#endif /* HAVE_MMAP */
 #undef PROTOTYPE
 
 extern struct sfnt_glyph *sfnt_read_glyph (sfnt_glyph, struct sfnt_glyf_table 
*,
diff --git a/src/sfntfont.c b/src/sfntfont.c
index 20c109f2401..bb816fabd3e 100644
--- a/src/sfntfont.c
+++ b/src/sfntfont.c
@@ -1805,6 +1805,11 @@ struct sfnt_font_info
   /* Parent font structure.  */
   struct font font;
 
+#ifdef HAVE_MMAP
+  /* The next font in this chain.  */
+  struct sfnt_font_info *next;
+#endif /* HAVE_MMAP */
+
   /* Various tables required to use the font.  */
   struct sfnt_cmap_table *cmap;
   struct sfnt_hhea_table *hhea;
@@ -1842,8 +1847,21 @@ struct sfnt_font_info
   /* Graphics state after the execution of the font and control value
      programs.  */
   struct sfnt_graphics_state state;
+
+#ifdef HAVE_MMAP
+  /* Whether or not the glyph table has been mmapped.  */
+  bool glyf_table_mapped;
+#endif /* HAVE_MMAP */
 };
 
+#ifdef HAVE_MMAP
+
+/* List of all open fonts.  */
+
+static struct sfnt_font_info *open_fonts;
+
+#endif /* HAVE_MMAP */
+
 /* Look up the glyph corresponding to the character C in FONT.  Return
    0 upon failure, and the glyph otherwise.  */
 
@@ -2040,6 +2058,9 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
   struct sfnt_font_desc *desc;
   Lisp_Object font_object;
   int fd, i;
+#ifdef HAVE_MMAP
+  int rc;
+#endif /* HAVE_MMAP */
   struct sfnt_offset_subtable *subtable;
   struct sfnt_cmap_encoding_subtable *subtables;
   struct sfnt_cmap_encoding_subtable_data **data;
@@ -2096,6 +2117,9 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
   font_info->raster_cache.last = &font_info->raster_cache;
   font_info->raster_cache_size = 0;
   font_info->interpreter = NULL;
+#ifdef HAVE_MMAP
+  font_info->glyf_table_mapped = false;
+#endif /* HAVE_MMAP */
 
   /* Open the font.  */
   fd = emacs_open (desc->path, O_RDONLY, 0);
@@ -2145,7 +2169,24 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
   /* Read the hhea, maxp, glyf, and head tables.  */
   font_info->hhea = sfnt_read_hhea_table (fd, subtable);
   font_info->maxp = sfnt_read_maxp_table (fd, subtable);
-  font_info->glyf = sfnt_read_glyf_table (fd, subtable);
+
+#ifdef HAVE_MMAP
+
+  /* First try to map the glyf table.  If that fails, then read the
+     glyf table.  */
+
+  font_info->glyf = sfnt_map_glyf_table (fd, subtable);
+
+  /* Next, if this fails, read the glyf table.  */
+
+  if (!font_info->glyf)
+#endif /* HAVE_MMAP */
+    font_info->glyf = sfnt_read_glyf_table (fd, subtable);
+#ifdef HAVE_MMAP
+  else
+    font_info->glyf_table_mapped = true;
+#endif /* HAVE_MMAP */
+
   font_info->head = sfnt_read_head_table (fd, subtable);
 
   /* If any of those tables couldn't be read, bail.  */
@@ -2266,6 +2307,12 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
   /* Free the offset subtable.  */
   xfree (subtable);
 
+#ifdef HAVE_MMAP
+  /* Link the font onto the font table.  */
+  font_info->next = open_fonts;
+  open_fonts = font_info;
+#endif /* HAVE_MMAP */
+
   /* All done.  */
   unblock_input ();
   return font_object;
@@ -2281,7 +2328,19 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
  bail4:
   xfree (font_info->hhea);
   xfree (font_info->maxp);
-  xfree (font_info->glyf);
+
+#ifdef HAVE_MMAP
+  if (font_info->glyf_table_mapped)
+    {
+      rc = sfnt_unmap_glyf_table (font_info->glyf);
+
+      if (rc)
+       emacs_abort ();
+    }
+  else
+#endif /* HAVE_MMAP */
+    xfree (font_info->glyf);
+
   xfree (font_info->head);
   font_info->hhea = NULL;
   font_info->maxp = NULL;
@@ -2473,7 +2532,10 @@ sfntfont_text_extents (struct font *font, const unsigned 
int *code,
 void
 sfntfont_close (struct font *font)
 {
-  struct sfnt_font_info *info;
+  struct sfnt_font_info *info, **next;
+#ifdef HAVE_MMAP
+  int rc;
+#endif /* HAVE_MMAP */
 
   info = (struct sfnt_font_info *) font;
   xfree (info->cmap);
@@ -2481,7 +2543,20 @@ sfntfont_close (struct font *font)
   xfree (info->maxp);
   xfree (info->head);
   xfree (info->hmtx);
-  xfree (info->glyf);
+
+#ifdef HAVE_MMAP
+
+  if (info->glyf_table_mapped)
+    {
+      rc = sfnt_unmap_glyf_table (info->glyf);
+
+      if (rc)
+       emacs_abort ();
+    }
+  else
+#endif /* HAVE_MMAP */
+    xfree (info->glyf);
+
   xfree (info->loca_short);
   xfree (info->loca_long);
   xfree (info->cmap_data);
@@ -2490,6 +2565,16 @@ sfntfont_close (struct font *font)
   xfree (info->cvt);
   xfree (info->interpreter);
 
+  /* Unlink INFO.  */
+
+  next = &open_fonts;
+  while (*next && (*next) != info)
+    next = &(*next)->next;
+
+  if (*next)
+    *next = info->next;
+  info->next = NULL;
+
   sfntfont_free_outline_cache (&info->outline_cache);
   sfntfont_free_raster_cache (&info->raster_cache);
 }
@@ -2627,6 +2712,34 @@ sfntfont_list_family (struct frame *f)
 
 
 
+/* mmap specific stuff.  */
+
+#ifdef HAVE_MMAP
+
+/* Return whether or not ADDR lies in a mapped glyph, and bus faults
+   should be ignored.  */
+
+bool
+sfntfont_detect_sigbus (void *addr)
+{
+  struct sfnt_font_info *info;
+
+  for (info = open_fonts; info; info = info->next)
+    {
+      if (info->glyf_table_mapped
+         && (unsigned char *) addr >= info->glyf->glyphs
+         && (unsigned char *) addr < (info->glyf->glyphs
+                                      + info->glyf->size))
+       return true;
+    }
+
+  return false;
+}
+
+#endif
+
+
+
 void
 syms_of_sfntfont (void)
 {
diff --git a/src/sfntfont.h b/src/sfntfont.h
index f49121438a5..dc37883b4a9 100644
--- a/src/sfntfont.h
+++ b/src/sfntfont.h
@@ -56,4 +56,13 @@ extern void mark_sfntfont (void);
 extern void init_sfntfont_vendor (Lisp_Object, const struct font_driver *,
                                  sfntfont_put_glyph_proc);
 
+
+/* mmap specific functions.  */
+
+#ifdef HAVE_MMAP
+
+extern bool sfntfont_detect_sigbus (void *);
+
+#endif /* HAVE_MMAP */
+
 #endif /* _SFNTFONT_H_ */
diff --git a/src/sysdep.c b/src/sysdep.c
index ac26b12e9a5..cb63d8bba08 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -138,6 +138,10 @@ int _cdecl _spawnlp (int, const char *, const char *, ...);
 #include "android.h"
 #endif
 
+#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
+#include "sfntfont.h"
+#endif
+
 /* Declare here, including term.h is problematic on some systems.  */
 extern void tputs (const char *, int, int (*)(int));
 
@@ -1816,6 +1820,40 @@ handle_arith_signal (int sig)
   xsignal0 (Qarith_error);
 }
 
+#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY && defined HAVE_MMAP
+
+static void
+handle_sigbus (int sig, siginfo_t *siginfo, void *arg)
+{
+  /* If this arrives during sfntfont_open, then Emacs may be
+     screwed.  */
+
+  if (sfntfont_detect_sigbus (siginfo->si_addr))
+    return;
+
+  handle_fatal_signal (sig);
+}
+
+/* Try to set up SIGBUS handling for the sfnt font driver.
+   Value is 1 upon failure, 0 otherwise.  */
+
+static int
+init_sigbus (void)
+{
+  struct sigaction sa;
+
+  sigfillset (&sa.sa_mask);
+  sa.sa_sigaction = handle_sigbus;
+  sa.sa_flags = SA_SIGINFO;
+
+  if (sigaction (SIGBUS, &sa, NULL))
+    return 1;
+
+  return 0;
+}
+
+#endif
+
 /* This does not work on Android and interferes with the system
    tombstone generation.  */
 
@@ -2076,7 +2114,10 @@ init_signals (void)
   sigaction (SIGEMT, &thread_fatal_action, 0);
 #endif
 #ifdef SIGBUS
-  sigaction (SIGBUS, &thread_fatal_action, 0);
+#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY && defined HAVE_MMAP
+  if (init_sigbus ())
+#endif
+    sigaction (SIGBUS, &thread_fatal_action, 0);
 #endif
 #if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
   if (!init_sigsegv ())



reply via email to

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