xref: /OK3568_Linux_fs/external/mpp/osal/mpp_thread.cpp (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright 2015 Rockchip Electronics Co. LTD
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define MODULE_TAG "mpp_thread"
18 
19 #include <string.h>
20 
21 #include "mpp_log.h"
22 #include "mpp_common.h"
23 #include "mpp_thread.h"
24 
25 #define MPP_THREAD_DBG_FUNCTION     (0x00000001)
26 
27 static RK_U32 thread_debug = 0;
28 
29 #define thread_dbg(flag, fmt, ...)  _mpp_dbg(thread_debug, flag, fmt, ## __VA_ARGS__)
30 
MppThread(MppThreadFunc func,void * ctx,const char * name)31 MppThread::MppThread(MppThreadFunc func, void *ctx, const char *name)
32     : mFunction(func),
33       mContext(ctx)
34 {
35     mStatus[THREAD_WORK]    = MPP_THREAD_UNINITED;
36     mStatus[THREAD_INPUT]   = MPP_THREAD_RUNNING;
37     mStatus[THREAD_OUTPUT]  = MPP_THREAD_RUNNING;
38     mStatus[THREAD_CONTROL] = MPP_THREAD_RUNNING;
39 
40     if (name)
41         strncpy(mName, name, sizeof(mName) - 1);
42     else
43         snprintf(mName, sizeof(mName) - 1, "mpp_thread");
44 }
45 
get_status(MppThreadSignal id)46 MppThreadStatus MppThread::get_status(MppThreadSignal id)
47 {
48     return mStatus[id];
49 }
50 
set_status(MppThreadStatus status,MppThreadSignal id)51 void MppThread::set_status(MppThreadStatus status, MppThreadSignal id)
52 {
53     mStatus[id] = status;
54 }
55 
dump_status()56 void MppThread::dump_status()
57 {
58     mpp_log("thread %s status: %d %d %d %d\n", mName,
59             mStatus[THREAD_WORK], mStatus[THREAD_INPUT], mStatus[THREAD_OUTPUT],
60             mStatus[THREAD_CONTROL]);
61 }
62 
start()63 void MppThread::start()
64 {
65     pthread_attr_t attr;
66     pthread_attr_init(&attr);
67     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
68 
69     if (MPP_THREAD_UNINITED == get_status()) {
70         // NOTE: set status here first to avoid unexpected loop quit racing condition
71         set_status(MPP_THREAD_RUNNING);
72         if (0 == pthread_create(&mThread, &attr, mFunction, mContext)) {
73 #ifndef ARMLINUX
74             RK_S32 ret = pthread_setname_np(mThread, mName);
75             if (ret)
76                 mpp_err("thread %p setname %s failed\n", mFunction, mName);
77 #endif
78 
79             thread_dbg(MPP_THREAD_DBG_FUNCTION, "thread %s %p context %p create success\n",
80                        mName, mFunction, mContext);
81         } else
82             set_status(MPP_THREAD_UNINITED);
83     }
84     pthread_attr_destroy(&attr);
85 }
86 
stop()87 void MppThread::stop()
88 {
89     if (MPP_THREAD_UNINITED != get_status()) {
90         lock();
91         set_status(MPP_THREAD_STOPPING);
92         thread_dbg(MPP_THREAD_DBG_FUNCTION,
93                    "MPP_THREAD_STOPPING status set mThread %p", this);
94         signal();
95         unlock();
96         void *dummy;
97         pthread_join(mThread, &dummy);
98         thread_dbg(MPP_THREAD_DBG_FUNCTION,
99                    "thread %s %p context %p destroy success\n",
100                    mName, mFunction, mContext);
101 
102         set_status(MPP_THREAD_UNINITED);
103     }
104 }
105 
106 #if defined(_WIN32) && !defined(__MINGW32CE__)
107 //
108 // Usage: SetThreadName ((DWORD)-1, "MainThread");
109 //
110 #include <windows.h>
111 const DWORD MS_VC_EXCEPTION = 0x406D1388;
112 
113 #pragma pack(push,8)
114 typedef struct tagTHREADNAME_INFO {
115     DWORD dwType; // Must be 0x1000.
116     LPCSTR szName; // Pointer to name (in user addr space).
117     DWORD dwThreadID; // Thread ID (-1=caller thread).
118     DWORD dwFlags; // Reserved for future use, must be zero.
119 } THREADNAME_INFO;
120 #pragma pack(pop)
121 
SetThreadName(DWORD dwThreadID,const char * threadName)122 void SetThreadName(DWORD dwThreadID, const char* threadName)
123 {
124     THREADNAME_INFO info;
125     info.dwType = 0x1000;
126     info.szName = threadName;
127     info.dwThreadID = dwThreadID;
128     info.dwFlags = 0;
129 #pragma warning(push)
130 #pragma warning(disable: 6320 6322)
131     __try {
132         RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
133     } __except (EXCEPTION_EXECUTE_HANDLER) {
134     }
135 #pragma warning(pop)
136 }
137 
138 
139 #ifndef ARMLINUX
140 /*
141  * add pthread_setname_np for windows
142  */
pthread_setname_np(pthread_t thread,const char * name)143 int pthread_setname_np(pthread_t thread, const char *name)
144 {
145     DWORD dwThreadID = pthread_getw32threadid_np(thread);
146     SetThreadName(dwThreadID, name);
147     return 0;
148 }
149 #endif
150 
151 #endif
152 
153