threading.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /**
  2. * Copyright (c) 2016 Tino Reichardt
  3. * All rights reserved.
  4. *
  5. * You can contact the author at:
  6. * - zstdmt source repository: https://github.com/mcmilk/zstdmt
  7. *
  8. * This source code is licensed under both the BSD-style license (found in the
  9. * LICENSE file in the root directory of this source tree) and the GPLv2 (found
  10. * in the COPYING file in the root directory of this source tree).
  11. * You may select, at your option, one of the above-listed licenses.
  12. */
  13. /**
  14. * This file will hold wrapper for systems, which do not support pthreads
  15. */
  16. #include "threading.h"
  17. /* create fake symbol to avoid empty translation unit warning */
  18. int g_ZSTD_threading_useless_symbol;
  19. #if defined(ZSTD_MULTITHREAD) && defined(_WIN32)
  20. /**
  21. * Windows minimalist Pthread Wrapper
  22. */
  23. /* === Dependencies === */
  24. #include <process.h>
  25. #include <errno.h>
  26. /* === Implementation === */
  27. typedef struct {
  28. void* (*start_routine)(void*);
  29. void* arg;
  30. int initialized;
  31. ZSTD_pthread_cond_t initialized_cond;
  32. ZSTD_pthread_mutex_t initialized_mutex;
  33. } ZSTD_thread_params_t;
  34. static unsigned __stdcall worker(void *arg)
  35. {
  36. void* (*start_routine)(void*);
  37. void* thread_arg;
  38. /* Initialized thread_arg and start_routine and signal main thread that we don't need it
  39. * to wait any longer.
  40. */
  41. {
  42. ZSTD_thread_params_t* thread_param = (ZSTD_thread_params_t*)arg;
  43. thread_arg = thread_param->arg;
  44. start_routine = thread_param->start_routine;
  45. /* Signal main thread that we are running and do not depend on its memory anymore */
  46. ZSTD_pthread_mutex_lock(&thread_param->initialized_mutex);
  47. thread_param->initialized = 1;
  48. ZSTD_pthread_cond_signal(&thread_param->initialized_cond);
  49. ZSTD_pthread_mutex_unlock(&thread_param->initialized_mutex);
  50. }
  51. start_routine(thread_arg);
  52. return 0;
  53. }
  54. int ZSTD_pthread_create(ZSTD_pthread_t* thread, const void* unused,
  55. void* (*start_routine) (void*), void* arg)
  56. {
  57. ZSTD_thread_params_t thread_param;
  58. (void)unused;
  59. thread_param.start_routine = start_routine;
  60. thread_param.arg = arg;
  61. thread_param.initialized = 0;
  62. *thread = NULL;
  63. /* Setup thread initialization synchronization */
  64. if(ZSTD_pthread_cond_init(&thread_param.initialized_cond, NULL)) {
  65. /* Should never happen on Windows */
  66. return -1;
  67. }
  68. if(ZSTD_pthread_mutex_init(&thread_param.initialized_mutex, NULL)) {
  69. /* Should never happen on Windows */
  70. ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
  71. return -1;
  72. }
  73. /* Spawn thread */
  74. *thread = (HANDLE)_beginthreadex(NULL, 0, worker, &thread_param, 0, NULL);
  75. if (!thread) {
  76. ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);
  77. ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
  78. return errno;
  79. }
  80. /* Wait for thread to be initialized */
  81. ZSTD_pthread_mutex_lock(&thread_param.initialized_mutex);
  82. while(!thread_param.initialized) {
  83. ZSTD_pthread_cond_wait(&thread_param.initialized_cond, &thread_param.initialized_mutex);
  84. }
  85. ZSTD_pthread_mutex_unlock(&thread_param.initialized_mutex);
  86. ZSTD_pthread_mutex_destroy(&thread_param.initialized_mutex);
  87. ZSTD_pthread_cond_destroy(&thread_param.initialized_cond);
  88. return 0;
  89. }
  90. int ZSTD_pthread_join(ZSTD_pthread_t thread)
  91. {
  92. DWORD result;
  93. if (!thread) return 0;
  94. result = WaitForSingleObject(thread, INFINITE);
  95. CloseHandle(thread);
  96. switch (result) {
  97. case WAIT_OBJECT_0:
  98. return 0;
  99. case WAIT_ABANDONED:
  100. return EINVAL;
  101. default:
  102. return GetLastError();
  103. }
  104. }
  105. #endif /* ZSTD_MULTITHREAD */
  106. #if defined(ZSTD_MULTITHREAD) && DEBUGLEVEL >= 1 && !defined(_WIN32)
  107. #define ZSTD_DEPS_NEED_MALLOC
  108. #include "zstd_deps.h"
  109. int ZSTD_pthread_mutex_init(ZSTD_pthread_mutex_t* mutex, pthread_mutexattr_t const* attr)
  110. {
  111. *mutex = (pthread_mutex_t*)ZSTD_malloc(sizeof(pthread_mutex_t));
  112. if (!*mutex)
  113. return 1;
  114. return pthread_mutex_init(*mutex, attr);
  115. }
  116. int ZSTD_pthread_mutex_destroy(ZSTD_pthread_mutex_t* mutex)
  117. {
  118. if (!*mutex)
  119. return 0;
  120. {
  121. int const ret = pthread_mutex_destroy(*mutex);
  122. ZSTD_free(*mutex);
  123. return ret;
  124. }
  125. }
  126. int ZSTD_pthread_cond_init(ZSTD_pthread_cond_t* cond, pthread_condattr_t const* attr)
  127. {
  128. *cond = (pthread_cond_t*)ZSTD_malloc(sizeof(pthread_cond_t));
  129. if (!*cond)
  130. return 1;
  131. return pthread_cond_init(*cond, attr);
  132. }
  133. int ZSTD_pthread_cond_destroy(ZSTD_pthread_cond_t* cond)
  134. {
  135. if (!*cond)
  136. return 0;
  137. {
  138. int const ret = pthread_cond_destroy(*cond);
  139. ZSTD_free(*cond);
  140. return ret;
  141. }
  142. }
  143. #endif