blob: 2177a033ecbb029aa0a3855a360e4123fb920d20 [file] [log] [blame]
Nest DevInfra8e1cc552016-03-17 14:59:01 -07001/*
Nest DevInfrad0967452020-06-02 18:02:16 +00002 * Copyright (c) 2011-2017 KO Myung-Hun <komh@chollian.net>
Nest DevInfra8e1cc552016-03-17 14:59:01 -07003 *
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/**
22 * @file
23 * os2threads to pthreads wrapper
24 */
25
26#ifndef COMPAT_OS2THREADS_H
27#define COMPAT_OS2THREADS_H
28
29#define INCL_DOS
30#include <os2.h>
31
32#undef __STRICT_ANSI__ /* for _beginthread() */
33#include <stdlib.h>
34
35#include <sys/builtin.h>
36#include <sys/fmutex.h>
37
38#include "libavutil/attributes.h"
39
40typedef struct {
41 TID tid;
42 void *(*start_routine)(void *);
43 void *arg;
44 void *result;
45} pthread_t;
46
47typedef void pthread_attr_t;
48
Nest DevInfrad0967452020-06-02 18:02:16 +000049typedef _fmutex pthread_mutex_t;
Nest DevInfra8e1cc552016-03-17 14:59:01 -070050typedef void pthread_mutexattr_t;
51
Nest DevInfrad0967452020-06-02 18:02:16 +000052#define PTHREAD_MUTEX_INITIALIZER _FMUTEX_INITIALIZER
53
Nest DevInfra8e1cc552016-03-17 14:59:01 -070054typedef struct {
55 HEV event_sem;
56 HEV ack_sem;
57 volatile unsigned wait_count;
58} pthread_cond_t;
59
60typedef void pthread_condattr_t;
61
62typedef struct {
63 volatile int done;
64 _fmutex mtx;
65} pthread_once_t;
66
67#define PTHREAD_ONCE_INIT {0, _FMUTEX_INITIALIZER}
68
69static void thread_entry(void *arg)
70{
71 pthread_t *thread = arg;
72
73 thread->result = thread->start_routine(thread->arg);
74}
75
76static av_always_inline int pthread_create(pthread_t *thread,
77 const pthread_attr_t *attr,
78 void *(*start_routine)(void*),
79 void *arg)
80{
81 thread->start_routine = start_routine;
82 thread->arg = arg;
83 thread->result = NULL;
84
85 thread->tid = _beginthread(thread_entry, NULL, 1024 * 1024, thread);
86
87 return 0;
88}
89
90static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
91{
92 DosWaitThread(&thread.tid, DCWW_WAIT);
93
94 if (value_ptr)
95 *value_ptr = thread.result;
96
97 return 0;
98}
99
100static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex,
101 const pthread_mutexattr_t *attr)
102{
Nest DevInfrad0967452020-06-02 18:02:16 +0000103 _fmutex_create(mutex, 0);
Nest DevInfra8e1cc552016-03-17 14:59:01 -0700104
105 return 0;
106}
107
108static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
109{
Nest DevInfrad0967452020-06-02 18:02:16 +0000110 _fmutex_close(mutex);
Nest DevInfra8e1cc552016-03-17 14:59:01 -0700111
112 return 0;
113}
114
115static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
116{
Nest DevInfrad0967452020-06-02 18:02:16 +0000117 _fmutex_request(mutex, 0);
Nest DevInfra8e1cc552016-03-17 14:59:01 -0700118
119 return 0;
120}
121
122static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
123{
Nest DevInfrad0967452020-06-02 18:02:16 +0000124 _fmutex_release(mutex);
Nest DevInfra8e1cc552016-03-17 14:59:01 -0700125
126 return 0;
127}
128
129static av_always_inline int pthread_cond_init(pthread_cond_t *cond,
130 const pthread_condattr_t *attr)
131{
132 DosCreateEventSem(NULL, &cond->event_sem, DCE_POSTONE, FALSE);
133 DosCreateEventSem(NULL, &cond->ack_sem, DCE_POSTONE, FALSE);
134
135 cond->wait_count = 0;
136
137 return 0;
138}
139
140static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
141{
142 DosCloseEventSem(cond->event_sem);
143 DosCloseEventSem(cond->ack_sem);
144
145 return 0;
146}
147
148static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
149{
150 if (!__atomic_cmpxchg32(&cond->wait_count, 0, 0)) {
151 DosPostEventSem(cond->event_sem);
152 DosWaitEventSem(cond->ack_sem, SEM_INDEFINITE_WAIT);
153 }
154
155 return 0;
156}
157
158static av_always_inline int pthread_cond_broadcast(pthread_cond_t *cond)
159{
160 while (!__atomic_cmpxchg32(&cond->wait_count, 0, 0))
161 pthread_cond_signal(cond);
162
163 return 0;
164}
165
166static av_always_inline int pthread_cond_wait(pthread_cond_t *cond,
167 pthread_mutex_t *mutex)
168{
169 __atomic_increment(&cond->wait_count);
170
171 pthread_mutex_unlock(mutex);
172
173 DosWaitEventSem(cond->event_sem, SEM_INDEFINITE_WAIT);
174
175 __atomic_decrement(&cond->wait_count);
176
177 DosPostEventSem(cond->ack_sem);
178
179 pthread_mutex_lock(mutex);
180
181 return 0;
182}
183
184static av_always_inline int pthread_once(pthread_once_t *once_control,
185 void (*init_routine)(void))
186{
187 if (!once_control->done)
188 {
189 _fmutex_request(&once_control->mtx, 0);
190
191 if (!once_control->done)
192 {
193 init_routine();
194
195 once_control->done = 1;
196 }
197
198 _fmutex_release(&once_control->mtx);
199 }
200
201 return 0;
202}
203#endif /* COMPAT_OS2THREADS_H */