13d0407baSopenharmony_ci/* 23d0407baSopenharmony_ci * Copyright 2015 Rockchip Electronics Co. LTD 33d0407baSopenharmony_ci * 43d0407baSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 53d0407baSopenharmony_ci * you may not use this file except in compliance with the License. 63d0407baSopenharmony_ci * You may obtain a copy of the License at 73d0407baSopenharmony_ci * 83d0407baSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 93d0407baSopenharmony_ci * 103d0407baSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 113d0407baSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 123d0407baSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133d0407baSopenharmony_ci * See the License for the specific language governing permissions and 143d0407baSopenharmony_ci * limitations under the License. 153d0407baSopenharmony_ci */ 163d0407baSopenharmony_ci 173d0407baSopenharmony_ci/* 183d0407baSopenharmony_ci * File : mpp_thread.h 193d0407baSopenharmony_ci * Description : thread library for different OS 203d0407baSopenharmony_ci * Author : herman.chen@rock-chips.com 213d0407baSopenharmony_ci * Date : 9:47 2015/7/27 223d0407baSopenharmony_ci */ 233d0407baSopenharmony_ci 243d0407baSopenharmony_ci#ifndef __MPP_THREAD_H__ 253d0407baSopenharmony_ci#define __MPP_THREAD_H__ 263d0407baSopenharmony_ci 273d0407baSopenharmony_ci#if defined(_WIN32) && !defined(__MINGW32CE__) 283d0407baSopenharmony_ci 293d0407baSopenharmony_ci/* 303d0407baSopenharmony_ci * NOTE: POSIX Threads for Win32 313d0407baSopenharmony_ci * Downloaded from http://www.sourceware.org/pthreads-win32/ 323d0407baSopenharmony_ci */ 333d0407baSopenharmony_ci#include "semaphore.h" 343d0407baSopenharmony_ci#include "pthread.h" 353d0407baSopenharmony_ci#pragma comment(lib, "pthreadVC2.lib") 363d0407baSopenharmony_ci 373d0407baSopenharmony_ci/* 383d0407baSopenharmony_ci * add pthread_setname_np for windows 393d0407baSopenharmony_ci */ 403d0407baSopenharmony_ciint pthread_setname_np(pthread_t thread, const char *name); 413d0407baSopenharmony_ci 423d0407baSopenharmony_ci#else 433d0407baSopenharmony_ci 443d0407baSopenharmony_ci#include <unistd.h> 453d0407baSopenharmony_ci#include <semaphore.h> 463d0407baSopenharmony_ci#include <pthread.h> 473d0407baSopenharmony_ci#include <sys/time.h> 483d0407baSopenharmony_ci 493d0407baSopenharmony_ci#ifndef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP 503d0407baSopenharmony_ci#define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP PTHREAD_RECURSIVE_MUTEX_INITIALIZER 513d0407baSopenharmony_ci#endif 523d0407baSopenharmony_ci 533d0407baSopenharmony_ci#endif 543d0407baSopenharmony_ci 553d0407baSopenharmony_ci#define THREAD_NAME_LEN 16 563d0407baSopenharmony_ci 573d0407baSopenharmony_citypedef void *(*MppThreadFunc)(void *); 583d0407baSopenharmony_ci 593d0407baSopenharmony_citypedef enum { 603d0407baSopenharmony_ci MPP_THREAD_UNINITED, 613d0407baSopenharmony_ci MPP_THREAD_RUNNING, 623d0407baSopenharmony_ci MPP_THREAD_WAITING, 633d0407baSopenharmony_ci MPP_THREAD_STOPPING, 643d0407baSopenharmony_ci} MppThreadStatus; 653d0407baSopenharmony_ci 663d0407baSopenharmony_ci#ifdef __cplusplus 673d0407baSopenharmony_ci 683d0407baSopenharmony_ci#include "mpp_debug.h" 693d0407baSopenharmony_ci 703d0407baSopenharmony_ciclass Mutex; 713d0407baSopenharmony_ciclass Condition; 723d0407baSopenharmony_ci 733d0407baSopenharmony_ci/* 743d0407baSopenharmony_ci * for shorter type name and function name 753d0407baSopenharmony_ci */ 763d0407baSopenharmony_ciclass Mutex 773d0407baSopenharmony_ci{ 783d0407baSopenharmony_cipublic: 793d0407baSopenharmony_ci Mutex(); 803d0407baSopenharmony_ci ~Mutex(); 813d0407baSopenharmony_ci 823d0407baSopenharmony_ci void lock(); 833d0407baSopenharmony_ci void unlock(); 843d0407baSopenharmony_ci int trylock(); 853d0407baSopenharmony_ci 863d0407baSopenharmony_ci class Autolock 873d0407baSopenharmony_ci { 883d0407baSopenharmony_ci public: 893d0407baSopenharmony_ci inline Autolock(Mutex* mutex, RK_U32 enable = 1) : 903d0407baSopenharmony_ci mEnabled(enable), 913d0407baSopenharmony_ci mLock(*mutex) { 923d0407baSopenharmony_ci if (mEnabled) 933d0407baSopenharmony_ci mLock.lock(); 943d0407baSopenharmony_ci } 953d0407baSopenharmony_ci inline ~Autolock() { 963d0407baSopenharmony_ci if (mEnabled) 973d0407baSopenharmony_ci mLock.unlock(); 983d0407baSopenharmony_ci } 993d0407baSopenharmony_ci private: 1003d0407baSopenharmony_ci RK_S32 mEnabled; 1013d0407baSopenharmony_ci Mutex& mLock; 1023d0407baSopenharmony_ci }; 1033d0407baSopenharmony_ci 1043d0407baSopenharmony_ciprivate: 1053d0407baSopenharmony_ci friend class Condition; 1063d0407baSopenharmony_ci 1073d0407baSopenharmony_ci pthread_mutex_t mMutex; 1083d0407baSopenharmony_ci 1093d0407baSopenharmony_ci Mutex(const Mutex &); 1103d0407baSopenharmony_ci Mutex &operator = (const Mutex&); 1113d0407baSopenharmony_ci}; 1123d0407baSopenharmony_ci 1133d0407baSopenharmony_ciinline Mutex::Mutex() 1143d0407baSopenharmony_ci{ 1153d0407baSopenharmony_ci pthread_mutexattr_t attr; 1163d0407baSopenharmony_ci pthread_mutexattr_init(&attr); 1173d0407baSopenharmony_ci pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 1183d0407baSopenharmony_ci pthread_mutex_init(&mMutex, &attr); 1193d0407baSopenharmony_ci pthread_mutexattr_destroy(&attr); 1203d0407baSopenharmony_ci} 1213d0407baSopenharmony_ciinline Mutex::~Mutex() 1223d0407baSopenharmony_ci{ 1233d0407baSopenharmony_ci pthread_mutex_destroy(&mMutex); 1243d0407baSopenharmony_ci} 1253d0407baSopenharmony_ciinline void Mutex::lock() 1263d0407baSopenharmony_ci{ 1273d0407baSopenharmony_ci pthread_mutex_lock(&mMutex); 1283d0407baSopenharmony_ci} 1293d0407baSopenharmony_ciinline void Mutex::unlock() 1303d0407baSopenharmony_ci{ 1313d0407baSopenharmony_ci pthread_mutex_unlock(&mMutex); 1323d0407baSopenharmony_ci} 1333d0407baSopenharmony_ciinline int Mutex::trylock() 1343d0407baSopenharmony_ci{ 1353d0407baSopenharmony_ci return pthread_mutex_trylock(&mMutex); 1363d0407baSopenharmony_ci} 1373d0407baSopenharmony_ci 1383d0407baSopenharmony_citypedef Mutex::Autolock AutoMutex; 1393d0407baSopenharmony_ci 1403d0407baSopenharmony_ci 1413d0407baSopenharmony_ci/* 1423d0407baSopenharmony_ci * for shorter type name and function name 1433d0407baSopenharmony_ci */ 1443d0407baSopenharmony_ciclass Condition 1453d0407baSopenharmony_ci{ 1463d0407baSopenharmony_cipublic: 1473d0407baSopenharmony_ci Condition(); 1483d0407baSopenharmony_ci Condition(int type); 1493d0407baSopenharmony_ci ~Condition(); 1503d0407baSopenharmony_ci RK_S32 wait(Mutex& mutex); 1513d0407baSopenharmony_ci RK_S32 wait(Mutex* mutex); 1523d0407baSopenharmony_ci RK_S32 timedwait(Mutex& mutex, RK_S64 timeout); 1533d0407baSopenharmony_ci RK_S32 timedwait(Mutex* mutex, RK_S64 timeout); 1543d0407baSopenharmony_ci RK_S32 signal(); 1553d0407baSopenharmony_ci RK_S32 broadcast(); 1563d0407baSopenharmony_ci 1573d0407baSopenharmony_ciprivate: 1583d0407baSopenharmony_ci pthread_cond_t mCond; 1593d0407baSopenharmony_ci}; 1603d0407baSopenharmony_ci 1613d0407baSopenharmony_ciinline Condition::Condition() 1623d0407baSopenharmony_ci{ 1633d0407baSopenharmony_ci pthread_cond_init(&mCond, NULL); 1643d0407baSopenharmony_ci} 1653d0407baSopenharmony_ciinline Condition::~Condition() 1663d0407baSopenharmony_ci{ 1673d0407baSopenharmony_ci pthread_cond_destroy(&mCond); 1683d0407baSopenharmony_ci} 1693d0407baSopenharmony_ciinline RK_S32 Condition::wait(Mutex& mutex) 1703d0407baSopenharmony_ci{ 1713d0407baSopenharmony_ci return pthread_cond_wait(&mCond, &mutex.mMutex); 1723d0407baSopenharmony_ci} 1733d0407baSopenharmony_ciinline RK_S32 Condition::wait(Mutex* mutex) 1743d0407baSopenharmony_ci{ 1753d0407baSopenharmony_ci return pthread_cond_wait(&mCond, &mutex->mMutex); 1763d0407baSopenharmony_ci} 1773d0407baSopenharmony_ciinline RK_S32 Condition::timedwait(Mutex& mutex, RK_S64 timeout) 1783d0407baSopenharmony_ci{ 1793d0407baSopenharmony_ci return timedwait(&mutex, timeout); 1803d0407baSopenharmony_ci} 1813d0407baSopenharmony_ciinline RK_S32 Condition::timedwait(Mutex* mutex, RK_S64 timeout) 1823d0407baSopenharmony_ci{ 1833d0407baSopenharmony_ci struct timespec ts; 1843d0407baSopenharmony_ci 1853d0407baSopenharmony_ci clock_gettime(CLOCK_REALTIME_COARSE, &ts); 1863d0407baSopenharmony_ci 1873d0407baSopenharmony_ci ts.tv_sec += timeout / 1000; 1883d0407baSopenharmony_ci ts.tv_nsec += (timeout % 1000) * 1000000; 1893d0407baSopenharmony_ci /* Prevent the out of range at nanoseconds field */ 1903d0407baSopenharmony_ci ts.tv_sec += ts.tv_nsec / 1000000000; 1913d0407baSopenharmony_ci ts.tv_nsec %= 1000000000; 1923d0407baSopenharmony_ci 1933d0407baSopenharmony_ci return pthread_cond_timedwait(&mCond, &mutex->mMutex, &ts); 1943d0407baSopenharmony_ci} 1953d0407baSopenharmony_ciinline RK_S32 Condition::signal() 1963d0407baSopenharmony_ci{ 1973d0407baSopenharmony_ci return pthread_cond_signal(&mCond); 1983d0407baSopenharmony_ci} 1993d0407baSopenharmony_ciinline RK_S32 Condition::broadcast() 2003d0407baSopenharmony_ci{ 2013d0407baSopenharmony_ci return pthread_cond_broadcast(&mCond); 2023d0407baSopenharmony_ci} 2033d0407baSopenharmony_ci 2043d0407baSopenharmony_ciclass MppMutexCond 2053d0407baSopenharmony_ci{ 2063d0407baSopenharmony_cipublic: 2073d0407baSopenharmony_ci MppMutexCond() {}; 2083d0407baSopenharmony_ci ~MppMutexCond() {}; 2093d0407baSopenharmony_ci 2103d0407baSopenharmony_ci void lock() { mLock.lock(); } 2113d0407baSopenharmony_ci void unlock() { mLock.unlock(); } 2123d0407baSopenharmony_ci int trylock() { return mLock.trylock(); } 2133d0407baSopenharmony_ci void wait() { mCondition.wait(mLock); } 2143d0407baSopenharmony_ci RK_S32 wait(RK_S64 timeout) { return mCondition.timedwait(mLock, timeout); } 2153d0407baSopenharmony_ci void signal() { mCondition.signal(); } 2163d0407baSopenharmony_ci void broadcast() { mCondition.broadcast(); } 2173d0407baSopenharmony_ci Mutex *mutex() { return &mLock; } 2183d0407baSopenharmony_ci 2193d0407baSopenharmony_ciprivate: 2203d0407baSopenharmony_ci Mutex mLock; 2213d0407baSopenharmony_ci Condition mCondition; 2223d0407baSopenharmony_ci}; 2233d0407baSopenharmony_ci 2243d0407baSopenharmony_ci// Thread lock / signal is distinguished by its source 2253d0407baSopenharmony_citypedef enum MppThreadSignal_e { 2263d0407baSopenharmony_ci THREAD_WORK, // for working loop 2273d0407baSopenharmony_ci THREAD_INPUT, // for thread input 2283d0407baSopenharmony_ci THREAD_OUTPUT, // for thread output 2293d0407baSopenharmony_ci THREAD_CONTROL, // for thread async control (reset) 2303d0407baSopenharmony_ci THREAD_SIGNAL_BUTT, 2313d0407baSopenharmony_ci} MppThreadSignal; 2323d0407baSopenharmony_ci 2333d0407baSopenharmony_ci#define THREAD_NORMAL 0 2343d0407baSopenharmony_ci#define THRE 0 2353d0407baSopenharmony_ci 2363d0407baSopenharmony_ciclass MppThread 2373d0407baSopenharmony_ci{ 2383d0407baSopenharmony_cipublic: 2393d0407baSopenharmony_ci MppThread(MppThreadFunc func, void *ctx, const char *name = NULL); 2403d0407baSopenharmony_ci ~MppThread() {}; 2413d0407baSopenharmony_ci 2423d0407baSopenharmony_ci MppThreadStatus get_status(MppThreadSignal id = THREAD_WORK); 2433d0407baSopenharmony_ci void set_status(MppThreadStatus status, MppThreadSignal id = THREAD_WORK); 2443d0407baSopenharmony_ci void dump_status(); 2453d0407baSopenharmony_ci 2463d0407baSopenharmony_ci void start(); 2473d0407baSopenharmony_ci void stop(); 2483d0407baSopenharmony_ci 2493d0407baSopenharmony_ci void lock(MppThreadSignal id = THREAD_WORK) { 2503d0407baSopenharmony_ci mpp_assert(id < THREAD_SIGNAL_BUTT); 2513d0407baSopenharmony_ci mMutexCond[id].lock(); 2523d0407baSopenharmony_ci } 2533d0407baSopenharmony_ci 2543d0407baSopenharmony_ci void unlock(MppThreadSignal id = THREAD_WORK) { 2553d0407baSopenharmony_ci mpp_assert(id < THREAD_SIGNAL_BUTT); 2563d0407baSopenharmony_ci mMutexCond[id].unlock(); 2573d0407baSopenharmony_ci } 2583d0407baSopenharmony_ci 2593d0407baSopenharmony_ci void wait(MppThreadSignal id = THREAD_WORK) { 2603d0407baSopenharmony_ci mpp_assert(id < THREAD_SIGNAL_BUTT); 2613d0407baSopenharmony_ci MppThreadStatus status = mStatus[id]; 2623d0407baSopenharmony_ci 2633d0407baSopenharmony_ci mStatus[id] = MPP_THREAD_WAITING; 2643d0407baSopenharmony_ci mMutexCond[id].wait(); 2653d0407baSopenharmony_ci 2663d0407baSopenharmony_ci // check the status is not changed then restore status 2673d0407baSopenharmony_ci if (mStatus[id] == MPP_THREAD_WAITING) 2683d0407baSopenharmony_ci mStatus[id] = status; 2693d0407baSopenharmony_ci } 2703d0407baSopenharmony_ci 2713d0407baSopenharmony_ci void signal(MppThreadSignal id = THREAD_WORK) { 2723d0407baSopenharmony_ci mpp_assert(id < THREAD_SIGNAL_BUTT); 2733d0407baSopenharmony_ci mMutexCond[id].signal(); 2743d0407baSopenharmony_ci } 2753d0407baSopenharmony_ci 2763d0407baSopenharmony_ci Mutex *mutex(MppThreadSignal id = THREAD_WORK) { 2773d0407baSopenharmony_ci mpp_assert(id < THREAD_SIGNAL_BUTT); 2783d0407baSopenharmony_ci return mMutexCond[id].mutex(); 2793d0407baSopenharmony_ci } 2803d0407baSopenharmony_ci 2813d0407baSopenharmony_ciprivate: 2823d0407baSopenharmony_ci pthread_t mThread; 2833d0407baSopenharmony_ci MppMutexCond mMutexCond[THREAD_SIGNAL_BUTT]; 2843d0407baSopenharmony_ci MppThreadStatus mStatus[THREAD_SIGNAL_BUTT]; 2853d0407baSopenharmony_ci 2863d0407baSopenharmony_ci MppThreadFunc mFunction; 2873d0407baSopenharmony_ci char mName[THREAD_NAME_LEN]; 2883d0407baSopenharmony_ci void *mContext; 2893d0407baSopenharmony_ci 2903d0407baSopenharmony_ci MppThread(); 2913d0407baSopenharmony_ci MppThread(const MppThread &); 2923d0407baSopenharmony_ci MppThread &operator=(const MppThread &); 2933d0407baSopenharmony_ci}; 2943d0407baSopenharmony_ci 2953d0407baSopenharmony_ci#endif 2963d0407baSopenharmony_ci 2973d0407baSopenharmony_ci#endif /*__MPP_THREAD_H__*/ 298