kernel: Eliminate the need for command packet sets

Revises microkernel semaphore sub-system to allow ISRs and fibers
to give a semaphore without having to define a command packet set.
The microkernel server now supports a 3rd command type on its
command stack, allowing a semaphore to be given in a similar manner
to the one used for the existing "give event" command type.

Change-Id: Ibd7fb1a77949792f72acd20a9ee304d6eabd62f7
Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
This commit is contained in:
Allan Stephens 2015-10-29 08:47:46 -04:00 committed by Anas Nashif
parent 30f01d86e0
commit 7c4b9ce1f7
7 changed files with 45 additions and 115 deletions

View file

@ -20,23 +20,8 @@
* @brief Microkernel command packet library
*
* A command packet is an opaque data structure that maps to a k_args without
* exposing its innards. It allows a subsystem, like a driver, that needs its
* fibers or ISRs to communicate with tasks to define a set of such packets to
* be passed to the isr_xxx routines, such as isr_sem_give(), that, in turn,
* needs to obtain command packets to interact with the microkernel.
*
* Each command packet set is created in global memory using ...
* CMD_PKT_SET_INSTANCE(set variable name, # of command packets in the set);
*
* Once created, the command packet set is referenced as an ordinary structured
* variable.
* A command packet set is a simple ring buffer. No error checking is performed
* when a command packet is retrieved from the set. Each obtained command packet
* is implicitly released once the command packet has been processed. Thus, it is
* important that each command packet be processed in a near-FIFO order to prevent
* corruption of command packets that are already in use. To this end, drivers
* that have an ISR component should use their own command packet set.
* exposing its innards. This library allows a subsystem that needs to define
* a command packet the ability to do so.
*/
#ifndef _COMMAND_PACKET_H
@ -52,35 +37,10 @@ extern "C" {
#define CMD_PKT_SIZE_IN_WORDS (19)
/* define command packet set types */
/* define command packet type */
typedef uint32_t cmdPkt_t[CMD_PKT_SIZE_IN_WORDS];
struct cmd_pkt_set {
uint32_t num_packets; /* number of command packets in set */
uint32_t index; /* index into command packet array */
cmdPkt_t *command_packet; /* pointer to array of command packets */
};
/**
* @brief Define a command packet set
*
* This macro is used to create a command packet set of the specified size.
*
* @param name Name of command packet set
* @param num Number of packets in the set
*
* @warning The command packet set exists in the global namespace,
* and cannot be hidden by prefixing the macro with "static".
*/
#define CMD_PKT_SET_INSTANCE(name, num) \
uint32_t __noinit(_k_cmd_pkts_ ## name)[CMD_PKT_SIZE_IN_WORDS * (num)]; \
struct cmd_pkt_set name = {(num), 0, (cmdPkt_t *)(_k_cmd_pkts_ ## name)}
/* externs */
extern struct k_args *_cmd_pkt_get(struct cmd_pkt_set *pSet);
#ifdef __cplusplus
}
#endif

View file

@ -40,33 +40,27 @@ extern "C" {
*
* @brief Signal a semaphore from a fiber
*
* This routine (to only be called from a fiber) signals a semaphore. It
* requires a statically allocated command packet (from a command packet set)
* that is implicitly released once the command packet has been processed.
* This routine (to only be called from a fiber) signals a semaphore.
* To signal a semaphore from a task, task_sem_give() should be used instead.
*
* @param sema Semaphore to signal.
* @param pSet Pointer to command packet set.
*
* @return N/A
*/
extern void isr_sem_give(ksem_t sema, struct cmd_pkt_set *pSet);
extern void isr_sem_give(ksem_t sema);
/**
*
* @brief Signal a semaphore from an ISR
*
* This routine (to only be called from an ISR) signals a semaphore. It
* requires a statically allocated command packet (from a command packet set)
* that is implicitly released once the command packet has been processed.
* This routine (to only be called from an ISR) signals a semaphore.
* To signal a semaphore from a task, task_sem_give() should be used instead.
*
* @param sema Semaphore to signal.
* @param pSet Pointer to command packet set.
*
* @return N/A
*/
extern void fiber_sem_give(ksem_t sema, struct cmd_pkt_set *pSet);
extern void fiber_sem_give(ksem_t sema);
/**
*
@ -142,6 +136,21 @@ extern void task_sem_group_reset(ksemg_t semagroup);
/**
* @cond internal
*/
/**
*
* @brief Update value of semaphore structure
*
* This routine updates the value of the semaphore by 0 or more units, then
* gives the semaphore to any waiting tasks that can now be satisfied.
*
* @param n Number of additional times semaphore has been given.
* @param sema Semaphore structure to update.
*
* @return N/A
*/
extern void _k_sem_struct_value_update(int n, struct _k_sem_struct *S);
/**
*
* @brief Test a semaphore

View file

@ -33,39 +33,6 @@
uint32_t _k_test_cmd_pkt_size
[0 - ((CMD_PKT_SIZE_IN_WORDS * sizeof(uint32_t)) != sizeof(struct k_args))];
/**
* @brief Get the next command packet
*
* This routine gets the next command packet from the specified set.
* @param pSet Pointer to set of command packets
*
* @return pointer to the command packet
*
* @internal
* It is critical that the word corresponding to the [alloc] field in the
* equivalent struct k_args command packet be zero so that the system knows the
* command packet is not part of the free list.
* @endinternal
*/
struct k_args *_cmd_pkt_get(struct cmd_pkt_set *pSet)
{
uint32_t index; /* index into command packet array */
struct k_args *cmd_pkt; /* pointer to command packet */
int key; /* interrupt lock level */
key = irq_lock();
index = pSet->index;
pSet->index++;
if (pSet->index >= pSet->num_packets)
pSet->index = 0;
irq_unlock(key);
cmd_pkt = (struct k_args *)&pSet->command_packet[index];
cmd_pkt->alloc = false;
return cmd_pkt;
}
/**
*
* @brief Send command packet to be processed by _k_server

View file

@ -26,13 +26,7 @@
#include <micro_private.h>
/**
*
* @brief Common code for signaling a semaphore
*
* @return N/A
*/
static void signal_semaphore(int n, struct _k_sem_struct *S)
void _k_sem_struct_value_update(int n, struct _k_sem_struct *S)
{
struct k_args *A, *X, *Y;
@ -127,7 +121,7 @@ void _k_sem_group_wait_cancel(struct k_args *A)
ENDLIST)) {
waitTaskArgs->args.s1.sema = A->args.s1.sema;
} else {
signal_semaphore(1, S);
_k_sem_struct_value_update(1, S);
}
}
@ -271,7 +265,7 @@ void _k_sem_group_wait_request(struct k_args *A)
} else {
S->waiters = A;
}
signal_semaphore(0, S);
_k_sem_struct_value_update(0, S);
}
void _k_sem_group_wait_any(struct k_args *A)
@ -371,7 +365,7 @@ void _k_sem_signal(struct k_args *A)
uint32_t Sid = A->args.s1.sema;
struct _k_sem_struct *S = (struct _k_sem_struct *)Sid;
signal_semaphore(1, S);
_k_sem_struct_value_update(1, S);
}
void _k_sem_group_signal(struct k_args *A)
@ -403,15 +397,10 @@ void task_sem_group_give(ksemg_t group)
FUNC_ALIAS(isr_sem_give, fiber_sem_give, void);
void isr_sem_give(ksem_t sema, struct cmd_pkt_set *pSet)
void isr_sem_give(ksem_t sema)
{
struct k_args *pCommand; /* ptr to command packet */
pCommand = _cmd_pkt_get(pSet);
pCommand->Comm = _K_SVC_SEM_SIGNAL;
pCommand->args.s1.sema = sema;
nano_isr_stack_push(&_k_command_stack, (uint32_t)pCommand);
nano_isr_stack_push(&_k_command_stack,
(uint32_t)sema | KERNEL_CMD_SEMAPHORE_TYPE);
}
void _k_sem_reset(struct k_args *A)

