microkernel: Don't initialize packets in a command packet set

Reworks the internal design of a command packet set so that
the command packet array is split out into a separate variable
lying in uninitialized memory. This shrinks the command packet's
data section footprint to almost nothing.

Note: A side effect of this change is that it is no longer possible
to define a command packet set as a "static" variable since the
CMD_PKT_SET_INSTANCE() macro now generates two variables.

Change-Id: I9c7ebe637edf879758589ff4a26ace1303790bf7
Signed-off-by: Allan Stephens <allan.stephens@windriver.com>
This commit is contained in:
Allan Stephens 2015-10-14 16:02:04 -04:00 committed by Anas Nashif
commit f330d5adfe
5 changed files with 42 additions and 51 deletions

View file

@ -28,8 +28,8 @@
* 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 accessed using ...
* CMD_PKT_SET(set variable name).<member field name>
* 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
@ -52,47 +52,34 @@ extern "C" {
#define CMD_PKT_SIZE_IN_WORDS (19)
/**
* @brief Define a command packet set
*
*
* This macro is used to create a command packet set in the global namespace.
* Each packet set can have a different number of packets.
*
* @param name Name of command packet set
* @param num Number of packets in the set
*
* @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 that the
* command packet is not part of the free list.
* @endinternal
*/
#define CMD_PKT_SET_INSTANCE(name, num) \
uint32_t name[2 + CMD_PKT_SIZE_IN_WORDS * (num)] = {num, 0}
/**
* @brief Wrapper for accessing a command packet set
*
* A command packet set must be typecast to the cmd_pkt_set type
* when accessed, because it is instantiated as an array of uint32_t.
*
* @param name Name of command packet set
*
*/
#define CMD_PKT_SET(name) (*(struct cmd_pkt_set *)(name))
/* define command packet set types */
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[]; /* array of command packets */
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 cmdPkt_t *_cmd_pkt_get(struct cmd_pkt_set *pSet);
extern struct k_args *_cmd_pkt_get(struct cmd_pkt_set *pSet);
#ifdef __cplusplus
}

View file

@ -40,10 +40,17 @@ uint32_t _k_test_cmd_pkt_size
* @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
*/
cmdPkt_t *_cmd_pkt_get(struct cmd_pkt_set *pSet)
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();
@ -53,7 +60,10 @@ cmdPkt_t *_cmd_pkt_get(struct cmd_pkt_set *pSet)
pSet->index = 0;
irq_unlock(key);
return &pSet->command_packet[index];
cmd_pkt = (struct k_args *)&pSet->command_packet[index];
cmd_pkt->alloc = false;
return cmd_pkt;
}
/**

View file

@ -407,13 +407,7 @@ void isr_sem_give(ksem_t sema, struct cmd_pkt_set *pSet)
{
struct k_args *pCommand; /* ptr to command packet */
/*
* The cmdPkt_t data structure was designed to work seamlessly with the
* struct k_args data structure and it is thus safe (and expected) to typecast
* the return value of _cmd_pkt_get() to "struct k_args *".
*/
pCommand = (struct k_args *)_cmd_pkt_get(pSet);
pCommand = _cmd_pkt_get(pSet);
pCommand->Comm = _K_SVC_SEM_SIGNAL;
pCommand->args.s1.sema = sema;

View file

@ -46,7 +46,7 @@ extern struct nano_sem fiberSem; /* semaphore that allows test control the fiber
static ksem_t testIsrInfo;
static CMD_PKT_SET_INSTANCE(cmdPktSet, 2);
CMD_PKT_SET_INSTANCE(cmdPktSetIsr, 2);
/*
* Note that semaphore group entries are arranged so that resultSems[TC_PASS]
@ -167,7 +167,7 @@ void LowPriTaskEntry(void)
static void testIsrHandler(void *isrData)
{
isr_sem_give(*(ksem_t *)isrData, &CMD_PKT_SET(cmdPktSet));
isr_sem_give(*(ksem_t *)isrData, &cmdPktSetIsr);
}
/**

View file

@ -38,8 +38,8 @@ extern ksem_t semList[];
static char __stack fiberStack[FIBER_STACK_SIZE]; /* test fiber stack size */
/* array of command packets used by test fiber to signal semaphores */
static CMD_PKT_SET_INSTANCE(cmdPktSet, N_TESTS + 1);
/* command packet set used by test fiber to signal semaphores */
CMD_PKT_SET_INSTANCE(cmdPktSetFiber, N_TESTS + 1);
/**
*
@ -59,18 +59,18 @@ static void testFiberEntry(void)
int i;
/* release semaphore test task is waiting for */
nano_fiber_sem_take_wait(&fiberSem);
fiber_sem_give(simpleSem, &CMD_PKT_SET(cmdPktSet));
fiber_sem_give(simpleSem, &cmdPktSetFiber);
/* release the semaphore for N_TESTS times */
nano_fiber_sem_take_wait(&fiberSem);
for (i = 0; i < N_TESTS; i++) {
fiber_sem_give(simpleSem, &CMD_PKT_SET(cmdPktSet));
fiber_sem_give(simpleSem, &cmdPktSetFiber);
}
/* signal each semaphore in the group */
for (i = 0; semList[i] != ENDLIST; i++) {
nano_fiber_sem_take_wait(&fiberSem);
fiber_sem_give(semList[i], &CMD_PKT_SET(cmdPktSet));
fiber_sem_give(semList[i], &cmdPktSetFiber);
}
}