xref: /OK3568_Linux_fs/external/mpp/osal/inc/mpp_thread.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2015 Rockchip Electronics Co. LTD
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Licensed under the Apache License, Version 2.0 (the "License");
5*4882a593Smuzhiyun  * you may not use this file except in compliance with the License.
6*4882a593Smuzhiyun  * You may obtain a copy of the License at
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  *      http://www.apache.org/licenses/LICENSE-2.0
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Unless required by applicable law or agreed to in writing, software
11*4882a593Smuzhiyun  * distributed under the License is distributed on an "AS IS" BASIS,
12*4882a593Smuzhiyun  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4882a593Smuzhiyun  * See the License for the specific language governing permissions and
14*4882a593Smuzhiyun  * limitations under the License.
15*4882a593Smuzhiyun  */
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun /*
18*4882a593Smuzhiyun  * File         : mpp_thread.h
19*4882a593Smuzhiyun  * Description  : thread library for different OS
20*4882a593Smuzhiyun  * Author       : herman.chen@rock-chips.com
21*4882a593Smuzhiyun  * Date         : 9:47 2015/7/27
22*4882a593Smuzhiyun  */
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #ifndef __MPP_THREAD_H__
25*4882a593Smuzhiyun #define __MPP_THREAD_H__
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #if defined(_WIN32) && !defined(__MINGW32CE__)
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /*
30*4882a593Smuzhiyun  * NOTE: POSIX Threads for Win32
31*4882a593Smuzhiyun  * Downloaded from http://www.sourceware.org/pthreads-win32/
32*4882a593Smuzhiyun  */
33*4882a593Smuzhiyun #include "semaphore.h"
34*4882a593Smuzhiyun #include "pthread.h"
35*4882a593Smuzhiyun #pragma comment(lib, "pthreadVC2.lib")
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun /*
38*4882a593Smuzhiyun  * add pthread_setname_np for windows
39*4882a593Smuzhiyun  */
40*4882a593Smuzhiyun int pthread_setname_np(pthread_t thread, const char *name);
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #else
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #include <unistd.h>
45*4882a593Smuzhiyun #include <semaphore.h>
46*4882a593Smuzhiyun #include <pthread.h>
47*4882a593Smuzhiyun #include <sys/time.h>
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun #ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
50*4882a593Smuzhiyun #define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER
51*4882a593Smuzhiyun #endif
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun #endif
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #define THREAD_NAME_LEN 16
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun typedef void *(*MppThreadFunc)(void *);
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun typedef enum {
60*4882a593Smuzhiyun     MPP_THREAD_UNINITED,
61*4882a593Smuzhiyun     MPP_THREAD_RUNNING,
62*4882a593Smuzhiyun     MPP_THREAD_WAITING,
63*4882a593Smuzhiyun     MPP_THREAD_STOPPING,
64*4882a593Smuzhiyun } MppThreadStatus;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun #ifdef __cplusplus
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun #include "mpp_debug.h"
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun class Mutex;
71*4882a593Smuzhiyun class Condition;
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun /*
74*4882a593Smuzhiyun  * for shorter type name and function name
75*4882a593Smuzhiyun  */
76*4882a593Smuzhiyun class Mutex
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun public:
79*4882a593Smuzhiyun     Mutex();
80*4882a593Smuzhiyun     ~Mutex();
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun     void lock();
83*4882a593Smuzhiyun     void unlock();
84*4882a593Smuzhiyun     int  trylock();
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun     class Autolock
87*4882a593Smuzhiyun     {
88*4882a593Smuzhiyun     public:
89*4882a593Smuzhiyun         inline Autolock(Mutex* mutex, RK_U32 enable = 1) :
mEnabled(enable)90*4882a593Smuzhiyun             mEnabled(enable),
91*4882a593Smuzhiyun             mLock(*mutex) {
92*4882a593Smuzhiyun             if (mEnabled)
93*4882a593Smuzhiyun                 mLock.lock();
94*4882a593Smuzhiyun         }
~Autolock()95*4882a593Smuzhiyun         inline ~Autolock() {
96*4882a593Smuzhiyun             if (mEnabled)
97*4882a593Smuzhiyun                 mLock.unlock();
98*4882a593Smuzhiyun         }
99*4882a593Smuzhiyun     private:
100*4882a593Smuzhiyun         RK_S32 mEnabled;
101*4882a593Smuzhiyun         Mutex& mLock;
102*4882a593Smuzhiyun     };
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun private:
105*4882a593Smuzhiyun     friend class Condition;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun     pthread_mutex_t mMutex;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun     Mutex(const Mutex &);
110*4882a593Smuzhiyun     Mutex &operator = (const Mutex&);
111*4882a593Smuzhiyun };
112*4882a593Smuzhiyun 
Mutex()113*4882a593Smuzhiyun inline Mutex::Mutex()
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun     pthread_mutexattr_t attr;
116*4882a593Smuzhiyun     pthread_mutexattr_init(&attr);
117*4882a593Smuzhiyun     pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
118*4882a593Smuzhiyun     pthread_mutex_init(&mMutex, &attr);
119*4882a593Smuzhiyun     pthread_mutexattr_destroy(&attr);
120*4882a593Smuzhiyun }
~Mutex()121*4882a593Smuzhiyun inline Mutex::~Mutex()
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun     pthread_mutex_destroy(&mMutex);
124*4882a593Smuzhiyun }
lock()125*4882a593Smuzhiyun inline void Mutex::lock()
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun     pthread_mutex_lock(&mMutex);
128*4882a593Smuzhiyun }
unlock()129*4882a593Smuzhiyun inline void Mutex::unlock()
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun     pthread_mutex_unlock(&mMutex);
132*4882a593Smuzhiyun }
trylock()133*4882a593Smuzhiyun inline int Mutex::trylock()
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun     return pthread_mutex_trylock(&mMutex);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun typedef Mutex::Autolock AutoMutex;
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun /*
142*4882a593Smuzhiyun  * for shorter type name and function name
143*4882a593Smuzhiyun  */
144*4882a593Smuzhiyun class Condition
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun public:
147*4882a593Smuzhiyun     Condition();
148*4882a593Smuzhiyun     Condition(int type);
149*4882a593Smuzhiyun     ~Condition();
150*4882a593Smuzhiyun     RK_S32 wait(Mutex& mutex);
151*4882a593Smuzhiyun     RK_S32 wait(Mutex* mutex);
152*4882a593Smuzhiyun     RK_S32 timedwait(Mutex& mutex, RK_S64 timeout);
153*4882a593Smuzhiyun     RK_S32 timedwait(Mutex* mutex, RK_S64 timeout);
154*4882a593Smuzhiyun     RK_S32 signal();
155*4882a593Smuzhiyun     RK_S32 broadcast();
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun private:
158*4882a593Smuzhiyun     pthread_cond_t mCond;
159*4882a593Smuzhiyun };
160*4882a593Smuzhiyun 
Condition()161*4882a593Smuzhiyun inline Condition::Condition()
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun     pthread_cond_init(&mCond, NULL);
164*4882a593Smuzhiyun }
~Condition()165*4882a593Smuzhiyun inline Condition::~Condition()
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun     pthread_cond_destroy(&mCond);
168*4882a593Smuzhiyun }
wait(Mutex & mutex)169*4882a593Smuzhiyun inline RK_S32 Condition::wait(Mutex& mutex)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun     return pthread_cond_wait(&mCond, &mutex.mMutex);
172*4882a593Smuzhiyun }
wait(Mutex * mutex)173*4882a593Smuzhiyun inline RK_S32 Condition::wait(Mutex* mutex)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun     return pthread_cond_wait(&mCond, &mutex->mMutex);
176*4882a593Smuzhiyun }
timedwait(Mutex & mutex,RK_S64 timeout)177*4882a593Smuzhiyun inline RK_S32 Condition::timedwait(Mutex& mutex, RK_S64 timeout)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun     return timedwait(&mutex, timeout);
180*4882a593Smuzhiyun }
timedwait(Mutex * mutex,RK_S64 timeout)181*4882a593Smuzhiyun inline RK_S32 Condition::timedwait(Mutex* mutex, RK_S64 timeout)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun     struct timespec ts;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun     clock_gettime(CLOCK_REALTIME_COARSE, &ts);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun     ts.tv_sec += timeout / 1000;
188*4882a593Smuzhiyun     ts.tv_nsec += (timeout % 1000) * 1000000;
189*4882a593Smuzhiyun     /* Prevent the out of range at nanoseconds field */
190*4882a593Smuzhiyun     ts.tv_sec += ts.tv_nsec / 1000000000;
191*4882a593Smuzhiyun     ts.tv_nsec %= 1000000000;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun     return pthread_cond_timedwait(&mCond, &mutex->mMutex, &ts);
194*4882a593Smuzhiyun }
signal()195*4882a593Smuzhiyun inline RK_S32 Condition::signal()
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun     return pthread_cond_signal(&mCond);
198*4882a593Smuzhiyun }
broadcast()199*4882a593Smuzhiyun inline RK_S32 Condition::broadcast()
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun     return pthread_cond_broadcast(&mCond);
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun class MppMutexCond
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun public:
MppMutexCond()207*4882a593Smuzhiyun     MppMutexCond() {};
~MppMutexCond()208*4882a593Smuzhiyun     ~MppMutexCond() {};
209*4882a593Smuzhiyun 
lock()210*4882a593Smuzhiyun     void    lock()      { mLock.lock(); }
unlock()211*4882a593Smuzhiyun     void    unlock()    { mLock.unlock(); }
trylock()212*4882a593Smuzhiyun     int     trylock()   { return mLock.trylock(); }
wait()213*4882a593Smuzhiyun     void    wait()      { mCondition.wait(mLock); }
wait(RK_S64 timeout)214*4882a593Smuzhiyun     RK_S32  wait(RK_S64 timeout) { return mCondition.timedwait(mLock, timeout); }
signal()215*4882a593Smuzhiyun     void    signal()    { mCondition.signal(); }
broadcast()216*4882a593Smuzhiyun     void    broadcast() { mCondition.broadcast(); }
mutex()217*4882a593Smuzhiyun     Mutex   *mutex()    { return &mLock; }
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun private:
220*4882a593Smuzhiyun     Mutex           mLock;
221*4882a593Smuzhiyun     Condition       mCondition;
222*4882a593Smuzhiyun };
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun // Thread lock / signal is distinguished by its source
225*4882a593Smuzhiyun typedef enum MppThreadSignal_e {
226*4882a593Smuzhiyun     THREAD_WORK,        // for working loop
227*4882a593Smuzhiyun     THREAD_INPUT,       // for thread input
228*4882a593Smuzhiyun     THREAD_OUTPUT,      // for thread output
229*4882a593Smuzhiyun     THREAD_CONTROL,     // for thread async control (reset)
230*4882a593Smuzhiyun     THREAD_SIGNAL_BUTT,
231*4882a593Smuzhiyun } MppThreadSignal;
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun #define THREAD_NORMAL       0
234*4882a593Smuzhiyun #define THRE       0
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun class MppThread
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun public:
239*4882a593Smuzhiyun     MppThread(MppThreadFunc func, void *ctx, const char *name = NULL);
~MppThread()240*4882a593Smuzhiyun     ~MppThread() {};
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun     MppThreadStatus get_status(MppThreadSignal id = THREAD_WORK);
243*4882a593Smuzhiyun     void set_status(MppThreadStatus status, MppThreadSignal id = THREAD_WORK);
244*4882a593Smuzhiyun     void dump_status();
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun     void start();
247*4882a593Smuzhiyun     void stop();
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun     void lock(MppThreadSignal id = THREAD_WORK) {
250*4882a593Smuzhiyun         mpp_assert(id < THREAD_SIGNAL_BUTT);
251*4882a593Smuzhiyun         mMutexCond[id].lock();
252*4882a593Smuzhiyun     }
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun     void unlock(MppThreadSignal id = THREAD_WORK) {
255*4882a593Smuzhiyun         mpp_assert(id < THREAD_SIGNAL_BUTT);
256*4882a593Smuzhiyun         mMutexCond[id].unlock();
257*4882a593Smuzhiyun     }
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun     void wait(MppThreadSignal id = THREAD_WORK) {
260*4882a593Smuzhiyun         mpp_assert(id < THREAD_SIGNAL_BUTT);
261*4882a593Smuzhiyun         MppThreadStatus status = mStatus[id];
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun         mStatus[id] = MPP_THREAD_WAITING;
264*4882a593Smuzhiyun         mMutexCond[id].wait();
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun         // check the status is not changed then restore status
267*4882a593Smuzhiyun         if (mStatus[id] == MPP_THREAD_WAITING)
268*4882a593Smuzhiyun             mStatus[id] = status;
269*4882a593Smuzhiyun     }
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun     void signal(MppThreadSignal id = THREAD_WORK) {
272*4882a593Smuzhiyun         mpp_assert(id < THREAD_SIGNAL_BUTT);
273*4882a593Smuzhiyun         mMutexCond[id].signal();
274*4882a593Smuzhiyun     }
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun     Mutex *mutex(MppThreadSignal id = THREAD_WORK) {
277*4882a593Smuzhiyun         mpp_assert(id < THREAD_SIGNAL_BUTT);
278*4882a593Smuzhiyun         return mMutexCond[id].mutex();
279*4882a593Smuzhiyun     }
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun private:
282*4882a593Smuzhiyun     pthread_t       mThread;
283*4882a593Smuzhiyun     MppMutexCond    mMutexCond[THREAD_SIGNAL_BUTT];
284*4882a593Smuzhiyun     MppThreadStatus mStatus[THREAD_SIGNAL_BUTT];
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun     MppThreadFunc   mFunction;
287*4882a593Smuzhiyun     char            mName[THREAD_NAME_LEN];
288*4882a593Smuzhiyun     void            *mContext;
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun     MppThread();
291*4882a593Smuzhiyun     MppThread(const MppThread &);
292*4882a593Smuzhiyun     MppThread &operator=(const MppThread &);
293*4882a593Smuzhiyun };
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun #endif
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun #endif /*__MPP_THREAD_H__*/
298