summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2022-04-03 11:16:39 +0100
committerAidan MacDonald <amachronic@protonmail.com>2022-10-16 14:50:39 +0100
commit1718cf5f8a39b922eba3ad1b3c9a9570188362b1 (patch)
tree4f6bf81cb4f382ca04856b98492289825133c5ae
parentb16bae6fe624d30631bf83290e204197ab136c12 (diff)
downloadrockbox-1718cf5f8a39b922eba3ad1b3c9a9570188362b1.tar.gz
rockbox-1718cf5f8a39b922eba3ad1b3c9a9570188362b1.zip
Convert a number of allocations to use buflib pinning
Several places in the codebase implemented an ad-hoc form of pinning; they can be converted to use buflib pinning instead. Change-Id: I4450be007e80f6c9cc9f56c2929fa4b9b85ebff3
-rw-r--r--apps/gui/icon.c8
-rw-r--r--apps/gui/skin_engine/skin_backdrops.c14
-rw-r--r--apps/gui/skin_engine/skin_parser.c16
-rw-r--r--apps/tagcache.c13
-rw-r--r--apps/tagtree.c66
-rw-r--r--apps/tree.c15
-rw-r--r--apps/tree.h13
-rw-r--r--firmware/common/dircache.c60
-rw-r--r--firmware/common/unicode.c29
-rw-r--r--firmware/font.c16
10 files changed, 93 insertions, 157 deletions
diff --git a/apps/gui/icon.c b/apps/gui/icon.c
index 9fe7090f4a..e78aa6841c 100644
--- a/apps/gui/icon.c
+++ b/apps/gui/icon.c
@@ -63,7 +63,6 @@ static struct iconset {
63 struct bitmap bmp; 63 struct bitmap bmp;
64 bool loaded; 64 bool loaded;
65 int handle; 65 int handle;
66 int handle_locked;
67} iconsets[Iconset_Count][NB_SCREENS]; 66} iconsets[Iconset_Count][NB_SCREENS];
68 67
69#define ICON_HEIGHT(screen) (!iconsets[Iconset_user][screen].loaded ? \ 68#define ICON_HEIGHT(screen) (!iconsets[Iconset_user][screen].loaded ? \
@@ -160,8 +159,6 @@ static int buflib_move_callback(int handle, void* current, void* new)
160 struct iconset *set = &iconsets[i][j]; 159 struct iconset *set = &iconsets[i][j];
161 if (set->bmp.data == current) 160 if (set->bmp.data == current)
162 { 161 {
163 if (set->handle_locked > 0)
164 return BUFLIB_CB_CANNOT_MOVE;
165 set->bmp.data = new; 162 set->bmp.data = new;
166 return BUFLIB_CB_OK; 163 return BUFLIB_CB_OK;
167 } 164 }
@@ -201,11 +198,10 @@ static void load_icons(const char* filename, enum Iconset iconset,
201 goto finished; 198 goto finished;
202 } 199 }
203 lseek(fd, 0, SEEK_SET); 200 lseek(fd, 0, SEEK_SET);
201 core_pin(ic->handle);
204 ic->bmp.data = core_get_data(ic->handle); 202 ic->bmp.data = core_get_data(ic->handle);
205
206 ic->handle_locked = 1;
207 size_read = read_bmp_fd(fd, &ic->bmp, buf_size, bmpformat, NULL); 203 size_read = read_bmp_fd(fd, &ic->bmp, buf_size, bmpformat, NULL);
208 ic->handle_locked = 0; 204 core_unpin(ic->handle);
209 205
210 if (size_read < 0) 206 if (size_read < 0)
211 { 207 {
diff --git a/apps/gui/skin_engine/skin_backdrops.c b/apps/gui/skin_engine/skin_backdrops.c
index 1def0812da..215667d585 100644
--- a/apps/gui/skin_engine/skin_backdrops.c
+++ b/apps/gui/skin_engine/skin_backdrops.c
@@ -41,7 +41,6 @@ static struct skin_backdrop {
41} backdrops[NB_BDROPS]; 41} backdrops[NB_BDROPS];
42 42
43#define NB_BDROPS SKINNABLE_SCREENS_COUNT*NB_SCREENS 43#define NB_BDROPS SKINNABLE_SCREENS_COUNT*NB_SCREENS
44static int handle_being_loaded;
45static int current_lcd_backdrop[NB_SCREENS]; 44static int current_lcd_backdrop[NB_SCREENS];
46 45
47bool skin_backdrop_get_debug(int index, char **path, int *ref_count, size_t *size) 46bool skin_backdrop_get_debug(int index, char **path, int *ref_count, size_t *size)
@@ -65,8 +64,8 @@ bool skin_backdrop_get_debug(int index, char **path, int *ref_count, size_t *siz
65 64
66static int buflib_move_callback(int handle, void* current, void* new) 65static int buflib_move_callback(int handle, void* current, void* new)
67{ 66{
68 if (handle == handle_being_loaded) 67 (void)handle;
69 return BUFLIB_CB_CANNOT_MOVE; 68
70 for (int i=0; i<NB_BDROPS; i++) 69 for (int i=0; i<NB_BDROPS; i++)
71 { 70 {
72 if (backdrops[i].buffer == current) 71 if (backdrops[i].buffer == current)
@@ -96,7 +95,6 @@ bool skin_backdrop_init(void)
96 } 95 }
97 FOR_NB_SCREENS(i) 96 FOR_NB_SCREENS(i)
98 current_lcd_backdrop[i] = -1; 97 current_lcd_backdrop[i] = -1;
99 handle_being_loaded = -1;
100 first_go = false; 98 first_go = false;
101 } 99 }
102 return go_status; 100 return go_status;
@@ -182,16 +180,16 @@ bool skin_backdrops_preload(void)
182 backdrops[i].buffer = core_get_data(backdrops[i].buflib_handle); 180 backdrops[i].buffer = core_get_data(backdrops[i].buflib_handle);
183 if (strcmp(filename, BACKDROP_BUFFERNAME)) 181 if (strcmp(filename, BACKDROP_BUFFERNAME))
184 { 182 {
185 handle_being_loaded = backdrops[i].buflib_handle; 183 core_pin(backdrops[i].buflib_handle);
186 backdrops[i].loaded = 184 backdrops[i].loaded =
187 screens[screen].backdrop_load(filename, backdrops[i].buffer); 185 screens[screen].backdrop_load(filename, backdrops[i].buffer);
186 core_unpin(backdrops[i].buflib_handle);
188 if (!backdrops[i].loaded) 187 if (!backdrops[i].loaded)
189 { 188 {
190 core_free(backdrops[i].buflib_handle); 189 core_free(backdrops[i].buflib_handle);
191 backdrops[i].buflib_handle = -1; 190 backdrops[i].buflib_handle = -1;
192 retval = false; 191 retval = false;
193 } 192 }
194 handle_being_loaded = -1;
195 } 193 }
196 else 194 else
197 backdrops[i].loaded = true; 195 backdrops[i].loaded = true;
@@ -295,12 +293,12 @@ void skin_backdrop_load_setting(void)
295 return; 293 return;
296 } 294 }
297 bool loaded; 295 bool loaded;
296 core_pin(backdrops[i].buflib_handle);
298 backdrops[i].buffer = core_get_data(backdrops[i].buflib_handle); 297 backdrops[i].buffer = core_get_data(backdrops[i].buflib_handle);
299 handle_being_loaded = backdrops[i].buflib_handle;
300 loaded = screens[SCREEN_MAIN].backdrop_load( 298 loaded = screens[SCREEN_MAIN].backdrop_load(
301 global_settings.backdrop_file, 299 global_settings.backdrop_file,
302 backdrops[i].buffer); 300 backdrops[i].buffer);
303 handle_being_loaded = -1; 301 core_unpin(backdrops[i].buflib_handle);
304 backdrops[i].name[2] = loaded ? '.' : '\0'; 302 backdrops[i].name[2] = loaded ? '.' : '\0';
305 backdrops[i].loaded = loaded; 303 backdrops[i].loaded = loaded;
306 return; 304 return;
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index 047c4735a0..2eef2af7c0 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -1870,13 +1870,11 @@ static void skin_data_reset(struct wps_data *wps_data)
1870} 1870}
1871 1871
1872#ifndef __PCTOOL__ 1872#ifndef __PCTOOL__
1873static int currently_loading_handle = -1;
1874static int buflib_move_callback(int handle, void* current, void* new) 1873static int buflib_move_callback(int handle, void* current, void* new)
1875{ 1874{
1875 (void)handle;
1876 (void)current; 1876 (void)current;
1877 (void)new; 1877 (void)new;
1878 if (handle == currently_loading_handle)
1879 return BUFLIB_CB_CANNOT_MOVE;
1880 /* Any active skins may be scrolling - which means using viewports which 1878 /* Any active skins may be scrolling - which means using viewports which
1881 * will be moved after this callback returns. This is a hammer to make that 1879 * will be moved after this callback returns. This is a hammer to make that
1882 * safe. TODO: use a screwdriver instead. 1880 * safe. TODO: use a screwdriver instead.
@@ -1890,14 +1888,6 @@ static int buflib_move_callback(int handle, void* current, void* new)
1890 return BUFLIB_CB_OK; 1888 return BUFLIB_CB_OK;
1891} 1889}
1892static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL, NULL}; 1890static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL, NULL};
1893static void lock_handle(int handle)
1894{
1895 currently_loading_handle = handle;
1896}
1897static void unlock_handle(void)
1898{
1899 currently_loading_handle = -1;
1900}
1901#endif 1891#endif
1902 1892
1903static int load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char* bmpdir) 1893static int load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char* bmpdir)
@@ -1944,12 +1934,12 @@ static int load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char*
1944 _stats->buflib_handles++; 1934 _stats->buflib_handles++;
1945 _stats->images_size += buf_size; 1935 _stats->images_size += buf_size;
1946 lseek(fd, 0, SEEK_SET); 1936 lseek(fd, 0, SEEK_SET);
1947 lock_handle(handle); 1937 core_pin(handle);
1948 bitmap->data = core_get_data(handle); 1938 bitmap->data = core_get_data(handle);
1949 int ret = read_bmp_fd(fd, bitmap, buf_size, format, NULL); 1939 int ret = read_bmp_fd(fd, bitmap, buf_size, format, NULL);
1950 bitmap->data = NULL; /* do this to force a crash later if the 1940 bitmap->data = NULL; /* do this to force a crash later if the
1951 caller doesnt call core_get_data() */ 1941 caller doesnt call core_get_data() */
1952 unlock_handle(); 1942 core_unpin(handle);
1953 close(fd); 1943 close(fd);
1954 if (ret > 0) 1944 if (ret > 0)
1955 { 1945 {
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 8db1569379..b6c86d7ddb 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -277,17 +277,16 @@ static struct tcramcache
277{ 277{
278 struct ramcache_header *hdr; /* allocated ramcache_header */ 278 struct ramcache_header *hdr; /* allocated ramcache_header */
279 int handle; /* buffer handle */ 279 int handle; /* buffer handle */
280 int move_lock;
281} tcramcache; 280} tcramcache;
282 281
283static inline void tcrc_buffer_lock(void) 282static inline void tcrc_buffer_lock(void)
284{ 283{
285 tcramcache.move_lock++; 284 core_pin(tcramcache.handle);
286} 285}
287 286
288static inline void tcrc_buffer_unlock(void) 287static inline void tcrc_buffer_unlock(void)
289{ 288{
290 tcramcache.move_lock--; 289 core_unpin(tcramcache.handle);
291} 290}
292 291
293#else /* ndef HAVE_TC_RAMCACHE */ 292#else /* ndef HAVE_TC_RAMCACHE */
@@ -3861,10 +3860,9 @@ static bool delete_entry(long idx_id)
3861 struct tagfile_entry *tfe; 3860 struct tagfile_entry *tfe;
3862 int32_t *seek = &tcramcache.hdr->indices[idx_id].tag_seek[tag]; 3861 int32_t *seek = &tcramcache.hdr->indices[idx_id].tag_seek[tag];
3863 3862
3863 /* crc_32 is assumed not to yield (why would it...?) */
3864 tfe = (struct tagfile_entry *)&tcramcache.hdr->tags[tag][*seek]; 3864 tfe = (struct tagfile_entry *)&tcramcache.hdr->tags[tag][*seek];
3865 tcrc_buffer_lock(); /* protect tfe and seek if crc_32() yield()s */
3866 *seek = crc_32(tfe->tag_data, strlen(tfe->tag_data), 0xffffffff); 3865 *seek = crc_32(tfe->tag_data, strlen(tfe->tag_data), 0xffffffff);
3867 tcrc_buffer_unlock();
3868 myidx.tag_seek[tag] = *seek; 3866 myidx.tag_seek[tag] = *seek;
3869 } 3867 }
3870 else 3868 else
@@ -4005,9 +4003,6 @@ static void fix_ramcache(void* old_addr, void* new_addr)
4005static int move_cb(int handle, void* current, void* new) 4003static int move_cb(int handle, void* current, void* new)
4006{ 4004{
4007 (void)handle; 4005 (void)handle;
4008 if (tcramcache.move_lock > 0)
4009 return BUFLIB_CB_CANNOT_MOVE;
4010
4011 fix_ramcache(current, new); 4006 fix_ramcache(current, new);
4012 tcramcache.hdr = new; 4007 tcramcache.hdr = new;
4013 return BUFLIB_CB_OK; 4008 return BUFLIB_CB_OK;
@@ -4092,8 +4087,8 @@ static bool tagcache_dumpload(void)
4092 return false; 4087 return false;
4093 } 4088 }
4094 4089
4095 tcrc_buffer_lock();
4096 tcramcache.handle = handle; 4090 tcramcache.handle = handle;
4091 tcrc_buffer_lock();
4097 tcramcache.hdr = core_get_data(handle); 4092 tcramcache.hdr = core_get_data(handle);
4098 rc = read(fd, tcramcache.hdr, shdr.tc_stat.ramcache_allocated); 4093 rc = read(fd, tcramcache.hdr, shdr.tc_stat.ramcache_allocated);
4099 tcrc_buffer_unlock(); 4094 tcrc_buffer_unlock();
diff --git a/apps/tagtree.c b/apps/tagtree.c
index 39bc0ab37c..2ebab7949c 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -192,7 +192,7 @@ static int current_entry_count;
192static struct tree_context *tc; 192static struct tree_context *tc;
193 193
194/* a few memory alloc helper */ 194/* a few memory alloc helper */
195static int tagtree_handle, lock_count; 195static int tagtree_handle;
196static size_t tagtree_bufsize, tagtree_buf_used; 196static size_t tagtree_bufsize, tagtree_buf_used;
197 197
198#define UPDATE(x, y) { x = (typeof(x))((char*)(x) + (y)); } 198#define UPDATE(x, y) { x = (typeof(x))((char*)(x) + (y)); }
@@ -201,9 +201,6 @@ static int move_callback(int handle, void* current, void* new)
201 (void)handle; (void)current; (void)new; 201 (void)handle; (void)current; (void)new;
202 ptrdiff_t diff = new - current; 202 ptrdiff_t diff = new - current;
203 203
204 if (lock_count > 0)
205 return BUFLIB_CB_CANNOT_MOVE;
206
207 if (menu) 204 if (menu)
208 UPDATE(menu, diff); 205 UPDATE(menu, diff);
209 206
@@ -251,16 +248,6 @@ static int move_callback(int handle, void* current, void* new)
251} 248}
252#undef UPDATE 249#undef UPDATE
253 250
254static inline void tagtree_lock(void)
255{
256 lock_count++;
257}
258
259static inline void tagtree_unlock(void)
260{
261 lock_count--;
262}
263
264static struct buflib_callbacks ops = { 251static struct buflib_callbacks ops = {
265 .move_callback = move_callback, 252 .move_callback = move_callback,
266 .shrink_callback = NULL, 253 .shrink_callback = NULL,
@@ -623,7 +610,7 @@ static int add_format(const char *buf)
623 int clause_count = 0; 610 int clause_count = 0;
624 strp++; 611 strp++;
625 612
626 tagtree_lock(); 613 core_pin(tagtree_handle);
627 while (1) 614 while (1)
628 { 615 {
629 struct tagcache_search_clause *new_clause; 616 struct tagcache_search_clause *new_clause;
@@ -646,7 +633,7 @@ static int add_format(const char *buf)
646 633
647 clause_count++; 634 clause_count++;
648 } 635 }
649 tagtree_unlock(); 636 core_unpin(tagtree_handle);
650 637
651 formats[format_count]->clause_count = clause_count; 638 formats[format_count]->clause_count = clause_count;
652 } 639 }
@@ -719,9 +706,9 @@ static int get_condition(struct search_instruction *inst)
719 } 706 }
720 else 707 else
721 { 708 {
722 tagtree_lock(); 709 core_pin(tagtree_handle);
723 bool ret = read_clause(new_clause); 710 bool ret = read_clause(new_clause);
724 tagtree_unlock(); 711 core_unpin(tagtree_handle);
725 if (!ret) 712 if (!ret)
726 return -1; 713 return -1;
727 } 714 }
@@ -812,9 +799,9 @@ static bool parse_search(struct menu_entry *entry, const char *str)
812 799
813 logf("tag: %d", inst->tagorder[inst->tagorder_count]); 800 logf("tag: %d", inst->tagorder[inst->tagorder_count]);
814 801
815 tagtree_lock(); 802 core_pin(tagtree_handle);
816 while ( (ret = get_condition(inst)) > 0 ) ; 803 while ( (ret = get_condition(inst)) > 0 ) ;
817 tagtree_unlock(); 804 core_unpin(tagtree_handle);
818 805
819 if (ret < 0) 806 if (ret < 0)
820 return false; 807 return false;
@@ -1176,10 +1163,10 @@ static int parse_line(int n, char *buf, void *parameters)
1176 logf("tagtree failed to allocate %s", "menu items"); 1163 logf("tagtree failed to allocate %s", "menu items");
1177 return -2; 1164 return -2;
1178 } 1165 }
1179 tagtree_lock(); 1166 core_pin(tagtree_handle);
1180 if (parse_search(menu->items[menu->itemcount], buf)) 1167 if (parse_search(menu->items[menu->itemcount], buf))
1181 menu->itemcount++; 1168 menu->itemcount++;
1182 tagtree_unlock(); 1169 core_unpin(tagtree_handle);
1183 1170
1184 return 0; 1171 return 0;
1185} 1172}
@@ -1212,8 +1199,8 @@ static bool parse_menu(const char *filename)
1212 1199
1213static void tagtree_unload(struct tree_context *c) 1200static void tagtree_unload(struct tree_context *c)
1214{ 1201{
1215 int i; 1202 /* may be spurious... */
1216 tagtree_lock(); 1203 core_pin(tagtree_handle);
1217 1204
1218 remove_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event); 1205 remove_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event);
1219 remove_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event); 1206 remove_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event);
@@ -1229,7 +1216,7 @@ static void tagtree_unload(struct tree_context *c)
1229 return; 1216 return;
1230 } 1217 }
1231 1218
1232 for (i = 0; i < menu->itemcount; i++) 1219 for (int i = 0; i < menu->itemcount; i++)
1233 { 1220 {
1234 dptr->name = NULL; 1221 dptr->name = NULL;
1235 dptr->newtable = 0; 1222 dptr->newtable = 0;
@@ -1238,11 +1225,11 @@ static void tagtree_unload(struct tree_context *c)
1238 } 1225 }
1239 } 1226 }
1240 1227
1241 for (i = 0; i < menu_count; i++) 1228 for (int i = 0; i < menu_count; i++)
1242 menus[i] = NULL; 1229 menus[i] = NULL;
1243 menu_count = 0; 1230 menu_count = 0;
1244 1231
1245 for (i = 0; i < format_count; i++) 1232 for (int i = 0; i < format_count; i++)
1246 formats[i] = NULL; 1233 formats[i] = NULL;
1247 format_count = 0; 1234 format_count = 0;
1248 1235
@@ -1253,9 +1240,6 @@ static void tagtree_unload(struct tree_context *c)
1253 1240
1254 if (c) 1241 if (c)
1255 tree_unlock_cache(c); 1242 tree_unlock_cache(c);
1256 tagtree_unlock();
1257 if (lock_count > 0)
1258 tagtree_unlock();/* second unlock to enable re-init */
1259} 1243}
1260 1244
1261void tagtree_init(void) 1245void tagtree_init(void)
@@ -1285,8 +1269,6 @@ void tagtree_init(void)
1285 if (sizeof(struct tagentry) != sizeof(struct entry)) 1269 if (sizeof(struct tagentry) != sizeof(struct entry))
1286 panicf("tagentry(%zu) and entry mismatch(%zu)", 1270 panicf("tagentry(%zu) and entry mismatch(%zu)",
1287 sizeof(struct tagentry), sizeof(struct entry)); 1271 sizeof(struct tagentry), sizeof(struct entry));
1288 if (lock_count > 0)
1289 panicf("tagtree locked after parsing");
1290 1272
1291 /* If no root menu is set, assume it's the first single menu 1273 /* If no root menu is set, assume it's the first single menu
1292 * we have. That shouldn't normally happen. */ 1274 * we have. That shouldn't normally happen. */
@@ -1502,7 +1484,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
1502 1484
1503 /* because tagcache saves the clauses, we need to lock the buffer 1485 /* because tagcache saves the clauses, we need to lock the buffer
1504 * for the entire duration of the search */ 1486 * for the entire duration of the search */
1505 tagtree_lock(); 1487 core_pin(tagtree_handle);
1506 for (i = 0; i <= level; i++) 1488 for (i = 0; i <= level; i++)
1507 { 1489 {
1508 int j; 1490 int j;
@@ -1579,7 +1561,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
1579 1561
1580 fmt = NULL; 1562 fmt = NULL;
1581 /* Check the format */ 1563 /* Check the format */
1582 tagtree_lock(); 1564 core_pin(tagtree_handle);
1583 for (i = 0; i < format_count; i++) 1565 for (i = 0; i < format_count; i++)
1584 { 1566 {
1585 if (formats[i]->group_id != csi->format_id[level]) 1567 if (formats[i]->group_id != csi->format_id[level])
@@ -1592,7 +1574,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
1592 break; 1574 break;
1593 } 1575 }
1594 } 1576 }
1595 tagtree_unlock(); 1577 core_unpin(tagtree_handle);
1596 1578
1597 if (strcmp(tcs.result, UNTAGGED) == 0) 1579 if (strcmp(tcs.result, UNTAGGED) == 0)
1598 { 1580 {
@@ -1634,7 +1616,7 @@ static int retrieve_entries(struct tree_context *c, int offset, bool init)
1634 logf("format_str() failed"); 1616 logf("format_str() failed");
1635 tagcache_search_finish(&tcs); 1617 tagcache_search_finish(&tcs);
1636 tree_unlock_cache(c); 1618 tree_unlock_cache(c);
1637 tagtree_unlock(); 1619 core_unpin(tagtree_handle);
1638 return 0; 1620 return 0;
1639 } 1621 }
1640 else 1622 else
@@ -1675,7 +1657,7 @@ entry_skip_formatter:
1675 { /* user aborted */ 1657 { /* user aborted */
1676 tagcache_search_finish(&tcs); 1658 tagcache_search_finish(&tcs);
1677 tree_unlock_cache(c); 1659 tree_unlock_cache(c);
1678 tagtree_unlock(); 1660 core_unpin(tagtree_handle);
1679 return current_entry_count; 1661 return current_entry_count;
1680 } 1662 }
1681 } 1663 }
@@ -1694,7 +1676,7 @@ entry_skip_formatter:
1694 { 1676 {
1695 tagcache_search_finish(&tcs); 1677 tagcache_search_finish(&tcs);
1696 tree_unlock_cache(c); 1678 tree_unlock_cache(c);
1697 tagtree_unlock(); 1679 core_unpin(tagtree_handle);
1698 return current_entry_count; 1680 return current_entry_count;
1699 } 1681 }
1700 1682
@@ -1710,7 +1692,7 @@ entry_skip_formatter:
1710 1692
1711 tagcache_search_finish(&tcs); 1693 tagcache_search_finish(&tcs);
1712 tree_unlock_cache(c); 1694 tree_unlock_cache(c);
1713 tagtree_unlock(); 1695 core_unpin(tagtree_handle);
1714 1696
1715 if (!sort && (sort_inverse || sort_limit)) 1697 if (!sort && (sort_inverse || sort_limit))
1716 { 1698 {
@@ -1870,7 +1852,7 @@ int tagtree_enter(struct tree_context* c)
1870 1852
1871 /* lock buflib for possible I/O to protect dptr */ 1853 /* lock buflib for possible I/O to protect dptr */
1872 tree_lock_cache(c); 1854 tree_lock_cache(c);
1873 tagtree_lock(); 1855 core_pin(tagtree_handle);
1874 1856
1875 bool reset_selection = true; 1857 bool reset_selection = true;
1876 1858
@@ -1940,7 +1922,7 @@ int tagtree_enter(struct tree_context* c)
1940 { 1922 {
1941 tagtree_exit(c); 1923 tagtree_exit(c);
1942 tree_unlock_cache(c); 1924 tree_unlock_cache(c);
1943 tagtree_unlock(); 1925 core_unpin(tagtree_handle);
1944 return 0; 1926 return 0;
1945 } 1927 }
1946 if (csi->clause[i][j]->numeric) 1928 if (csi->clause[i][j]->numeric)
@@ -1999,7 +1981,7 @@ int tagtree_enter(struct tree_context* c)
1999 } 1981 }
2000 1982
2001 tree_unlock_cache(c); 1983 tree_unlock_cache(c);
2002 tagtree_unlock(); 1984 core_unpin(tagtree_handle);
2003 1985
2004 return rc; 1986 return rc;
2005} 1987}
diff --git a/apps/tree.c b/apps/tree.c
index a034fd0545..6622e1c4c2 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -314,6 +314,18 @@ struct tree_context* tree_get_context(void)
314 return &tc; 314 return &tc;
315} 315}
316 316
317void tree_lock_cache(struct tree_context *t)
318{
319 core_pin(t->cache.name_buffer_handle);
320 core_pin(t->cache.entries_handle);
321}
322
323void tree_unlock_cache(struct tree_context *t)
324{
325 core_unpin(t->cache.name_buffer_handle);
326 core_unpin(t->cache.entries_handle);
327}
328
317/* 329/*
318 * Returns the position of a given file in the current directory 330 * Returns the position of a given file in the current directory
319 * returns -1 if not found 331 * returns -1 if not found
@@ -1020,9 +1032,6 @@ int rockbox_browse(struct browse_context *browse)
1020static int move_callback(int handle, void* current, void* new) 1032static int move_callback(int handle, void* current, void* new)
1021{ 1033{
1022 struct tree_cache* cache = &tc.cache; 1034 struct tree_cache* cache = &tc.cache;
1023 if (cache->lock_count > 0)
1024 return BUFLIB_CB_CANNOT_MOVE;
1025
1026 ptrdiff_t diff = new - current; 1035 ptrdiff_t diff = new - current;
1027 /* FIX_PTR makes sure to not accidentally update static allocations */ 1036 /* FIX_PTR makes sure to not accidentally update static allocations */
1028#define FIX_PTR(x) \ 1037#define FIX_PTR(x) \
diff --git a/apps/tree.h b/apps/tree.h
index c70ae8dac1..a75e8d2260 100644
--- a/apps/tree.h
+++ b/apps/tree.h
@@ -52,7 +52,6 @@ struct tree_cache {
52 int name_buffer_handle; /* handle to the name cache */ 52 int name_buffer_handle; /* handle to the name cache */
53 int max_entries; /* Max entries in the cache */ 53 int max_entries; /* Max entries in the cache */
54 int name_buffer_size; /* in bytes */ 54 int name_buffer_size; /* in bytes */
55 volatile int lock_count; /* non-0 if buffers may not move */
56}; 55};
57 56
58struct browse_context { 57struct browse_context {
@@ -120,14 +119,10 @@ void browse_context_init(struct browse_context *browse,
120int rockbox_browse(struct browse_context *browse); 119int rockbox_browse(struct browse_context *browse);
121int create_playlist(void); 120int create_playlist(void);
122void resume_directory(const char *dir); 121void resume_directory(const char *dir);
123static inline void tree_lock_cache(struct tree_context *t) 122
124{ 123void tree_lock_cache(struct tree_context *t);
125 t->cache.lock_count++; 124void tree_unlock_cache(struct tree_context *t);
126} 125
127static inline void tree_unlock_cache(struct tree_context *t)
128{
129 t->cache.lock_count--;
130}
131#ifdef WIN32 126#ifdef WIN32
132/* it takes an int on windows */ 127/* it takes an int on windows */
133#define getcwd_size_t int 128#define getcwd_size_t int
diff --git a/firmware/common/dircache.c b/firmware/common/dircache.c
index 8917b3348e..1d6371a6b5 100644
--- a/firmware/common/dircache.c
+++ b/firmware/common/dircache.c
@@ -249,7 +249,6 @@ static struct dircache_runinfo
249 /* cache buffer info */ 249 /* cache buffer info */
250 int handle; /* buflib buffer handle */ 250 int handle; /* buflib buffer handle */
251 size_t bufsize; /* size of buflib allocation - 1 */ 251 size_t bufsize; /* size of buflib allocation - 1 */
252 int buflocked; /* don't move due to other allocs */
253 union { 252 union {
254 void *p; /* address of buffer - ENTRYSIZE */ 253 void *p; /* address of buffer - ENTRYSIZE */
255 struct dircache_entry *pentry; /* alias of .p to assist entry resolution */ 254 struct dircache_entry *pentry; /* alias of .p to assist entry resolution */
@@ -329,29 +328,9 @@ static inline void dumpster_clean_buffer(void *p, size_t size)
329 */ 328 */
330static int move_callback(int handle, void *current, void *new) 329static int move_callback(int handle, void *current, void *new)
331{ 330{
332 if (dircache_runinfo.buflocked) 331 (void)handle; (void)current;
333 return BUFLIB_CB_CANNOT_MOVE;
334
335 dircache_runinfo.p = new - ENTRYSIZE; 332 dircache_runinfo.p = new - ENTRYSIZE;
336
337 return BUFLIB_CB_OK; 333 return BUFLIB_CB_OK;
338 (void)handle; (void)current;
339}
340
341/**
342 * add a "don't move" lock count
343 */
344static inline void buffer_lock(void)
345{
346 dircache_runinfo.buflocked++;
347}
348
349/**
350 * remove a "don't move" lock count
351 */
352static inline void buffer_unlock(void)
353{
354 dircache_runinfo.buflocked--;
355} 334}
356 335
357 336
@@ -530,14 +509,14 @@ static void set_buffer(int handle, size_t size)
530 509
531/** 510/**
532 * remove the allocation from dircache control and return the handle 511 * remove the allocation from dircache control and return the handle
512 * Note that dircache must not be using the buffer!
533 */ 513 */
534static int reset_buffer(void) 514static int reset_buffer(void)
535{ 515{
536 int handle = dircache_runinfo.handle; 516 int handle = dircache_runinfo.handle;
537 if (handle > 0) 517 if (handle > 0)
538 { 518 {
539 /* don't mind .p; it might get changed by the callback even after 519 /* don't mind .p; buffer presence is determined by the following: */
540 this call; buffer presence is determined by the following: */
541 dircache_runinfo.handle = 0; 520 dircache_runinfo.handle = 0;
542 dircache_runinfo.bufsize = 0; 521 dircache_runinfo.bufsize = 0;
543 } 522 }
@@ -1857,7 +1836,7 @@ static void reset_cache(void)
1857 */ 1836 */
1858static void build_volumes(void) 1837static void build_volumes(void)
1859{ 1838{
1860 buffer_lock(); 1839 core_pin(dircache_runinfo.handle);
1861 1840
1862 for (int i = 0; i < NUM_VOLUMES; i++) 1841 for (int i = 0; i < NUM_VOLUMES; i++)
1863 { 1842 {
@@ -1903,12 +1882,14 @@ static void build_volumes(void)
1903 1882
1904 logf("Done, %ld KiB used", dircache.size / 1024); 1883 logf("Done, %ld KiB used", dircache.size / 1024);
1905 1884
1906 buffer_unlock(); 1885 core_unpin(dircache_runinfo.handle);
1907} 1886}
1908 1887
1909/** 1888/**
1910 * allocate buffer and return whether or not a synchronous build should take 1889 * allocate buffer and return whether or not a synchronous build should take
1911 * place; if 'realloced' is NULL, it's just a query about what will happen 1890 * place; if 'realloced' is NULL, it's just a query about what will happen
1891 *
1892 * Note this must be called with the dircache_lock() active.
1912 */ 1893 */
1913static int prepare_build(bool *realloced) 1894static int prepare_build(bool *realloced)
1914{ 1895{
@@ -1958,16 +1939,14 @@ static int prepare_build(bool *realloced)
1958 *realloced = true; 1939 *realloced = true;
1959 reset_cache(); 1940 reset_cache();
1960 1941
1961 buffer_lock();
1962
1963 int handle = reset_buffer(); 1942 int handle = reset_buffer();
1964 dircache_unlock(); 1943 dircache_unlock(); /* release lock held by caller */
1965 1944
1966 core_free(handle); 1945 core_free(handle);
1967 1946
1968 handle = alloc_cache(size); 1947 handle = alloc_cache(size);
1969 1948
1970 dircache_lock(); 1949 dircache_lock(); /* reacquire lock */
1971 1950
1972 if (dircache_runinfo.suspended && handle > 0) 1951 if (dircache_runinfo.suspended && handle > 0)
1973 { 1952 {
@@ -1979,13 +1958,9 @@ static int prepare_build(bool *realloced)
1979 } 1958 }
1980 1959
1981 if (handle <= 0) 1960 if (handle <= 0)
1982 {
1983 buffer_unlock();
1984 return -1; 1961 return -1;
1985 }
1986 1962
1987 set_buffer(handle, size); 1963 set_buffer(handle, size);
1988 buffer_unlock();
1989 1964
1990 return syncbuild; 1965 return syncbuild;
1991} 1966}
@@ -2384,9 +2359,9 @@ void dircache_fileop_create(struct file_base_info *dirinfop,
2384 if ((dinp->attr & ATTR_DIRECTORY) && !is_dotdir_name(basename)) 2359 if ((dinp->attr & ATTR_DIRECTORY) && !is_dotdir_name(basename))
2385 { 2360 {
2386 /* scan-in the contents of the new directory at this level only */ 2361 /* scan-in the contents of the new directory at this level only */
2387 buffer_lock(); 2362 core_pin(dircache_runinfo.handle);
2388 sab_process_dir(infop, false); 2363 sab_process_dir(infop, false);
2389 buffer_unlock(); 2364 core_unpin(dircache_runinfo.handle);
2390 } 2365 }
2391} 2366}
2392 2367
@@ -2915,7 +2890,7 @@ void dircache_dump(void)
2915 2890
2916 if (dircache_runinfo.handle) 2891 if (dircache_runinfo.handle)
2917 { 2892 {
2918 buffer_lock(); 2893 core_pin(dircache_runinfo.handle);
2919 2894
2920 /* bin */ 2895 /* bin */
2921 write(fdbin, dircache_runinfo.p + ENTRYSIZE, 2896 write(fdbin, dircache_runinfo.p + ENTRYSIZE,
@@ -2985,7 +2960,7 @@ void dircache_dump(void)
2985 tm.tm_hour, tm.tm_min, tm.tm_sec); 2960 tm.tm_hour, tm.tm_min, tm.tm_sec);
2986 } 2961 }
2987 2962
2988 buffer_unlock(); 2963 core_unpin(dircache_runinfo.handle);
2989 } 2964 }
2990 2965
2991 dircache_unlock(); 2966 dircache_unlock();
@@ -3104,7 +3079,6 @@ int dircache_load(void)
3104 } 3079 }
3105 3080
3106 dircache_lock(); 3081 dircache_lock();
3107 buffer_lock();
3108 3082
3109 if (!dircache_is_clean(false)) 3083 if (!dircache_is_clean(false))
3110 goto error; 3084 goto error;
@@ -3113,6 +3087,7 @@ int dircache_load(void)
3113 dircache = maindata.dircache; 3087 dircache = maindata.dircache;
3114 3088
3115 set_buffer(handle, bufsize); 3089 set_buffer(handle, bufsize);
3090 core_pin(handle);
3116 hasbuffer = true; 3091 hasbuffer = true;
3117 3092
3118 /* convert back to in-RAM representation */ 3093 /* convert back to in-RAM representation */
@@ -3167,13 +3142,13 @@ int dircache_load(void)
3167 dircache_enable_internal(false); 3142 dircache_enable_internal(false);
3168 3143
3169 /* cache successfully loaded */ 3144 /* cache successfully loaded */
3145 core_unpin(handle);
3170 logf("Done, %ld KiB used", dircache.size / 1024); 3146 logf("Done, %ld KiB used", dircache.size / 1024);
3171 rc = 0; 3147 rc = 0;
3172error: 3148error:
3173 if (rc < 0 && hasbuffer) 3149 if (rc < 0 && hasbuffer)
3174 reset_buffer(); 3150 reset_buffer();
3175 3151
3176 buffer_unlock();
3177 dircache_unlock(); 3152 dircache_unlock();
3178 3153
3179error_nolock: 3154error_nolock:
@@ -3199,8 +3174,9 @@ int dircache_save(void)
3199 if (fd < 0) 3174 if (fd < 0)
3200 return -1; 3175 return -1;
3201 3176
3177 /* it seems the handle *must* exist if this function is called */
3202 dircache_lock(); 3178 dircache_lock();
3203 buffer_lock(); 3179 core_pin(dircache_runinfo.handle);
3204 3180
3205 int rc = -1; 3181 int rc = -1;
3206 3182
@@ -3269,7 +3245,7 @@ int dircache_save(void)
3269 that makes what was saved completely invalid */ 3245 that makes what was saved completely invalid */
3270 rc = 0; 3246 rc = 0;
3271error: 3247error:
3272 buffer_unlock(); 3248 core_unpin(dircache_runinfo.handle);
3273 dircache_unlock(); 3249 dircache_unlock();
3274 3250
3275 if (rc < 0) 3251 if (rc < 0)
diff --git a/firmware/common/unicode.c b/firmware/common/unicode.c
index f0f663f712..e53ad6bcb0 100644
--- a/firmware/common/unicode.c
+++ b/firmware/common/unicode.c
@@ -168,6 +168,10 @@ static unsigned short default_cp_table_buf[MAX_CP_TABLE_SIZE+1];
168 do {} while (0) 168 do {} while (0)
169#define cp_table_alloc(filename, size, opsp) \ 169#define cp_table_alloc(filename, size, opsp) \
170 ({ (void)(opsp); 1; }) 170 ({ (void)(opsp); 1; })
171#define cp_table_pin(handle) \
172 do { (void)handle; } while(0)
173#define cp_table_unpin(handle) \
174 do { (void)handle; } while(0)
171#else 175#else
172#define cp_table_alloc(filename, size, opsp) \ 176#define cp_table_alloc(filename, size, opsp) \
173 core_alloc_ex((filename), (size), (opsp)) 177 core_alloc_ex((filename), (size), (opsp))
@@ -175,6 +179,10 @@ static unsigned short default_cp_table_buf[MAX_CP_TABLE_SIZE+1];
175 core_free(handle) 179 core_free(handle)
176#define cp_table_get_data(handle) \ 180#define cp_table_get_data(handle) \
177 core_get_data(handle) 181 core_get_data(handle)
182#define cp_table_pin(handle) \
183 core_pin(handle)
184#define cp_table_unpin(handle) \
185 core_unpin(handle)
178#endif 186#endif
179 187
180static const unsigned char utf8comp[6] = 188static const unsigned char utf8comp[6] =
@@ -191,21 +199,8 @@ static inline void cptable_tohw16(uint16_t *buf, unsigned int count)
191 (void)buf; (void)count; 199 (void)buf; (void)count;
192} 200}
193 201
194static int move_callback(int handle, void *current, void *new)
195{
196 /* we don't keep a pointer but we have to stop it if this applies to a
197 buffer not yet swapped-in since it will likely be in use in an I/O
198 call */
199 return (handle != default_cp_handle || default_cp_table_ref != 0) ?
200 BUFLIB_CB_CANNOT_MOVE : BUFLIB_CB_OK;
201 (void)current; (void)new;
202}
203
204static int alloc_and_load_cp_table(int cp, void *buf) 202static int alloc_and_load_cp_table(int cp, void *buf)
205{ 203{
206 static struct buflib_callbacks ops =
207 { .move_callback = move_callback };
208
209 /* alloc and read only if there is an associated file */ 204 /* alloc and read only if there is an associated file */
210 const char *filename = cp_info[cp].filename; 205 const char *filename = cp_info[cp].filename;
211 if (!filename) 206 if (!filename)
@@ -228,13 +223,17 @@ static int alloc_and_load_cp_table(int cp, void *buf)
228 !(size % (off_t)sizeof (uint16_t))) { 223 !(size % (off_t)sizeof (uint16_t))) {
229 224
230 /* if the buffer is provided, use that but don't alloc */ 225 /* if the buffer is provided, use that but don't alloc */
231 int handle = buf ? 0 : cp_table_alloc(filename, size, &ops); 226 int handle = buf ? 0 : cp_table_alloc(filename, size, NULL);
232 if (handle > 0) 227 if (handle > 0) {
228 cp_table_pin(handle);
233 buf = cp_table_get_data(handle); 229 buf = cp_table_get_data(handle);
230 }
234 231
235 if (buf && read(fd, buf, size) == size) { 232 if (buf && read(fd, buf, size) == size) {
236 close(fd); 233 close(fd);
237 cptable_tohw16(buf, size / sizeof (uint16_t)); 234 cptable_tohw16(buf, size / sizeof (uint16_t));
235 if (handle > 0)
236 cp_table_unpin(handle);
238 return handle; 237 return handle;
239 } 238 }
240 239
diff --git a/firmware/font.c b/firmware/font.c
index 724cb84d57..7ce64ed47d 100644
--- a/firmware/font.c
+++ b/firmware/font.c
@@ -90,7 +90,6 @@ extern struct font sysfont;
90 90
91struct buflib_alloc_data { 91struct buflib_alloc_data {
92 struct font font; /* must be the first member! */ 92 struct font font; /* must be the first member! */
93 int handle_locks; /* is the buflib handle currently locked? */
94 int refcount; /* how many times has this font been loaded? */ 93 int refcount; /* how many times has this font been loaded? */
95 unsigned char buffer[]; 94 unsigned char buffer[];
96}; 95};
@@ -107,9 +106,6 @@ static int buflibmove_callback(int handle, void* current, void* new)
107 struct buflib_alloc_data *alloc = (struct buflib_alloc_data*)current; 106 struct buflib_alloc_data *alloc = (struct buflib_alloc_data*)current;
108 ptrdiff_t diff = new - current; 107 ptrdiff_t diff = new - current;
109 108
110 if (alloc->handle_locks > 0)
111 return BUFLIB_CB_CANNOT_MOVE;
112
113#define UPDATE(x) if (x) { x = PTR_ADD(x, diff); } 109#define UPDATE(x) if (x) { x = PTR_ADD(x, diff); }
114 110
115 UPDATE(alloc->font.bits); 111 UPDATE(alloc->font.bits);
@@ -129,18 +125,18 @@ static void lock_font_handle(int handle, bool lock)
129{ 125{
130 if ( handle < 0 ) 126 if ( handle < 0 )
131 return; 127 return;
132 struct buflib_alloc_data *alloc = core_get_data(handle); 128
133 if ( lock ) 129 if (lock)
134 alloc->handle_locks++; 130 core_pin(handle);
135 else 131 else
136 alloc->handle_locks--; 132 core_unpin(handle);
137} 133}
138 134
139void font_lock(int font_id, bool lock) 135void font_lock(int font_id, bool lock)
140{ 136{
141 if( font_id < 0 || font_id >= MAXFONTS ) 137 if( font_id < 0 || font_id >= MAXFONTS )
142 return; 138 return;
143 if( buflib_allocations[font_id] >= 0 ) 139 if( buflib_allocations[font_id] > 0 )
144 lock_font_handle(buflib_allocations[font_id], lock); 140 lock_font_handle(buflib_allocations[font_id], lock);
145} 141}
146 142
@@ -522,8 +518,8 @@ int font_load_ex( const char *path, size_t buf_size, int glyphs )
522 return -1; 518 return -1;
523 } 519 }
524 struct buflib_alloc_data *pdata; 520 struct buflib_alloc_data *pdata;
521 core_pin(handle);
525 pdata = core_get_data(handle); 522 pdata = core_get_data(handle);
526 pdata->handle_locks = 1;
527 pdata->refcount = 1; 523 pdata->refcount = 1;
528 524
529 /* load and init */ 525 /* load and init */