summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vrhel <michael.vrhel@artifex.com>2015-01-21 13:20:36 -0800
committerMichael Vrhel <michael.vrhel@artifex.com>2015-01-27 14:05:20 -0800
commit7584edc737ebb5277801a9e6b51eb5531fdf84d2 (patch)
tree957a9d2e3d25ea63f0592fe09f1887f297445c9f
parentb4e11b0b493c88e94a205643767e3c744ae17fde (diff)
downloadmupdf-7584edc737ebb5277801a9e6b51eb5531fdf84d2.tar.xz
Fix issue in display list Cache
The commit fc05b51c2b198dcc5553f6de1b8fb0e22e7d28ae cleaned up a few issues in the display list cache but it introduced issues when multiple threads are using the lists. In particular one thread could be using a list at the tail of the cache list, while another thread is adding one to the cache, and removing the entry at the tail. The solution is to make sure the ref count of the list is incremented when someone is using the list and making sure that it gets decremented when they are done with the list.
-rw-r--r--platform/windows/gsview/mudocument.cs39
-rw-r--r--platform/windows/mupdfnet/mupdfnet.cpp8
-rw-r--r--platform/windows/mupdfnet/mupdfnet.h2
-rw-r--r--platform/windows/mupdfwinrt/Cache.cpp10
-rw-r--r--platform/windows/mupdfwinrt/muctx.cpp15
-rw-r--r--platform/windows/mupdfwinrt/muctx.h1
-rw-r--r--platform/windows/mupdfwinrt/mudocument.cpp6
7 files changed, 79 insertions, 2 deletions
diff --git a/platform/windows/gsview/mudocument.cs b/platform/windows/gsview/mudocument.cs
index 3087d3d0..e41de6e3 100644
--- a/platform/windows/gsview/mudocument.cs
+++ b/platform/windows/gsview/mudocument.cs
@@ -159,6 +159,11 @@ namespace gsview
private static extern IntPtr mCreateDisplayListText64(IntPtr ctx, int page_num,
ref int page_width, ref int page_height, ref IntPtr text, ref int length);
+ [DllImport("mupdfnet64.dll", EntryPoint = "mReleaseLists", CharSet = CharSet.Auto,
+ CallingConvention = CallingConvention.StdCall)]
+ private static extern void mReleaseLists64(IntPtr ctx, IntPtr dlist,
+ IntPtr annot_dlist);
+
[DllImport("mupdfnet64.dll", EntryPoint = "mRenderPageMT", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int mRenderPageMT64(IntPtr ctx, IntPtr dlist,
@@ -308,6 +313,11 @@ namespace gsview
private static extern IntPtr mCreateDisplayListText32(IntPtr ctx, int page_num,
ref int page_width, ref int page_height, ref IntPtr text, ref int length);
+ [DllImport("mupdfnet32.dll", EntryPoint = "mReleaseLists", CharSet = CharSet.Auto,
+ CallingConvention = CallingConvention.StdCall)]
+ private static extern void mReleaseLists32(IntPtr ctx, IntPtr dlist,
+ IntPtr annot_dlist);
+
[DllImport("mupdfnet32.dll", EntryPoint = "mRenderPageMT", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int mRenderPageMT32(IntPtr ctx, IntPtr dlist,
@@ -805,6 +815,33 @@ namespace gsview
return output;
}
+ private void tc_mReleaseLists(IntPtr ctx, IntPtr dlist, IntPtr annot_dlist)
+ {
+ int output;
+ try
+ {
+ if (is64bit)
+ mReleaseLists64(ctx, dlist, annot_dlist);
+ else
+ mReleaseLists32(ctx, dlist, annot_dlist);
+ }
+ catch (DllNotFoundException)
+ {
+ /* DLL not found */
+ String err = "DllNotFoundException: MuPDF DLL not found 16";
+ mupdfDLLProblemMain(this, err);
+ return;
+ }
+ catch (BadImageFormatException)
+ {
+ /* Using 32 bit with 64 or vice versa */
+ String err = "BadImageFormatException: Incorrect MuPDF DLL";
+ mupdfDLLProblemMain(this, err);
+ return;
+ }
+ return;
+ }
+
private int tc_mRenderPageMT(IntPtr ctx, IntPtr dlist, IntPtr annot_dlist,
int page_width, int page_height, Byte[] bmp_data, int bmp_width,
int bmp_height, double scale, bool flipy)
@@ -1417,6 +1454,8 @@ namespace gsview
}
code = tc_mRenderPageMT(mu_object, dlist, annot_dlist, page_width,
page_height, bmp_data, bmp_width, bmp_height, scale, flipy);
+ /* We are done with the display lists */
+ tc_mReleaseLists(mu_object, dlist, annot_dlist);
}
else
{
diff --git a/platform/windows/mupdfnet/mupdfnet.cpp b/platform/windows/mupdfnet/mupdfnet.cpp
index 6a59aec9..854d40c5 100644
--- a/platform/windows/mupdfnet/mupdfnet.cpp
+++ b/platform/windows/mupdfnet/mupdfnet.cpp
@@ -287,6 +287,14 @@ SYMBOL_DECLSPEC void* __stdcall mCreateDisplayListText(void *ctx, int page_num,
return text_ptr;
}
+SYMBOL_DECLSPEC void __stdcall mReleaseLists(void *ctx, void *dlist,
+ void *annot_dlist)
+{
+ muctx *mu_ctx = static_cast<muctx*>(ctx);
+ mu_ctx->ReleaseDisplayLists(dlist, annot_dlist);
+ return;
+}
+
SYMBOL_DECLSPEC int __stdcall mRenderPageMT(void *ctx, void *dlist,
void *annot_dlist, int page_width, int page_height, byte *bmp_data, int bmp_width,
int bmp_height, double scale, bool flipy)
diff --git a/platform/windows/mupdfnet/mupdfnet.h b/platform/windows/mupdfnet/mupdfnet.h
index 99d23062..44a4382b 100644
--- a/platform/windows/mupdfnet/mupdfnet.h
+++ b/platform/windows/mupdfnet/mupdfnet.h
@@ -50,6 +50,8 @@ EXTERN_C SYMBOL_DECLSPEC void* __stdcall mCreateDisplayListText(void *ctx, int p
int *page_width, int *page_height, void **textptr, int *length);
EXTERN_C SYMBOL_DECLSPEC void* __stdcall mCreateDisplayListAnnot(void *ctx,
int page_num);
+EXTERN_C SYMBOL_DECLSPEC void __stdcall mReleaseLists(void *ctx, void *dlist,
+ void *annot_dlist);
EXTERN_C SYMBOL_DECLSPEC int __stdcall mRenderPageMT(void *ctx, void *dlist,
void *annot_dlist, int page_width, int page_height, byte *bmp_data, int bmp_width,
diff --git a/platform/windows/mupdfwinrt/Cache.cpp b/platform/windows/mupdfwinrt/Cache.cpp
index d2567bc2..d5108a7c 100644
--- a/platform/windows/mupdfwinrt/Cache.cpp
+++ b/platform/windows/mupdfwinrt/Cache.cpp
@@ -48,7 +48,10 @@ void Cache::Add(int value, int width_in, int height_in, fz_display_list *dlist,
tail = prev_entry;
- /* Decrement the caches rc of this list */
+ /* Decrement the caches rc of this list. It is gone from cache but
+ may still be in use by other threads, when threads are done they
+ should decrement and it should be freed at that time. See
+ ReleaseDisplayLists in muctx class */
fz_drop_display_list(mu_ctx, curr_entry->dlist);
delete curr_entry;
size--;
@@ -75,6 +78,8 @@ void Cache::Add(int value, int width_in, int height_in, fz_display_list *dlist,
head = new_entry;
}
size++;
+ /* Everytime we add an entry, we are also using it. Increment rc. See above */
+ fz_keep_display_list(mu_ctx, dlist);
}
fz_display_list* Cache::Use(int value, int *width_out, int *height_out, fz_context *mu_ctx)
@@ -109,6 +114,9 @@ fz_display_list* Cache::Use(int value, int *width_out, int *height_out, fz_conte
}
*width_out = curr_entry->width;
*height_out = curr_entry->height;
+ /* We must increment our reference to this one to ensure it is not
+ freed when removed from the cache. See above comments */
+ fz_keep_display_list(mu_ctx, curr_entry->dlist);
return curr_entry->dlist;
}
else
diff --git a/platform/windows/mupdfwinrt/muctx.cpp b/platform/windows/mupdfwinrt/muctx.cpp
index fbcb01f3..e51ea403 100644
--- a/platform/windows/mupdfwinrt/muctx.cpp
+++ b/platform/windows/mupdfwinrt/muctx.cpp
@@ -531,6 +531,21 @@ fz_display_list * muctx::CreateDisplayList(int page_num, int *width, int *height
return dlist;
}
+void muctx::ReleaseDisplayLists(void *opdlist, void *opannotlist)
+{
+ fz_display_list *dlist = (fz_display_list*) opdlist;
+ fz_display_list *annotlist = (fz_display_list*) opannotlist;
+
+ if (dlist != NULL)
+ {
+ fz_drop_display_list(mu_ctx, dlist);
+ }
+ if (annotlist != NULL)
+ {
+ fz_drop_display_list(mu_ctx, annotlist);
+ }
+}
+
/* A special version which will create the display list AND get the information
that we need for various text selection tasks */
fz_display_list * muctx::CreateDisplayListText(int page_num, int *width, int *height,
diff --git a/platform/windows/mupdfwinrt/muctx.h b/platform/windows/mupdfwinrt/muctx.h
index 16c44cd1..5b870543 100644
--- a/platform/windows/mupdfwinrt/muctx.h
+++ b/platform/windows/mupdfwinrt/muctx.h
@@ -101,6 +101,7 @@ public:
fz_display_list * CreateDisplayListText(int page_num, int *width,
int *height, fz_text_page **text, int *length);
fz_display_list * CreateAnnotationList(int page_num);
+ void ReleaseDisplayLists(void *dlist, void *annotlist);
int MeasurePage(int page_num, point_t *size);
point_t MeasurePage(fz_page *page);
unsigned int GetLinks(int page_num, sh_vector_link links_vec);
diff --git a/platform/windows/mupdfwinrt/mudocument.cpp b/platform/windows/mupdfwinrt/mudocument.cpp
index 060144b3..29df67c3 100644
--- a/platform/windows/mupdfwinrt/mudocument.cpp
+++ b/platform/windows/mupdfwinrt/mudocument.cpp
@@ -217,6 +217,8 @@ int mudocument::RenderPageBitmapSync(int page_num, int bmp_width, int bmp_height
&(bmp_data[0]), bmp_width, bmp_height,
scale, flipy, tile, { top_left.X, top_left.Y },
{ bottom_right.X, bottom_right.Y });
+ /* Done with lists */
+ mu_object.ReleaseDisplayLists(dlist, annotlist);
}
else
{
@@ -290,7 +292,9 @@ Windows::Foundation::IAsyncOperation<InMemoryRandomAccessStream^>^
&(bmp_data[0]), bmp_width, bmp_height,
scale, true, false, { 0.0, 0.0 },
{ (float) bmp_width, (float) bmp_height });
- }
+ /* Done with lists */
+ mu_object.ReleaseDisplayLists(dlist, annotlist);
+ }
else
{
/* Rendering in immediate mode. Keep lock in place */