You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
5.4KB

  1. /*
  2. * Copyright (c) 2011-2017 KO Myung-Hun <komh@chollian.net>
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * FFmpeg is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with FFmpeg; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. /**
  21. * @file
  22. * os2threads to pthreads wrapper
  23. */
  24. #ifndef COMPAT_OS2THREADS_H
  25. #define COMPAT_OS2THREADS_H
  26. #define INCL_DOS
  27. #include <os2.h>
  28. #undef __STRICT_ANSI__ /* for _beginthread() */
  29. #include <stdlib.h>
  30. #include <time.h>
  31. #include <sys/builtin.h>
  32. #include <sys/fmutex.h>
  33. #include "libavutil/attributes.h"
  34. #include "libavutil/common.h"
  35. #include "libavutil/time.h"
  36. typedef struct {
  37. TID tid;
  38. void *(*start_routine)(void *);
  39. void *arg;
  40. void *result;
  41. } pthread_t;
  42. typedef void pthread_attr_t;
  43. typedef _fmutex pthread_mutex_t;
  44. typedef void pthread_mutexattr_t;
  45. #define PTHREAD_MUTEX_INITIALIZER _FMUTEX_INITIALIZER
  46. typedef struct {
  47. HEV event_sem;
  48. HEV ack_sem;
  49. volatile unsigned wait_count;
  50. } pthread_cond_t;
  51. typedef void pthread_condattr_t;
  52. typedef struct {
  53. volatile int done;
  54. _fmutex mtx;
  55. } pthread_once_t;
  56. #define PTHREAD_ONCE_INIT {0, _FMUTEX_INITIALIZER}
  57. static void thread_entry(void *arg)
  58. {
  59. pthread_t *thread = arg;
  60. thread->result = thread->start_routine(thread->arg);
  61. }
  62. static av_always_inline int pthread_create(pthread_t *thread,
  63. const pthread_attr_t *attr,
  64. void *(*start_routine)(void*),
  65. void *arg)
  66. {
  67. thread->start_routine = start_routine;
  68. thread->arg = arg;
  69. thread->result = NULL;
  70. thread->tid = _beginthread(thread_entry, NULL, 1024 * 1024, thread);
  71. return 0;
  72. }
  73. static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
  74. {
  75. DosWaitThread(&thread.tid, DCWW_WAIT);
  76. if (value_ptr)
  77. *value_ptr = thread.result;
  78. return 0;
  79. }
  80. static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex,
  81. const pthread_mutexattr_t *attr)
  82. {
  83. _fmutex_create(mutex, 0);
  84. return 0;
  85. }
  86. static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
  87. {
  88. _fmutex_close(mutex);
  89. return 0;
  90. }
  91. static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
  92. {
  93. _fmutex_request(mutex, 0);
  94. return 0;
  95. }
  96. static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
  97. {
  98. _fmutex_release(mutex);
  99. return 0;
  100. }
  101. static av_always_inline int pthread_cond_init(pthread_cond_t *cond,
  102. const pthread_condattr_t *attr)
  103. {
  104. DosCreateEventSem(NULL, &cond->event_sem, DCE_POSTONE, FALSE);
  105. DosCreateEventSem(NULL, &cond->ack_sem, DCE_POSTONE, FALSE);
  106. cond->wait_count = 0;
  107. return 0;
  108. }
  109. static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
  110. {
  111. DosCloseEventSem(cond->event_sem);
  112. DosCloseEventSem(cond->ack_sem);
  113. return 0;
  114. }
  115. static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
  116. {
  117. if (!__atomic_cmpxchg32(&cond->wait_count, 0, 0)) {
  118. DosPostEventSem(cond->event_sem);
  119. DosWaitEventSem(cond->ack_sem, SEM_INDEFINITE_WAIT);
  120. }
  121. return 0;
  122. }
  123. static av_always_inline int pthread_cond_broadcast(pthread_cond_t *cond)
  124. {
  125. while (!__atomic_cmpxchg32(&cond->wait_count, 0, 0))
  126. pthread_cond_signal(cond);
  127. return 0;
  128. }
  129. static av_always_inline int pthread_cond_timedwait(pthread_cond_t *cond,
  130. pthread_mutex_t *mutex,
  131. const struct timespec *abstime)
  132. {
  133. int64_t abs_milli = abstime->tv_sec * 1000LL + abstime->tv_nsec / 1000000;
  134. ULONG t = av_clip64(abs_milli - av_gettime() / 1000, 0, ULONG_MAX);
  135. __atomic_increment(&cond->wait_count);
  136. pthread_mutex_unlock(mutex);
  137. APIRET ret = DosWaitEventSem(cond->event_sem, t);
  138. __atomic_decrement(&cond->wait_count);
  139. DosPostEventSem(cond->ack_sem);
  140. pthread_mutex_lock(mutex);
  141. return (ret == ERROR_TIMEOUT) ? ETIMEDOUT : 0;
  142. }
  143. static av_always_inline int pthread_cond_wait(pthread_cond_t *cond,
  144. pthread_mutex_t *mutex)
  145. {
  146. __atomic_increment(&cond->wait_count);
  147. pthread_mutex_unlock(mutex);
  148. DosWaitEventSem(cond->event_sem, SEM_INDEFINITE_WAIT);
  149. __atomic_decrement(&cond->wait_count);
  150. DosPostEventSem(cond->ack_sem);
  151. pthread_mutex_lock(mutex);
  152. return 0;
  153. }
  154. static av_always_inline int pthread_once(pthread_once_t *once_control,
  155. void (*init_routine)(void))
  156. {
  157. if (!once_control->done)
  158. {
  159. _fmutex_request(&once_control->mtx, 0);
  160. if (!once_control->done)
  161. {
  162. init_routine();
  163. once_control->done = 1;
  164. }
  165. _fmutex_release(&once_control->mtx);
  166. }
  167. return 0;
  168. }
  169. #endif /* COMPAT_OS2THREADS_H */