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