Change directory structure to align with Atmel softpack

This way we can easily check with 'diff' for differences in our code and
Atmel softpack.  Also, this layout is more suitable for building various
different firmware images (e.g. factory-test, dfu-loader, main
application) for a variety of different boards (simtrace, owhw, qmod).
This commit is contained in:
Harald Welte
2017-02-27 13:53:17 +01:00
parent 7ed6f3bc37
commit 3f5e3ddffc
81 changed files with 1218 additions and 12 deletions

View File

@@ -0,0 +1,372 @@
#pragma once
/*! \defgroup linuxlist Simple doubly linked list implementation
* @{
*/
/*!
* \file linuxlist.h
*
* \brief Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole llists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
#include <stddef.h>
#ifndef inline
#define inline __inline__
#endif
static inline void prefetch(const void *x) {;}
/*! \brief cast a member of a structure out to the containing structure
*
* \param[in] ptr the pointer to the member.
* \param[in] type the type of the container struct this is embedded in.
* \param[in] member the name of the member within the struct.
*/
#define container_of(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type, member) );})
/*!
* These are non-NULL pointers that will result in page faults
* under normal circumstances, used to verify that nobody uses
* non-initialized llist entries.
*/
#define LLIST_POISON1 ((void *) 0x00100100)
#define LLIST_POISON2 ((void *) 0x00200200)
/*! \brief (double) linked list header structure */
struct llist_head {
/*! \brief Pointer to next and previous item */
struct llist_head *next, *prev;
};
#define LLIST_HEAD_INIT(name) { &(name), &(name) }
/*! \brief define a statically-initialized \ref llist_head
* \param[in] name Variable name
*
* This is a helper macro that will define a named variable of type
* \ref llist_head and initialize it */
#define LLIST_HEAD(name) \
struct llist_head name = LLIST_HEAD_INIT(name)
/*! \brief initialize a \ref llist_head to point back to self */
#define INIT_LLIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
/*! \brief Insert a new entry between two known consecutive entries.
*
* This is only for internal llist manipulation where we know
* the prev/next entries already!
*/
static inline void __llist_add(struct llist_head *_new,
struct llist_head *prev,
struct llist_head *next)
{
next->prev = _new;
_new->next = next;
_new->prev = prev;
prev->next = _new;
}
/*! \brief add a new entry into a linked list (at head)
* \param _new New entry to be added
* \param head \ref llist_head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void llist_add(struct llist_head *_new, struct llist_head *head)
{
__llist_add(_new, head, head->next);
}
/*! \brief add a new entry into a linked list (at tail)
* \param _new New entry to be added
* \param head Head of linked list to whose tail we shall add \a _new
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void llist_add_tail(struct llist_head *_new, struct llist_head *head)
{
__llist_add(_new, head->prev, head);
}
/*
* Delete a llist entry by making the prev/next entries
* point to each other.
*
* This is only for internal llist manipulation where we know
* the prev/next entries already!
*/
static inline void __llist_del(struct llist_head * prev, struct llist_head * next)
{
next->prev = prev;
prev->next = next;
}
/*! \brief Delete entry from linked list
* \param entry The element to delete from the llist
*
* Note: llist_empty on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void llist_del(struct llist_head *entry)
{
__llist_del(entry->prev, entry->next);
entry->next = (struct llist_head *)LLIST_POISON1;
entry->prev = (struct llist_head *)LLIST_POISON2;
}
/*! \brief Delete entry from linked list and reinitialize it
* \param entry The element to delete from the list
*/
static inline void llist_del_init(struct llist_head *entry)
{
__llist_del(entry->prev, entry->next);
INIT_LLIST_HEAD(entry);
}
/*! \brief Delete from one llist and add as another's head
* \param llist The entry to move
* \param head The head that will precede our entry
*/
static inline void llist_move(struct llist_head *llist, struct llist_head *head)
{
__llist_del(llist->prev, llist->next);
llist_add(llist, head);
}
/*! \brief Delete from one llist and add as another's tail
* \param llist The entry to move
* \param head The head that will follow our entry
*/
static inline void llist_move_tail(struct llist_head *llist,
struct llist_head *head)
{
__llist_del(llist->prev, llist->next);
llist_add_tail(llist, head);
}
/*! \brief Test whether a linked list is empty
* \param[in] head The llist to test.
* \returns 1 if the list is empty, 0 otherwise
*/
static inline int llist_empty(const struct llist_head *head)
{
return head->next == head;
}
static inline void __llist_splice(struct llist_head *llist,
struct llist_head *head)
{
struct llist_head *first = llist->next;
struct llist_head *last = llist->prev;
struct llist_head *at = head->next;
first->prev = head;
head->next = first;
last->next = at;
at->prev = last;
}
/*! \brief Join two llists
* \param llist The new linked list to add
* \param head The place to add \a llist in the other list
*/
static inline void llist_splice(struct llist_head *llist, struct llist_head *head)
{
if (!llist_empty(llist))
__llist_splice(llist, head);
}
/*! \brief join two llists and reinitialise the emptied llist.
* \param llist The new linked list to add.
* \param head The place to add it in the first llist.
*
* The llist at @llist is reinitialised
*/
static inline void llist_splice_init(struct llist_head *llist,
struct llist_head *head)
{
if (!llist_empty(llist)) {
__llist_splice(llist, head);
INIT_LLIST_HEAD(llist);
}
}
/*! \brief Get the struct containing this list entry
* \param ptr The \ref llist_head pointer
* \param type The type of the struct this is embedded in
* \param @member The name of the \ref llist_head within the struct
*/
#define llist_entry(ptr, type, member) \
container_of(ptr, type, member)
/*! \brief Iterate over a linked list
* \param pos The \ref llist_head to use as a loop counter
* \param head The head of the list over which to iterate
*/
#define llist_for_each(pos, head) \
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
pos = pos->next, prefetch(pos->next))
/*! \brief Iterate over a llist (no prefetch)
* \param pos The \ref llist_head to use as a loop counter
* \param head The head of the list over which to iterate
*
* This variant differs from llist_for_each() in that it's the
* simplest possible llist iteration code, no prefetching is done.
* Use this for code that knows the llist to be very short (empty
* or 1 entry) most of the time.
*/
#define __llist_for_each(pos, head) \
for (pos = (head)->next; pos != (head); pos = pos->next)
/*! \brief Iterate over a llist backwards
* \param pos The \ref llist_head to use as a loop counter
* \param head The head of the list over which to iterate
*/
#define llist_for_each_prev(pos, head) \
for (pos = (head)->prev, prefetch(pos->prev); pos != (head); \
pos = pos->prev, prefetch(pos->prev))
/*! \brief Iterate over a list; safe against removal of llist entry
* \param pos The \ref llist_head to use as a loop counter
* \param n Another \ref llist_head to use as temporary storage
* \param head The head of the list over which to iterate
*/
#define llist_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/*! \brief Iterate over llist of given type
* \param pos The 'type *' to use as a loop counter
* \param head The head of the list over which to iterate
* \param member The name of the \ref llist_head within struct \a pos
*/
#define llist_for_each_entry(pos, head, member) \
for (pos = llist_entry((head)->next, typeof(*pos), member), \
prefetch(pos->member.next); \
&pos->member != (head); \
pos = llist_entry(pos->member.next, typeof(*pos), member), \
prefetch(pos->member.next))
/*! \brief Iterate backwards over llist of given type.
* \param pos The 'type *' to use as a loop counter
* \param head The head of the list over which to iterate
* \param member The name of the \ref llist_head within struct \a pos
*/
#define llist_for_each_entry_reverse(pos, head, member) \
for (pos = llist_entry((head)->prev, typeof(*pos), member), \
prefetch(pos->member.prev); \
&pos->member != (head); \
pos = llist_entry(pos->member.prev, typeof(*pos), member), \
prefetch(pos->member.prev))
/*! \brief iterate over llist of given type continuing after existing
* point
* \param pos The 'type *' to use as a loop counter
* \param head The head of the list over which to iterate
* \param member The name of the \ref llist_head within struct \a pos
*/
#define llist_for_each_entry_continue(pos, head, member) \
for (pos = llist_entry(pos->member.next, typeof(*pos), member), \
prefetch(pos->member.next); \
&pos->member != (head); \
pos = llist_entry(pos->member.next, typeof(*pos), member), \
prefetch(pos->member.next))
/*! \brief iterate over llist of given type, safe against removal of
* non-consecutive(!) llist entries
* \param pos The 'type *' to use as a loop counter
* \param n Another type * to use as temporary storage
* \param head The head of the list over which to iterate
* \param member The name of the \ref llist_head within struct \a pos
*/
#define llist_for_each_entry_safe(pos, n, head, member) \
for (pos = llist_entry((head)->next, typeof(*pos), member), \
n = llist_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = llist_entry(n->member.next, typeof(*n), member))
/**
* llist_for_each_rcu - iterate over an rcu-protected llist
* @pos: the &struct llist_head to use as a loop counter.
* @head: the head for your llist.
*/
#define llist_for_each_rcu(pos, head) \
for (pos = (head)->next, prefetch(pos->next); pos != (head); \
pos = pos->next, ({ smp_read_barrier_depends(); 0;}), prefetch(pos->next))
#define __llist_for_each_rcu(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next, ({ smp_read_barrier_depends(); 0;}))
/**
* llist_for_each_safe_rcu - iterate over an rcu-protected llist safe
* against removal of llist entry
* @pos: the &struct llist_head to use as a loop counter.
* @n: another &struct llist_head to use as temporary storage
* @head: the head for your llist.
*/
#define llist_for_each_safe_rcu(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, ({ smp_read_barrier_depends(); 0;}), n = pos->next)
/**
* llist_for_each_entry_rcu - iterate over rcu llist of given type
* @pos: the type * to use as a loop counter.
* @head: the head for your llist.
* @member: the name of the llist_struct within the struct.
*/
#define llist_for_each_entry_rcu(pos, head, member) \
for (pos = llist_entry((head)->next, typeof(*pos), member), \
prefetch(pos->member.next); \
&pos->member != (head); \
pos = llist_entry(pos->member.next, typeof(*pos), member), \
({ smp_read_barrier_depends(); 0;}), \
prefetch(pos->member.next))
/**
* llist_for_each_continue_rcu - iterate over an rcu-protected llist
* continuing after existing point.
* @pos: the &struct llist_head to use as a loop counter.
* @head: the head for your llist.
*/
#define llist_for_each_continue_rcu(pos, head) \
for ((pos) = (pos)->next, prefetch((pos)->next); (pos) != (head); \
(pos) = (pos)->next, ({ smp_read_barrier_depends(); 0;}), prefetch((pos)->next))
/*! \brief count nr of llist items by iterating.
* \param head The llist head to count items of.
* \returns Number of items.
*
* This function is not efficient, mostly useful for small lists and non time
* critical cases like unit tests.
*/
static inline unsigned int llist_count(struct llist_head *head)
{
struct llist_head *entry;
unsigned int i = 0;
llist_for_each(entry, head)
i++;
return i;
}
/*!
* }@
*/

