From fcf36dd4f9879a82342e5606535d2dcf46d1de2a Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Mon, 17 May 2010 12:34:05 +0000 Subject: Simplify mpegplayer a bit and use array-based lists rather than linked lists for stream management. Move a couple useful functions to handle pointer arrays from kernel.c into general.c; mpeglayer now makes use of them. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26101 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugin.c | 5 + apps/plugin.h | 7 +- apps/plugins/mpegplayer/SOURCES | 1 - apps/plugins/mpegplayer/disk_buf.c | 37 ++++---- apps/plugins/mpegplayer/mpeg_linkedlist.c | 151 ------------------------------ apps/plugins/mpegplayer/mpeg_linkedlist.h | 71 -------------- apps/plugins/mpegplayer/mpeg_misc.c | 60 ++++++++++++ apps/plugins/mpegplayer/mpeg_misc.h | 26 +++++ apps/plugins/mpegplayer/mpegplayer.h | 4 +- apps/plugins/mpegplayer/stream_mgr.c | 52 +++++----- apps/plugins/mpegplayer/stream_mgr.h | 4 +- apps/plugins/mpegplayer/stream_thread.h | 7 +- firmware/export/general.h | 15 +++ firmware/general.c | 37 ++++++++ firmware/kernel.c | 35 +------ 15 files changed, 199 insertions(+), 313 deletions(-) delete mode 100644 apps/plugins/mpegplayer/mpeg_linkedlist.c delete mode 100644 apps/plugins/mpegplayer/mpeg_linkedlist.h diff --git a/apps/plugin.c b/apps/plugin.c index 90380a0039..b45220acdb 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -724,6 +724,11 @@ static const struct plugin_api rockbox_api = { #ifdef AUDIOHW_HAVE_EQ sound_enum_hw_eq_band_setting, #endif + +#if CONFIG_CODEC == SWCODEC + find_array_ptr, + remove_array_ptr, +#endif }; int plugin_load(const char* plugin, const void* parameter) diff --git a/apps/plugin.h b/apps/plugin.h index 108a283596..785ba6f6a2 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -142,7 +142,7 @@ void* plugin_get_buffer(size_t *buffer_size); #define PLUGIN_MAGIC 0x526F634B /* RocK */ /* increase this every time the api struct changes */ -#define PLUGIN_API_VERSION 185 +#define PLUGIN_API_VERSION 186 /* update this to latest version if a change to the api struct breaks backwards compatibility (and please take the opportunity to sort in any @@ -889,6 +889,11 @@ int (*round_value_to_list32)(unsigned long value, int (*sound_enum_hw_eq_band_setting)(unsigned int band, unsigned int band_setting); #endif /* AUDIOHW_HAVE_EQ */ + +#if CONFIG_CODEC == SWCODEC + void ** (*find_array_ptr)(void **arr, void *ptr); + int (*remove_array_ptr)(void **arr, void *ptr); +#endif }; /* plugin header */ diff --git a/apps/plugins/mpegplayer/SOURCES b/apps/plugins/mpegplayer/SOURCES index 5ca0fcd86e..cf1e54aff5 100644 --- a/apps/plugins/mpegplayer/SOURCES +++ b/apps/plugins/mpegplayer/SOURCES @@ -29,6 +29,5 @@ disk_buf.c mpeg_settings.c stream_mgr.c mpegplayer.c -mpeg_linkedlist.c mpeg_parser.c mpeg_misc.c diff --git a/apps/plugins/mpegplayer/disk_buf.c b/apps/plugins/mpegplayer/disk_buf.c index af349c302a..4d0f98e5a3 100644 --- a/apps/plugins/mpegplayer/disk_buf.c +++ b/apps/plugins/mpegplayer/disk_buf.c @@ -30,7 +30,7 @@ static struct queue_sender_list disk_buf_queue_send SHAREDBSS_ATTR; static uint32_t disk_buf_stack[DEFAULT_STACK_SIZE*2/sizeof(uint32_t)]; struct disk_buf disk_buf SHAREDBSS_ATTR; -static struct list_item nf_list; +static void *nf_list[MPEGPLAYER_MAX_STREAMS+1]; static inline void disk_buf_lock(void) { @@ -45,13 +45,12 @@ static inline void disk_buf_unlock(void) static inline void disk_buf_on_clear_data_notify(struct stream_hdr *sh) { DEBUGF("DISK_BUF_CLEAR_DATA_NOTIFY: 0x%02X (cleared)\n", - STR_FROM_HEADER(sh)->id); - list_remove_item(&sh->nf); + STR_FROM_HDR(sh)->id); + list_remove_item(nf_list, sh); } - inline bool disk_buf_is_data_ready(struct stream_hdr *sh, - ssize_t margin) + ssize_t margin) { /* Data window available? */ off_t right = sh->win_right; @@ -71,7 +70,7 @@ void dbuf_l2_init(struct dbuf_l2_cache *l2_p) static int disk_buf_on_data_notify(struct stream_hdr *sh) { - DEBUGF("DISK_BUF_DATA_NOTIFY: 0x%02X ", STR_FROM_HEADER(sh)->id); + DEBUGF("DISK_BUF_DATA_NOTIFY: 0x%02X ", STR_FROM_HDR(sh)->id); if (sh->win_left <= sh->win_right) { @@ -85,7 +84,7 @@ static int disk_buf_on_data_notify(struct stream_hdr *sh) sh->win_left, sh->win_right, disk_buf.win_left, disk_buf.win_right); /* Be sure it's not listed though if multiple requests were made */ - list_remove_item(&sh->nf); + list_remove_item(nf_list, sh); return DISK_BUF_NOTIFY_OK; } @@ -95,7 +94,7 @@ static int disk_buf_on_data_notify(struct stream_hdr *sh) case TSTATE_BUFFERING: case TSTATE_INIT: disk_buf.state = TSTATE_BUFFERING; - list_add_item(&nf_list, &sh->nf); + list_add_item(nf_list, sh); DEBUGF("(registered)\n" " swl:%lu swr:%lu\n" " dwl:%lu dwr:%lu\n", @@ -109,20 +108,17 @@ static int disk_buf_on_data_notify(struct stream_hdr *sh) return DISK_BUF_NOTIFY_ERROR; } -static bool check_data_notifies_callback(struct list_item *item, - intptr_t data) +static bool check_data_notifies_callback(struct stream_hdr *sh, intptr_t data) { - struct stream_hdr *sh = TYPE_FROM_MEMBER(struct stream_hdr, item, nf); - if (disk_buf_is_data_ready(sh, 0)) { /* Remove from list then post notification - post because send * could result in a wait for each thread to finish resulting * in deadlock */ - list_remove_item(item); - str_post_msg(STR_FROM_HEADER(sh), DISK_BUF_DATA_NOTIFY, 0); + list_remove_item(nf_list, sh); + str_post_msg(STR_FROM_HDR(sh), DISK_BUF_DATA_NOTIFY, 0); DEBUGF("DISK_BUF_DATA_NOTIFY: 0x%02X (notified)\n", - STR_FROM_HEADER(sh)->id); + STR_FROM_HDR(sh)->id); } return true; @@ -130,15 +126,17 @@ static bool check_data_notifies_callback(struct list_item *item, } /* Check registered streams and notify them if their data is available */ -static void check_data_notifies(void) +static inline void check_data_notifies(void) { - list_enum_items(&nf_list, check_data_notifies_callback, 0); + list_enum_items(nf_list, + (list_enum_callback_t)check_data_notifies_callback, + 0); } /* Clear all registered notifications - do not post them */ static inline void clear_data_notifies(void) { - list_clear_all(&nf_list); + list_clear_all(nf_list); } /* Background buffering when streaming */ @@ -492,7 +490,7 @@ static void disk_buf_thread(void) disk_buf_buffer(); /* Check for any due notifications if any are pending */ - if (nf_list.next != NULL) + if (*nf_list != NULL) check_data_notifies(); /* Still more data left? */ @@ -915,7 +913,6 @@ void disk_buf_reply_msg(intptr_t retval) bool disk_buf_init(void) { disk_buf.thread = 0; - list_initialize(&nf_list); rb->mutex_init(&disk_buf_mtx); diff --git a/apps/plugins/mpegplayer/mpeg_linkedlist.c b/apps/plugins/mpegplayer/mpeg_linkedlist.c deleted file mode 100644 index f2d01ee493..0000000000 --- a/apps/plugins/mpegplayer/mpeg_linkedlist.c +++ /dev/null @@ -1,151 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Linked list API definitions - * - * Copyright (c) 2007 Michael Sevakis - * - * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#include "plugin.h" -#include "mpegplayer.h" -#include "mpeg_linkedlist.h" - -/* Initialize a master list head */ -void list_initialize(struct list_item *master_list_head) -{ - master_list_head->prev = master_list_head->next = NULL; -} - -/* Are there items after the head item? */ -bool list_is_empty(struct list_item *head_item) -{ - return head_item->next == NULL; -} - -/* Does the item belong to a list? */ -bool list_is_item_listed(struct list_item *item) -{ - return item->prev != NULL; -} - -/* Is the item a member in a particular list? */ -bool list_is_member(struct list_item *master_list_head, - struct list_item *item) -{ - if (item != master_list_head && item->prev != NULL) - { - struct list_item *curr = master_list_head->next; - - while (curr != NULL) - { - if (item != curr) - { - curr = curr->next; - continue; - } - - return true; - } - } - - return false; -} - -/* Remove an item from a list - no head item needed */ -void list_remove_item(struct list_item *item) -{ - if (item->prev == NULL) - { - /* Not in a list - no change - could be the master list head - * as well which cannot be removed */ - return; - } - - item->prev->next = item->next; - - if (item->next != NULL) - { - /* Not last item */ - item->next->prev = item->prev; - } - - /* Mark as not in a list */ - item->prev = NULL; -} - -/* Add a list item after the base item */ -void list_add_item(struct list_item *head_item, - struct list_item *item) -{ - if (item->prev != NULL) - { - /* Already in a list - no change */ - DEBUGF("list_add_item: item already in a list\n"); - return; - } - - if (item == head_item) - { - /* Cannot add the item to itself */ - DEBUGF("list_add_item: item == head_item\n"); - return; - } - - /* Insert first */ - item->prev = head_item; - item->next = head_item->next; - - if (head_item->next != NULL) - { - /* Not first item */ - head_item->next->prev = item; - } - - head_item->next = item; -} - -/* Clear list items after the head item */ -void list_clear_all(struct list_item *head_item) -{ - struct list_item *curr = head_item->next; - - while (curr != NULL) - { - list_remove_item(curr); - curr = head_item->next; - } -} - -/* Enumerate all items after the head item - passing each item in turn - * to the callback as well as the data value. The current item may be - * safely removed. Items added after the current position will be enumated - * but not ones added before it. The callback may return false to stop - * the enumeration. */ -void list_enum_items(struct list_item *head_item, - list_enum_callback_t callback, - intptr_t data) -{ - struct list_item *next = head_item->next; - - while (next != NULL) - { - struct list_item *curr = next; - next = curr->next; - if (!callback(curr, data)) - break; - } -} diff --git a/apps/plugins/mpegplayer/mpeg_linkedlist.h b/apps/plugins/mpegplayer/mpeg_linkedlist.h deleted file mode 100644 index d4f8305d7d..0000000000 --- a/apps/plugins/mpegplayer/mpeg_linkedlist.h +++ /dev/null @@ -1,71 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Linked list API declarations - * - * Copyright (c) 2007 Michael Sevakis - * - * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ -#ifndef MPEG_LINKEDLIST_H -#define MPEG_LINKEDLIST_H - -struct list_item -{ - struct list_item *prev; /* previous item in list */ - struct list_item *next; /* next item in list */ -}; - -/* Utility macros to help get the actual structure pointer back */ -#define OFFSETOF(type, membername) ((off_t)&((type *)0)->membername) -#define TYPE_FROM_MEMBER(type, memberptr, membername) \ - ((type *)((intptr_t)(memberptr) - OFFSETOF(type, membername))) - -/* Initialize a master list head */ -void list_initialize(struct list_item *master_list_head); - -/* Are there items after the head item? */ -bool list_is_empty(struct list_item *head_item); - -/* Does the item belong to a list? */ -bool list_is_item_listed(struct list_item *item); - -/* Is the item a member in a particular list? */ -bool list_is_member(struct list_item *master_list_head, - struct list_item *item); - -/* Remove an item from a list - no head item needed */ -void list_remove_item(struct list_item *item); - -/* Add a list item after the base item */ -void list_add_item(struct list_item *head_item, - struct list_item *item); - -/* Clear list items after the head item */ -void list_clear_all(struct list_item *head_item); - -/* Enumerate all items after the head item - passing each item in turn - * to the callback as well as the data value. The current item may be - * safely removed. Items added after the current position will be enumated - * but not ones added before it. The callback may return false to stop - * the enumeration. */ -typedef bool (*list_enum_callback_t)(struct list_item *item, intptr_t data); - -void list_enum_items(struct list_item *head_item, - list_enum_callback_t callback, - intptr_t data); - -#endif /* MPEG_LINKEDLIST_H */ diff --git a/apps/plugins/mpegplayer/mpeg_misc.c b/apps/plugins/mpegplayer/mpeg_misc.c index 8e6ccf650f..e201aa69c7 100644 --- a/apps/plugins/mpegplayer/mpeg_misc.c +++ b/apps/plugins/mpegplayer/mpeg_misc.c @@ -102,3 +102,63 @@ uint32_t muldiv_uint32(uint32_t multiplicand, return UINT32_MAX; /* Saturate */ } + + +/** Lists **/ + +/* Does the list have any members? */ +bool list_is_empty(void **list) +{ + return *list == NULL; +} + +/* Is the item inserted into a particular list? */ +bool list_is_member(void **list, void *item) +{ + return *rb->find_array_ptr(list, item) != NULL; +} + +/* Removes an item from a list - returns true if item was found + * and thus removed. */ +bool list_remove_item(void **list, void *item) +{ + return rb->remove_array_ptr(list, item) != -1; +} + +/* Adds a list item, insert last, if not already present. */ +void list_add_item(void **list, void *item) +{ + void **item_p = rb->find_array_ptr(list, item); + if (*item_p == NULL) + *item_p = item; +} + +/* Clears the entire list. */ +void list_clear_all(void **list) +{ + while (*list != NULL) + *list++ = NULL; +} + +/* Enumerate all items in the array, passing each item in turn to the + * callback as well as the data value. The current item may be safely + * removed. Other changes during enumeration are undefined. The callback + * may return 'false' to stop the enumeration early. */ +void list_enum_items(void **list, + list_enum_callback_t callback, + intptr_t data) +{ + for (;;) + { + void *item = *list; + + if (item == NULL) + break; + + if (callback != NULL && !callback(item, data)) + break; + + if (*list == item) + list++; /* Item still there */ + } +} diff --git a/apps/plugins/mpegplayer/mpeg_misc.h b/apps/plugins/mpegplayer/mpeg_misc.h index 5f60193d52..c36f4faddc 100644 --- a/apps/plugins/mpegplayer/mpeg_misc.h +++ b/apps/plugins/mpegplayer/mpeg_misc.h @@ -202,4 +202,30 @@ uint32_t muldiv_uint32(uint32_t multiplicand, uint32_t multiplier, uint32_t divisor); + +/** Lists **/ + +/* Does the list have any members? */ +bool list_is_empty(void **list); + +/* Is the item inserted into a particular list? */ +bool list_is_member(void **list, void *item); + +/* Removes an item from a list - returns true if item was found + * and thus removed. */ +bool list_remove_item(void **list, void *item); + +/* Adds a list item, insert last, if not already present. */ +void list_add_item(void **list, void *item); + +/* Clears the entire list. */ +void list_clear_all(void **list); + +/* Enumerate all items in the array. */ +typedef bool (*list_enum_callback_t)(void *item, intptr_t data); + +void list_enum_items(void **list, + list_enum_callback_t callback, + intptr_t data); + #endif /* MPEG_MISC_H */ diff --git a/apps/plugins/mpegplayer/mpegplayer.h b/apps/plugins/mpegplayer/mpegplayer.h index bf223c3330..f6617cedff 100644 --- a/apps/plugins/mpegplayer/mpegplayer.h +++ b/apps/plugins/mpegplayer/mpegplayer.h @@ -31,6 +31,9 @@ #endif /* #else function-like empty macros are defined in the headers */ +/* Should be enough for now */ +#define MPEGPLAYER_MAX_STREAMS 4 + /* Memory allotments for various subsystems */ #define MIN_MEMMARGIN (4*1024) @@ -85,7 +88,6 @@ #include "mpeg2.h" #include "video_out.h" #include "mpeg_stream.h" -#include "mpeg_linkedlist.h" #include "mpeg_misc.h" #include "mpeg_alloc.h" #include "stream_thread.h" diff --git a/apps/plugins/mpegplayer/stream_mgr.c b/apps/plugins/mpegplayer/stream_mgr.c index 065843a344..2eed3d355d 100644 --- a/apps/plugins/mpegplayer/stream_mgr.c +++ b/apps/plugins/mpegplayer/stream_mgr.c @@ -148,21 +148,21 @@ void stream_add_stream(struct stream *str) { actl_lock(); - list_remove_item(&str->l); - list_add_item(&stream_mgr.strl, &str->l); + list_remove_item(stream_mgr.strl, str); + list_add_item(stream_mgr.strl, str); actl_unlock(); } /* Callback for various list-moving operations */ -static bool strl_enum_callback(struct list_item *item, intptr_t data) +static bool strl_enum_callback(struct stream *str, intptr_t data) { actl_lock(); - list_remove_item(item); + list_remove_item(stream_mgr.strl, str); if (data == 1) - list_add_item(&stream_mgr.actl, item); + list_add_item(stream_mgr.actl, str); actl_unlock(); @@ -172,38 +172,38 @@ static bool strl_enum_callback(struct list_item *item, intptr_t data) /* Clear all streams from active and playback pools */ void stream_remove_streams(void) { - list_enum_items(&stream_mgr.strl, strl_enum_callback, 0); + list_enum_items(stream_mgr.strl, + (list_enum_callback_t)strl_enum_callback, 0); } /* Move the playback pool to the active list */ void move_strl_to_actl(void) { - list_enum_items(&stream_mgr.strl, strl_enum_callback, 1); + list_enum_items(stream_mgr.strl, + (list_enum_callback_t)strl_enum_callback, 1); } /* Remove a stream from the active list and return it to the pool */ static bool actl_stream_remove(struct stream *str) { - if (list_is_member(&stream_mgr.actl, &str->l)) - { - actl_lock(); + bool retval; - list_remove_item(&str->l); - list_add_item(&stream_mgr.strl, &str->l); + actl_lock(); - actl_unlock(); - return true; - } + retval = list_remove_item(stream_mgr.actl, str); + + if (retval) + list_add_item(stream_mgr.strl, str); - return false; + actl_unlock(); + + return retval; } /* Broadcast a message to all active streams */ -static bool actl_stream_broadcast_callback(struct list_item *item, +static bool actl_stream_broadcast_callback(struct stream *str, struct str_broadcast_data *sbd) { - struct stream *str = TYPE_FROM_MEMBER(struct stream, item, l); - switch (sbd->cmd) { case STREAM_PLAY: @@ -215,8 +215,8 @@ static bool actl_stream_broadcast_callback(struct list_item *item, { actl_lock(); - list_remove_item(item); - list_add_item(&stream_mgr.strl, item); + list_remove_item(stream_mgr.actl, str); + list_add_item(stream_mgr.strl, str); actl_unlock(); sbd->data = 0; @@ -236,7 +236,7 @@ static void actl_stream_broadcast(int cmd, intptr_t data) struct str_broadcast_data sbd; sbd.cmd = cmd; sbd.data = data; - list_enum_items(&stream_mgr.actl, + list_enum_items(stream_mgr.actl, (list_enum_callback_t)actl_stream_broadcast_callback, (intptr_t)&sbd); } @@ -623,7 +623,7 @@ static void stream_on_ev_complete(struct stream *str) { /* No - remove this stream from the active list */ DEBUGF(" finished: 0x%02x\n", str->id); - if (list_is_empty(&stream_mgr.actl)) + if (list_is_empty(stream_mgr.actl)) { /* All streams have acked - stop playback */ stream_on_stop(false); @@ -820,10 +820,9 @@ void stream_wait_status(void) /* Returns the smallest file window that includes all active streams' * windows */ -static bool stream_get_window_callback(struct list_item *item, +static bool stream_get_window_callback(struct stream *str, struct stream_window *sw) { - struct stream *str = TYPE_FROM_MEMBER(struct stream, item, l); off_t swl = str->hdr.win_left; off_t swr = str->hdr.win_right; @@ -845,7 +844,7 @@ bool stream_get_window(struct stream_window *sw) sw->right = LONG_MIN; actl_lock(); - list_enum_items(&stream_mgr.actl, + list_enum_items(stream_mgr.actl, (list_enum_callback_t)stream_get_window_callback, (intptr_t)sw); actl_unlock(); @@ -981,7 +980,6 @@ int stream_init(void) stream_mgr.status = STREAM_STOPPED; stream_mgr_init_state(); - list_initialize(&stream_mgr.actl); /* Initialize our window to the outside world first */ rb->mutex_init(&stream_mgr.str_mtx); diff --git a/apps/plugins/mpegplayer/stream_mgr.h b/apps/plugins/mpegplayer/stream_mgr.h index a00b39f189..a07305a847 100644 --- a/apps/plugins/mpegplayer/stream_mgr.h +++ b/apps/plugins/mpegplayer/stream_mgr.h @@ -35,8 +35,8 @@ struct stream_mgr bool seeked; /* A seek happened and things must be resynced */ int status; /* Current playback status */ - struct list_item strl; /* List of available streams */ - struct list_item actl; /* List of active streams */ + void *strl[MPEGPLAYER_MAX_STREAMS+1]; /* List of available streams */ + void *actl[MPEGPLAYER_MAX_STREAMS+1]; /* List of active streams */ struct mutex str_mtx; /* Main stream manager mutex */ struct mutex actl_mtx; /* Lock for current-streams list */ union /* A place for reusable non-cacheable parameters */ diff --git a/apps/plugins/mpegplayer/stream_thread.h b/apps/plugins/mpegplayer/stream_thread.h index 30bf46e6ff..1d3a445735 100644 --- a/apps/plugins/mpegplayer/stream_thread.h +++ b/apps/plugins/mpegplayer/stream_thread.h @@ -39,7 +39,6 @@ struct stream_hdr off_t pos; /* Start/current position for random-access read */ }; off_t limit; /* Limit for random-access read */ - struct list_item nf; /* List for data notification */ }; struct stream @@ -48,8 +47,6 @@ struct stream unsigned int thread; /* Stream's thread */ uint8_t* curr_packet; /* Current stream packet beginning */ uint8_t* curr_packet_end; /* Current stream packet end */ - struct list_item l; /* List of streams - either reserve pool - or active pool */ int state; /* State machine parsing mode */ uint32_t start_pts; /* First timestamp for stream */ uint32_t end_pts; /* Last timestamp for stream */ @@ -58,6 +55,8 @@ struct stream unsigned id; /* Stream identifier */ }; +#define STR_FROM_HDR(sh) ((struct stream *)(sh)) + /* Make sure there there is always enough data buffered ahead for * the worst possible case - regardless of whether a valid stream * would actually produce that */ @@ -145,8 +144,6 @@ enum stream_status STREAM_NOT_FOUND, /* Match not found */ }; -#define STR_FROM_HEADER(sh) ((struct stream *)(sh)) - /* Clip time to range for a particular stream */ static inline uint32_t clip_time(struct stream *str, uint32_t time) { diff --git a/firmware/export/general.h b/firmware/export/general.h index 8da4a0ad59..16c824086b 100644 --- a/firmware/export/general.h +++ b/firmware/export/general.h @@ -72,4 +72,19 @@ char *create_datetime_filename(char *buffer, const char *path, bool unique_time); #endif /* CONFIG_RTC */ +/*** + ** Compacted pointer lists + ** + ** N-length list requires N+1 elements to ensure NULL-termination. + **/ + +/* Find a pointer in a pointer array. Returns the addess of the element if + found or the address of the terminating NULL otherwise. This can be used + to bounds check and add items. */ +void ** find_array_ptr(void **arr, void *ptr); + +/* Remove a pointer from a pointer array if it exists. Compacts it so that + no gaps exist. Returns 0 on success and -1 if the element wasn't found. */ +int remove_array_ptr(void **arr, void *ptr); + #endif /* GENERAL_H */ diff --git a/firmware/general.c b/firmware/general.c index fa1025492b..20b0277c09 100644 --- a/firmware/general.c +++ b/firmware/general.c @@ -196,3 +196,40 @@ char *create_datetime_filename(char *buffer, const char *path, return buffer; } #endif /* CONFIG_RTC */ + +/*** + ** Compacted pointer lists + ** + ** N-length list requires N+1 elements to ensure NULL-termination. + **/ + +/* Find a pointer in a pointer array. Returns the addess of the element if + * found or the address of the terminating NULL otherwise. This can be used + * to bounds check and add items. */ +void ** find_array_ptr(void **arr, void *ptr) +{ + void *curr; + for (curr = *arr; curr != NULL && curr != ptr; curr = *(++arr)); + return arr; +} + +/* Remove a pointer from a pointer array if it exists. Compacts it so that + * no gaps exist. Returns 0 on success and -1 if the element wasn't found. */ +int remove_array_ptr(void **arr, void *ptr) +{ + void *curr; + arr = find_array_ptr(arr, ptr); + + if (*arr == NULL) + return -1; + + /* Found. Slide up following items. */ + do + { + void **arr1 = arr + 1; + *arr++ = curr = *arr1; + } + while (curr != NULL); + + return 0; +} diff --git a/firmware/kernel.c b/firmware/kernel.c index d8c67e8485..fe40c35002 100644 --- a/firmware/kernel.c +++ b/firmware/kernel.c @@ -27,6 +27,7 @@ #include "system.h" #include "panic.h" #include "debug.h" +#include "general.h" /* Make this nonzero to enable more elaborate checks on objects */ #if defined(DEBUG) || defined(SIMULATOR) @@ -61,40 +62,6 @@ static struct IF_COP( struct corelock cl; ) } all_queues SHAREDBSS_ATTR; -/**************************************************************************** - * Common utilities - ****************************************************************************/ - -/* Find a pointer in a pointer array. Returns the addess of the element if - * found or the address of the terminating NULL otherwise. */ -static void ** find_array_ptr(void **arr, void *ptr) -{ - void *curr; - for(curr = *arr; curr != NULL && curr != ptr; curr = *(++arr)); - return arr; -} - -/* Remove a pointer from a pointer array if it exists. Compacts it so that - * no gaps exist. Returns 0 on success and -1 if the element wasn't found. */ -static int remove_array_ptr(void **arr, void *ptr) -{ - void *curr; - arr = find_array_ptr(arr, ptr); - - if(*arr == NULL) - return -1; - - /* Found. Slide up following items. */ - do - { - void **arr1 = arr + 1; - *arr++ = curr = *arr1; - } - while(curr != NULL); - - return 0; -} - /**************************************************************************** * Standard kernel stuff ****************************************************************************/ -- cgit v1.2.3