View file

@ -110,9 +110,9 @@ FUNC_NORETURN void _k_server(int unused1, int unused2)
}
#endif
(*pArgs->Comm)(pArgs);
} else {
} else if (cmd_type == KERNEL_CMD_EVENT_TYPE) {
/* cmd_type == KERNEL_CMD_EVENT_TYPE */
/* give event */
#ifdef CONFIG_TASK_MONITOR
if (_k_monitor_mask & MON_EVENT) {
@ -122,6 +122,16 @@ FUNC_NORETURN void _k_server(int unused1, int unused2)
kevent_t event = (int)pArgs & ~KERNEL_CMD_TYPE_MASK;
_k_do_event_signal(event);
} else { /* cmd_type == KERNEL_CMD_SEMAPHORE_TYPE */
/* give semaphore */
#ifdef CONFIG_TASK_MONITOR
/* task monitoring for giving semaphore not implemented */
#endif
ksem_t sem = (int)pArgs & ~KERNEL_CMD_TYPE_MASK;
_k_sem_struct_value_update(1, (struct _k_sem_struct *)sem);
}
/*

View file

@ -44,8 +44,6 @@ extern struct nano_sem fiberSem; /* semaphore that allows test control the fiber
static ksem_t testIsrInfo;
CMD_PKT_SET_INSTANCE(cmdPktSetIsr, 2);
/*
* Note that semaphore group entries are arranged so that resultSems[TC_PASS]
* refers to SEM_TASKDONE and resultSems[TC_FAIL] refers to SEM_TASKFAIL.
@ -165,7 +163,7 @@ void LowPriTaskEntry(void)
static void testIsrHandler(void *isrData)
{
isr_sem_give(*(ksem_t *)isrData, &cmdPktSetIsr);
isr_sem_give(*(ksem_t *)isrData);
}
/**

View file

@ -36,9 +36,6 @@ extern ksem_t semList[];
static char __stack fiberStack[FIBER_STACK_SIZE]; /* test fiber stack size */
/* command packet set used by test fiber to signal semaphores */
CMD_PKT_SET_INSTANCE(cmdPktSetFiber, N_TESTS + 1);
/**
*
* @brief The test fiber entry function
@ -57,18 +54,18 @@ static void testFiberEntry(void)
int i;
/* release semaphore test task is waiting for */
nano_fiber_sem_take_wait(&fiberSem);
fiber_sem_give(simpleSem, &cmdPktSetFiber);
fiber_sem_give(simpleSem);
/* release the semaphore for N_TESTS times */
nano_fiber_sem_take_wait(&fiberSem);
for (i = 0; i < N_TESTS; i++) {
fiber_sem_give(simpleSem, &cmdPktSetFiber);
fiber_sem_give(simpleSem);
}
/* signal each semaphore in the group */
for (i = 0; semList[i] != ENDLIST; i++) {
nano_fiber_sem_take_wait(&fiberSem);
fiber_sem_give(semList[i], &cmdPktSetFiber);
fiber_sem_give(semList[i]);
}
}