Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers TaskBase.cpp Source File

TaskBase.cpp

00001 /*
00002  * Copyright (c) 2018-2019, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "drivers/internal/TaskBase.h"
00019 #include "drivers/internal/TaskQueue.h"
00020 #include "events/mbed_events.h"
00021 #include "rtos/Semaphore.h"
00022 #include "platform/mbed_critical.h"
00023 
00024 TaskBase::TaskBase(TaskQueue *q)
00025     : _queue(q), _posted(false), _start_count(0), _flush_sem(NULL)
00026 {
00027 
00028 }
00029 
00030 TaskBase::~TaskBase()
00031 {
00032     cancel();
00033     wait();
00034 }
00035 
00036 void TaskBase::set(TaskQueue *q)
00037 {
00038     core_util_critical_section_enter();
00039 
00040     // Cannot set the queue when it has been posted but has not been finished
00041     MBED_ASSERT(!_posted);
00042     _queue = q;
00043 
00044     core_util_critical_section_exit();
00045 }
00046 
00047 void TaskBase::cancel()
00048 {
00049     core_util_critical_section_enter();
00050 
00051     if (_posted) {
00052         _queue->cancel(this);
00053         _posted = false;
00054         _wake_check();
00055     }
00056 
00057     core_util_critical_section_exit();
00058 }
00059 
00060 void TaskBase::wait()
00061 {
00062     // Fast path check for finished
00063     core_util_critical_section_enter();
00064     if (finished()) {
00065         core_util_critical_section_exit();
00066         return;
00067     }
00068     core_util_critical_section_exit();
00069 
00070     rtos::Semaphore sem;
00071 
00072     // If the event is in-flight then wait for it to complete
00073     core_util_critical_section_enter();
00074     if (finished()) {
00075         // This element has been flushed from the queue
00076         core_util_critical_section_exit();
00077         return;
00078     }
00079     _flush_sem = &sem;
00080     core_util_critical_section_exit();
00081 
00082     sem.acquire();
00083 }
00084 
00085 bool TaskBase::ready()
00086 {
00087     core_util_critical_section_enter();
00088 
00089     bool is_ready = !_posted;
00090 
00091     core_util_critical_section_exit();
00092     return is_ready;
00093 }
00094 
00095 bool TaskBase::finished()
00096 {
00097     core_util_critical_section_enter();
00098 
00099     bool is_finished = !_posted && (_start_count == 0);
00100 
00101     core_util_critical_section_exit();
00102     return is_finished;
00103 }
00104 
00105 void TaskBase::finish()
00106 {
00107     // Nothing to do
00108 }
00109 
00110 void TaskBase::post()
00111 {
00112     core_util_critical_section_enter();
00113 
00114     MBED_ASSERT(_queue);
00115     if (_queue) {
00116         MBED_ASSERT(!_posted);
00117         _queue->post(this);
00118         _posted = true;
00119     }
00120 
00121     core_util_critical_section_exit();
00122 }
00123 
00124 TaskBase::run_callback_t TaskBase::_start(void *buffer, uint32_t size)
00125 {
00126     // Each call to _start must result in a call to _finish
00127     MBED_ASSERT(_start_count < 0xFFFF);
00128     _start_count++;
00129     _posted = false;
00130 
00131     return start(buffer, size);
00132 }
00133 
00134 void TaskBase::_finish()
00135 {
00136     // Each call to _finish must be preceded by a call to _start
00137     MBED_ASSERT(_start_count > 0);
00138     _start_count--;
00139     _wake_check();
00140     finish();
00141 }
00142 
00143 void TaskBase::_wake_check()
00144 {
00145     if (!finished()) {
00146         return;
00147     }
00148     if (_flush_sem) {
00149         _flush_sem->release();
00150         _flush_sem = NULL;
00151     }
00152 }