Skip to content

Commit

Permalink
lifo/fifo: first word is not always first 4 bytes
Browse files Browse the repository at this point in the history
The first word is used as a pointer, meaning it is 64 bits on 64-bit
systems. To reserve it, it has to be either a pointer, a long, or an
intptr_t. Not an int nor an u32_t.

Signed-off-by: Nicolas Pitre <[email protected]>
  • Loading branch information
Nicolas Pitre authored and nashif committed Jun 26, 2019
1 parent 002bebd commit 659fa0d
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 82 deletions.
10 changes: 5 additions & 5 deletions doc/reference/kernel/data_passing/fifos.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ A fifo has the following key properties:

A fifo must be initialized before it can be used. This sets its queue to empty.

FIFO data items must be aligned on a 4-byte boundary, as the kernel reserves
the first 32 bits of an item for use as a pointer to the next data item in the
queue. Consequently, a data item that holds N bytes of application data
requires N+4 bytes of memory. There are no alignment or reserved space
requirements for data items if they are added with
FIFO data items must be aligned on a word boundary, as the kernel reserves
the first word of an item for use as a pointer to the next data item in
the queue. Consequently, a data item that holds N bytes of application
data requires N+4 (or N+8) bytes of memory. There are no alignment or
reserved space requirements for data items if they are added with
:cpp:func:`k_fifo_alloc_put()`, instead additional memory is temporarily
allocated from the calling thread's resource pool.

Expand Down
8 changes: 4 additions & 4 deletions doc/reference/kernel/data_passing/lifos.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ A lifo has the following key properties:

A lifo must be initialized before it can be used. This sets its queue to empty.

LIFO data items must be aligned on a 4-byte boundary, as the kernel reserves
the first 32 bits of an item for use as a pointer to the next data item in the
LIFO data items must be aligned on a word boundary, as the kernel reserves
the first word of an item for use as a pointer to the next data item in the
queue. Consequently, a data item that holds N bytes of application data
requires N+4 bytes of memory. There are no alignment or reserved space
requirements for data items if they are added with
requires N+4 (or N+8) bytes of memory. There are no alignment or reserved
space requirements for data items if they are added with
:cpp:func:`k_lifo_alloc_put()`, instead additional memory is temporarily
allocated from the calling thread's resource pool.

