xref: /rockchip-linux_mpp/osal/mpp_thread.c (revision 437bfbeb9567cca9cd9080e3f6954aa9d6a94f18)
1*437bfbebSnyanmisaka /* SPDX-License-Identifier: Apache-2.0 OR MIT */
2*437bfbebSnyanmisaka /*
3*437bfbebSnyanmisaka  * Copyright (c) 2015 Rockchip Electronics Co., Ltd.
4*437bfbebSnyanmisaka  */
5*437bfbebSnyanmisaka 
6*437bfbebSnyanmisaka #define MODULE_TAG "mpp_thread"
7*437bfbebSnyanmisaka 
8*437bfbebSnyanmisaka #include <string.h>
9*437bfbebSnyanmisaka 
10*437bfbebSnyanmisaka #include "mpp_mem.h"
11*437bfbebSnyanmisaka #include "mpp_lock.h"
12*437bfbebSnyanmisaka #include "mpp_debug.h"
13*437bfbebSnyanmisaka #include "mpp_common.h"
14*437bfbebSnyanmisaka #include "mpp_thread.h"
15*437bfbebSnyanmisaka 
16*437bfbebSnyanmisaka #define THREAD_DBG_FUNC             (0x00000001)
17*437bfbebSnyanmisaka 
18*437bfbebSnyanmisaka static rk_u32 thread_debug = 0;
19*437bfbebSnyanmisaka 
20*437bfbebSnyanmisaka #define thread_dbg(flag, fmt, ...)  _mpp_dbg(thread_debug, flag, fmt, ## __VA_ARGS__)
21*437bfbebSnyanmisaka 
mpp_thread_create(MppThreadFunc func,void * ctx,const char * name)22*437bfbebSnyanmisaka MppThread *mpp_thread_create(MppThreadFunc func, void *ctx, const char *name)
23*437bfbebSnyanmisaka {
24*437bfbebSnyanmisaka     MppThread *thread = mpp_malloc(MppThread, 1);
25*437bfbebSnyanmisaka     int i;
26*437bfbebSnyanmisaka 
27*437bfbebSnyanmisaka     if (thread) {
28*437bfbebSnyanmisaka         thread->func = func;
29*437bfbebSnyanmisaka         thread->ctx = ctx;
30*437bfbebSnyanmisaka 
31*437bfbebSnyanmisaka         thread->thd_status[THREAD_WORK] = MPP_THREAD_UNINITED;
32*437bfbebSnyanmisaka         thread->thd_status[THREAD_INPUT] = MPP_THREAD_RUNNING;
33*437bfbebSnyanmisaka         thread->thd_status[THREAD_OUTPUT] = MPP_THREAD_RUNNING;
34*437bfbebSnyanmisaka         thread->thd_status[THREAD_CONTROL] = MPP_THREAD_RUNNING;
35*437bfbebSnyanmisaka 
36*437bfbebSnyanmisaka         if (name) {
37*437bfbebSnyanmisaka             strncpy(thread->name, name, THREAD_NAME_LEN - 1);
38*437bfbebSnyanmisaka             thread->name[THREAD_NAME_LEN - 1] = '\0';
39*437bfbebSnyanmisaka         } else {
40*437bfbebSnyanmisaka             snprintf(thread->name, THREAD_NAME_LEN, "MppThread");
41*437bfbebSnyanmisaka         }
42*437bfbebSnyanmisaka         for (i = 0; i < THREAD_SIGNAL_BUTT; i++) {
43*437bfbebSnyanmisaka             mpp_mutex_cond_init(&thread->mutex_cond[i]);
44*437bfbebSnyanmisaka         }
45*437bfbebSnyanmisaka     }
46*437bfbebSnyanmisaka 
47*437bfbebSnyanmisaka     return thread;
48*437bfbebSnyanmisaka }
49*437bfbebSnyanmisaka 
mpp_thread_dump_status(MppThread * thread)50*437bfbebSnyanmisaka void mpp_thread_dump_status(MppThread *thread)
51*437bfbebSnyanmisaka {
52*437bfbebSnyanmisaka     mpp_log("thread %s status: %d %d %d %d\n", thread->name,
53*437bfbebSnyanmisaka             thread->thd_status[THREAD_WORK], thread->thd_status[THREAD_INPUT],
54*437bfbebSnyanmisaka             thread->thd_status[THREAD_OUTPUT], thread->thd_status[THREAD_CONTROL]);
55*437bfbebSnyanmisaka }
56*437bfbebSnyanmisaka 
mpp_thread_start(MppThread * thread)57*437bfbebSnyanmisaka void mpp_thread_start(MppThread *thread)
58*437bfbebSnyanmisaka {
59*437bfbebSnyanmisaka     pthread_attr_t attr;
60*437bfbebSnyanmisaka 
61*437bfbebSnyanmisaka     pthread_attr_init(&attr);
62*437bfbebSnyanmisaka     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
63*437bfbebSnyanmisaka 
64*437bfbebSnyanmisaka     if (mpp_thread_get_status(thread, THREAD_WORK) == MPP_THREAD_UNINITED) {
65*437bfbebSnyanmisaka         mpp_thread_set_status(thread, MPP_THREAD_RUNNING, THREAD_WORK);
66*437bfbebSnyanmisaka         if (0 == pthread_create(&thread->thd, &attr, thread->func, thread->ctx)) {
67*437bfbebSnyanmisaka             int ret = pthread_setname_np(thread->thd, thread->name);
68*437bfbebSnyanmisaka             if (ret) {
69*437bfbebSnyanmisaka                 mpp_err("thread %p setname %s failed\n", thread->func, thread->name);
70*437bfbebSnyanmisaka             }
71*437bfbebSnyanmisaka             thread_dbg(THREAD_DBG_FUNC, "thread %s %p context %p create success\n",
72*437bfbebSnyanmisaka                        thread->name, thread->func, thread->ctx);
73*437bfbebSnyanmisaka         } else {
74*437bfbebSnyanmisaka             mpp_thread_set_status(thread, MPP_THREAD_UNINITED, THREAD_WORK);
75*437bfbebSnyanmisaka         }
76*437bfbebSnyanmisaka     }
77*437bfbebSnyanmisaka 
78*437bfbebSnyanmisaka     pthread_attr_destroy(&attr);
79*437bfbebSnyanmisaka }
80*437bfbebSnyanmisaka 
mpp_thread_stop(MppThread * thread)81*437bfbebSnyanmisaka void mpp_thread_stop(MppThread *thread)
82*437bfbebSnyanmisaka {
83*437bfbebSnyanmisaka     if (mpp_thread_get_status(thread, THREAD_WORK) != MPP_THREAD_UNINITED) {
84*437bfbebSnyanmisaka         void *dummy;
85*437bfbebSnyanmisaka 
86*437bfbebSnyanmisaka         mpp_thread_lock(thread, THREAD_WORK);
87*437bfbebSnyanmisaka         mpp_thread_set_status(thread, MPP_THREAD_STOPPING, THREAD_WORK);
88*437bfbebSnyanmisaka 
89*437bfbebSnyanmisaka         thread_dbg(THREAD_DBG_FUNC, "MPP_THREAD_STOPPING status set thd %p\n", (void *)thread);
90*437bfbebSnyanmisaka         mpp_thread_signal(thread, THREAD_WORK);
91*437bfbebSnyanmisaka         mpp_thread_unlock(thread, THREAD_WORK);
92*437bfbebSnyanmisaka 
93*437bfbebSnyanmisaka         pthread_join(thread->thd, &dummy);
94*437bfbebSnyanmisaka         thread_dbg(THREAD_DBG_FUNC, "thread %s %p context %p destroy success\n", thread->name, thread->func, thread->ctx);
95*437bfbebSnyanmisaka 
96*437bfbebSnyanmisaka         mpp_thread_set_status(thread, MPP_THREAD_UNINITED, THREAD_WORK);
97*437bfbebSnyanmisaka     }
98*437bfbebSnyanmisaka }
99*437bfbebSnyanmisaka 
mpp_thread_destroy(MppThread * thread)100*437bfbebSnyanmisaka void mpp_thread_destroy(MppThread *thread)
101*437bfbebSnyanmisaka {
102*437bfbebSnyanmisaka     if (thread) {
103*437bfbebSnyanmisaka         mpp_thread_stop(thread);
104*437bfbebSnyanmisaka         mpp_free(thread);
105*437bfbebSnyanmisaka     }
106*437bfbebSnyanmisaka }
107*437bfbebSnyanmisaka 
mpp_mutex_init(MppMutex * mutex)108*437bfbebSnyanmisaka void mpp_mutex_init(MppMutex *mutex)
109*437bfbebSnyanmisaka {
110*437bfbebSnyanmisaka     pthread_mutexattr_t attr;
111*437bfbebSnyanmisaka     pthread_mutexattr_init(&attr);
112*437bfbebSnyanmisaka     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
113*437bfbebSnyanmisaka     pthread_mutex_init(&mutex->lock, &attr);
114*437bfbebSnyanmisaka     pthread_mutexattr_destroy(&attr);
115*437bfbebSnyanmisaka }
116*437bfbebSnyanmisaka 
mpp_mutex_destroy(MppMutex * mutex)117*437bfbebSnyanmisaka void mpp_mutex_destroy(MppMutex *mutex)
118*437bfbebSnyanmisaka {
119*437bfbebSnyanmisaka     pthread_mutex_destroy(&mutex->lock);
120*437bfbebSnyanmisaka }
121*437bfbebSnyanmisaka 
mpp_mutex_lock(MppMutex * mutex)122*437bfbebSnyanmisaka void mpp_mutex_lock(MppMutex *mutex)
123*437bfbebSnyanmisaka {
124*437bfbebSnyanmisaka     pthread_mutex_lock(&mutex->lock);
125*437bfbebSnyanmisaka }
126*437bfbebSnyanmisaka 
mpp_mutex_unlock(MppMutex * mutex)127*437bfbebSnyanmisaka void mpp_mutex_unlock(MppMutex *mutex)
128*437bfbebSnyanmisaka {
129*437bfbebSnyanmisaka     pthread_mutex_unlock(&mutex->lock);
130*437bfbebSnyanmisaka }
131*437bfbebSnyanmisaka 
mpp_mutex_trylock(MppMutex * mutex)132*437bfbebSnyanmisaka int mpp_mutex_trylock(MppMutex *mutex)
133*437bfbebSnyanmisaka {
134*437bfbebSnyanmisaka     return pthread_mutex_trylock(&mutex->lock);
135*437bfbebSnyanmisaka }
136*437bfbebSnyanmisaka 
137*437bfbebSnyanmisaka // MppCond functions
mpp_cond_init(MppCond * condition)138*437bfbebSnyanmisaka void mpp_cond_init(MppCond *condition)
139*437bfbebSnyanmisaka {
140*437bfbebSnyanmisaka #ifdef COND_USE_CLOCK_MONOTONIC
141*437bfbebSnyanmisaka     pthread_condattr_t attr;
142*437bfbebSnyanmisaka 
143*437bfbebSnyanmisaka     pthread_condattr_init(&attr);;
144*437bfbebSnyanmisaka 
145*437bfbebSnyanmisaka     if (pthread_condattr_setclock(&attr, CLOCK_MONOTONIC)) {
146*437bfbebSnyanmisaka         pthread_cond_init(&condition->cond, NULL);
147*437bfbebSnyanmisaka         condition->clock_id = CLOCK_REALTIME;
148*437bfbebSnyanmisaka     } else {
149*437bfbebSnyanmisaka         pthread_cond_init(&condition->cond, &attr);
150*437bfbebSnyanmisaka         condition->clock_id = CLOCK_MONOTONIC;
151*437bfbebSnyanmisaka     }
152*437bfbebSnyanmisaka 
153*437bfbebSnyanmisaka     pthread_condattr_destroy(&attr);
154*437bfbebSnyanmisaka #else
155*437bfbebSnyanmisaka     pthread_cond_init(&condition->cond, NULL);
156*437bfbebSnyanmisaka     condition->clock_id = CLOCK_REALTIME;
157*437bfbebSnyanmisaka #endif // COND_USE_CLOCK_MONOTONIC
158*437bfbebSnyanmisaka }
159*437bfbebSnyanmisaka 
mpp_cond_destroy(MppCond * condition)160*437bfbebSnyanmisaka void mpp_cond_destroy(MppCond *condition)
161*437bfbebSnyanmisaka {
162*437bfbebSnyanmisaka     pthread_cond_destroy(&condition->cond);
163*437bfbebSnyanmisaka }
164*437bfbebSnyanmisaka 
mpp_cond_wait(MppCond * condition,MppMutex * mutex)165*437bfbebSnyanmisaka rk_s32 mpp_cond_wait(MppCond *condition, MppMutex *mutex)
166*437bfbebSnyanmisaka {
167*437bfbebSnyanmisaka     return pthread_cond_wait(&condition->cond, &mutex->lock);
168*437bfbebSnyanmisaka }
169*437bfbebSnyanmisaka 
mpp_cond_timedwait(MppCond * condition,MppMutex * mutex,rk_s64 timeout)170*437bfbebSnyanmisaka rk_s32 mpp_cond_timedwait(MppCond *condition, MppMutex *mutex, rk_s64 timeout)
171*437bfbebSnyanmisaka {
172*437bfbebSnyanmisaka     struct timespec ts;
173*437bfbebSnyanmisaka 
174*437bfbebSnyanmisaka     clock_gettime(condition->clock_id, &ts);
175*437bfbebSnyanmisaka 
176*437bfbebSnyanmisaka     ts.tv_sec += timeout / 1000;
177*437bfbebSnyanmisaka     ts.tv_nsec += (timeout % 1000) * 1000000;
178*437bfbebSnyanmisaka     ts.tv_sec += ts.tv_nsec / 1000000000;
179*437bfbebSnyanmisaka     ts.tv_nsec %= 1000000000;
180*437bfbebSnyanmisaka 
181*437bfbebSnyanmisaka     return pthread_cond_timedwait(&condition->cond, &mutex->lock, &ts);
182*437bfbebSnyanmisaka }
183*437bfbebSnyanmisaka 
mpp_cond_signal(MppCond * condition)184*437bfbebSnyanmisaka rk_s32 mpp_cond_signal(MppCond *condition)
185*437bfbebSnyanmisaka {
186*437bfbebSnyanmisaka     return pthread_cond_signal(&condition->cond);
187*437bfbebSnyanmisaka }
188*437bfbebSnyanmisaka 
mpp_cond_broadcast(MppCond * condition)189*437bfbebSnyanmisaka rk_s32 mpp_cond_broadcast(MppCond *condition)
190*437bfbebSnyanmisaka {
191*437bfbebSnyanmisaka     return pthread_cond_broadcast(&condition->cond);
192*437bfbebSnyanmisaka }
193*437bfbebSnyanmisaka 
194*437bfbebSnyanmisaka // MppMutexCond functions
mpp_mutex_cond_init(MppMutexCond * mutexCond)195*437bfbebSnyanmisaka void mpp_mutex_cond_init(MppMutexCond *mutexCond)
196*437bfbebSnyanmisaka {
197*437bfbebSnyanmisaka     mpp_mutex_init(&mutexCond->lock);
198*437bfbebSnyanmisaka     mpp_cond_init(&mutexCond->cond);
199*437bfbebSnyanmisaka }
200*437bfbebSnyanmisaka 
mpp_mutex_cond_destroy(MppMutexCond * mutexCond)201*437bfbebSnyanmisaka void mpp_mutex_cond_destroy(MppMutexCond *mutexCond)
202*437bfbebSnyanmisaka {
203*437bfbebSnyanmisaka     mpp_mutex_destroy(&mutexCond->lock);
204*437bfbebSnyanmisaka     mpp_cond_destroy(&mutexCond->cond);
205*437bfbebSnyanmisaka }
206*437bfbebSnyanmisaka 
mpp_mutex_cond_lock(MppMutexCond * mutexCond)207*437bfbebSnyanmisaka void mpp_mutex_cond_lock(MppMutexCond *mutexCond)
208*437bfbebSnyanmisaka {
209*437bfbebSnyanmisaka     mpp_mutex_lock(&mutexCond->lock);
210*437bfbebSnyanmisaka }
211*437bfbebSnyanmisaka 
mpp_mutex_cond_unlock(MppMutexCond * mutexCond)212*437bfbebSnyanmisaka void mpp_mutex_cond_unlock(MppMutexCond *mutexCond)
213*437bfbebSnyanmisaka {
214*437bfbebSnyanmisaka     mpp_mutex_unlock(&mutexCond->lock);
215*437bfbebSnyanmisaka }
216*437bfbebSnyanmisaka 
mpp_mutex_cond_trylock(MppMutexCond * mutexCond)217*437bfbebSnyanmisaka int mpp_mutex_cond_trylock(MppMutexCond *mutexCond)
218*437bfbebSnyanmisaka {
219*437bfbebSnyanmisaka     return mpp_mutex_trylock(&mutexCond->lock);
220*437bfbebSnyanmisaka }
221*437bfbebSnyanmisaka 
mpp_mutex_cond_wait(MppMutexCond * mutexCond)222*437bfbebSnyanmisaka rk_s32 mpp_mutex_cond_wait(MppMutexCond *mutexCond)
223*437bfbebSnyanmisaka {
224*437bfbebSnyanmisaka     return mpp_cond_wait(&mutexCond->cond, &mutexCond->lock);
225*437bfbebSnyanmisaka }
226*437bfbebSnyanmisaka 
mpp_mutex_cond_timedwait(MppMutexCond * mutexCond,rk_s64 timeout)227*437bfbebSnyanmisaka rk_s32 mpp_mutex_cond_timedwait(MppMutexCond *mutexCond, rk_s64 timeout)
228*437bfbebSnyanmisaka {
229*437bfbebSnyanmisaka     return mpp_cond_timedwait(&mutexCond->cond, &mutexCond->lock, timeout);
230*437bfbebSnyanmisaka }
231*437bfbebSnyanmisaka 
mpp_mutex_cond_signal(MppMutexCond * mutexCond)232*437bfbebSnyanmisaka void mpp_mutex_cond_signal(MppMutexCond *mutexCond)
233*437bfbebSnyanmisaka {
234*437bfbebSnyanmisaka     mpp_cond_signal(&mutexCond->cond);
235*437bfbebSnyanmisaka }
236*437bfbebSnyanmisaka 
mpp_mutex_cond_broadcast(MppMutexCond * mutexCond)237*437bfbebSnyanmisaka void mpp_mutex_cond_broadcast(MppMutexCond *mutexCond)
238*437bfbebSnyanmisaka {
239*437bfbebSnyanmisaka     mpp_cond_broadcast(&mutexCond->cond);
240*437bfbebSnyanmisaka }
241*437bfbebSnyanmisaka 
242*437bfbebSnyanmisaka // MppThread functions
mpp_thread_init(MppThread * thread,MppThreadFunc func,void * ctx,const char * name)243*437bfbebSnyanmisaka void mpp_thread_init(MppThread *thread, MppThreadFunc func, void *ctx, const char *name)
244*437bfbebSnyanmisaka {
245*437bfbebSnyanmisaka     thread->func = func;
246*437bfbebSnyanmisaka     thread->ctx = ctx;
247*437bfbebSnyanmisaka     int i;
248*437bfbebSnyanmisaka 
249*437bfbebSnyanmisaka     if (name) {
250*437bfbebSnyanmisaka         strncpy(thread->name, name, THREAD_NAME_LEN - 1);
251*437bfbebSnyanmisaka         thread->name[THREAD_NAME_LEN - 1] = '\0';
252*437bfbebSnyanmisaka     }
253*437bfbebSnyanmisaka     for (i = 0; i < THREAD_SIGNAL_BUTT; i++) {
254*437bfbebSnyanmisaka         mpp_mutex_cond_init(&thread->mutex_cond[i]);
255*437bfbebSnyanmisaka         thread->thd_status[i] = MPP_THREAD_UNINITED;
256*437bfbebSnyanmisaka     }
257*437bfbebSnyanmisaka }
258*437bfbebSnyanmisaka 
mpp_thread_set_status(MppThread * thread,MppThreadStatus status,MppThreadSignalId id)259*437bfbebSnyanmisaka void mpp_thread_set_status(MppThread *thread, MppThreadStatus status, MppThreadSignalId id)
260*437bfbebSnyanmisaka {
261*437bfbebSnyanmisaka     assert(id < THREAD_SIGNAL_BUTT);
262*437bfbebSnyanmisaka     thread->thd_status[id] = status;
263*437bfbebSnyanmisaka }
264*437bfbebSnyanmisaka 
mpp_thread_get_status(MppThread * thread,MppThreadSignalId id)265*437bfbebSnyanmisaka MppThreadStatus mpp_thread_get_status(MppThread *thread, MppThreadSignalId id)
266*437bfbebSnyanmisaka {
267*437bfbebSnyanmisaka     assert(id < THREAD_SIGNAL_BUTT);
268*437bfbebSnyanmisaka     return thread->thd_status[id];
269*437bfbebSnyanmisaka }
270*437bfbebSnyanmisaka 
mpp_thread_lock(MppThread * thread,MppThreadSignalId id)271*437bfbebSnyanmisaka void mpp_thread_lock(MppThread *thread, MppThreadSignalId id)
272*437bfbebSnyanmisaka {
273*437bfbebSnyanmisaka     assert(id < THREAD_SIGNAL_BUTT);
274*437bfbebSnyanmisaka     mpp_mutex_cond_lock(&thread->mutex_cond[id]);
275*437bfbebSnyanmisaka }
276*437bfbebSnyanmisaka 
mpp_thread_unlock(MppThread * thread,MppThreadSignalId id)277*437bfbebSnyanmisaka void mpp_thread_unlock(MppThread *thread, MppThreadSignalId id)
278*437bfbebSnyanmisaka {
279*437bfbebSnyanmisaka     assert(id < THREAD_SIGNAL_BUTT);
280*437bfbebSnyanmisaka     mpp_mutex_cond_unlock(&thread->mutex_cond[id]);
281*437bfbebSnyanmisaka }
282*437bfbebSnyanmisaka 
mpp_thread_wait(MppThread * thread,MppThreadSignalId id)283*437bfbebSnyanmisaka void mpp_thread_wait(MppThread *thread, MppThreadSignalId id)
284*437bfbebSnyanmisaka {
285*437bfbebSnyanmisaka     assert(id < THREAD_SIGNAL_BUTT);
286*437bfbebSnyanmisaka     MppThreadStatus status = thread->thd_status[id];
287*437bfbebSnyanmisaka     thread->thd_status[id] = MPP_THREAD_WAITING;
288*437bfbebSnyanmisaka     mpp_mutex_cond_wait(&thread->mutex_cond[id]);
289*437bfbebSnyanmisaka 
290*437bfbebSnyanmisaka     if (thread->thd_status[id] == MPP_THREAD_WAITING)
291*437bfbebSnyanmisaka         thread->thd_status[id] = status;
292*437bfbebSnyanmisaka }
293*437bfbebSnyanmisaka 
mpp_thread_signal(MppThread * thread,MppThreadSignalId id)294*437bfbebSnyanmisaka void mpp_thread_signal(MppThread *thread, MppThreadSignalId id)
295*437bfbebSnyanmisaka {
296*437bfbebSnyanmisaka     assert(id < THREAD_SIGNAL_BUTT);
297*437bfbebSnyanmisaka     mpp_mutex_cond_signal(&thread->mutex_cond[id]);
298*437bfbebSnyanmisaka }
299*437bfbebSnyanmisaka 
300*437bfbebSnyanmisaka typedef struct MppSThdImpl_t {
301*437bfbebSnyanmisaka     char            *name;
302*437bfbebSnyanmisaka     MppSThdFunc     func;
303*437bfbebSnyanmisaka     MppSThdStatus   status;
304*437bfbebSnyanmisaka     rk_s32          idx;
305*437bfbebSnyanmisaka     pthread_t       thd;
306*437bfbebSnyanmisaka     pthread_mutex_t lock;
307*437bfbebSnyanmisaka     pthread_cond_t  cond;
308*437bfbebSnyanmisaka     MppSThdCtx      ctx;
309*437bfbebSnyanmisaka } MppSThdImpl;
310*437bfbebSnyanmisaka 
311*437bfbebSnyanmisaka typedef struct MppSThdGrpImpl_t {
312*437bfbebSnyanmisaka     char            name[THREAD_NAME_LEN];
313*437bfbebSnyanmisaka     rk_s32          count;
314*437bfbebSnyanmisaka     MppSThdStatus   status;
315*437bfbebSnyanmisaka     pthread_mutex_t lock;
316*437bfbebSnyanmisaka     MppSThdImpl     thds[];
317*437bfbebSnyanmisaka } MppSThdGrpImpl;
318*437bfbebSnyanmisaka 
state2str(MppSThdStatus state)319*437bfbebSnyanmisaka static const char *state2str(MppSThdStatus state)
320*437bfbebSnyanmisaka {
321*437bfbebSnyanmisaka     static const char *strof_sthd_status[] = {
322*437bfbebSnyanmisaka         "uninited",
323*437bfbebSnyanmisaka         "ready",
324*437bfbebSnyanmisaka         "running",
325*437bfbebSnyanmisaka         "waiting",
326*437bfbebSnyanmisaka         "stopping",
327*437bfbebSnyanmisaka         "invalid"
328*437bfbebSnyanmisaka     };
329*437bfbebSnyanmisaka 
330*437bfbebSnyanmisaka     return state < MPP_STHD_BUTT ? strof_sthd_status[state] : strof_sthd_status[MPP_STHD_BUTT];
331*437bfbebSnyanmisaka }
332*437bfbebSnyanmisaka 
check_sthd(const char * name,MppSThdImpl * thd)333*437bfbebSnyanmisaka static rk_s32 check_sthd(const char *name, MppSThdImpl *thd)
334*437bfbebSnyanmisaka {
335*437bfbebSnyanmisaka     if (!thd) {
336*437bfbebSnyanmisaka         mpp_err("mpp_sthd NULL found at %s\n", name);
337*437bfbebSnyanmisaka         return MPP_NOK;
338*437bfbebSnyanmisaka     }
339*437bfbebSnyanmisaka 
340*437bfbebSnyanmisaka     if (thd->ctx.thd != thd) {
341*437bfbebSnyanmisaka         mpp_err("mpp_sthd check %p:%p mismatch at %s\n", thd->ctx.thd, thd, name);
342*437bfbebSnyanmisaka         return MPP_NOK;
343*437bfbebSnyanmisaka     }
344*437bfbebSnyanmisaka 
345*437bfbebSnyanmisaka     return MPP_OK;
346*437bfbebSnyanmisaka }
347*437bfbebSnyanmisaka 
348*437bfbebSnyanmisaka #define CHECK_STHD(thd) check_sthd(__FUNCTION__, (MppSThdImpl *)(thd))
349*437bfbebSnyanmisaka 
mpp_sthd_init(MppSThdImpl * thd,rk_s32 idx)350*437bfbebSnyanmisaka static void mpp_sthd_init(MppSThdImpl *thd, rk_s32 idx)
351*437bfbebSnyanmisaka {
352*437bfbebSnyanmisaka     pthread_mutexattr_t attr;
353*437bfbebSnyanmisaka 
354*437bfbebSnyanmisaka     pthread_mutexattr_init(&attr);
355*437bfbebSnyanmisaka     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
356*437bfbebSnyanmisaka     pthread_mutex_init(&thd->lock, &attr);
357*437bfbebSnyanmisaka     pthread_mutexattr_destroy(&attr);
358*437bfbebSnyanmisaka 
359*437bfbebSnyanmisaka     pthread_cond_init(&thd->cond, NULL);
360*437bfbebSnyanmisaka     thd->ctx.thd = thd;
361*437bfbebSnyanmisaka     thd->idx = idx;
362*437bfbebSnyanmisaka }
363*437bfbebSnyanmisaka 
mpp_sthd_deinit(MppSThdImpl * thd)364*437bfbebSnyanmisaka static void mpp_sthd_deinit(MppSThdImpl *thd)
365*437bfbebSnyanmisaka {
366*437bfbebSnyanmisaka     mpp_assert(thd->ctx.thd == thd);
367*437bfbebSnyanmisaka     mpp_assert(thd->status < MPP_STHD_RUNNING);
368*437bfbebSnyanmisaka 
369*437bfbebSnyanmisaka     pthread_mutex_lock(&thd->lock);
370*437bfbebSnyanmisaka     thd->status = MPP_STHD_UNINITED;
371*437bfbebSnyanmisaka     thd->ctx.thd = NULL;
372*437bfbebSnyanmisaka     pthread_mutex_unlock(&thd->lock);
373*437bfbebSnyanmisaka 
374*437bfbebSnyanmisaka     pthread_cond_destroy(&thd->cond);
375*437bfbebSnyanmisaka     pthread_mutex_destroy(&thd->lock);
376*437bfbebSnyanmisaka }
377*437bfbebSnyanmisaka 
mpp_sthd_create(MppSThdImpl * thd)378*437bfbebSnyanmisaka static MPP_RET mpp_sthd_create(MppSThdImpl *thd)
379*437bfbebSnyanmisaka {
380*437bfbebSnyanmisaka     pthread_attr_t attr;
381*437bfbebSnyanmisaka     MPP_RET ret = MPP_NOK;
382*437bfbebSnyanmisaka 
383*437bfbebSnyanmisaka     mpp_assert(thd->ctx.thd == thd);
384*437bfbebSnyanmisaka     mpp_assert(thd->status < MPP_STHD_RUNNING);
385*437bfbebSnyanmisaka 
386*437bfbebSnyanmisaka     pthread_attr_init(&attr);
387*437bfbebSnyanmisaka     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
388*437bfbebSnyanmisaka 
389*437bfbebSnyanmisaka     // NOTE: set status to running first
390*437bfbebSnyanmisaka     thd->status = MPP_STHD_RUNNING;
391*437bfbebSnyanmisaka     if (0 == pthread_create(&thd->thd, &attr, (MppThreadFunc)thd->func, &thd->ctx)) {
392*437bfbebSnyanmisaka         ret = (MPP_RET)pthread_setname_np(thd->thd, thd->name);
393*437bfbebSnyanmisaka         if (ret)
394*437bfbebSnyanmisaka             mpp_err("%s %p setname failed\n", thd->thd, thd->func);
395*437bfbebSnyanmisaka 
396*437bfbebSnyanmisaka         thread_dbg(THREAD_DBG_FUNC, "thread %s %p context %p create success\n",
397*437bfbebSnyanmisaka                    thd->name, thd->func, thd->ctx.ctx);
398*437bfbebSnyanmisaka         ret = MPP_OK;
399*437bfbebSnyanmisaka     } else {
400*437bfbebSnyanmisaka         thd->status = MPP_STHD_READY;
401*437bfbebSnyanmisaka     }
402*437bfbebSnyanmisaka 
403*437bfbebSnyanmisaka     pthread_attr_destroy(&attr);
404*437bfbebSnyanmisaka 
405*437bfbebSnyanmisaka     return ret;
406*437bfbebSnyanmisaka }
407*437bfbebSnyanmisaka 
mpp_sthd_get(const char * name)408*437bfbebSnyanmisaka MppSThd mpp_sthd_get(const char *name)
409*437bfbebSnyanmisaka {
410*437bfbebSnyanmisaka     rk_s32 size = MPP_ALIGN(sizeof(MppSThdImpl), 8) + THREAD_NAME_LEN;
411*437bfbebSnyanmisaka     MppSThdImpl *thd = mpp_calloc_size(MppSThdImpl, size);
412*437bfbebSnyanmisaka 
413*437bfbebSnyanmisaka     if (!thd) {
414*437bfbebSnyanmisaka         mpp_err_f("failed to create simple thread\n");
415*437bfbebSnyanmisaka         return NULL;
416*437bfbebSnyanmisaka     }
417*437bfbebSnyanmisaka 
418*437bfbebSnyanmisaka     thd->name = (char *)(thd + 1);
419*437bfbebSnyanmisaka     if (!name)
420*437bfbebSnyanmisaka         name = "mpp_sthd";
421*437bfbebSnyanmisaka 
422*437bfbebSnyanmisaka     snprintf(thd->name, THREAD_NAME_LEN - 1, "%s", name);
423*437bfbebSnyanmisaka 
424*437bfbebSnyanmisaka     mpp_sthd_init(thd, -1);
425*437bfbebSnyanmisaka 
426*437bfbebSnyanmisaka     return thd;
427*437bfbebSnyanmisaka }
428*437bfbebSnyanmisaka 
mpp_sthd_put(MppSThd thd)429*437bfbebSnyanmisaka void mpp_sthd_put(MppSThd thd)
430*437bfbebSnyanmisaka {
431*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
432*437bfbebSnyanmisaka 
433*437bfbebSnyanmisaka     mpp_assert(impl);
434*437bfbebSnyanmisaka     mpp_assert(impl->ctx.thd == impl);
435*437bfbebSnyanmisaka     mpp_assert(impl->status == MPP_STHD_UNINITED || impl->status == MPP_STHD_READY);
436*437bfbebSnyanmisaka 
437*437bfbebSnyanmisaka     mpp_sthd_deinit(impl);
438*437bfbebSnyanmisaka 
439*437bfbebSnyanmisaka     mpp_free(impl);
440*437bfbebSnyanmisaka }
441*437bfbebSnyanmisaka 
mpp_sthd_get_status(MppSThd thd)442*437bfbebSnyanmisaka MppSThdStatus mpp_sthd_get_status(MppSThd thd)
443*437bfbebSnyanmisaka {
444*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
445*437bfbebSnyanmisaka 
446*437bfbebSnyanmisaka     CHECK_STHD(impl);
447*437bfbebSnyanmisaka 
448*437bfbebSnyanmisaka     return impl->status;
449*437bfbebSnyanmisaka }
450*437bfbebSnyanmisaka 
mpp_sthd_get_name(MppSThd thd)451*437bfbebSnyanmisaka const char* mpp_sthd_get_name(MppSThd thd)
452*437bfbebSnyanmisaka {
453*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
454*437bfbebSnyanmisaka 
455*437bfbebSnyanmisaka     CHECK_STHD(impl);
456*437bfbebSnyanmisaka 
457*437bfbebSnyanmisaka     return impl->name;
458*437bfbebSnyanmisaka }
459*437bfbebSnyanmisaka 
mpp_sthd_get_idx(MppSThd thd)460*437bfbebSnyanmisaka rk_s32 mpp_sthd_get_idx(MppSThd thd)
461*437bfbebSnyanmisaka {
462*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
463*437bfbebSnyanmisaka 
464*437bfbebSnyanmisaka     CHECK_STHD(impl);
465*437bfbebSnyanmisaka 
466*437bfbebSnyanmisaka     return impl->idx;
467*437bfbebSnyanmisaka }
468*437bfbebSnyanmisaka 
mpp_sthd_check(MppSThd thd)469*437bfbebSnyanmisaka rk_s32 mpp_sthd_check(MppSThd thd)
470*437bfbebSnyanmisaka {
471*437bfbebSnyanmisaka     return CHECK_STHD(thd);
472*437bfbebSnyanmisaka }
473*437bfbebSnyanmisaka 
mpp_sthd_setup(MppSThd thd,MppSThdFunc func,void * ctx)474*437bfbebSnyanmisaka void mpp_sthd_setup(MppSThd thd, MppSThdFunc func, void *ctx)
475*437bfbebSnyanmisaka {
476*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
477*437bfbebSnyanmisaka     MppSThdStatus status;
478*437bfbebSnyanmisaka 
479*437bfbebSnyanmisaka     CHECK_STHD(impl);
480*437bfbebSnyanmisaka 
481*437bfbebSnyanmisaka     pthread_mutex_lock(&impl->lock);
482*437bfbebSnyanmisaka     status = impl->status;
483*437bfbebSnyanmisaka     switch (status) {
484*437bfbebSnyanmisaka     case MPP_STHD_UNINITED :
485*437bfbebSnyanmisaka     case MPP_STHD_READY : {
486*437bfbebSnyanmisaka         impl->func = func;
487*437bfbebSnyanmisaka         impl->ctx.ctx = ctx;
488*437bfbebSnyanmisaka         impl->status = func ? MPP_STHD_READY : MPP_STHD_UNINITED;
489*437bfbebSnyanmisaka     } break;
490*437bfbebSnyanmisaka     default : {
491*437bfbebSnyanmisaka         mpp_err("%s can NOT setup on %s\n", impl->name, state2str(status));
492*437bfbebSnyanmisaka     } break;
493*437bfbebSnyanmisaka     }
494*437bfbebSnyanmisaka     pthread_mutex_unlock(&impl->lock);
495*437bfbebSnyanmisaka 
496*437bfbebSnyanmisaka     CHECK_STHD(impl);
497*437bfbebSnyanmisaka }
498*437bfbebSnyanmisaka 
mpp_sthd_start(MppSThd thd)499*437bfbebSnyanmisaka void mpp_sthd_start(MppSThd thd)
500*437bfbebSnyanmisaka {
501*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
502*437bfbebSnyanmisaka     MppSThdStatus status;
503*437bfbebSnyanmisaka 
504*437bfbebSnyanmisaka     CHECK_STHD(impl);
505*437bfbebSnyanmisaka 
506*437bfbebSnyanmisaka     /* we can only change callback function on uninit */
507*437bfbebSnyanmisaka     pthread_mutex_lock(&impl->lock);
508*437bfbebSnyanmisaka     status = impl->status;
509*437bfbebSnyanmisaka     switch (status) {
510*437bfbebSnyanmisaka     case MPP_STHD_READY : {
511*437bfbebSnyanmisaka         mpp_sthd_create(impl);
512*437bfbebSnyanmisaka     } break;
513*437bfbebSnyanmisaka     default : {
514*437bfbebSnyanmisaka         mpp_err("%s can NOT start on %s\n", impl->name, state2str(status));
515*437bfbebSnyanmisaka     } break;
516*437bfbebSnyanmisaka     }
517*437bfbebSnyanmisaka     pthread_mutex_unlock(&impl->lock);
518*437bfbebSnyanmisaka 
519*437bfbebSnyanmisaka     CHECK_STHD(impl);
520*437bfbebSnyanmisaka }
521*437bfbebSnyanmisaka 
mpp_sthd_stop(MppSThd thd)522*437bfbebSnyanmisaka void mpp_sthd_stop(MppSThd thd)
523*437bfbebSnyanmisaka {
524*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
525*437bfbebSnyanmisaka     MppSThdStatus status;
526*437bfbebSnyanmisaka 
527*437bfbebSnyanmisaka     CHECK_STHD(impl);
528*437bfbebSnyanmisaka 
529*437bfbebSnyanmisaka     pthread_mutex_lock(&impl->lock);
530*437bfbebSnyanmisaka     status = impl->status;
531*437bfbebSnyanmisaka     switch (status) {
532*437bfbebSnyanmisaka     case MPP_STHD_RUNNING :
533*437bfbebSnyanmisaka     case MPP_STHD_WAITING : {
534*437bfbebSnyanmisaka         status = MPP_STHD_STOPPING;
535*437bfbebSnyanmisaka         pthread_cond_signal(&impl->cond);
536*437bfbebSnyanmisaka     } break;
537*437bfbebSnyanmisaka     default : {
538*437bfbebSnyanmisaka         mpp_err("%s can NOT stop on %s\n", impl->name, state2str(status));
539*437bfbebSnyanmisaka     } break;
540*437bfbebSnyanmisaka     }
541*437bfbebSnyanmisaka     pthread_mutex_unlock(&impl->lock);
542*437bfbebSnyanmisaka 
543*437bfbebSnyanmisaka     CHECK_STHD(impl);
544*437bfbebSnyanmisaka }
545*437bfbebSnyanmisaka 
mpp_sthd_stop_sync(MppSThd thd)546*437bfbebSnyanmisaka void mpp_sthd_stop_sync(MppSThd thd)
547*437bfbebSnyanmisaka {
548*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
549*437bfbebSnyanmisaka     MppSThdStatus status;
550*437bfbebSnyanmisaka 
551*437bfbebSnyanmisaka     CHECK_STHD(impl);
552*437bfbebSnyanmisaka 
553*437bfbebSnyanmisaka     pthread_mutex_lock(&impl->lock);
554*437bfbebSnyanmisaka     status = impl->status;
555*437bfbebSnyanmisaka     switch (status) {
556*437bfbebSnyanmisaka     case MPP_STHD_STOPPING : {
557*437bfbebSnyanmisaka         void *dummy;
558*437bfbebSnyanmisaka 
559*437bfbebSnyanmisaka         pthread_join(impl->thd, &dummy);
560*437bfbebSnyanmisaka         impl->status = MPP_STHD_READY;
561*437bfbebSnyanmisaka     } break;
562*437bfbebSnyanmisaka     default : {
563*437bfbebSnyanmisaka         mpp_err("%s can NOT stop on %s\n", impl->name, state2str(status));
564*437bfbebSnyanmisaka     } break;
565*437bfbebSnyanmisaka     }
566*437bfbebSnyanmisaka     pthread_mutex_unlock(&impl->lock);
567*437bfbebSnyanmisaka 
568*437bfbebSnyanmisaka     CHECK_STHD(impl);
569*437bfbebSnyanmisaka }
570*437bfbebSnyanmisaka 
mpp_sthd_lock(MppSThd thd)571*437bfbebSnyanmisaka void mpp_sthd_lock(MppSThd thd)
572*437bfbebSnyanmisaka {
573*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
574*437bfbebSnyanmisaka 
575*437bfbebSnyanmisaka     CHECK_STHD(impl);
576*437bfbebSnyanmisaka 
577*437bfbebSnyanmisaka     pthread_mutex_lock(&impl->lock);
578*437bfbebSnyanmisaka }
579*437bfbebSnyanmisaka 
mpp_sthd_unlock(MppSThd thd)580*437bfbebSnyanmisaka void mpp_sthd_unlock(MppSThd thd)
581*437bfbebSnyanmisaka {
582*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
583*437bfbebSnyanmisaka 
584*437bfbebSnyanmisaka     CHECK_STHD(impl);
585*437bfbebSnyanmisaka 
586*437bfbebSnyanmisaka     pthread_mutex_unlock(&impl->lock);
587*437bfbebSnyanmisaka }
588*437bfbebSnyanmisaka 
mpp_sthd_trylock(MppSThd thd)589*437bfbebSnyanmisaka int mpp_sthd_trylock(MppSThd thd)
590*437bfbebSnyanmisaka {
591*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
592*437bfbebSnyanmisaka 
593*437bfbebSnyanmisaka     CHECK_STHD(impl);
594*437bfbebSnyanmisaka 
595*437bfbebSnyanmisaka     return pthread_mutex_trylock(&impl->lock);
596*437bfbebSnyanmisaka }
597*437bfbebSnyanmisaka 
mpp_sthd_wait(MppSThd thd)598*437bfbebSnyanmisaka void mpp_sthd_wait(MppSThd thd)
599*437bfbebSnyanmisaka {
600*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
601*437bfbebSnyanmisaka 
602*437bfbebSnyanmisaka     CHECK_STHD(impl);
603*437bfbebSnyanmisaka 
604*437bfbebSnyanmisaka     if (impl->status == MPP_STHD_RUNNING)
605*437bfbebSnyanmisaka         impl->status = MPP_STHD_WAITING;
606*437bfbebSnyanmisaka 
607*437bfbebSnyanmisaka     pthread_cond_wait(&impl->cond, &impl->lock);
608*437bfbebSnyanmisaka 
609*437bfbebSnyanmisaka     if (impl->status == MPP_STHD_WAITING)
610*437bfbebSnyanmisaka         impl->status = MPP_STHD_RUNNING;
611*437bfbebSnyanmisaka }
612*437bfbebSnyanmisaka 
mpp_sthd_signal(MppSThd thd)613*437bfbebSnyanmisaka void mpp_sthd_signal(MppSThd thd)
614*437bfbebSnyanmisaka {
615*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
616*437bfbebSnyanmisaka 
617*437bfbebSnyanmisaka     CHECK_STHD(impl);
618*437bfbebSnyanmisaka 
619*437bfbebSnyanmisaka     pthread_cond_signal(&impl->cond);
620*437bfbebSnyanmisaka }
621*437bfbebSnyanmisaka 
mpp_sthd_broadcast(MppSThd thd)622*437bfbebSnyanmisaka void mpp_sthd_broadcast(MppSThd thd)
623*437bfbebSnyanmisaka {
624*437bfbebSnyanmisaka     MppSThdImpl *impl = (MppSThdImpl *)thd;
625*437bfbebSnyanmisaka 
626*437bfbebSnyanmisaka     CHECK_STHD(impl);
627*437bfbebSnyanmisaka 
628*437bfbebSnyanmisaka     pthread_cond_broadcast(&impl->cond);
629*437bfbebSnyanmisaka }
630*437bfbebSnyanmisaka 
mpp_sthd_grp_get(const char * name,rk_s32 count)631*437bfbebSnyanmisaka MppSThdGrp mpp_sthd_grp_get(const char *name, rk_s32 count)
632*437bfbebSnyanmisaka {
633*437bfbebSnyanmisaka     MppSThdGrpImpl *grp = NULL;
634*437bfbebSnyanmisaka 
635*437bfbebSnyanmisaka     if (count > 0) {
636*437bfbebSnyanmisaka         rk_s32 elem_size = MPP_ALIGN(sizeof(MppSThdImpl), 8);
637*437bfbebSnyanmisaka         rk_s32 total_size = MPP_ALIGN(sizeof(MppSThdGrpImpl), 8) + count * elem_size;
638*437bfbebSnyanmisaka 
639*437bfbebSnyanmisaka         grp = mpp_calloc_size(MppSThdGrpImpl, total_size);
640*437bfbebSnyanmisaka         if (grp) {
641*437bfbebSnyanmisaka             pthread_mutexattr_t attr;
642*437bfbebSnyanmisaka             rk_s32 i;
643*437bfbebSnyanmisaka 
644*437bfbebSnyanmisaka             if (!name)
645*437bfbebSnyanmisaka                 name = "mpp_sthd_grp";
646*437bfbebSnyanmisaka 
647*437bfbebSnyanmisaka             snprintf(grp->name, THREAD_NAME_LEN - 1, "%s", name);
648*437bfbebSnyanmisaka 
649*437bfbebSnyanmisaka             grp->count = count;
650*437bfbebSnyanmisaka             for (i = 0; i < count; i++) {
651*437bfbebSnyanmisaka                 MppSThdImpl *thd = &grp->thds[i];
652*437bfbebSnyanmisaka 
653*437bfbebSnyanmisaka                 thd->name = grp->name;
654*437bfbebSnyanmisaka                 mpp_sthd_init(thd, i);
655*437bfbebSnyanmisaka             }
656*437bfbebSnyanmisaka 
657*437bfbebSnyanmisaka             pthread_mutexattr_init(&attr);
658*437bfbebSnyanmisaka             pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
659*437bfbebSnyanmisaka             pthread_mutex_init(&grp->lock, &attr);
660*437bfbebSnyanmisaka             pthread_mutexattr_destroy(&attr);
661*437bfbebSnyanmisaka         }
662*437bfbebSnyanmisaka     }
663*437bfbebSnyanmisaka 
664*437bfbebSnyanmisaka     if (!grp)
665*437bfbebSnyanmisaka         mpp_err_f("can NOT create %d threads group\n", count);
666*437bfbebSnyanmisaka 
667*437bfbebSnyanmisaka     return grp;
668*437bfbebSnyanmisaka }
669*437bfbebSnyanmisaka 
mpp_sthd_grp_put(MppSThdGrp grp)670*437bfbebSnyanmisaka void mpp_sthd_grp_put(MppSThdGrp grp)
671*437bfbebSnyanmisaka {
672*437bfbebSnyanmisaka     MppSThdGrpImpl *impl = (MppSThdGrpImpl *)grp;
673*437bfbebSnyanmisaka     rk_s32 i;
674*437bfbebSnyanmisaka 
675*437bfbebSnyanmisaka     mpp_assert(impl);
676*437bfbebSnyanmisaka     mpp_assert(impl->status == MPP_STHD_UNINITED || impl->status == MPP_STHD_READY);
677*437bfbebSnyanmisaka 
678*437bfbebSnyanmisaka     for (i = 0; i < impl->count; i++) {
679*437bfbebSnyanmisaka         MppSThdImpl *thd = &impl->thds[i];
680*437bfbebSnyanmisaka 
681*437bfbebSnyanmisaka         mpp_sthd_deinit(thd);
682*437bfbebSnyanmisaka     }
683*437bfbebSnyanmisaka 
684*437bfbebSnyanmisaka     mpp_free(impl);
685*437bfbebSnyanmisaka }
686*437bfbebSnyanmisaka 
mpp_sthd_grp_setup(MppSThdGrp grp,MppSThdFunc func,void * ctx)687*437bfbebSnyanmisaka void mpp_sthd_grp_setup(MppSThdGrp grp, MppSThdFunc func, void *ctx)
688*437bfbebSnyanmisaka {
689*437bfbebSnyanmisaka     MppSThdGrpImpl *impl = (MppSThdGrpImpl *)grp;
690*437bfbebSnyanmisaka     MppSThdStatus status;
691*437bfbebSnyanmisaka 
692*437bfbebSnyanmisaka     mpp_assert(impl);
693*437bfbebSnyanmisaka 
694*437bfbebSnyanmisaka     pthread_mutex_lock(&impl->lock);
695*437bfbebSnyanmisaka     status = impl->status;
696*437bfbebSnyanmisaka     switch (status) {
697*437bfbebSnyanmisaka     case MPP_STHD_UNINITED :
698*437bfbebSnyanmisaka     case MPP_STHD_READY : {
699*437bfbebSnyanmisaka         MppSThdStatus next = func ? MPP_STHD_READY : MPP_STHD_UNINITED;
700*437bfbebSnyanmisaka         rk_s32 i;
701*437bfbebSnyanmisaka 
702*437bfbebSnyanmisaka         for (i = 0; i < impl->count; i++) {
703*437bfbebSnyanmisaka             MppSThdImpl *thd = &impl->thds[i];
704*437bfbebSnyanmisaka 
705*437bfbebSnyanmisaka             thd->func = func;
706*437bfbebSnyanmisaka             thd->ctx.ctx = ctx;
707*437bfbebSnyanmisaka             thd->status = next;
708*437bfbebSnyanmisaka         }
709*437bfbebSnyanmisaka         impl->status = next;
710*437bfbebSnyanmisaka     } break;
711*437bfbebSnyanmisaka     default : {
712*437bfbebSnyanmisaka         mpp_err("%s can NOT setup on %s\n", impl->name, state2str(status));
713*437bfbebSnyanmisaka     } break;
714*437bfbebSnyanmisaka     }
715*437bfbebSnyanmisaka     pthread_mutex_unlock(&impl->lock);
716*437bfbebSnyanmisaka }
717*437bfbebSnyanmisaka 
mpp_sthd_grp_start(MppSThdGrp grp)718*437bfbebSnyanmisaka void mpp_sthd_grp_start(MppSThdGrp grp)
719*437bfbebSnyanmisaka {
720*437bfbebSnyanmisaka     MppSThdGrpImpl *impl = (MppSThdGrpImpl *)grp;
721*437bfbebSnyanmisaka     MppSThdStatus status;
722*437bfbebSnyanmisaka 
723*437bfbebSnyanmisaka     mpp_assert(impl);
724*437bfbebSnyanmisaka 
725*437bfbebSnyanmisaka     /* we can only change callback function on uninit */
726*437bfbebSnyanmisaka     pthread_mutex_lock(&impl->lock);
727*437bfbebSnyanmisaka     status = impl->status;
728*437bfbebSnyanmisaka     switch (status) {
729*437bfbebSnyanmisaka     case MPP_STHD_READY : {
730*437bfbebSnyanmisaka         rk_s32 i;
731*437bfbebSnyanmisaka 
732*437bfbebSnyanmisaka         for (i = 0; i < impl->count; i++)
733*437bfbebSnyanmisaka             mpp_sthd_start(&impl->thds[i]);
734*437bfbebSnyanmisaka 
735*437bfbebSnyanmisaka         impl->status = MPP_STHD_RUNNING;
736*437bfbebSnyanmisaka     } break;
737*437bfbebSnyanmisaka     default : {
738*437bfbebSnyanmisaka         mpp_err("%s can NOT start on %s\n", impl->name, state2str(status));
739*437bfbebSnyanmisaka     } break;
740*437bfbebSnyanmisaka     }
741*437bfbebSnyanmisaka     pthread_mutex_unlock(&impl->lock);
742*437bfbebSnyanmisaka }
743*437bfbebSnyanmisaka 
mpp_sthd_grp_stop(MppSThdGrp grp)744*437bfbebSnyanmisaka void mpp_sthd_grp_stop(MppSThdGrp grp)
745*437bfbebSnyanmisaka {
746*437bfbebSnyanmisaka     MppSThdGrpImpl *impl = (MppSThdGrpImpl *)grp;
747*437bfbebSnyanmisaka     MppSThdStatus status;
748*437bfbebSnyanmisaka 
749*437bfbebSnyanmisaka     mpp_assert(impl);
750*437bfbebSnyanmisaka 
751*437bfbebSnyanmisaka     /* we can only change callback function on uninit */
752*437bfbebSnyanmisaka     pthread_mutex_lock(&impl->lock);
753*437bfbebSnyanmisaka     status = impl->status;
754*437bfbebSnyanmisaka     switch (status) {
755*437bfbebSnyanmisaka     case MPP_STHD_RUNNING :
756*437bfbebSnyanmisaka     case MPP_STHD_WAITING : {
757*437bfbebSnyanmisaka         rk_s32 i;
758*437bfbebSnyanmisaka 
759*437bfbebSnyanmisaka         impl->status = MPP_STHD_STOPPING;
760*437bfbebSnyanmisaka 
761*437bfbebSnyanmisaka         for (i = 0; i < impl->count; i++) {
762*437bfbebSnyanmisaka             MppSThdImpl *thd = &impl->thds[i];
763*437bfbebSnyanmisaka 
764*437bfbebSnyanmisaka             pthread_mutex_lock(&thd->lock);
765*437bfbebSnyanmisaka             thd->status = MPP_STHD_STOPPING;
766*437bfbebSnyanmisaka             pthread_cond_signal(&thd->cond);
767*437bfbebSnyanmisaka             pthread_mutex_unlock(&thd->lock);
768*437bfbebSnyanmisaka         }
769*437bfbebSnyanmisaka     } break;
770*437bfbebSnyanmisaka     default : {
771*437bfbebSnyanmisaka         mpp_err("%s can NOT stop on %s\n", impl->name, state2str(status));
772*437bfbebSnyanmisaka     } break;
773*437bfbebSnyanmisaka     }
774*437bfbebSnyanmisaka     pthread_mutex_unlock(&impl->lock);
775*437bfbebSnyanmisaka }
776*437bfbebSnyanmisaka 
mpp_sthd_grp_stop_sync(MppSThdGrp grp)777*437bfbebSnyanmisaka void mpp_sthd_grp_stop_sync(MppSThdGrp grp)
778*437bfbebSnyanmisaka {
779*437bfbebSnyanmisaka     MppSThdGrpImpl *impl = (MppSThdGrpImpl *)grp;
780*437bfbebSnyanmisaka     MppSThdStatus status;
781*437bfbebSnyanmisaka 
782*437bfbebSnyanmisaka     mpp_assert(impl);
783*437bfbebSnyanmisaka 
784*437bfbebSnyanmisaka     /* we can only change callback function on uninit */
785*437bfbebSnyanmisaka     pthread_mutex_lock(&impl->lock);
786*437bfbebSnyanmisaka     status = impl->status;
787*437bfbebSnyanmisaka     switch (status) {
788*437bfbebSnyanmisaka     case MPP_STHD_STOPPING : {
789*437bfbebSnyanmisaka         void *dummy;
790*437bfbebSnyanmisaka         rk_s32 i;
791*437bfbebSnyanmisaka 
792*437bfbebSnyanmisaka         status = MPP_STHD_STOPPING;
793*437bfbebSnyanmisaka         for (i = 0; i < impl->count; i++) {
794*437bfbebSnyanmisaka             MppSThdImpl *thd = &impl->thds[i];
795*437bfbebSnyanmisaka 
796*437bfbebSnyanmisaka             pthread_join(thd->thd, &dummy);
797*437bfbebSnyanmisaka             thd->status = MPP_STHD_READY;
798*437bfbebSnyanmisaka         }
799*437bfbebSnyanmisaka         impl->status = MPP_STHD_READY;
800*437bfbebSnyanmisaka     } break;
801*437bfbebSnyanmisaka     default : {
802*437bfbebSnyanmisaka         mpp_err("%s can NOT stop sync on %s\n", impl->name, state2str(status));
803*437bfbebSnyanmisaka     } break;
804*437bfbebSnyanmisaka     }
805*437bfbebSnyanmisaka     pthread_mutex_unlock(&impl->lock);
806*437bfbebSnyanmisaka }
807*437bfbebSnyanmisaka 
mpp_sthd_grp_get_each(MppSThdGrp grp,rk_s32 idx)808*437bfbebSnyanmisaka MppSThd mpp_sthd_grp_get_each(MppSThdGrp grp, rk_s32 idx)
809*437bfbebSnyanmisaka {
810*437bfbebSnyanmisaka     MppSThdGrpImpl *impl = (MppSThdGrpImpl *)grp;
811*437bfbebSnyanmisaka     MppSThd ret = NULL;
812*437bfbebSnyanmisaka 
813*437bfbebSnyanmisaka     mpp_assert(impl);
814*437bfbebSnyanmisaka     mpp_assert(idx >= 0 && idx < impl->count);
815*437bfbebSnyanmisaka 
816*437bfbebSnyanmisaka     pthread_mutex_lock(&impl->lock);
817*437bfbebSnyanmisaka     ret = &impl->thds[idx];
818*437bfbebSnyanmisaka     pthread_mutex_unlock(&impl->lock);
819*437bfbebSnyanmisaka 
820*437bfbebSnyanmisaka     return ret;
821*437bfbebSnyanmisaka }