View File

@@ -0,0 +1,158 @@
/*
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
linux/include/linux/rbtree.h
To use rbtrees you'll have to implement your own insert and search cores.
This will avoid us to use callbacks and to drop drammatically performances.
I know it's not the cleaner way, but in C (not in C++) to get
performances and genericity...
Some example of insert and search follows here. The search is a plain
normal search over an ordered tree. The insert instead must be implemented
int two steps: as first thing the code must insert the element in
order as a red leaf in the tree, then the support library function
rb_insert_color() must be called. Such function will do the
not trivial work to rebalance the rbtree if necessary.
-----------------------------------------------------------------------
static inline struct page * rb_search_page_cache(struct inode * inode,
unsigned long offset)
{
struct rb_node * n = inode->i_rb_page_cache.rb_node;
struct page * page;
while (n)
{
page = rb_entry(n, struct page, rb_page_cache);
if (offset < page->offset)
n = n->rb_left;
else if (offset > page->offset)
n = n->rb_right;
else
return page;
}
return NULL;
}
static inline struct page * __rb_insert_page_cache(struct inode * inode,
unsigned long offset,
struct rb_node * node)
{
struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
struct rb_node * parent = NULL;
struct page * page;
while (*p)
{
parent = *p;
page = rb_entry(parent, struct page, rb_page_cache);
if (offset < page->offset)
p = &(*p)->rb_left;
else if (offset > page->offset)
p = &(*p)->rb_right;
else
return page;
}
rb_link_node(node, parent, p);
return NULL;
}
static inline struct page * rb_insert_page_cache(struct inode * inode,
unsigned long offset,
struct rb_node * node)
{
struct page * ret;
if ((ret = __rb_insert_page_cache(inode, offset, node)))
goto out;
rb_insert_color(node, &inode->i_rb_page_cache);
out:
return ret;
}
-----------------------------------------------------------------------
*/
#pragma once
#include <stdlib.h>
struct rb_node
{
unsigned long rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
/* The alignment might seem pointless, but allegedly CRIS needs it */
struct rb_root
{
struct rb_node *rb_node;
};
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r) ((r)->rb_parent_color & 1)
#define rb_is_red(r) (!rb_color(r))
#define rb_is_black(r) rb_color(r)
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
#define RB_ROOT { NULL, }
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
extern void rb_insert_color(struct rb_node *, struct rb_root *);
extern void rb_erase(struct rb_node *, struct rb_root *);
/* Find logical next and previous nodes in a tree */
extern struct rb_node *rb_next(const struct rb_node *);
extern struct rb_node *rb_prev(const struct rb_node *);
extern struct rb_node *rb_first(const struct rb_root *);
extern struct rb_node *rb_last(const struct rb_root *);
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
extern void rb_replace_node(struct rb_node *victim, struct rb_node *_new,
struct rb_root *root);
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
{
node->rb_parent_color = (unsigned long )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}

