121 lines
3.6 KiB
C++
121 lines
3.6 KiB
C++
/*
|
|
* Copyright (C) EdgeTX
|
|
*
|
|
* Based on code named
|
|
* opentx - https://github.com/opentx/opentx
|
|
* th9x - http://code.google.com/p/th9x
|
|
* er9x - http://code.google.com/p/er9x
|
|
* gruvin9x - http://code.google.com/p/gruvin9x
|
|
*
|
|
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
|
|
// OS specific implementation
|
|
#if defined(NATIVE_THREADS)
|
|
#include "task_native.h"
|
|
#elif defined(FREE_RTOS)
|
|
#include "task_freertos.h"
|
|
#endif
|
|
|
|
typedef void (*task_func_t)();
|
|
|
|
void task_create(task_handle_t* h, task_func_t func, const char* name,
|
|
void* stack, unsigned stack_size, unsigned priority);
|
|
|
|
unsigned task_get_stack_usage(task_handle_t* h);
|
|
unsigned task_get_stack_size(task_handle_t* h);
|
|
|
|
bool scheduler_is_running();
|
|
|
|
void mutex_create(mutex_handle_t* h);
|
|
bool mutex_lock(mutex_handle_t* h);
|
|
void mutex_unlock(mutex_handle_t* h);
|
|
bool mutex_trylock(mutex_handle_t* h);
|
|
|
|
|
|
// this helper class is only to be used on the stack and never to be shared outside the scope where it was created
|
|
/* example usage
|
|
*
|
|
* void doWork()
|
|
* {
|
|
*
|
|
* MutexLock lock = MutexLock::MakeInstance(mutex);
|
|
* while(!queue.isEmpty)
|
|
* {
|
|
* lock.unlock();
|
|
* auto item = queue.pop();
|
|
* <do something with item>
|
|
* lock.lock();
|
|
* }
|
|
* } // auto mutex unlock, because lock is destructed here
|
|
*
|
|
* int sendMessage()
|
|
* {
|
|
* MutexLock lock = MutexLock::MakeInstance(busMutex);
|
|
* if(busSendData(...) != OK)
|
|
* return ERROR; // auto mutex unlock, because lock is destructed here
|
|
*
|
|
* lock.unlock();
|
|
* <do some other stuff>
|
|
* if(<something>)
|
|
* return ERROR; // no auto mutex unlock, because already unlocked
|
|
* lock.lock()
|
|
* if(busSendData(...) != OK)
|
|
* return ERROR; // auto mutex unlock, because lock is destructed here
|
|
*
|
|
* return OK;
|
|
* } // auto mutex unlock here, because lock is destructed here
|
|
*
|
|
* int doSomething()
|
|
* {
|
|
*
|
|
* <code here>
|
|
* if(<bus usage condition>)
|
|
* {
|
|
* MutexLock lock = MutexLock::MakeInstance(busMutex);
|
|
* if(busSendData(...) != OK)
|
|
* return ERROR; // auto mutex unlock, because lock is destructed here
|
|
* } // auto mutex unlock here, because lock is destructed here
|
|
*
|
|
* <code here>
|
|
*
|
|
* return OK;
|
|
* }
|
|
*/
|
|
|
|
class MutexLock
|
|
{
|
|
public:
|
|
static MutexLock MakeInstance(mutex_handle_t* mtx) {return MutexLock(mtx);}
|
|
~MutexLock() {if(!scheduler_is_running()) return; if(locked) mutex_unlock(mutex);}
|
|
void lock() {if(!scheduler_is_running()) return; if(!locked) mutex_lock(mutex); locked=true;}
|
|
void unlock() {if(!scheduler_is_running()) return; if(locked) mutex_unlock(mutex); locked=false;}
|
|
|
|
MutexLock(const MutexLock&) = delete;
|
|
MutexLock(MutexLock&&) = delete;
|
|
MutexLock& operator =(const MutexLock&) = delete;
|
|
MutexLock& operator =(MutexLock&&) = delete;
|
|
static void* operator new (size_t) = delete;
|
|
static void* operator new[] (size_t) = delete;
|
|
static void operator delete (void*) = delete;
|
|
static void operator delete[](void*) = delete;
|
|
private:
|
|
MutexLock(mutex_handle_t* mtx):mutex(mtx),locked(false) {if(!scheduler_is_running()) return; mutex_lock(mutex); locked = true;}
|
|
mutex_handle_t* mutex;
|
|
bool locked;
|
|
};
|
|
|