Expand Down
4 changes: 2 additions & 2 deletions include/drivers/console/console.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ extern "C" {
* Recorded line must be NULL terminated.
*/
struct console_input {
/** FIFO uses first 4 bytes itself, reserve space */
int _unused;
/** FIFO uses first word itself, reserve space */
intptr_t _unused;
/** Whether this is an mcumgr command */
u8_t is_mcumgr : 1;
/** Buffer where the input line is recorded */
Expand Down
38 changes: 19 additions & 19 deletions include/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -1843,8 +1843,8 @@ __syscall void k_queue_cancel_wait(struct k_queue *queue);
* @brief Append an element to the end of a queue.
*
* This routine appends a data item to @a queue. A queue data item must be
* aligned on a 4-byte boundary, and the first 32 bits of the item are
* reserved for the kernel's use.
* aligned on a word boundary, and the first word of the item is reserved
* for the kernel's use.
*
* @note Can be called by ISRs.
*
Expand Down Expand Up @@ -1877,8 +1877,8 @@ __syscall s32_t k_queue_alloc_append(struct k_queue *queue, void *data);
* @brief Prepend an element to a queue.
*
* This routine prepends a data item to @a queue. A queue data item must be
* aligned on a 4-byte boundary, and the first 32 bits of the item are
* reserved for the kernel's use.
* aligned on a word boundary, and the first word of the item is reserved
* for the kernel's use.
*
* @note Can be called by ISRs.
*
Expand Down Expand Up @@ -1911,8 +1911,8 @@ __syscall s32_t k_queue_alloc_prepend(struct k_queue *queue, void *data);
* @brief Inserts an element to a queue.
*
* This routine inserts a data item to @a queue after previous item. A queue
* data item must be aligned on a 4-byte boundary, and the first 32 bits of the
* item are reserved for the kernel's use.
* data item must be aligned on a word boundary, and the first word of
* the item is reserved for the kernel's use.
*
* @note Can be called by ISRs.
*
Expand All @@ -1928,7 +1928,7 @@ extern void k_queue_insert(struct k_queue *queue, void *prev, void *data);
* @brief Atomically append a list of elements to a queue.
*
* This routine adds a list of data items to @a queue in one operation.
* The data items must be in a singly-linked list, with the first 32 bits
* The data items must be in a singly-linked list, with the first word
* in each data item pointing to the next data item; the list must be
* NULL-terminated.
*
Expand Down Expand Up @@ -1961,8 +1961,8 @@ extern void k_queue_merge_slist(struct k_queue *queue, sys_slist_t *list);
/**
* @brief Get an element from a queue.
*
* This routine removes first data item from @a queue. The first 32 bits of the
* data item are reserved for the kernel's use.
* This routine removes first data item from @a queue. The first word of the
* data item is reserved for the kernel's use.
*
* @note Can be called by ISRs, but @a timeout must be set to K_NO_WAIT.
*
Expand All @@ -1978,8 +1978,8 @@ __syscall void *k_queue_get(struct k_queue *queue, s32_t timeout);
/**
* @brief Remove an element from a queue.
*
* This routine removes data item from @a queue. The first 32 bits of the
* data item are reserved for the kernel's use. Removing elements from k_queue
* This routine removes data item from @a queue. The first word of the
* data item is reserved for the kernel's use. Removing elements from k_queue
* rely on sys_slist_find_and_remove which is not a constant time operation.
*
* @note Can be called by ISRs
Expand All @@ -1997,8 +1997,8 @@ static inline bool k_queue_remove(struct k_queue *queue, void *data)
/**
* @brief Append an element to a queue only if it's not present already.
*
* This routine appends data item to @a queue. The first 32 bits of the
* data item are reserved for the kernel's use. Appending elements to k_queue
* This routine appends data item to @a queue. The first word of the data
* item is reserved for the kernel's use. Appending elements to k_queue
* relies on sys_slist_is_node_in_list which is not a constant time operation.
*
* @note Can be called by ISRs
Expand Down Expand Up @@ -2235,8 +2235,8 @@ struct k_fifo {
* @brief Add an element to a FIFO queue.
*
* This routine adds a data item to @a fifo. A FIFO data item must be
* aligned on a 4-byte boundary, and the first 32 bits of the item are
* reserved for the kernel's use.
* aligned on a word boundary, and the first word of the item is reserved
* for the kernel's use.
*
* @note Can be called by ISRs.
*
Expand Down Expand Up @@ -2273,7 +2273,7 @@ struct k_fifo {
* @brief Atomically add a list of elements to a FIFO.
*
* This routine adds a list of data items to @a fifo in one operation.
* The data items must be in a singly-linked list, with the first 32 bits
* The data items must be in a singly-linked list, with the first word of
* each data item pointing to the next data item; the list must be
* NULL-terminated.
*
Expand Down Expand Up @@ -2312,7 +2312,7 @@ struct k_fifo {
* @brief Get an element from a FIFO queue.
*
* This routine removes a data item from @a fifo in a "first in, first out"
* manner. The first 32 bits of the data item are reserved for the kernel's use.
* manner. The first word of the data item is reserved for the kernel's use.
*
* @note Can be called by ISRs, but @a timeout must be set to K_NO_WAIT.
*
Expand Down Expand Up @@ -2434,7 +2434,7 @@ struct k_lifo {
* @brief Add an element to a LIFO queue.
*
* This routine adds a data item to @a lifo. A LIFO queue data item must be
* aligned on a 4-byte boundary, and the first 32 bits of the item are
* aligned on a word boundary, and the first word of the item is
* reserved for the kernel's use.
*
* @note Can be called by ISRs.
Expand Down Expand Up @@ -2472,7 +2472,7 @@ struct k_lifo {
* @brief Get an element from a LIFO queue.
*
* This routine removes a data item from @a lifo in a "last in, first out"
* manner. The first 32 bits of the data item are reserved for the kernel's use.
* manner. The first word of the data item is reserved for the kernel's use.
*
* @note Can be called by ISRs, but @a timeout must be set to K_NO_WAIT.
*
Expand Down
2 changes: 1 addition & 1 deletion include/net/net_pkt.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ struct net_pkt {
* RX path, it is then fine to have both attributes sharing
* the same memory area.
*/
int sock_recv_fifo;
intptr_t sock_recv_fifo;
};

/** Slab pointer from where it belongs to */
Expand Down
2 changes: 1 addition & 1 deletion kernel/queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ void *z_queue_node_peek(sys_sfnode_t *node, bool needs_free)
k_free(anode);
}
} else {
/* Data was directly placed in the queue, the first 4 bytes
/* Data was directly placed in the queue, the first word
* reserved for the linked list. User mode isn't allowed to
* do this, although it can get data sent this way.
*/
Expand Down
44 changes: 19 additions & 25 deletions tests/benchmarks/sys_kernel/src/lifo.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,21 @@ void lifo_test_init(void)
void lifo_thread1(void *par1, void *par2, void *par3)
{
int i;
int element_a[2];
int element_b[2];
int *pelement;
intptr_t element_a[2];
intptr_t element_b[2];
intptr_t *pelement;
int num_loops = POINTER_TO_INT(par2);

ARG_UNUSED(par1);

for (i = 0; i < num_loops / 2; i++) {
pelement = (int *)k_lifo_get(&lifo1,
K_FOREVER);
pelement = k_lifo_get(&lifo1, K_FOREVER);
if (pelement[1] != 2 * i) {
break;
}
element_a[1] = 2 * i;
k_lifo_put(&lifo2, element_a);
pelement = (int *)k_lifo_get(&lifo1,
K_FOREVER);
pelement = k_lifo_get(&lifo1, K_FOREVER);
if (pelement[1] != 2 * i + 1) {
break;
}
Expand All @@ -80,16 +78,15 @@ void lifo_thread1(void *par1, void *par2, void *par3)
void lifo_thread2(void *par1, void *par2, void *par3)
{
int i;
int element[2];
int *pelement;
intptr_t element[2];
intptr_t *pelement;
int *pcounter = par1;
int num_loops = POINTER_TO_INT(par2);

for (i = 0; i < num_loops; i++) {
element[1] = i;
k_lifo_put(&lifo1, element);
pelement = (int *)k_lifo_get(&lifo2,
K_FOREVER);
pelement = k_lifo_get(&lifo2, K_FOREVER);
if (pelement[1] != i) {
break;
}
Expand All @@ -112,16 +109,15 @@ void lifo_thread2(void *par1, void *par2, void *par3)
void lifo_thread3(void *par1, void *par2, void *par3)
{
int i;
int element[2];
int *pelement;
intptr_t element[2];
intptr_t *pelement;
int *pcounter = par1;
int num_loops = POINTER_TO_INT(par2);

for (i = 0; i < num_loops; i++) {
element[1] = i;
k_lifo_put(&lifo1, element);
while ((pelement = k_lifo_get(&lifo2,
K_NO_WAIT)) == NULL) {
while ((pelement = k_lifo_get(&lifo2, K_NO_WAIT)) == NULL) {
k_yield();
}
if (pelement[1] != i) {
Expand All @@ -144,7 +140,7 @@ int lifo_test(void)
u32_t t;
int i = 0;
int return_value = 0;
int element[2];
intptr_t element[2];
int j;

k_fifo_init(&sync_fifo);
Expand Down Expand Up @@ -176,7 +172,7 @@ int lifo_test(void)

/* threads have done their job, they can stop now safely: */
for (j = 0; j < 2; j++) {
k_fifo_put(&sync_fifo, (void *) element);
k_fifo_put(&sync_fifo, element);
}

/* test get/yield & put thread functions between co-op threads */
Expand Down Expand Up @@ -210,7 +206,7 @@ int lifo_test(void)

/* threads have done their job, they can stop now safely: */
for (j = 0; j < 2; j++) {
k_fifo_put(&sync_fifo, (void *) element);
k_fifo_put(&sync_fifo, element);
}

/* test get wait & put functions between co-op and premptive threads */
Expand All @@ -232,21 +228,19 @@ int lifo_test(void)
NULL, INT_TO_POINTER(number_of_loops), NULL,
K_PRIO_COOP(3), 0, K_NO_WAIT);
for (i = 0; i < number_of_loops / 2U; i++) {
int element[2];
int *pelement;
intptr_t element[2];
intptr_t *pelement;

element[1] = 2 * i;
k_lifo_put(&lifo1, element);
element[1] = 2 * i + 1;
k_lifo_put(&lifo1, element);

pelement = (int *)k_lifo_get(&lifo2,
K_FOREVER);
pelement = k_lifo_get(&lifo2, K_FOREVER);
if (pelement[1] != 2 * i + 1) {
break;
}
pelement = (int *)k_lifo_get(&lifo2,
K_FOREVER);
pelement = k_lifo_get(&lifo2, K_FOREVER);
if (pelement[1] != 2 * i) {
break;
}
Expand All @@ -258,7 +252,7 @@ int lifo_test(void)

/* threads have done their job, they can stop now safely: */
for (j = 0; j < 2; j++) {
k_fifo_put(&sync_fifo, (void *) element);
k_fifo_put(&sync_fifo, element);
}

return return_value;
Expand Down
Loading

0 comments on commit 659fa0d

Please sign in to comment.