aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-02-18 11:50:44 +0800
committerPo Lu2023-02-18 11:50:44 +0800
commit265435fdf8b39b564fefda2f0dd40f2668c3f607 (patch)
tree47abb19f2da43072b6dc85ec188fbe31a4236d1d /src
parentce440ae92cd5c6217648a3557e79d95d50b65b1f (diff)
downloademacs-265435fdf8b39b564fefda2f0dd40f2668c3f607.tar.gz
emacs-265435fdf8b39b564fefda2f0dd40f2668c3f607.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/pdumper.c4
-rw-r--r--src/sfnt.c90
-rw-r--r--src/sfnt.h9
-rw-r--r--src/sfntfont.c121
-rw-r--r--src/sfntfont.h9
-rw-r--r--src/sysdep.c43
6 files changed, 270 insertions, 6 deletions
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)
4747# ifdef HAVE_POSIX_MADVISE 4747# ifdef HAVE_POSIX_MADVISE
4748 /* Discard COWed pages. */ 4748 /* Discard COWed pages. */
4749 (void) posix_madvise (mem, size, POSIX_MADV_DONTNEED); 4749 (void) posix_madvise (mem, size, POSIX_MADV_DONTNEED);
4750# endif 4750# elif defined HAVE_MADVISE
4751 (void) madvise (mem, size, MADV_DONTNEED);
4752#endif
4751 /* Release the commit charge for the mapping. */ 4753 /* Release the commit charge for the mapping. */
4752 (void) mprotect (mem, size, PROT_NONE); 4754 (void) mprotect (mem, size, PROT_NONE);
4753#endif 4755#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. */
34#include <string.h> 34#include <string.h>
35#include <unistd.h> 35#include <unistd.h>
36#include <setjmp.h> 36#include <setjmp.h>
37#include <errno.h>
38
39#ifdef HAVE_MMAP
40#include <sys/mman.h>
41#endif
37 42
38#if defined __GNUC__ && !defined __clang__ 43#if defined __GNUC__ && !defined __clang__
39#pragma GCC diagnostic ignored "-Wstringop-overflow" 44#pragma GCC diagnostic ignored "-Wstringop-overflow"
@@ -1584,6 +1589,91 @@ sfnt_read_glyf_table (int fd, struct sfnt_offset_subtable *subtable)
1584 return glyf; 1589 return glyf;
1585} 1590}
1586 1591
1592#if defined HAVE_MMAP && !defined TEST
1593
1594/* Map a glyph table from the given font FD. Use the table directory
1595 specified in SUBTABLE. The glyph data is not byte-swapped.
1596
1597 Value is the glyf table upon success, else NULL.
1598 A mapped glyf table must be unmapped using `sfnt_unmap_glyf_table'.
1599 The caller must correctly handle bus errors in between glyf->table
1600 and glyf->size. */
1601
1602struct sfnt_glyf_table *
1603sfnt_map_glyf_table (int fd, struct sfnt_offset_subtable *subtable)
1604{
1605 struct sfnt_table_directory *directory;
1606 struct sfnt_glyf_table *glyf;
1607 void *glyphs;
1608 size_t offset, page, map_offset;
1609
1610 /* Find the table in the directory. */
1611
1612 directory = sfnt_find_table (subtable, SFNT_TABLE_GLYF);
1613
1614 if (!directory)
1615 return NULL;
1616
1617 /* Now try to map the glyph data. Make sure offset is a multiple of
1618 the page size. */
1619
1620 page = getpagesize ();
1621 offset = directory->offset & ~(page - 1);
1622
1623 /* Figure out how much larger the mapping should be. */
1624 map_offset = directory->offset - offset;
1625
1626 /* Do the mmap. */
1627 glyphs = mmap (NULL, directory->length + map_offset,
1628 PROT_READ, MAP_PRIVATE, fd, offset);
1629
1630 if (glyphs == MAP_FAILED)
1631 {
1632 fprintf (stderr, "sfnt_map_glyf_table: mmap: %s\n",
1633 strerror (errno));
1634
1635 return NULL;
1636 }
1637
1638 /* An observation is that glyphs tend to be accessed in sequential
1639 order and immediately after the font's glyph table is loaded. */
1640
1641#ifdef HAVE_POSIX_MADVISE
1642 posix_madvise (glyphs, directory->length,
1643 POSIX_MADV_WILLNEED);
1644#elif defined HAVE_MADVISE
1645 madvise (glyphs, directory->length, MADV_WILLNEED);
1646#endif
1647
1648 /* Allocate the glyf table. */
1649 glyf = xmalloc (sizeof *glyf);
1650 glyf->size = directory->length;
1651 glyf->glyphs = (unsigned char *) glyphs + map_offset;
1652 glyf->start = glyphs;
1653 return glyf;
1654}
1655
1656/* Unmap the mmap'ed glyf table GLYF, then free its associated data.
1657 Value is 0 upon success, else 1, in which case GLYF is still freed
1658 all the same. */
1659
1660int
1661sfnt_unmap_glyf_table (struct sfnt_glyf_table *glyf)
1662{
1663 int rc;
1664 size_t size;
1665
1666 /* Calculate the size of the mapping. */
1667 size = glyf->size + (glyf->glyphs - glyf->start);
1668
1669 rc = munmap (glyf->start, size);
1670 xfree (glyf);
1671
1672 return rc != 0;
1673}
1674
1675#endif /* HAVE_MMAP */
1676
1587/* Read the simple glyph outline from the glyph GLYPH from the 1677/* Read the simple glyph outline from the glyph GLYPH from the
1588 specified glyf table at the given offset. Set GLYPH->simple to a 1678 specified glyf table at the given offset. Set GLYPH->simple to a
1589 non-NULL value upon success, else set it to NULL. */ 1679 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
524 524
525 /* Pointer to possibly unaligned glyph data. */ 525 /* Pointer to possibly unaligned glyph data. */
526 unsigned char *glyphs; 526 unsigned char *glyphs;
527
528 /* Pointer to the start of the mapping.
529 Only initialized if this table was mmapped. */
530 unsigned char *start;
527}; 531};
528 532
529struct sfnt_simple_glyph 533struct sfnt_simple_glyph
@@ -951,6 +955,11 @@ extern struct sfnt_loca_table_short *sfnt_read_loca_table_short (PROTOTYPE);
951extern struct sfnt_loca_table_long *sfnt_read_loca_table_long (PROTOTYPE); 955extern struct sfnt_loca_table_long *sfnt_read_loca_table_long (PROTOTYPE);
952extern struct sfnt_maxp_table *sfnt_read_maxp_table (PROTOTYPE); 956extern struct sfnt_maxp_table *sfnt_read_maxp_table (PROTOTYPE);
953extern struct sfnt_glyf_table *sfnt_read_glyf_table (PROTOTYPE); 957extern struct sfnt_glyf_table *sfnt_read_glyf_table (PROTOTYPE);
958
959#ifdef HAVE_MMAP
960extern struct sfnt_glyf_table *sfnt_map_glyf_table (PROTOTYPE);
961extern int sfnt_unmap_glyf_table (struct sfnt_glyf_table *);
962#endif /* HAVE_MMAP */
954#undef PROTOTYPE 963#undef PROTOTYPE
955 964
956extern struct sfnt_glyph *sfnt_read_glyph (sfnt_glyph, struct sfnt_glyf_table *, 965extern 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
1805 /* Parent font structure. */ 1805 /* Parent font structure. */
1806 struct font font; 1806 struct font font;
1807 1807
1808#ifdef HAVE_MMAP
1809 /* The next font in this chain. */
1810 struct sfnt_font_info *next;
1811#endif /* HAVE_MMAP */
1812
1808 /* Various tables required to use the font. */ 1813 /* Various tables required to use the font. */
1809 struct sfnt_cmap_table *cmap; 1814 struct sfnt_cmap_table *cmap;
1810 struct sfnt_hhea_table *hhea; 1815 struct sfnt_hhea_table *hhea;
@@ -1842,8 +1847,21 @@ struct sfnt_font_info
1842 /* Graphics state after the execution of the font and control value 1847 /* Graphics state after the execution of the font and control value
1843 programs. */ 1848 programs. */
1844 struct sfnt_graphics_state state; 1849 struct sfnt_graphics_state state;
1850
1851#ifdef HAVE_MMAP
1852 /* Whether or not the glyph table has been mmapped. */
1853 bool glyf_table_mapped;
1854#endif /* HAVE_MMAP */
1845}; 1855};
1846 1856
1857#ifdef HAVE_MMAP
1858
1859/* List of all open fonts. */
1860
1861static struct sfnt_font_info *open_fonts;
1862
1863#endif /* HAVE_MMAP */
1864
1847/* Look up the glyph corresponding to the character C in FONT. Return 1865/* Look up the glyph corresponding to the character C in FONT. Return
1848 0 upon failure, and the glyph otherwise. */ 1866 0 upon failure, and the glyph otherwise. */
1849 1867
@@ -2040,6 +2058,9 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
2040 struct sfnt_font_desc *desc; 2058 struct sfnt_font_desc *desc;
2041 Lisp_Object font_object; 2059 Lisp_Object font_object;
2042 int fd, i; 2060 int fd, i;
2061#ifdef HAVE_MMAP
2062 int rc;
2063#endif /* HAVE_MMAP */
2043 struct sfnt_offset_subtable *subtable; 2064 struct sfnt_offset_subtable *subtable;
2044 struct sfnt_cmap_encoding_subtable *subtables; 2065 struct sfnt_cmap_encoding_subtable *subtables;
2045 struct sfnt_cmap_encoding_subtable_data **data; 2066 struct sfnt_cmap_encoding_subtable_data **data;
@@ -2096,6 +2117,9 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
2096 font_info->raster_cache.last = &font_info->raster_cache; 2117 font_info->raster_cache.last = &font_info->raster_cache;
2097 font_info->raster_cache_size = 0; 2118 font_info->raster_cache_size = 0;
2098 font_info->interpreter = NULL; 2119 font_info->interpreter = NULL;
2120#ifdef HAVE_MMAP
2121 font_info->glyf_table_mapped = false;
2122#endif /* HAVE_MMAP */
2099 2123
2100 /* Open the font. */ 2124 /* Open the font. */
2101 fd = emacs_open (desc->path, O_RDONLY, 0); 2125 fd = emacs_open (desc->path, O_RDONLY, 0);
@@ -2145,7 +2169,24 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
2145 /* Read the hhea, maxp, glyf, and head tables. */ 2169 /* Read the hhea, maxp, glyf, and head tables. */
2146 font_info->hhea = sfnt_read_hhea_table (fd, subtable); 2170 font_info->hhea = sfnt_read_hhea_table (fd, subtable);
2147 font_info->maxp = sfnt_read_maxp_table (fd, subtable); 2171 font_info->maxp = sfnt_read_maxp_table (fd, subtable);
2148 font_info->glyf = sfnt_read_glyf_table (fd, subtable); 2172
2173#ifdef HAVE_MMAP
2174
2175 /* First try to map the glyf table. If that fails, then read the
2176 glyf table. */
2177
2178 font_info->glyf = sfnt_map_glyf_table (fd, subtable);
2179
2180 /* Next, if this fails, read the glyf table. */
2181
2182 if (!font_info->glyf)
2183#endif /* HAVE_MMAP */
2184 font_info->glyf = sfnt_read_glyf_table (fd, subtable);
2185#ifdef HAVE_MMAP
2186 else
2187 font_info->glyf_table_mapped = true;
2188#endif /* HAVE_MMAP */
2189
2149 font_info->head = sfnt_read_head_table (fd, subtable); 2190 font_info->head = sfnt_read_head_table (fd, subtable);
2150 2191
2151 /* If any of those tables couldn't be read, bail. */ 2192 /* If any of those tables couldn't be read, bail. */
@@ -2266,6 +2307,12 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
2266 /* Free the offset subtable. */ 2307 /* Free the offset subtable. */
2267 xfree (subtable); 2308 xfree (subtable);
2268 2309
2310#ifdef HAVE_MMAP
2311 /* Link the font onto the font table. */
2312 font_info->next = open_fonts;
2313 open_fonts = font_info;
2314#endif /* HAVE_MMAP */
2315
2269 /* All done. */ 2316 /* All done. */
2270 unblock_input (); 2317 unblock_input ();
2271 return font_object; 2318 return font_object;
@@ -2281,7 +2328,19 @@ sfntfont_open (struct frame *f, Lisp_Object font_entity,
2281 bail4: 2328 bail4:
2282 xfree (font_info->hhea); 2329 xfree (font_info->hhea);
2283 xfree (font_info->maxp); 2330 xfree (font_info->maxp);
2284 xfree (font_info->glyf); 2331
2332#ifdef HAVE_MMAP
2333 if (font_info->glyf_table_mapped)
2334 {
2335 rc = sfnt_unmap_glyf_table (font_info->glyf);
2336
2337 if (rc)
2338 emacs_abort ();
2339 }
2340 else
2341#endif /* HAVE_MMAP */
2342 xfree (font_info->glyf);
2343
2285 xfree (font_info->head); 2344 xfree (font_info->head);
2286 font_info->hhea = NULL; 2345 font_info->hhea = NULL;
2287 font_info->maxp = NULL; 2346 font_info->maxp = NULL;
@@ -2473,7 +2532,10 @@ sfntfont_text_extents (struct font *font, const unsigned int *code,
2473void 2532void
2474sfntfont_close (struct font *font) 2533sfntfont_close (struct font *font)
2475{ 2534{
2476 struct sfnt_font_info *info; 2535 struct sfnt_font_info *info, **next;
2536#ifdef HAVE_MMAP
2537 int rc;
2538#endif /* HAVE_MMAP */
2477 2539
2478 info = (struct sfnt_font_info *) font; 2540 info = (struct sfnt_font_info *) font;
2479 xfree (info->cmap); 2541 xfree (info->cmap);
@@ -2481,7 +2543,20 @@ sfntfont_close (struct font *font)
2481 xfree (info->maxp); 2543 xfree (info->maxp);
2482 xfree (info->head); 2544 xfree (info->head);
2483 xfree (info->hmtx); 2545 xfree (info->hmtx);
2484 xfree (info->glyf); 2546
2547#ifdef HAVE_MMAP
2548
2549 if (info->glyf_table_mapped)
2550 {
2551 rc = sfnt_unmap_glyf_table (info->glyf);
2552
2553 if (rc)
2554 emacs_abort ();
2555 }
2556 else
2557#endif /* HAVE_MMAP */
2558 xfree (info->glyf);
2559
2485 xfree (info->loca_short); 2560 xfree (info->loca_short);
2486 xfree (info->loca_long); 2561 xfree (info->loca_long);
2487 xfree (info->cmap_data); 2562 xfree (info->cmap_data);
@@ -2490,6 +2565,16 @@ sfntfont_close (struct font *font)
2490 xfree (info->cvt); 2565 xfree (info->cvt);
2491 xfree (info->interpreter); 2566 xfree (info->interpreter);
2492 2567
2568 /* Unlink INFO. */
2569
2570 next = &open_fonts;
2571 while (*next && (*next) != info)
2572 next = &(*next)->next;
2573
2574 if (*next)
2575 *next = info->next;
2576 info->next = NULL;
2577
2493 sfntfont_free_outline_cache (&info->outline_cache); 2578 sfntfont_free_outline_cache (&info->outline_cache);
2494 sfntfont_free_raster_cache (&info->raster_cache); 2579 sfntfont_free_raster_cache (&info->raster_cache);
2495} 2580}
@@ -2627,6 +2712,34 @@ sfntfont_list_family (struct frame *f)
2627 2712
2628 2713
2629 2714
2715/* mmap specific stuff. */
2716
2717#ifdef HAVE_MMAP
2718
2719/* Return whether or not ADDR lies in a mapped glyph, and bus faults
2720 should be ignored. */
2721
2722bool
2723sfntfont_detect_sigbus (void *addr)
2724{
2725 struct sfnt_font_info *info;
2726
2727 for (info = open_fonts; info; info = info->next)
2728 {
2729 if (info->glyf_table_mapped
2730 && (unsigned char *) addr >= info->glyf->glyphs
2731 && (unsigned char *) addr < (info->glyf->glyphs
2732 + info->glyf->size))
2733 return true;
2734 }
2735
2736 return false;
2737}
2738
2739#endif
2740
2741
2742
2630void 2743void
2631syms_of_sfntfont (void) 2744syms_of_sfntfont (void)
2632{ 2745{
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);
56extern void init_sfntfont_vendor (Lisp_Object, const struct font_driver *, 56extern void init_sfntfont_vendor (Lisp_Object, const struct font_driver *,
57 sfntfont_put_glyph_proc); 57 sfntfont_put_glyph_proc);
58 58
59
60/* mmap specific functions. */
61
62#ifdef HAVE_MMAP
63
64extern bool sfntfont_detect_sigbus (void *);
65
66#endif /* HAVE_MMAP */
67
59#endif /* _SFNTFONT_H_ */ 68#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 *, ...);
138#include "android.h" 138#include "android.h"
139#endif 139#endif
140 140
141#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
142#include "sfntfont.h"
143#endif
144
141/* Declare here, including term.h is problematic on some systems. */ 145/* Declare here, including term.h is problematic on some systems. */
142extern void tputs (const char *, int, int (*)(int)); 146extern void tputs (const char *, int, int (*)(int));
143 147
@@ -1816,6 +1820,40 @@ handle_arith_signal (int sig)
1816 xsignal0 (Qarith_error); 1820 xsignal0 (Qarith_error);
1817} 1821}
1818 1822
1823#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY && defined HAVE_MMAP
1824
1825static void
1826handle_sigbus (int sig, siginfo_t *siginfo, void *arg)
1827{
1828 /* If this arrives during sfntfont_open, then Emacs may be
1829 screwed. */
1830
1831 if (sfntfont_detect_sigbus (siginfo->si_addr))
1832 return;
1833
1834 handle_fatal_signal (sig);
1835}
1836
1837/* Try to set up SIGBUS handling for the sfnt font driver.
1838 Value is 1 upon failure, 0 otherwise. */
1839
1840static int
1841init_sigbus (void)
1842{
1843 struct sigaction sa;
1844
1845 sigfillset (&sa.sa_mask);
1846 sa.sa_sigaction = handle_sigbus;
1847 sa.sa_flags = SA_SIGINFO;
1848
1849 if (sigaction (SIGBUS, &sa, NULL))
1850 return 1;
1851
1852 return 0;
1853}
1854
1855#endif
1856
1819/* This does not work on Android and interferes with the system 1857/* This does not work on Android and interferes with the system
1820 tombstone generation. */ 1858 tombstone generation. */
1821 1859
@@ -2076,7 +2114,10 @@ init_signals (void)
2076 sigaction (SIGEMT, &thread_fatal_action, 0); 2114 sigaction (SIGEMT, &thread_fatal_action, 0);
2077#endif 2115#endif
2078#ifdef SIGBUS 2116#ifdef SIGBUS
2079 sigaction (SIGBUS, &thread_fatal_action, 0); 2117#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY && defined HAVE_MMAP
2118 if (init_sigbus ())
2119#endif
2120 sigaction (SIGBUS, &thread_fatal_action, 0);
2080#endif 2121#endif
2081#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY 2122#if !defined HAVE_ANDROID || defined ANDROID_STUBIFY
2082 if (!init_sigsegv ()) 2123 if (!init_sigsegv ())