Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions sys/cb_mux/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base
124 changes: 124 additions & 0 deletions sys/cb_mux/cb_mux.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Copyright (C) 2018 Acutam Automation, LLC
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @ingroup sys_cb_mux
* @{
*
* @file
* @brief cb_mux implementation
*
* @author Matthew Blue <matthew.blue.neuro@gmail.com>
* @}
*/

#include "cb_mux.h"
#include "utlist.h"

void cb_mux_add(cb_mux_t **head, cb_mux_t *entry)
{
LL_APPEND(*head, entry);
}

void cb_mux_del(cb_mux_t **head, cb_mux_t *entry)
{
LL_DELETE(*head, entry);
}

cb_mux_t *cb_mux_find_cbid(cb_mux_t *head, cb_mux_cbid_t cbid_val)
{
cb_mux_t *entry;

LL_SEARCH_SCALAR(head, entry, cbid, cbid_val);

return entry;
}

cb_mux_t *cb_mux_find_low(cb_mux_t *head)
{
cb_mux_t *entry;
cb_mux_t *entry_low = NULL;
cb_mux_cbid_t id = (cb_mux_cbid_t)(-1);

LL_FOREACH(head, entry) {
/* Entry does not have lower ID */
if (entry->cbid >= id) {
continue;
}

id = entry->cbid;
entry_low = entry;
}

return entry_low;
}

cb_mux_t *cb_mux_find_high(cb_mux_t *head)
{
cb_mux_t *entry;
cb_mux_t *entry_high = NULL;
cb_mux_cbid_t id = 0;

LL_FOREACH(head, entry) {
/* Entry does not have higher ID */
if (entry->cbid <= id) {
continue;
}

id = entry->cbid;
entry_high = entry;
}

return entry_high;
}

cb_mux_cbid_t cb_mux_find_free_id(cb_mux_t *head)
{
uint32_t free;
cb_mux_cbid_t block;
cb_mux_t *entry;
uint8_t num;

/* Search for free IDs in blocks of 32 IDs */
for (block = 0; block + 31 < (cb_mux_cbid_t)(-1); block += 32) {
/* Set all IDs in block to free */
free = 0;

LL_FOREACH(head, entry) {
/* cbid falls within this block */
if ((entry->cbid >= block) && (entry->cbid < block + 32)) {
/* Set cbid to taken */
free |= 1 << (entry->cbid & 0x1F);
}
}

/* At least one ID in block free */
if (~free) {
break;
}
}

/* Find which ID in block was free */
for (num = 0; num < 32; num++) {
if (~free & (1 << num)) {
return block | num;
}
}

/* No free IDs */
return (cb_mux_cbid_t)(-1);
}

void cb_mux_iter(cb_mux_t *head, cb_mux_iter_t func, void *arg)
{
cb_mux_t *entry;

LL_FOREACH(head, entry) {
func(entry, arg);
}
}
143 changes: 143 additions & 0 deletions sys/include/cb_mux.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright (C) 2018 Acutam Automation, LLC
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/

/**
* @defgroup sys_cb_mux Callback multiplexer
* @ingroup sys
* @brief cb_mux provides utilities for storing, retrieving, and managing
* callback information in a singly linked list.
*
* If an API provides the ability to call multiple callbacks, cb_mux can
* simplify handling of an arbitrary number of callbacks by requiring memory
* for a cb_mux entry to be passed along with other arguments. The cb_mux entry
* is then attached to a list using cb_mux_add. The code implementing that API
* can manage the list using the various utility functions that cb_mux provides.
*
* @{
*
* @file
* @brief cb_mux interface definitions
*
* @author Matthew Blue <matthew.blue.neuro@gmail.com>
*/

#ifndef CB_MUX_H
#define CB_MUX_H

#include <stdint.h>

/* For alternate cb_mux_cbid_t */
#include "periph_cpu.h"

#ifdef __cplusplus
extern "C" {
#endif

#ifndef HAVE_CB_MUX_CBID_T
/**
* @brief cb_mux identifier type
*/
typedef unsigned int cb_mux_cbid_t;
#endif

/**
* @brief cb_mux callback type
*/
typedef void (*cb_mux_cb_t)(void *);

/**
* @brief cb_mux list entry structure
*/
typedef struct cb_mux {
struct cb_mux *next; /**< next entry in the cb_mux list */
cb_mux_cbid_t cbid; /**< identifier for this callback */
void *info; /**< optional extra information */
cb_mux_cb_t cb; /**< callback function */
void *arg; /**< argument for callback function */
} cb_mux_t;

/**
* @brief cb_mux iterate function callback type for cb_mux_iter
*/
typedef void (*cb_mux_iter_t)(cb_mux_t *, void *);

/**
* @brief Add a new entry to the end of a cb_mux list
*
* @param[in] head double pointer to first list entry
* @param[in] entry entry to add
*/
void cb_mux_add(cb_mux_t **head, cb_mux_t *entry);

/**
* @brief Remove a entry from a cb_mux list
*
* @param[in] head double pointer to first list entry
* @param[in] entry entry to remove
*/
void cb_mux_del(cb_mux_t **head, cb_mux_t *entry);

/**
* @brief Find an entry in the list by ID
*
* @param[in] head pointer to first list entry
* @param[in] cbid_val ID to find
*
* @return pointer to the list entry
*/
cb_mux_t *cb_mux_find_cbid(cb_mux_t *head, cb_mux_cbid_t cbid_val);

/**
* @brief Find the entry with the lowest ID
*
* If there are multiple hits, this returns the oldest.
*
* @param[in] head pointer to first list entry
*
* @return pointer to the list entry
*/
cb_mux_t *cb_mux_find_low(cb_mux_t *head);

/**
* @brief Find the entry with the highest ID
*
* If there are multiple hits, this returns the oldest.
*
* @param[in] head pointer to first list entry
*
* @return pointer to the list entry
*/
cb_mux_t *cb_mux_find_high(cb_mux_t *head);

/**
* @brief Find the lowest unused ID
*
* Returns highest possible ID on failure
*
* @param[in] head pointer to first list entry
*
* @return lowest unused ID
*/
cb_mux_cbid_t cb_mux_find_free_id(cb_mux_t *head);

/**
* @brief Run a function on every item in the cb_mux list
*
* @param[in] head pointer to first list entry
* @param[in] func function to run on each entry
* @param[in] arg argument for the function
*/
void cb_mux_iter(cb_mux_t *head, cb_mux_iter_t func, void *arg);

#ifdef __cplusplus
}
#endif

/** @} */

#endif /* CB_MUX_H */
10 changes: 10 additions & 0 deletions tests/cb_mux/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
include ../Makefile.tests_common

USEMODULE += cb_mux

TEST_ON_CI_WHITELIST += all

include $(RIOTBASE)/Makefile.include

test:
./tests/01-run.py
Loading