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.

198 lines
4.5KB

  1. /*
  2. * Copyright (c) 2011 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 <sys/builtin.h>
  31. #include <sys/fmutex.h>
  32. #include "libavutil/mem.h"
  33. typedef TID pthread_t;
  34. typedef void pthread_attr_t;
  35. typedef HMTX pthread_mutex_t;
  36. typedef void pthread_mutexattr_t;
  37. typedef struct {
  38. HEV event_sem;
  39. HEV ack_sem;
  40. volatile unsigned wait_count;
  41. } pthread_cond_t;
  42. typedef void pthread_condattr_t;
  43. typedef struct {
  44. volatile int done;
  45. _fmutex mtx;
  46. } pthread_once_t;
  47. #define PTHREAD_ONCE_INIT {0, _FMUTEX_INITIALIZER}
  48. struct thread_arg {
  49. void *(*start_routine)(void *);
  50. void *arg;
  51. };
  52. static void thread_entry(void *arg)
  53. {
  54. struct thread_arg *thread_arg = arg;
  55. thread_arg->start_routine(thread_arg->arg);
  56. av_free(thread_arg);
  57. }
  58. static av_always_inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg)
  59. {
  60. struct thread_arg *thread_arg;
  61. thread_arg = av_mallocz(sizeof(struct thread_arg));
  62. if (!thread_arg)
  63. return ENOMEM;
  64. thread_arg->start_routine = start_routine;
  65. thread_arg->arg = arg;
  66. *thread = _beginthread(thread_entry, NULL, 256 * 1024, thread_arg);
  67. return 0;
  68. }
  69. static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
  70. {
  71. DosWaitThread((PTID)&thread, DCWW_WAIT);
  72. return 0;
  73. }
  74. static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
  75. {
  76. DosCreateMutexSem(NULL, (PHMTX)mutex, 0, FALSE);
  77. return 0;
  78. }
  79. static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
  80. {
  81. DosCloseMutexSem(*(PHMTX)mutex);
  82. return 0;
  83. }
  84. static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
  85. {
  86. DosRequestMutexSem(*(PHMTX)mutex, SEM_INDEFINITE_WAIT);
  87. return 0;
  88. }
  89. static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
  90. {
  91. DosReleaseMutexSem(*(PHMTX)mutex);
  92. return 0;
  93. }
  94. static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
  95. {
  96. DosCreateEventSem(NULL, &cond->event_sem, DCE_POSTONE, FALSE);
  97. DosCreateEventSem(NULL, &cond->ack_sem, DCE_POSTONE, FALSE);
  98. cond->wait_count = 0;
  99. return 0;
  100. }
  101. static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
  102. {
  103. DosCloseEventSem(cond->event_sem);
  104. DosCloseEventSem(cond->ack_sem);
  105. return 0;
  106. }
  107. static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
  108. {
  109. if (!__atomic_cmpxchg32(&cond->wait_count, 0, 0)) {
  110. DosPostEventSem(cond->event_sem);
  111. DosWaitEventSem(cond->ack_sem, SEM_INDEFINITE_WAIT);
  112. }
  113. return 0;
  114. }
  115. static av_always_inline int pthread_cond_broadcast(pthread_cond_t *cond)
  116. {
  117. while (!__atomic_cmpxchg32(&cond->wait_count, 0, 0))
  118. pthread_cond_signal(cond);
  119. return 0;
  120. }
  121. static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
  122. {
  123. __atomic_increment(&cond->wait_count);
  124. pthread_mutex_unlock(mutex);
  125. DosWaitEventSem(cond->event_sem, SEM_INDEFINITE_WAIT);
  126. __atomic_decrement(&cond->wait_count);
  127. DosPostEventSem(cond->ack_sem);
  128. pthread_mutex_lock(mutex);
  129. return 0;
  130. }
  131. static av_always_inline int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
  132. {
  133. if (!once_control->done)
  134. {
  135. _fmutex_request(&once_control->mtx, 0);
  136. if (!once_control->done)
  137. {
  138. init_routine();
  139. once_control->done = 1;
  140. }
  141. _fmutex_release(&once_control->mtx);
  142. }
  143. return 0;
  144. }
  145. #endif /* COMPAT_OS2THREADS_H */