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.
This commit is contained in:
parent
ce440ae92c
commit
265435fdf8
8 changed files with 276 additions and 9 deletions
|
@ -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],
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
90
src/sfnt.c
90
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. */
|
||||
|
|
|
@ -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 *,
|
||||
|
|
121
src/sfntfont.c
121
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)
|
||||
{
|
||||
|
|
|
@ -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_ */
|
||||
|
|
43
src/sysdep.c
43
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 ())
|
||||
|
|
Loading…
Add table
Reference in a new issue