qtbug-84619.patch 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. From 9d2b474b5f6aa07ee731d28f9774d10dfaa49b32 Mon Sep 17 00:00:00 2001
  2. From: Allan Sandfeld Jensen <allan.jensen@qt.io>
  3. Date: Tue, 2 Jun 2020 10:59:21 +0200
  4. Subject: Do not multithread if already in a global threadpool thread
  5. This can lead to a deadlock if we block all the worker threads, waiting
  6. for the worker threads to finish.
  7. Fixes: QTBUG-84619
  8. Change-Id: I92b7f96007897d86ece0c34223bab0df4ccbed9a
  9. Reviewed-by: Sona Kurazyan <sona.kurazyan@qt.io>
  10. (cherry picked from commit 87d32424de2f471a520c1f3ba0c3035fbff7ee06)
  11. Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
  12. ---
  13. src/corelib/thread/qthreadpool.cpp | 24 ++++++++++++++++++++++++
  14. src/corelib/thread/qthreadpool.h | 2 ++
  15. src/gui/image/qimage.cpp | 7 ++++---
  16. src/gui/image/qimage_conversions.cpp | 15 +++++++++------
  17. src/gui/painting/qimagescale.cpp | 5 +++--
  18. src/gui/painting/qimagescale_neon.cpp | 5 +++--
  19. src/gui/painting/qimagescale_sse4.cpp | 5 +++--
  20. 7 files changed, 48 insertions(+), 15 deletions(-)
  21. diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
  22. index 1f99bad247..d2dcc32280 100644
  23. --- a/src/corelib/thread/qthreadpool.cpp
  24. +++ b/src/corelib/thread/qthreadpool.cpp
  25. @@ -52,6 +52,7 @@ Q_GLOBAL_STATIC(QThreadPool, theInstance)
  26. */
  27. class QThreadPoolThread : public QThread
  28. {
  29. + Q_OBJECT
  30. public:
  31. QThreadPoolThread(QThreadPoolPrivate *manager);
  32. void run() override;
  33. @@ -763,6 +764,28 @@ void QThreadPool::clear()
  34. d->clear();
  35. }
  36. +#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
  37. +/*!
  38. + \internal
  39. +
  40. + Returns \c true if \a thread is a thread managed by this thread pool.
  41. +*/
  42. +#else
  43. +/*!
  44. + \since 6.0
  45. +
  46. + Returns \c true if \a thread is a thread managed by this thread pool.
  47. +*/
  48. +#endif
  49. +bool QThreadPool::contains(const QThread *thread) const
  50. +{
  51. + Q_D(const QThreadPool);
  52. + const QThreadPoolThread *poolThread = qobject_cast<const QThreadPoolThread *>(thread);
  53. + if (!poolThread)
  54. + return false;
  55. + return d->allThreads.contains(const_cast<QThreadPoolThread *>(poolThread));
  56. +}
  57. +
  58. #if QT_DEPRECATED_SINCE(5, 9)
  59. /*!
  60. \since 5.5
  61. @@ -784,3 +807,4 @@ void QThreadPool::cancel(QRunnable *runnable)
  62. QT_END_NAMESPACE
  63. #include "moc_qthreadpool.cpp"
  64. +#include "qthreadpool.moc"
  65. diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h
  66. index e3691ab010..004f76a240 100644
  67. --- a/src/corelib/thread/qthreadpool.h
  68. +++ b/src/corelib/thread/qthreadpool.h
  69. @@ -93,6 +93,8 @@ public:
  70. void clear();
  71. + bool contains(const QThread *thread) const;
  72. +
  73. #if QT_DEPRECATED_SINCE(5, 9)
  74. QT_DEPRECATED_X("use tryTake(), but note the different deletion rules")
  75. void cancel(QRunnable *runnable);
  76. diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
  77. index 499c527cfc..c443836c0a 100644
  78. --- a/src/gui/image/qimage.cpp
  79. +++ b/src/gui/image/qimage.cpp
  80. @@ -5042,15 +5042,16 @@ void QImage::applyColorTransform(const QColorTransform &transform)
  81. };
  82. }
  83. -#if QT_CONFIG(thread)
  84. +#if QT_CONFIG(thread) && !defined(Q_OS_WASM)
  85. int segments = sizeInBytes() / (1<<16);
  86. segments = std::min(segments, height());
  87. - if (segments > 1) {
  88. + QThreadPool *threadPool = QThreadPool::globalInstance();
  89. + if (segments > 1 && !threadPool->contains(QThread::currentThread())) {
  90. QSemaphore semaphore;
  91. int y = 0;
  92. for (int i = 0; i < segments; ++i) {
  93. int yn = (height() - y) / (segments - i);
  94. - QThreadPool::globalInstance()->start([&, y, yn]() {
  95. + threadPool->start([&, y, yn]() {
  96. transformSegment(y, y + yn);
  97. semaphore.release(1);
  98. });
  99. diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
  100. index a3868a64c7..e804b3b788 100644
  101. --- a/src/gui/image/qimage_conversions.cpp
  102. +++ b/src/gui/image/qimage_conversions.cpp
  103. @@ -236,14 +236,15 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
  104. int segments = src->nbytes / (1<<16);
  105. segments = std::min(segments, src->height);
  106. - if (segments <= 1)
  107. + QThreadPool *threadPool = QThreadPool::globalInstance();
  108. + if (segments <= 1 || threadPool->contains(QThread::currentThread()))
  109. return convertSegment(0, src->height);
  110. QSemaphore semaphore;
  111. int y = 0;
  112. for (int i = 0; i < segments; ++i) {
  113. int yn = (src->height - y) / (segments - i);
  114. - QThreadPool::globalInstance()->start([&, y, yn]() {
  115. + threadPool->start([&, y, yn]() {
  116. convertSegment(y, y + yn);
  117. semaphore.release(1);
  118. });
  119. @@ -290,14 +291,15 @@ void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::Image
  120. int segments = src->nbytes / (1<<16);
  121. segments = std::min(segments, src->height);
  122. - if (segments <= 1)
  123. + QThreadPool *threadPool = QThreadPool::globalInstance();
  124. + if (segments <= 1 || threadPool->contains(QThread::currentThread()))
  125. return convertSegment(0, src->height);
  126. QSemaphore semaphore;
  127. int y = 0;
  128. for (int i = 0; i < segments; ++i) {
  129. int yn = (src->height - y) / (segments - i);
  130. - QThreadPool::globalInstance()->start([&, y, yn]() {
  131. + threadPool->start([&, y, yn]() {
  132. convertSegment(y, y + yn);
  133. semaphore.release(1);
  134. });
  135. @@ -396,12 +398,13 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
  136. #ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS
  137. int segments = data->nbytes / (1<<16);
  138. segments = std::min(segments, data->height);
  139. - if (segments > 1) {
  140. + QThreadPool *threadPool = QThreadPool::globalInstance();
  141. + if (segments > 1 && !threadPool->contains(QThread::currentThread())) {
  142. QSemaphore semaphore;
  143. int y = 0;
  144. for (int i = 0; i < segments; ++i) {
  145. int yn = (data->height - y) / (segments - i);
  146. - QThreadPool::globalInstance()->start([&, y, yn]() {
  147. + threadPool->start([&, y, yn]() {
  148. convertSegment(y, y + yn);
  149. semaphore.release(1);
  150. });
  151. diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
  152. index 2395c891ce..aac1e20f7b 100644
  153. --- a/src/gui/painting/qimagescale.cpp
  154. +++ b/src/gui/painting/qimagescale.cpp
  155. @@ -307,12 +307,13 @@ static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, con
  156. #if QT_CONFIG(thread) && !defined(Q_OS_WASM)
  157. int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
  158. segments = std::min(segments, dh);
  159. - if (segments > 1) {
  160. + QThreadPool *threadPool = QThreadPool::globalInstance();
  161. + if (segments > 1 && !threadPool->contains(QThread::currentThread())) {
  162. QSemaphore semaphore;
  163. int y = 0;
  164. for (int i = 0; i < segments; ++i) {
  165. int yn = (dh - y) / (segments - i);
  166. - QThreadPool::globalInstance()->start([&, y, yn]() {
  167. + threadPool->start([&, y, yn]() {
  168. scaleSection(y, y + yn);
  169. semaphore.release(1);
  170. });
  171. diff --git a/src/gui/painting/qimagescale_neon.cpp b/src/gui/painting/qimagescale_neon.cpp
  172. index 65fe3fac3c..046e56b419 100644
  173. --- a/src/gui/painting/qimagescale_neon.cpp
  174. +++ b/src/gui/painting/qimagescale_neon.cpp
  175. @@ -58,12 +58,13 @@ static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, con
  176. #if QT_CONFIG(thread) && !defined(Q_OS_WASM)
  177. int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
  178. segments = std::min(segments, dh);
  179. - if (segments > 1) {
  180. + QThreadPool *threadPool = QThreadPool::globalInstance();
  181. + if (segments > 1 && !threadPool->contains(QThread::currentThread())) {
  182. QSemaphore semaphore;
  183. int y = 0;
  184. for (int i = 0; i < segments; ++i) {
  185. int yn = (dh - y) / (segments - i);
  186. - QThreadPool::globalInstance()->start([&, y, yn]() {
  187. + threadPool->start([&, y, yn]() {
  188. scaleSection(y, y + yn);
  189. semaphore.release(1);
  190. });
  191. diff --git a/src/gui/painting/qimagescale_sse4.cpp b/src/gui/painting/qimagescale_sse4.cpp
  192. index 1760e72f65..70cfa08d95 100644
  193. --- a/src/gui/painting/qimagescale_sse4.cpp
  194. +++ b/src/gui/painting/qimagescale_sse4.cpp
  195. @@ -59,12 +59,13 @@ static inline void multithread_pixels_function(QImageScaleInfo *isi, int dh, con
  196. #if QT_CONFIG(thread) && !defined(Q_OS_WASM)
  197. int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
  198. segments = std::min(segments, dh);
  199. - if (segments > 1) {
  200. + QThreadPool *threadPool = QThreadPool::globalInstance();
  201. + if (segments > 1 && !threadPool->contains(QThread::currentThread())) {
  202. QSemaphore semaphore;
  203. int y = 0;
  204. for (int i = 0; i < segments; ++i) {
  205. int yn = (dh - y) / (segments - i);
  206. - QThreadPool::globalInstance()->start([&, y, yn]() {
  207. + threadPool->start([&, y, yn]() {
  208. scaleSection(y, y + yn);
  209. semaphore.release(1);
  210. });
  211. --
  212. cgit v1.2.1