]> git.sesse.net Git - ffmpeg/blob - compat/os2threads.h
Merge commit 'c011beda2611acfeb6f67d4fdf30d1eceed9e62f'
[ffmpeg] / compat / os2threads.h
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 /**
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
40 typedef struct {
41     TID tid;
42     void *(*start_routine)(void *);
43     void *arg;
44     void *result;
45 } pthread_t;
46
47 typedef void pthread_attr_t;
48
49 typedef _fmutex pthread_mutex_t;
50 typedef void pthread_mutexattr_t;
51
52 #define PTHREAD_MUTEX_INITIALIZER _FMUTEX_INITIALIZER
53
54 typedef struct {
55     HEV event_sem;
56     HEV ack_sem;
57     volatile unsigned  wait_count;
58 } pthread_cond_t;
59
60 typedef void pthread_condattr_t;
61
62 typedef struct {
63     volatile int done;
64     _fmutex mtx;
65 } pthread_once_t;
66
67 #define PTHREAD_ONCE_INIT {0, _FMUTEX_INITIALIZER}
68
69 static void thread_entry(void *arg)
70 {
71     pthread_t *thread = arg;
72
73     thread->result = thread->start_routine(thread->arg);
74 }
75
76 static 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
90 static 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
100 static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex,
101                                                const pthread_mutexattr_t *attr)
102 {
103     _fmutex_create(mutex, 0);
104
105     return 0;
106 }
107
108 static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
109 {
110     _fmutex_close(mutex);
111
112     return 0;
113 }
114
115 static av_always_inline int pthread_mutex_lock(pthread_mutex_t *mutex)
116 {
117     _fmutex_request(mutex, 0);
118
119     return 0;
120 }
121
122 static av_always_inline int pthread_mutex_unlock(pthread_mutex_t *mutex)
123 {
124     _fmutex_release(mutex);
125
126     return 0;
127 }
128
129 static 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
140 static 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
148 static 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
158 static 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
166 static 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
184 static 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 */