View File

@@ -0,0 +1,109 @@
/*
* (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
* All Rights Reserved
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
/*! \defgroup timer Osmocom timers
* @{
*/
/*! \file timer.h
* \brief Osmocom timer handling routines
*/
#pragma once
/* override 'struct timeval' for jififes based timers */
struct osmo_timeval {
unsigned long expires;
};
#define timerisset(tvp) ((tvp)->expires)
#define timerclear(tvp) (tvp)->expires = 0
#define timercmp(a, b, CMP) (a)->expires CMP (b)->expires
#define timersub(a, b, result) (result)->expires = (a)->expires - (b)->expires
#define timeradd(a, b, result) (result)->expires = (a)->expires + (b)->expires
struct timezone;
#include <stdbool.h>
#include "osmocom/core/linuxlist.h"
#include "osmocom/core/linuxrbtree.h"
/**
* Timer management:
* - Create a struct osmo_timer_list
* - Fill out timeout and use add_timer or
* use osmo_timer_schedule to schedule a timer in
* x seconds and microseconds from now...
* - Use osmo_timer_del to remove the timer
*
* Internally:
* - We hook into select.c to give a timeval of the
* nearest timer. On already passed timers we give
* it a 0 to immediately fire after the select
* - osmo_timers_update will call the callbacks and
* remove the timers.
*
*/
/*! \brief A structure representing a single instance of a timer */
struct osmo_timer_list {
struct rb_node node; /*!< \brief rb-tree node header */
struct llist_head list; /*!< \brief internal list header */
struct osmo_timeval timeout; /*!< \brief expiration time */
unsigned int active : 1; /*!< \brief is it active? */
void (*cb)(void*); /*!< \brief call-back called at timeout */
void *data; /*!< \brief user data for callback */
};
/**
* timer management
*/
void osmo_timer_add(struct osmo_timer_list *timer);
void osmo_timer_schedule(struct osmo_timer_list *timer, int seconds, int microseconds);
void osmo_timer_del(struct osmo_timer_list *timer);
int osmo_timer_pending(struct osmo_timer_list *timer);
int osmo_timer_remaining(const struct osmo_timer_list *timer,
const struct osmo_timeval *now,
struct osmo_timeval *remaining);
/*
* internal timer list management
*/
struct osmo_timeval *osmo_timers_nearest(void);
void osmo_timers_prepare(void);
int osmo_timers_update(void);
int osmo_timers_check(void);
int osmo_gettimeofday(struct osmo_timeval *tv, struct timezone *tz);
#if 0
/**
* timer override
*/
extern bool osmo_gettimeofday_override;
extern struct timeval osmo_gettimeofday_override_time;
void osmo_gettimeofday_override_add(time_t secs, suseconds_t usecs);
#endif
/*! @} */