+#ifdef CONFIG_UCW_THREADS
+
+#define TEST_THREADS_COUNT 4
+
+static void *
+test_threads_thread(void *param UNUSED)
+{
+ DBG("Starting thread");
+ struct image_context ctx;
+ struct image_io io;
+ image_context_init(&ctx);
+ TRY(image_io_init(&ctx, &io));
+
+ for (uns num = 0; num < 200; num++)
+ {
+ int r0 = random_max(100);
+
+ /* realloc context */
+ if ((r0 -= 2) < 0)
+ {
+ image_io_cleanup(&io);
+ image_context_cleanup(&ctx);
+ image_context_init(&ctx);
+ TRY(image_io_init(&ctx, &io));
+ }
+
+ /* realloc I/O */
+ else if ((r0 -= 2) < 0)
+ {
+ image_io_cleanup(&io);
+ TRY(image_io_init(&ctx, &io));
+ }
+
+ /* encode and decode random image */
+ else
+ {
+ struct image *img;
+
+ TRY(img = image_new(&ctx, 10 + random_max(140), 10 + random_max(140), COLOR_SPACE_RGB, NULL));
+ image_clear(&ctx, img);
+
+#if defined(CONFIG_IMAGES_LIBJPEG) || defined(CONFIG_IMAGES_LIBPNG) || defined(CONFIG_IMAGES_LIBMAGICK)
+
+ struct fastbuf *wfb = fbmem_create(10000);
+ struct fastbuf *rfb;
+ uns format = 0;
+ while (!format)
+ {
+ switch (random_max(3))
+ {
+ case 0:
+#if defined(CONFIG_IMAGES_LIBJPEG) || defined(CONFIG_IMAGES_LIBMAGICK)
+ format = IMAGE_FORMAT_JPEG;
+#endif
+ break;
+ case 1:
+#if defined(CONFIG_IMAGES_LIBPNG) || defined(CONFIG_IMAGES_LIBMAGICK)
+ format = IMAGE_FORMAT_PNG;
+#endif
+ break;
+ case 2:
+#if defined(CONFIG_IMAGES_LIBMAGICK)
+ format = IMAGE_FORMAT_GIF;
+#endif
+ break;
+ default:
+ ASSERT(0);
+ }
+ }
+
+ io.format = format;
+ io.fastbuf = wfb;
+ io.image = img;
+ TRY(image_io_write(&io));
+ image_io_reset(&io);
+
+ rfb = fbmem_clone_read(wfb);
+ io.format = format;
+ io.fastbuf = rfb;
+ TRY(image_io_read(&io, 0));
+ image_io_reset(&io);
+
+ bclose(rfb);
+ bclose(wfb);
+
+#endif
+ image_destroy(img);
+ }
+ }
+
+ image_io_cleanup(&io);
+ image_context_cleanup(&ctx);
+ DBG("Stopping thread");
+ return NULL;
+}
+
+#endif
+
+static void
+test_threads(void)
+{
+#ifdef CONFIG_UCW_THREADS
+ pthread_t threads[TEST_THREADS_COUNT - 1];
+ pthread_attr_t attr;
+ if (pthread_attr_init(&attr) < 0 ||
+ pthread_attr_setstacksize(&attr, default_thread_stack_size) < 0)
+ ASSERT(0);
+ for (uns i = 0; i < TEST_THREADS_COUNT - 1; i++)
+ {
+ if (pthread_create(threads + i, &attr, test_threads_thread, NULL) < 0)
+ die("Unable to create thread: %m");
+ }
+ test_threads_thread(NULL);
+ for (uns i = 0; i < TEST_THREADS_COUNT - 1; i++)
+ if (pthread_join(threads[i], NULL) < 0)
+ die("Cannot join thread: %m");
+#else
+ msg(L_WARN, "Disabled CONFIG_UCW_THREADS, threaded tests skipped");
+#endif
+}
+