157 lines
4.0 KiB
C
157 lines
4.0 KiB
C
/*
|
|
* 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 <micro_private.h>
|
|
#include <toolchain.h>
|
|
|
|
#include <wait_q.h>
|
|
#include <nanokernel.h>
|
|
#include <microkernel/event.h>
|
|
#include <drivers/system_timer.h>
|
|
|
|
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;
|
|
}
|