diff options
author | Andrew Mahone <andrew.mahone@gmail.com> | 2009-05-15 00:14:38 +0000 |
---|---|---|
committer | Andrew Mahone <andrew.mahone@gmail.com> | 2009-05-15 00:14:38 +0000 |
commit | 216424a27ffd8ce5efe93d02ff29d13d3fe92d5d (patch) | |
tree | e4a20b56f3fa7c9bcf2e9fce7fdf7cff612bd5a2 /apps/buffering.c | |
parent | 1775866fd38ca85faea879d4c71080b5be329bd5 (diff) | |
download | rockbox-216424a27ffd8ce5efe93d02ff29d13d3fe92d5d.tar.gz rockbox-216424a27ffd8ce5efe93d02ff29d13d3fe92d5d.zip |
Fix the lock contention stall during cover art load, by adding a separate modify mutex for the buffer. Operations that modify contents of a buffer entry can still proceed, but ones that add or remove buffer entries, or move them
in memory, will still block. Some members of struct memory_handle also need an earlier init in bufopen to make sure that buffer stats aren't trashed.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20932 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/buffering.c')
-rw-r--r-- | apps/buffering.c | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/apps/buffering.c b/apps/buffering.c index 3bcd790c35..4f2ec324de 100644 --- a/apps/buffering.c +++ b/apps/buffering.c | |||
@@ -144,6 +144,7 @@ static int num_handles; /* number of handles in the list */ | |||
144 | static int base_handle_id; | 144 | static int base_handle_id; |
145 | 145 | ||
146 | static struct mutex llist_mutex; | 146 | static struct mutex llist_mutex; |
147 | static struct mutex llist_mod_mutex; | ||
147 | 148 | ||
148 | /* Handle cache (makes find_handle faster). | 149 | /* Handle cache (makes find_handle faster). |
149 | This is global so that move_handle and rm_handle can invalidate it. */ | 150 | This is global so that move_handle and rm_handle can invalidate it. */ |
@@ -229,6 +230,7 @@ static struct memory_handle *add_handle(size_t data_size, bool can_wrap, | |||
229 | return NULL; | 230 | return NULL; |
230 | 231 | ||
231 | mutex_lock(&llist_mutex); | 232 | mutex_lock(&llist_mutex); |
233 | mutex_lock(&llist_mod_mutex); | ||
232 | 234 | ||
233 | if (cur_handle && cur_handle->filerem > 0) { | 235 | if (cur_handle && cur_handle->filerem > 0) { |
234 | /* the current handle hasn't finished buffering. We can only add | 236 | /* the current handle hasn't finished buffering. We can only add |
@@ -237,6 +239,7 @@ static struct memory_handle *add_handle(size_t data_size, bool can_wrap, | |||
237 | size_t req = cur_handle->filerem + sizeof(struct memory_handle); | 239 | size_t req = cur_handle->filerem + sizeof(struct memory_handle); |
238 | if (RINGBUF_ADD_CROSS(cur_handle->widx, req, buf_ridx) >= 0) { | 240 | if (RINGBUF_ADD_CROSS(cur_handle->widx, req, buf_ridx) >= 0) { |
239 | /* Not enough space */ | 241 | /* Not enough space */ |
242 | mutex_unlock(&llist_mod_mutex); | ||
240 | mutex_unlock(&llist_mutex); | 243 | mutex_unlock(&llist_mutex); |
241 | return NULL; | 244 | return NULL; |
242 | } else { | 245 | } else { |
@@ -265,6 +268,7 @@ static struct memory_handle *add_handle(size_t data_size, bool can_wrap, | |||
265 | overlap = RINGBUF_ADD_CROSS(buf_widx, shift + len, buf_ridx); | 268 | overlap = RINGBUF_ADD_CROSS(buf_widx, shift + len, buf_ridx); |
266 | if (overlap >= 0 && (alloc_all || (unsigned)overlap > data_size)) { | 269 | if (overlap >= 0 && (alloc_all || (unsigned)overlap > data_size)) { |
267 | /* Not enough space for required allocations */ | 270 | /* Not enough space for required allocations */ |
271 | mutex_unlock(&llist_mod_mutex); | ||
268 | mutex_unlock(&llist_mutex); | 272 | mutex_unlock(&llist_mutex); |
269 | return NULL; | 273 | return NULL; |
270 | } | 274 | } |
@@ -294,6 +298,7 @@ static struct memory_handle *add_handle(size_t data_size, bool can_wrap, | |||
294 | 298 | ||
295 | cur_handle = new_handle; | 299 | cur_handle = new_handle; |
296 | 300 | ||
301 | mutex_unlock(&llist_mod_mutex); | ||
297 | mutex_unlock(&llist_mutex); | 302 | mutex_unlock(&llist_mutex); |
298 | return new_handle; | 303 | return new_handle; |
299 | } | 304 | } |
@@ -306,6 +311,7 @@ static bool rm_handle(const struct memory_handle *h) | |||
306 | return true; | 311 | return true; |
307 | 312 | ||
308 | mutex_lock(&llist_mutex); | 313 | mutex_lock(&llist_mutex); |
314 | mutex_lock(&llist_mod_mutex); | ||
309 | 315 | ||
310 | if (h == first_handle) { | 316 | if (h == first_handle) { |
311 | first_handle = h->next; | 317 | first_handle = h->next; |
@@ -330,6 +336,7 @@ static bool rm_handle(const struct memory_handle *h) | |||
330 | buf_widx = cur_handle->widx; | 336 | buf_widx = cur_handle->widx; |
331 | } | 337 | } |
332 | } else { | 338 | } else { |
339 | mutex_unlock(&llist_mod_mutex); | ||
333 | mutex_unlock(&llist_mutex); | 340 | mutex_unlock(&llist_mutex); |
334 | return false; | 341 | return false; |
335 | } | 342 | } |
@@ -341,6 +348,7 @@ static bool rm_handle(const struct memory_handle *h) | |||
341 | 348 | ||
342 | num_handles--; | 349 | num_handles--; |
343 | 350 | ||
351 | mutex_unlock(&llist_mod_mutex); | ||
344 | mutex_unlock(&llist_mutex); | 352 | mutex_unlock(&llist_mutex); |
345 | return true; | 353 | return true; |
346 | } | 354 | } |
@@ -413,6 +421,7 @@ static bool move_handle(struct memory_handle **h, size_t *delta, | |||
413 | } | 421 | } |
414 | 422 | ||
415 | mutex_lock(&llist_mutex); | 423 | mutex_lock(&llist_mutex); |
424 | mutex_lock(&llist_mod_mutex); | ||
416 | 425 | ||
417 | newpos = RINGBUF_ADD((void *)src - (void *)buffer, final_delta); | 426 | newpos = RINGBUF_ADD((void *)src - (void *)buffer, final_delta); |
418 | overlap = RINGBUF_ADD_CROSS(newpos, size_to_move, buffer_len - 1); | 427 | overlap = RINGBUF_ADD_CROSS(newpos, size_to_move, buffer_len - 1); |
@@ -436,6 +445,7 @@ static bool move_handle(struct memory_handle **h, size_t *delta, | |||
436 | if (correction) { | 445 | if (correction) { |
437 | if (final_delta < correction + sizeof(struct memory_handle)) { | 446 | if (final_delta < correction + sizeof(struct memory_handle)) { |
438 | /* Delta cannot end up less than the size of the struct */ | 447 | /* Delta cannot end up less than the size of the struct */ |
448 | mutex_unlock(&llist_mod_mutex); | ||
439 | mutex_unlock(&llist_mutex); | 449 | mutex_unlock(&llist_mutex); |
440 | return false; | 450 | return false; |
441 | } | 451 | } |
@@ -459,6 +469,7 @@ static bool move_handle(struct memory_handle **h, size_t *delta, | |||
459 | if (m && m->next == src) { | 469 | if (m && m->next == src) { |
460 | m->next = dest; | 470 | m->next = dest; |
461 | } else { | 471 | } else { |
472 | mutex_unlock(&llist_mod_mutex); | ||
462 | mutex_unlock(&llist_mutex); | 473 | mutex_unlock(&llist_mutex); |
463 | return false; | 474 | return false; |
464 | } | 475 | } |
@@ -484,6 +495,7 @@ static bool move_handle(struct memory_handle **h, size_t *delta, | |||
484 | /* Update the caller with the new location of h and the distance moved */ | 495 | /* Update the caller with the new location of h and the distance moved */ |
485 | *h = dest; | 496 | *h = dest; |
486 | *delta = final_delta; | 497 | *delta = final_delta; |
498 | mutex_unlock(&llist_mod_mutex); | ||
487 | mutex_unlock(&llist_mutex); | 499 | mutex_unlock(&llist_mutex); |
488 | return dest; | 500 | return dest; |
489 | } | 501 | } |
@@ -941,7 +953,10 @@ int bufopen(const char *file, size_t offset, enum data_type type) | |||
941 | strncpy(h->path, file, MAX_PATH); | 953 | strncpy(h->path, file, MAX_PATH); |
942 | h->offset = adjusted_offset; | 954 | h->offset = adjusted_offset; |
943 | h->ridx = buf_widx; | 955 | h->ridx = buf_widx; |
956 | h->widx = buf_widx; | ||
944 | h->data = buf_widx; | 957 | h->data = buf_widx; |
958 | h->available = 0; | ||
959 | h->filerem = 0; | ||
945 | h->type = type; | 960 | h->type = type; |
946 | 961 | ||
947 | #ifdef HAVE_ALBUMART | 962 | #ifdef HAVE_ALBUMART |
@@ -949,9 +964,9 @@ int bufopen(const char *file, size_t offset, enum data_type type) | |||
949 | { | 964 | { |
950 | /* Bitmap file: we load the data instead of the file */ | 965 | /* Bitmap file: we load the data instead of the file */ |
951 | int rc; | 966 | int rc; |
952 | mutex_lock(&llist_mutex); /* Lock because load_bitmap yields */ | 967 | mutex_lock(&llist_mod_mutex); /* Lock because load_bitmap yields */ |
953 | rc = load_image(fd, file); | 968 | rc = load_image(fd, file); |
954 | mutex_unlock(&llist_mutex); | 969 | mutex_unlock(&llist_mod_mutex); |
955 | if (rc <= 0) | 970 | if (rc <= 0) |
956 | { | 971 | { |
957 | rm_handle(h); | 972 | rm_handle(h); |
@@ -1442,9 +1457,11 @@ void buffering_thread(void) | |||
1442 | void buffering_init(void) | 1457 | void buffering_init(void) |
1443 | { | 1458 | { |
1444 | mutex_init(&llist_mutex); | 1459 | mutex_init(&llist_mutex); |
1460 | mutex_init(&llist_mod_mutex); | ||
1445 | #ifdef HAVE_PRIORITY_SCHEDULING | 1461 | #ifdef HAVE_PRIORITY_SCHEDULING |
1446 | /* This behavior not safe atm */ | 1462 | /* This behavior not safe atm */ |
1447 | mutex_set_preempt(&llist_mutex, false); | 1463 | mutex_set_preempt(&llist_mutex, false); |
1464 | mutex_set_preempt(&llist_mod_mutex, false); | ||
1448 | #endif | 1465 | #endif |
1449 | 1466 | ||
1450 | conf_watermark = BUFFERING_DEFAULT_WATERMARK; | 1467 | conf_watermark = BUFFERING_DEFAULT_WATERMARK; |