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