/* * Copyright (c) 2016 Wind River Systems, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file * @brief Nanokernel object kernel service * * This module provides routines used by the nanokernel for pending/unpending * microkernel tasks on nanokernel objects. */ #include #include #include #include #include #include extern void _task_nop(void); extern void _nano_nop(void); /** * @brief Pend a task on a nanokernel object * * This routine pends a task on a nanokernel object. It is expected to only * be called by internal nanokernel code with the interrupts locked. * * @return N/A */ void _task_nano_pend_task(struct _nano_queue *queue, int32_t timeout) { _NANO_TIMEOUT_ADD(queue, timeout); /* Add task to nanokernel object's task wait queue */ _nano_wait_q_put(queue); _k_state_bit_set(_k_current_task, TF_NANO); _task_nop(); /* Trigger microkernel scheduler */ } #ifdef CONFIG_NANO_TIMERS /** * @brief Pend a task on a nanokernel timer * * This routine pends a task on a nanokernel timer. It is expected to only * be called by internal nanokernel code with the interrupts locked. * * @return N/A */ void _task_nano_timer_pend_task(struct nano_timer *timer) { struct _nano_timeout *t = &timer->timeout_data; t->tcs = (struct tcs *) _k_current_task->workspace; _k_state_bit_set(_k_current_task, TF_NANO); _task_nop(); /* Trigger microkernel scheduler */ } /** * @brief Ready the task waiting on a nanokernel timer * * This routine readies the task that was waiting on a a nanokernel timer. * It is expected to only be called by internal nanokernel code (fiber or * ISR context) with the interrupts locked. * * @return N/A */ void _nano_timer_task_ready(void *ptr) { struct k_task *uk_task_ptr = ptr; _k_state_bit_reset(uk_task_ptr, TF_NANO); _nano_nop(); /* Trigger microkernel scheduler */ } /** * @brief Ready the task waiting on a nanokernel timer * * This routine readies the task that was waiting on a a nanokernel timer. * It is expected to only be called by internal nanokernel code (task context) * with the interrupts locked. * * @return N/A */ void _task_nano_timer_task_ready(void *ptr) { struct k_task *uk_task_ptr = ptr; _k_state_bit_reset(uk_task_ptr, TF_NANO); _task_nop(); /* Trigger microkernel scheduler */ } #endif /* CONFIG_NANO_TIMERS */ /** * @brief Ready a microkernel task due to timeout * * This routine makes a microkernel task ready. As it is invoked in the * context of the kernel server fiber, there is no need to explicitly trigger * the microkernel task scheduler here. Interrupts are already locked. * * @return N/A */ void _nano_task_ready(void *ptr) { struct k_task *uk_task_ptr = ptr; _k_state_bit_reset(uk_task_ptr, TF_NANO); } /** * @brief Unpend all tasks from nanokernel object * * This routine unpends all tasks the nanokernel object's task queue. * It is expected to only be called by internal nanokernel code with * the interrupts locked. * * @return Number of tasks that were unpended */ int _nano_unpend_tasks(struct _nano_queue *queue) { struct tcs *task = (struct tcs *)queue->head; struct tcs *prev; int num = 0; /* Drain the nanokernel object's waiting task queue */ while (task != NULL) { _nano_timeout_abort(task); _k_state_bit_reset(task->uk_task_ptr, TF_NANO); prev = task; task = task->link; prev->link = NULL; num++; } _nano_wait_q_reset(queue); return num; }