xref: /OK3568_Linux_fs/external/mpp/osal/mpp_thread.cpp (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 #define MODULE_TAG "mpp_thread"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include <string.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #include "mpp_log.h"
22*4882a593Smuzhiyun #include "mpp_common.h"
23*4882a593Smuzhiyun #include "mpp_thread.h"
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define MPP_THREAD_DBG_FUNCTION     (0x00000001)
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun static RK_U32 thread_debug = 0;
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #define thread_dbg(flag, fmt, ...)  _mpp_dbg(thread_debug, flag, fmt, ## __VA_ARGS__)
30*4882a593Smuzhiyun 
MppThread(MppThreadFunc func,void * ctx,const char * name)31*4882a593Smuzhiyun MppThread::MppThread(MppThreadFunc func, void *ctx, const char *name)
32*4882a593Smuzhiyun     : mFunction(func),
33*4882a593Smuzhiyun       mContext(ctx)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun     mStatus[THREAD_WORK]    = MPP_THREAD_UNINITED;
36*4882a593Smuzhiyun     mStatus[THREAD_INPUT]   = MPP_THREAD_RUNNING;
37*4882a593Smuzhiyun     mStatus[THREAD_OUTPUT]  = MPP_THREAD_RUNNING;
38*4882a593Smuzhiyun     mStatus[THREAD_CONTROL] = MPP_THREAD_RUNNING;
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun     if (name)
41*4882a593Smuzhiyun         strncpy(mName, name, sizeof(mName) - 1);
42*4882a593Smuzhiyun     else
43*4882a593Smuzhiyun         snprintf(mName, sizeof(mName) - 1, "mpp_thread");
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun 
get_status(MppThreadSignal id)46*4882a593Smuzhiyun MppThreadStatus MppThread::get_status(MppThreadSignal id)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun     return mStatus[id];
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun 
set_status(MppThreadStatus status,MppThreadSignal id)51*4882a593Smuzhiyun void MppThread::set_status(MppThreadStatus status, MppThreadSignal id)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun     mStatus[id] = status;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
dump_status()56*4882a593Smuzhiyun void MppThread::dump_status()
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun     mpp_log("thread %s status: %d %d %d %d\n", mName,
59*4882a593Smuzhiyun             mStatus[THREAD_WORK], mStatus[THREAD_INPUT], mStatus[THREAD_OUTPUT],
60*4882a593Smuzhiyun             mStatus[THREAD_CONTROL]);
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
start()63*4882a593Smuzhiyun void MppThread::start()
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun     pthread_attr_t attr;
66*4882a593Smuzhiyun     pthread_attr_init(&attr);
67*4882a593Smuzhiyun     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun     if (MPP_THREAD_UNINITED == get_status()) {
70*4882a593Smuzhiyun         // NOTE: set status here first to avoid unexpected loop quit racing condition
71*4882a593Smuzhiyun         set_status(MPP_THREAD_RUNNING);
72*4882a593Smuzhiyun         if (0 == pthread_create(&mThread, &attr, mFunction, mContext)) {
73*4882a593Smuzhiyun #ifndef ARMLINUX
74*4882a593Smuzhiyun             RK_S32 ret = pthread_setname_np(mThread, mName);
75*4882a593Smuzhiyun             if (ret)
76*4882a593Smuzhiyun                 mpp_err("thread %p setname %s failed\n", mFunction, mName);
77*4882a593Smuzhiyun #endif
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun             thread_dbg(MPP_THREAD_DBG_FUNCTION, "thread %s %p context %p create success\n",
80*4882a593Smuzhiyun                        mName, mFunction, mContext);
81*4882a593Smuzhiyun         } else
82*4882a593Smuzhiyun             set_status(MPP_THREAD_UNINITED);
83*4882a593Smuzhiyun     }
84*4882a593Smuzhiyun     pthread_attr_destroy(&attr);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
stop()87*4882a593Smuzhiyun void MppThread::stop()
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun     if (MPP_THREAD_UNINITED != get_status()) {
90*4882a593Smuzhiyun         lock();
91*4882a593Smuzhiyun         set_status(MPP_THREAD_STOPPING);
92*4882a593Smuzhiyun         thread_dbg(MPP_THREAD_DBG_FUNCTION,
93*4882a593Smuzhiyun                    "MPP_THREAD_STOPPING status set mThread %p", this);
94*4882a593Smuzhiyun         signal();
95*4882a593Smuzhiyun         unlock();
96*4882a593Smuzhiyun         void *dummy;
97*4882a593Smuzhiyun         pthread_join(mThread, &dummy);
98*4882a593Smuzhiyun         thread_dbg(MPP_THREAD_DBG_FUNCTION,
99*4882a593Smuzhiyun                    "thread %s %p context %p destroy success\n",
100*4882a593Smuzhiyun                    mName, mFunction, mContext);
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun         set_status(MPP_THREAD_UNINITED);
103*4882a593Smuzhiyun     }
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun #if defined(_WIN32) && !defined(__MINGW32CE__)
107*4882a593Smuzhiyun //
108*4882a593Smuzhiyun // Usage: SetThreadName ((DWORD)-1, "MainThread");
109*4882a593Smuzhiyun //
110*4882a593Smuzhiyun #include <windows.h>
111*4882a593Smuzhiyun const DWORD MS_VC_EXCEPTION = 0x406D1388;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun #pragma pack(push,8)
114*4882a593Smuzhiyun typedef struct tagTHREADNAME_INFO {
115*4882a593Smuzhiyun     DWORD dwType; // Must be 0x1000.
116*4882a593Smuzhiyun     LPCSTR szName; // Pointer to name (in user addr space).
117*4882a593Smuzhiyun     DWORD dwThreadID; // Thread ID (-1=caller thread).
118*4882a593Smuzhiyun     DWORD dwFlags; // Reserved for future use, must be zero.
119*4882a593Smuzhiyun } THREADNAME_INFO;
120*4882a593Smuzhiyun #pragma pack(pop)
121*4882a593Smuzhiyun 
SetThreadName(DWORD dwThreadID,const char * threadName)122*4882a593Smuzhiyun void SetThreadName(DWORD dwThreadID, const char* threadName)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun     THREADNAME_INFO info;
125*4882a593Smuzhiyun     info.dwType = 0x1000;
126*4882a593Smuzhiyun     info.szName = threadName;
127*4882a593Smuzhiyun     info.dwThreadID = dwThreadID;
128*4882a593Smuzhiyun     info.dwFlags = 0;
129*4882a593Smuzhiyun #pragma warning(push)
130*4882a593Smuzhiyun #pragma warning(disable: 6320 6322)
131*4882a593Smuzhiyun     __try {
132*4882a593Smuzhiyun         RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
133*4882a593Smuzhiyun     } __except (EXCEPTION_EXECUTE_HANDLER) {
134*4882a593Smuzhiyun     }
135*4882a593Smuzhiyun #pragma warning(pop)
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun #ifndef ARMLINUX
140*4882a593Smuzhiyun /*
141*4882a593Smuzhiyun  * add pthread_setname_np for windows
142*4882a593Smuzhiyun  */
pthread_setname_np(pthread_t thread,const char * name)143*4882a593Smuzhiyun int pthread_setname_np(pthread_t thread, const char *name)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun     DWORD dwThreadID = pthread_getw32threadid_np(thread);
146*4882a593Smuzhiyun     SetThreadName(dwThreadID, name);
147*4882a593Smuzhiyun     return 0;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun #endif
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun #endif
152*4882a593Smuzhiyun 
153