Änderungen Gruppe 30_10_2022 V2
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
|
||||
set (HEADERS
|
||||
vcos_common.h
|
||||
vcos_generic_blockpool.h
|
||||
vcos_generic_event_flags.h
|
||||
vcos_generic_named_sem.h
|
||||
vcos_generic_quickslow_mutex.h
|
||||
vcos_generic_reentrant_mtx.h
|
||||
vcos_generic_tls.h
|
||||
vcos_joinable_thread_from_plain.h
|
||||
vcos_latch_from_sem.h
|
||||
vcos_mem_from_malloc.h
|
||||
vcos_mutexes_are_reentrant.h
|
||||
vcos_thread_reaper.h
|
||||
)
|
||||
|
||||
foreach (header ${HEADERS})
|
||||
configure_file ("${header}" "${VCOS_HEADERS_BUILD_DIR}/generic/${header}" COPYONLY)
|
||||
endforeach ()
|
||||
|
||||
install (FILES ${HEADERS} DESTINATION include/interface/vcos/generic)
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "interface/vcos/vcos.h"
|
||||
#ifdef __VIDEOCORE__
|
||||
#include "host_support/include/vc_debug_sym.h"
|
||||
#include "vcfw/vclib/vclib.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
int vcos_verify_bkpts = 0;
|
||||
#ifdef __VIDEOCORE__
|
||||
VC_DEBUG_VAR(vcos_verify_bkpts);
|
||||
#endif
|
||||
|
||||
int vcos_verify_bkpts_enabled(void)
|
||||
{
|
||||
return vcos_verify_bkpts;
|
||||
}
|
||||
|
||||
int vcos_verify_bkpts_enable(int enable)
|
||||
{
|
||||
int old = vcos_verify_bkpts;
|
||||
vcos_verify_bkpts = enable;
|
||||
return old;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the fatal error handler.
|
||||
*/
|
||||
void vcos_abort(void)
|
||||
{
|
||||
VCOS_ALERT("vcos_abort: Halting");
|
||||
|
||||
#ifdef __VIDEOCORE__
|
||||
_bkpt();
|
||||
#endif
|
||||
|
||||
#if defined(VCOS_HAVE_BACKTRACE) && !defined(NDEBUG)
|
||||
vcos_backtrace_self();
|
||||
#endif
|
||||
|
||||
#ifdef __VIDEOCORE__
|
||||
/* Flush the cache to help with postmortem RAM-dump debugging */
|
||||
vclib_cache_flush();
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_RASPBERRYPI
|
||||
extern void pattern(int);
|
||||
while(1)
|
||||
pattern(8);
|
||||
#endif
|
||||
|
||||
/* Insert chosen fatal error handler here */
|
||||
#if defined __VIDEOCORE__ && !defined(NDEBUG)
|
||||
while(1); /* allow us to attach a debugger after the fact and see where we came from. */
|
||||
#else
|
||||
abort(); /* on vc this ends up in _exit_halt which doesn't give us any stack backtrace */
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,722 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* This file provides a generic command line interface which allows
|
||||
* vcos internals to be manipulated and/or displayed.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/* ---- Include Files ---------------------------------------------------- */
|
||||
|
||||
#include "interface/vcos/vcos.h"
|
||||
|
||||
#ifdef HAVE_VCOS_VERSION
|
||||
#include "interface/vcos/vcos_build_info.h"
|
||||
#endif
|
||||
|
||||
#ifdef _VIDEOCORE
|
||||
#include "vcfw/logging/logging.h"
|
||||
#endif
|
||||
|
||||
/* ---- Public Variables ------------------------------------------------- */
|
||||
|
||||
/* ---- Private Constants and Types -------------------------------------- */
|
||||
|
||||
#define VCOS_LOG_CATEGORY (&vcos_cmd_log_category)
|
||||
VCOS_LOG_CAT_T vcos_cmd_log_category;
|
||||
|
||||
/* ---- Private Variables ------------------------------------------------ */
|
||||
|
||||
static struct VCOS_CMD_GLOBALS_T
|
||||
{
|
||||
VCOS_MUTEX_T lock;
|
||||
VCOS_ONCE_T initialized;
|
||||
|
||||
unsigned num_cmd_entries;
|
||||
unsigned num_cmd_alloc;
|
||||
VCOS_CMD_T *cmd_entry;
|
||||
|
||||
VCOS_LOG_CAT_T *log_category;
|
||||
} cmd_globals;
|
||||
|
||||
#ifdef HAVE_VCOS_VERSION
|
||||
/* Keep the static strings in the image from being dropped by
|
||||
* the linker.
|
||||
*/
|
||||
extern const char *vcos_get_build_strings(unsigned id);
|
||||
const char *(*vcos_keep_static_strings)(unsigned);
|
||||
#endif
|
||||
|
||||
/* ---- Private Function Prototypes -------------------------------------- */
|
||||
|
||||
static VCOS_STATUS_T help_cmd( VCOS_CMD_PARAM_T *param );
|
||||
|
||||
/* ---- Functions ------------------------------------------------------- */
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Walks through the commands looking for a particular command
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static VCOS_CMD_T *find_cmd( VCOS_CMD_T *cmd_entry, const char *name )
|
||||
{
|
||||
VCOS_CMD_T *scan_entry = cmd_entry;
|
||||
|
||||
while ( scan_entry->name != NULL )
|
||||
{
|
||||
if ( vcos_strcmp( scan_entry->name, name ) == 0 )
|
||||
{
|
||||
return scan_entry;
|
||||
}
|
||||
scan_entry++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Saves away
|
||||
* each line individually.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void vcos_cmd_always_log_output( VCOS_LOG_CAT_T *log_category )
|
||||
{
|
||||
cmd_globals.log_category = log_category;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Walks through a buffer containing newline separated lines, and logs
|
||||
* each line individually.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static void cmd_log_results( VCOS_CMD_PARAM_T *param )
|
||||
{
|
||||
char *start;
|
||||
char *end;
|
||||
|
||||
start = end = param->result_buf;
|
||||
|
||||
while ( *start != '\0' )
|
||||
{
|
||||
while (( *end != '\0' ) && ( *end != '\n' ))
|
||||
end++;
|
||||
|
||||
if ( *end == '\n' )
|
||||
{
|
||||
*end++ = '\0';
|
||||
}
|
||||
|
||||
if ( cmd_globals.log_category != NULL )
|
||||
{
|
||||
if ( vcos_is_log_enabled( cmd_globals.log_category, VCOS_LOG_INFO ))
|
||||
{
|
||||
vcos_log_impl( cmd_globals.log_category, VCOS_LOG_INFO, "%s", start );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vcos_log_info( "%s", start );
|
||||
}
|
||||
|
||||
start = end;
|
||||
}
|
||||
|
||||
/* Since we logged the buffer, reset the pointer back to the beginning. */
|
||||
|
||||
param->result_ptr = param->result_buf;
|
||||
param->result_buf[0] = '\0';
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Since we may have limited output space, we create a generic routine
|
||||
* which tries to use the result space, but will switch over to using
|
||||
* logging if the output is too large.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void vcos_cmd_vprintf( VCOS_CMD_PARAM_T *param, const char *fmt, va_list args )
|
||||
{
|
||||
int bytes_written;
|
||||
int bytes_remaining;
|
||||
|
||||
bytes_remaining = (int)(param->result_size - ( param->result_ptr - param->result_buf ));
|
||||
|
||||
bytes_written = vcos_vsnprintf( param->result_ptr, bytes_remaining, fmt, args );
|
||||
|
||||
if ( cmd_globals.log_category != NULL )
|
||||
{
|
||||
/* We're going to log each line as we encounter it. If the buffer
|
||||
* doesn't end in a newline, then we'll wait for one first.
|
||||
*/
|
||||
|
||||
if ( (( bytes_written + 1 ) >= bytes_remaining )
|
||||
|| ( param->result_ptr[ bytes_written - 1 ] == '\n' ))
|
||||
{
|
||||
cmd_log_results( param );
|
||||
}
|
||||
else
|
||||
{
|
||||
param->result_ptr += bytes_written;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (( bytes_written + 1 ) >= bytes_remaining )
|
||||
{
|
||||
/* Output doesn't fit - switch over to logging */
|
||||
|
||||
param->use_log = 1;
|
||||
|
||||
*param->result_ptr = '\0'; /* Zap the partial line that didn't fit above. */
|
||||
|
||||
cmd_log_results( param ); /* resets result_ptr */
|
||||
|
||||
bytes_written = vcos_vsnprintf( param->result_ptr, bytes_remaining, fmt, args );
|
||||
}
|
||||
param->result_ptr += bytes_written;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Prints the output.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void vcos_cmd_printf( VCOS_CMD_PARAM_T *param, const char *fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start( args, fmt );
|
||||
vcos_cmd_vprintf( param, fmt, args );
|
||||
va_end( args );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Prints the arguments which were on the command line prior to ours.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static void print_argument_prefix( VCOS_CMD_PARAM_T *param )
|
||||
{
|
||||
int arg_idx;
|
||||
|
||||
for ( arg_idx = 0; ¶m->argv_orig[arg_idx] != param->argv; arg_idx++ )
|
||||
{
|
||||
vcos_cmd_printf( param, "%s ", param->argv_orig[arg_idx] );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Prints an error message, prefixed by the command chain required to get
|
||||
* to where we're at.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void vcos_cmd_error( VCOS_CMD_PARAM_T *param, const char *fmt, ... )
|
||||
{
|
||||
va_list args;
|
||||
|
||||
print_argument_prefix( param );
|
||||
|
||||
va_start( args, fmt );
|
||||
vcos_cmd_vprintf( param, fmt, args );
|
||||
va_end( args );
|
||||
vcos_cmd_printf( param, "\n" );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* usage - prints command usage for an array of commands.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
static void usage( VCOS_CMD_PARAM_T *param, VCOS_CMD_T *cmd_entry )
|
||||
{
|
||||
int cmd_idx;
|
||||
int nameWidth = 0;
|
||||
int argsWidth = 0;
|
||||
VCOS_CMD_T *scan_entry;
|
||||
|
||||
vcos_cmd_printf( param, "Usage: " );
|
||||
print_argument_prefix( param );
|
||||
vcos_cmd_printf( param, "command [args ...]\n" );
|
||||
vcos_cmd_printf( param, "\n" );
|
||||
vcos_cmd_printf( param, "Where command is one of the following:\n" );
|
||||
|
||||
for ( cmd_idx = 0; cmd_entry[cmd_idx].name != NULL; cmd_idx++ )
|
||||
{
|
||||
int aw;
|
||||
int nw;
|
||||
|
||||
scan_entry = &cmd_entry[cmd_idx];
|
||||
|
||||
nw = vcos_strlen( scan_entry->name );
|
||||
aw = vcos_strlen( scan_entry->args );
|
||||
|
||||
if ( nw > nameWidth )
|
||||
{
|
||||
nameWidth = nw;
|
||||
}
|
||||
if ( aw > argsWidth )
|
||||
{
|
||||
argsWidth = aw;
|
||||
}
|
||||
}
|
||||
|
||||
for ( cmd_idx = 0; cmd_entry[cmd_idx].name != NULL; cmd_idx++ )
|
||||
{
|
||||
scan_entry = &cmd_entry[cmd_idx];
|
||||
|
||||
vcos_cmd_printf( param, " %-*s %-*s - %s\n",
|
||||
nameWidth, scan_entry->name,
|
||||
argsWidth, scan_entry->args,
|
||||
scan_entry->descr );
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* Prints the usage for the current command.
|
||||
*
|
||||
***************************************************************************/
|
||||
|
||||
void vcos_cmd_usage( VCOS_CMD_PARAM_T *param )
|
||||
{
|
||||
VCOS_CMD_T *cmd_entry;
|
||||
|
||||
cmd_entry = param->cmd_entry;
|
||||
|
||||
if ( cmd_entry->sub_cmd_entry != NULL )
|
||||
{
|
||||
/* This command is command with sub-commands */
|
||||
|
||||
usage( param, param->cmd_entry->sub_cmd_entry );
|
||||
}
|
||||
else
|
||||
{
|
||||
vcos_cmd_printf( param, "Usage: " );
|
||||
print_argument_prefix( param );
|
||||
vcos_cmd_printf( param, "%s %s - %s\n",
|
||||
param->argv[0],
|
||||
param->cmd_entry->args,
|
||||
param->cmd_entry->descr );
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Command to print out the help
|
||||
*
|
||||
* This help command is only called from the main menu.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static VCOS_STATUS_T help_cmd( VCOS_CMD_PARAM_T *param )
|
||||
{
|
||||
VCOS_CMD_T *found_entry;
|
||||
|
||||
#if 0
|
||||
{
|
||||
int arg_idx;
|
||||
|
||||
vcos_log_trace( "%s: argc = %d", __func__, param->argc );
|
||||
for ( arg_idx = 0; arg_idx < param->argc; arg_idx++ )
|
||||
{
|
||||
vcos_log_trace( "%s: argv[%d] = '%s'", __func__, arg_idx, param->argv[arg_idx] );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If there is an argument after the word help, then we want to print
|
||||
* help for that command.
|
||||
*/
|
||||
|
||||
if ( param->argc == 1 )
|
||||
{
|
||||
if ( param->cmd_parent_entry == cmd_globals.cmd_entry )
|
||||
{
|
||||
/* Bare help - print the command usage for the root */
|
||||
|
||||
usage( param, cmd_globals.cmd_entry );
|
||||
return VCOS_SUCCESS;
|
||||
}
|
||||
|
||||
/* For all other cases help requires an argument */
|
||||
|
||||
vcos_cmd_error( param, "%s requires an argument", param->argv[0] );
|
||||
return VCOS_EINVAL;
|
||||
}
|
||||
|
||||
/* We were given an argument. */
|
||||
|
||||
if (( found_entry = find_cmd( param->cmd_parent_entry, param->argv[1] )) != NULL )
|
||||
{
|
||||
/* Make it look like the command that was specified is the one that's
|
||||
* currently running
|
||||
*/
|
||||
|
||||
param->cmd_entry = found_entry;
|
||||
param->argv[0] = param->argv[1];
|
||||
param->argv++;
|
||||
param->argc--;
|
||||
|
||||
vcos_cmd_usage( param );
|
||||
return VCOS_SUCCESS;
|
||||
}
|
||||
|
||||
vcos_cmd_error( param, "- unrecognized command: '%s'", param->argv[1] );
|
||||
return VCOS_ENOENT;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Command to print out the version/build information.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef HAVE_VCOS_VERSION
|
||||
|
||||
static VCOS_STATUS_T version_cmd( VCOS_CMD_PARAM_T *param )
|
||||
{
|
||||
static const char* copyright = "Copyright (c) 2011 Broadcom";
|
||||
|
||||
vcos_cmd_printf( param, "%s %s\n%s\nversion %s\nhost %s",
|
||||
vcos_get_build_date(),
|
||||
vcos_get_build_time(),
|
||||
copyright,
|
||||
vcos_get_build_version(),
|
||||
vcos_get_build_hostname() );
|
||||
|
||||
return VCOS_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Internal commands
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static VCOS_CMD_T cmd_help = { "help", "[command]", help_cmd, NULL, "Prints command help information" };
|
||||
|
||||
#ifdef HAVE_VCOS_VERSION
|
||||
static VCOS_CMD_T cmd_version = { "version", "", version_cmd, NULL, "Prints build/version information" };
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Walks the command table and executes the commands
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static VCOS_STATUS_T execute_cmd( VCOS_CMD_PARAM_T *param, VCOS_CMD_T *cmd_entry )
|
||||
{
|
||||
const char *cmdStr;
|
||||
VCOS_CMD_T *found_entry;
|
||||
|
||||
#if 0
|
||||
{
|
||||
int arg_idx;
|
||||
|
||||
vcos_cmd_printf( param, "%s: argc = %d", __func__, param->argc );
|
||||
for ( arg_idx = 0; arg_idx < param->argc; arg_idx++ )
|
||||
{
|
||||
vcos_cmd_printf( param, " argv[%d] = '%s'", arg_idx, param->argv[arg_idx] );
|
||||
}
|
||||
vcos_cmd_printf( param, "\n" );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( param->argc <= 1 )
|
||||
{
|
||||
/* No command specified */
|
||||
|
||||
vcos_cmd_error( param, "%s - no command specified", param->argv[0] );
|
||||
return VCOS_EINVAL;
|
||||
}
|
||||
|
||||
/* argv[0] is the command/program that caused us to get invoked, so we strip
|
||||
* it off.
|
||||
*/
|
||||
|
||||
param->argc--;
|
||||
param->argv++;
|
||||
param->cmd_parent_entry = cmd_entry;
|
||||
|
||||
/* Not the help command, scan for the command and execute it. */
|
||||
|
||||
cmdStr = param->argv[0];
|
||||
|
||||
if (( found_entry = find_cmd( cmd_entry, cmdStr )) != NULL )
|
||||
{
|
||||
if ( found_entry->sub_cmd_entry != NULL )
|
||||
{
|
||||
return execute_cmd( param, found_entry->sub_cmd_entry );
|
||||
}
|
||||
|
||||
param->cmd_entry = found_entry;
|
||||
return found_entry->cmd_fn( param );
|
||||
}
|
||||
|
||||
/* Unrecognized command - check to see if it was the help command */
|
||||
|
||||
if ( vcos_strcmp( cmdStr, cmd_help.name ) == 0 )
|
||||
{
|
||||
return help_cmd( param );
|
||||
}
|
||||
|
||||
vcos_cmd_error( param, "- unrecognized command: '%s'", cmdStr );
|
||||
return VCOS_ENOENT;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Initializes the command line parser.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static void vcos_cmd_init( void )
|
||||
{
|
||||
vcos_mutex_create( &cmd_globals.lock, "vcos_cmd" );
|
||||
|
||||
cmd_globals.num_cmd_entries = 0;
|
||||
cmd_globals.num_cmd_alloc = 0;
|
||||
cmd_globals.cmd_entry = NULL;
|
||||
|
||||
#ifdef HAVE_VCOS_VERSION
|
||||
vcos_keep_static_strings = vcos_get_build_strings;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Shuts down the command line parser.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void vcos_cmd_shutdown( void )
|
||||
{
|
||||
vcos_mutex_delete( &cmd_globals.lock );
|
||||
|
||||
vcos_free( cmd_globals.cmd_entry );
|
||||
cmd_globals.cmd_entry = NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Command line processor.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
VCOS_STATUS_T vcos_cmd_execute( int argc, char **argv, size_t result_size, char *result_buf )
|
||||
{
|
||||
VCOS_STATUS_T rc = VCOS_EINVAL;
|
||||
VCOS_CMD_PARAM_T param;
|
||||
|
||||
vcos_once( &cmd_globals.initialized, vcos_cmd_init );
|
||||
|
||||
param.argc = argc;
|
||||
param.argv = param.argv_orig = argv;
|
||||
|
||||
param.use_log = 0;
|
||||
param.result_size = result_size;
|
||||
param.result_ptr = result_buf;
|
||||
param.result_buf = result_buf;
|
||||
|
||||
result_buf[0] = '\0';
|
||||
|
||||
vcos_mutex_lock( &cmd_globals.lock );
|
||||
|
||||
rc = execute_cmd( ¶m, cmd_globals.cmd_entry );
|
||||
|
||||
if ( param.use_log )
|
||||
{
|
||||
cmd_log_results( ¶m );
|
||||
vcos_snprintf( result_buf, result_size, "results logged" );
|
||||
}
|
||||
else
|
||||
if ( cmd_globals.log_category != NULL )
|
||||
{
|
||||
if ( result_buf[0] != '\0' )
|
||||
{
|
||||
/* There is a partial line still buffered. */
|
||||
|
||||
vcos_cmd_printf( ¶m, "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
vcos_mutex_unlock( &cmd_globals.lock );
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Registers a command entry with the command line processor
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
VCOS_STATUS_T vcos_cmd_register( VCOS_CMD_T *cmd_entry )
|
||||
{
|
||||
VCOS_STATUS_T rc;
|
||||
VCOS_UNSIGNED new_num_cmd_alloc;
|
||||
VCOS_CMD_T *new_cmd_entry;
|
||||
VCOS_CMD_T *old_cmd_entry;
|
||||
VCOS_CMD_T *scan_entry;
|
||||
|
||||
vcos_once( &cmd_globals.initialized, vcos_cmd_init );
|
||||
|
||||
vcos_assert( cmd_entry != NULL );
|
||||
vcos_assert( cmd_entry->name != NULL );
|
||||
|
||||
vcos_log_trace( "%s: cmd '%s'", __FUNCTION__, cmd_entry->name );
|
||||
|
||||
vcos_assert( cmd_entry->args != NULL );
|
||||
vcos_assert(( cmd_entry->cmd_fn != NULL ) || ( cmd_entry->sub_cmd_entry != NULL ));
|
||||
vcos_assert( cmd_entry->descr != NULL );
|
||||
|
||||
/* We expect vcos_cmd_init to be called before vcos_logging_init, so we
|
||||
* need to defer registering our logging category until someplace
|
||||
* like right here.
|
||||
*/
|
||||
|
||||
if ( vcos_cmd_log_category.name == NULL )
|
||||
{
|
||||
/*
|
||||
* If you're using the command interface, you pretty much always want
|
||||
* log messages from this file to show up. So we change the default
|
||||
* from ERROR to be the more reasonable INFO level.
|
||||
*/
|
||||
|
||||
vcos_log_set_level(&vcos_cmd_log_category, VCOS_LOG_INFO);
|
||||
vcos_log_register("vcos_cmd", &vcos_cmd_log_category);
|
||||
|
||||
/* We register a help command so that it shows up in the usage. */
|
||||
|
||||
vcos_cmd_register( &cmd_help );
|
||||
#ifdef HAVE_VCOS_VERSION
|
||||
vcos_cmd_register( &cmd_version );
|
||||
#endif
|
||||
}
|
||||
|
||||
vcos_mutex_lock( &cmd_globals.lock );
|
||||
|
||||
if ( cmd_globals.num_cmd_entries >= cmd_globals.num_cmd_alloc )
|
||||
{
|
||||
if ( cmd_globals.num_cmd_alloc == 0 )
|
||||
{
|
||||
/* We haven't allocated a table yet */
|
||||
}
|
||||
|
||||
/* The number 8 is rather arbitrary. */
|
||||
|
||||
new_num_cmd_alloc = cmd_globals.num_cmd_alloc + 8;
|
||||
|
||||
/* The + 1 is to ensure that we always have a NULL entry at the end. */
|
||||
|
||||
new_cmd_entry = (VCOS_CMD_T *)vcos_calloc( new_num_cmd_alloc + 1, sizeof( *cmd_entry ), "vcos_cmd_entries" );
|
||||
if ( new_cmd_entry == NULL )
|
||||
{
|
||||
rc = VCOS_ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
memcpy( new_cmd_entry, cmd_globals.cmd_entry, cmd_globals.num_cmd_entries * sizeof( *cmd_entry ));
|
||||
cmd_globals.num_cmd_alloc = new_num_cmd_alloc;
|
||||
old_cmd_entry = cmd_globals.cmd_entry;
|
||||
cmd_globals.cmd_entry = new_cmd_entry;
|
||||
vcos_free( old_cmd_entry );
|
||||
}
|
||||
|
||||
if ( cmd_globals.num_cmd_entries == 0 )
|
||||
{
|
||||
/* This is the first command being registered */
|
||||
|
||||
cmd_globals.cmd_entry[0] = *cmd_entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Keep the list in alphabetical order. We start at the end and work backwards
|
||||
* shuffling entries up one until we find an insertion point.
|
||||
*/
|
||||
|
||||
for ( scan_entry = &cmd_globals.cmd_entry[cmd_globals.num_cmd_entries - 1];
|
||||
scan_entry >= cmd_globals.cmd_entry; scan_entry-- )
|
||||
{
|
||||
if ( vcos_strcmp( cmd_entry->name, scan_entry->name ) > 0 )
|
||||
{
|
||||
/* We found an insertion point. */
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
scan_entry[1] = scan_entry[0];
|
||||
}
|
||||
scan_entry[1] = *cmd_entry;
|
||||
}
|
||||
cmd_globals.num_cmd_entries++;
|
||||
|
||||
rc = VCOS_SUCCESS;
|
||||
|
||||
out:
|
||||
|
||||
vcos_mutex_unlock( &cmd_globals.lock );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Registers multiple commands.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
VCOS_STATUS_T vcos_cmd_register_multiple( VCOS_CMD_T *cmd_entry )
|
||||
{
|
||||
VCOS_STATUS_T status;
|
||||
|
||||
while ( cmd_entry->name != NULL )
|
||||
{
|
||||
if (( status = vcos_cmd_register( cmd_entry )) != VCOS_SUCCESS )
|
||||
{
|
||||
return status;
|
||||
}
|
||||
cmd_entry++;
|
||||
}
|
||||
return VCOS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - common postamble code
|
||||
=============================================================================*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* Postamble code included by the platform-specific header files
|
||||
*/
|
||||
|
||||
#define VCOS_THREAD_PRI_DEFAULT VCOS_THREAD_PRI_NORMAL
|
||||
|
||||
#if !defined(VCOS_THREAD_PRI_INCREASE)
|
||||
#error Which way to thread priorities go?
|
||||
#endif
|
||||
|
||||
#if VCOS_THREAD_PRI_INCREASE < 0
|
||||
/* smaller numbers are higher priority */
|
||||
#define VCOS_THREAD_PRI_LESS(x) ((x)<VCOS_THREAD_PRI_MAX?(x)+1:VCOS_THREAD_PRI_MAX)
|
||||
#define VCOS_THREAD_PRI_MORE(x) ((x)>VCOS_THREAD_PRI_MIN?(x)-1:VCOS_THREAD_PRI_MIN)
|
||||
#else
|
||||
/* bigger numbers are lower priority */
|
||||
#define VCOS_THREAD_PRI_MORE(x) ((x)<VCOS_THREAD_PRI_MAX?(x)+1:VCOS_THREAD_PRI_MAX)
|
||||
#define VCOS_THREAD_PRI_LESS(x) ((x)>VCOS_THREAD_PRI_MIN?(x)-1:VCOS_THREAD_PRI_MIN)
|
||||
#endif
|
||||
|
||||
/* Convenience for Brits: */
|
||||
#define VCOS_APPLICATION_INITIALISE VCOS_APPLICATION_INITIALIZE
|
||||
|
||||
/*
|
||||
* Check for constant definitions
|
||||
*/
|
||||
#ifndef VCOS_TICKS_PER_SECOND
|
||||
#error VCOS_TICKS_PER_SECOND not defined
|
||||
#endif
|
||||
|
||||
#if !defined(VCOS_THREAD_PRI_MIN) || !defined(VCOS_THREAD_PRI_MAX)
|
||||
#error Priority range not defined
|
||||
#endif
|
||||
|
||||
#if !defined(VCOS_THREAD_PRI_HIGHEST) || !defined(VCOS_THREAD_PRI_LOWEST) || !defined(VCOS_THREAD_PRI_NORMAL)
|
||||
#error Priority ordering not defined
|
||||
#endif
|
||||
|
||||
#if !defined(VCOS_CAN_SET_STACK_ADDR)
|
||||
#error Can stack addresses be set on this platform? Please set this macro to either 0 or 1.
|
||||
#endif
|
||||
|
||||
#if (_VCOS_AFFINITY_CPU0|_VCOS_AFFINITY_CPU1) & (~_VCOS_AFFINITY_MASK)
|
||||
#error _VCOS_AFFINITY_CPUxxx values are not consistent with _VCOS_AFFINITY_MASK
|
||||
#endif
|
||||
|
||||
/** Append to the end of a singly-linked queue, O(1). Works with
|
||||
* any structure where list has members 'head' and 'tail' and
|
||||
* item has a 'next' pointer.
|
||||
*/
|
||||
#define VCOS_QUEUE_APPEND_TAIL(list, item) {\
|
||||
(item)->next = NULL;\
|
||||
if (!(list)->head) {\
|
||||
(list)->head = (list)->tail = (item); \
|
||||
} else {\
|
||||
(list)->tail->next = (item); \
|
||||
(list)->tail = (item); \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifndef VCOS_HAVE_TIMER
|
||||
VCOSPRE_ void VCOSPOST_ vcos_timer_init(void);
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
The symbol vcos_deprecated_code may be defined at most once, by the inclusion of "vcos_deprecated.h" in vcos_init.c.
|
||||
Any other inclusions of this header will cause the linker to warn about multiple definitions of vcos_deprecated_code, for example:
|
||||
[ldvc] (Warning) "vcos_deprecated_code" is multiply defined in libs/vcos_threadx/vcos_init.c.o and libs/xxxxx/xxxxx.c.o
|
||||
If you see a build message like this then the configuration you are building is using deprecated code.
|
||||
Contact the person named in the accompanying comment for advice - do not remove the inclusion.
|
||||
*/
|
||||
|
||||
int vcos_deprecated_code;
|
||||
+568
@@ -0,0 +1,568 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define VCOS_LOG_CATEGORY (&vcos_blockpool_log)
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "interface/vcos/vcos.h"
|
||||
#include "interface/vcos/generic/vcos_generic_blockpool.h"
|
||||
|
||||
#define VCOS_BLOCKPOOL_FOURCC(a,b,c,d) ((a) | (b << 8) | (c << 16) | (d << 24))
|
||||
#define VCOS_BLOCKPOOL_MAGIC VCOS_BLOCKPOOL_FOURCC('v', 'b', 'p', 'l')
|
||||
#define VCOS_BLOCKPOOL_SUBPOOL_MAGIC VCOS_BLOCKPOOL_FOURCC('v', 's', 'p', 'l')
|
||||
|
||||
#define VCOS_BLOCKPOOL_SUBPOOL_FLAG_NONE (0)
|
||||
#define VCOS_BLOCKPOOL_SUBPOOL_FLAG_OWNS_MEM (1 << 0)
|
||||
#define VCOS_BLOCKPOOL_SUBPOOL_FLAG_EXTENSION (1 << 1)
|
||||
|
||||
/* Uncomment to enable really verbose debug messages */
|
||||
/* #define VCOS_BLOCKPOOL_DEBUGGING */
|
||||
/* Whether to overwrite freed blocks with 0xBD */
|
||||
#ifdef VCOS_BLOCKPOOL_DEBUGGING
|
||||
#define VCOS_BLOCKPOOL_OVERWRITE_ON_FREE 1
|
||||
#define VCOS_BLOCKPOOL_DEBUG_MEMSET_MAX_SIZE (UINT32_MAX)
|
||||
#else
|
||||
#define VCOS_BLOCKPOOL_OVERWRITE_ON_FREE 0
|
||||
#define VCOS_BLOCKPOOL_DEBUG_MEMSET_MAX_SIZE (2 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
#ifdef VCOS_BLOCKPOOL_DEBUGGING
|
||||
#define VCOS_BLOCKPOOL_ASSERT vcos_demand
|
||||
#define VCOS_BLOCKPOOL_TRACE_LEVEL VCOS_LOG_TRACE
|
||||
#define VCOS_BLOCKPOOL_DEBUG_LOG(s, ...) vcos_log_trace("%s: " s, VCOS_FUNCTION, __VA_ARGS__)
|
||||
#undef VCOS_BLOCKPOOL_OVERWRITE_ON_FREE
|
||||
#define VCOS_BLOCKPOOL_OVERWRITE_ON_FREE 1
|
||||
#else
|
||||
#define VCOS_BLOCKPOOL_ASSERT vcos_demand
|
||||
#define VCOS_BLOCKPOOL_TRACE_LEVEL VCOS_LOG_ERROR
|
||||
#define VCOS_BLOCKPOOL_DEBUG_LOG(s, ...)
|
||||
#endif
|
||||
|
||||
#define ASSERT_POOL(p) \
|
||||
VCOS_BLOCKPOOL_ASSERT((p) && (p)->magic == VCOS_BLOCKPOOL_MAGIC);
|
||||
|
||||
#define ASSERT_SUBPOOL(p) \
|
||||
VCOS_BLOCKPOOL_ASSERT((p) && (p)->magic == VCOS_BLOCKPOOL_SUBPOOL_MAGIC && \
|
||||
p->start >= p->mem);
|
||||
|
||||
#if defined(VCOS_LOGGING_ENABLED)
|
||||
static VCOS_LOG_CAT_T vcos_blockpool_log =
|
||||
VCOS_LOG_INIT("vcos_blockpool", VCOS_BLOCKPOOL_TRACE_LEVEL);
|
||||
#endif
|
||||
|
||||
static void vcos_generic_blockpool_subpool_init(
|
||||
VCOS_BLOCKPOOL_T *pool, VCOS_BLOCKPOOL_SUBPOOL_T *subpool,
|
||||
void *mem, size_t pool_size, VCOS_UNSIGNED num_blocks, int align,
|
||||
uint32_t flags)
|
||||
{
|
||||
VCOS_BLOCKPOOL_HEADER_T *block;
|
||||
VCOS_BLOCKPOOL_HEADER_T *end;
|
||||
|
||||
vcos_unused(flags);
|
||||
|
||||
vcos_log_trace(
|
||||
"%s: pool %p subpool %p mem %p pool_size %d " \
|
||||
"num_blocks %d align %d flags %x",
|
||||
VCOS_FUNCTION,
|
||||
pool, subpool, mem, (uint32_t) pool_size,
|
||||
num_blocks, align, flags);
|
||||
|
||||
subpool->magic = VCOS_BLOCKPOOL_SUBPOOL_MAGIC;
|
||||
subpool->mem = mem;
|
||||
|
||||
/* The block data pointers must be aligned according to align and the
|
||||
* block header pre-preceeds the first block data.
|
||||
* For large alignments there may be wasted space between subpool->mem
|
||||
* and the first block header.
|
||||
*/
|
||||
subpool->start = (char *) subpool->mem + sizeof(VCOS_BLOCKPOOL_HEADER_T);
|
||||
subpool->start = (void*)
|
||||
VCOS_BLOCKPOOL_ROUND_UP((unsigned long) subpool->start, align);
|
||||
subpool->start = (char *) subpool->start - sizeof(VCOS_BLOCKPOOL_HEADER_T);
|
||||
|
||||
vcos_assert(subpool->start >= subpool->mem);
|
||||
|
||||
vcos_log_trace("%s: mem %p subpool->start %p" \
|
||||
" pool->block_size %d pool->block_data_size %d",
|
||||
VCOS_FUNCTION, mem, subpool->start,
|
||||
(int) pool->block_size, (int) pool->block_data_size);
|
||||
|
||||
subpool->num_blocks = num_blocks;
|
||||
subpool->available_blocks = num_blocks;
|
||||
subpool->free_list = NULL;
|
||||
subpool->owner = pool;
|
||||
|
||||
/* Initialise to a predictable bit pattern unless the pool is so big
|
||||
* that the delay would be noticable. */
|
||||
if (pool_size < VCOS_BLOCKPOOL_DEBUG_MEMSET_MAX_SIZE)
|
||||
memset(subpool->mem, 0xBC, pool_size); /* For debugging */
|
||||
|
||||
block = (VCOS_BLOCKPOOL_HEADER_T*) subpool->start;
|
||||
end = (VCOS_BLOCKPOOL_HEADER_T*)
|
||||
((char *) subpool->start + (pool->block_size * num_blocks));
|
||||
subpool->end = end;
|
||||
|
||||
/* Initialise the free list for this subpool */
|
||||
while (block < end)
|
||||
{
|
||||
block->owner.next = subpool->free_list;
|
||||
subpool->free_list = block;
|
||||
block = (VCOS_BLOCKPOOL_HEADER_T*)((char*) block + pool->block_size);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VCOS_STATUS_T vcos_generic_blockpool_init(VCOS_BLOCKPOOL_T *pool,
|
||||
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
|
||||
void *start, VCOS_UNSIGNED pool_size, VCOS_UNSIGNED align,
|
||||
VCOS_UNSIGNED flags, const char *name)
|
||||
{
|
||||
VCOS_STATUS_T status = VCOS_SUCCESS;
|
||||
|
||||
vcos_unused(name);
|
||||
vcos_unused(flags);
|
||||
|
||||
vcos_log_trace(
|
||||
"%s: pool %p num_blocks %d block_size %d start %p pool_size %d name %p",
|
||||
VCOS_FUNCTION, pool, num_blocks, block_size, start, pool_size, name);
|
||||
|
||||
vcos_demand(pool);
|
||||
vcos_demand(start);
|
||||
vcos_assert((block_size > 0));
|
||||
vcos_assert(num_blocks > 0);
|
||||
|
||||
if (! align)
|
||||
align = VCOS_BLOCKPOOL_ALIGN_DEFAULT;
|
||||
|
||||
if (align & 0x3)
|
||||
{
|
||||
vcos_log_error("%s: invalid alignment %d", VCOS_FUNCTION, align);
|
||||
return VCOS_EINVAL;
|
||||
}
|
||||
|
||||
if (VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align) > pool_size)
|
||||
{
|
||||
vcos_log_error("%s: Pool is too small" \
|
||||
" num_blocks %d block_size %d align %d"
|
||||
" pool_size %d required size %d", VCOS_FUNCTION,
|
||||
num_blocks, block_size, align,
|
||||
pool_size, (int) VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align));
|
||||
return VCOS_ENOMEM;
|
||||
}
|
||||
|
||||
status = vcos_mutex_create(&pool->mutex, "vcos blockpool mutex");
|
||||
if (status != VCOS_SUCCESS)
|
||||
return status;
|
||||
|
||||
pool->block_data_size = block_size;
|
||||
|
||||
/* TODO - create flag that if set forces the header to be in its own cache
|
||||
* line */
|
||||
pool->block_size = VCOS_BLOCKPOOL_ROUND_UP(pool->block_data_size +
|
||||
(align >= 4096 ? 32 : 0) +
|
||||
sizeof(VCOS_BLOCKPOOL_HEADER_T), align);
|
||||
|
||||
pool->magic = VCOS_BLOCKPOOL_MAGIC;
|
||||
pool->num_subpools = 1;
|
||||
pool->num_extension_blocks = 0;
|
||||
pool->align = align;
|
||||
memset(pool->subpools, 0, sizeof(pool->subpools));
|
||||
|
||||
vcos_generic_blockpool_subpool_init(pool, &pool->subpools[0], start,
|
||||
pool_size, num_blocks, align, VCOS_BLOCKPOOL_SUBPOOL_FLAG_NONE);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VCOS_STATUS_T vcos_generic_blockpool_create_on_heap(VCOS_BLOCKPOOL_T *pool,
|
||||
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size, VCOS_UNSIGNED align,
|
||||
VCOS_UNSIGNED flags, const char *name)
|
||||
{
|
||||
VCOS_STATUS_T status = VCOS_SUCCESS;
|
||||
size_t size = VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align);
|
||||
void* mem = vcos_malloc(size, name);
|
||||
|
||||
vcos_log_trace("%s: num_blocks %d block_size %d name %s",
|
||||
VCOS_FUNCTION, num_blocks, block_size, name);
|
||||
|
||||
if (! mem)
|
||||
return VCOS_ENOMEM;
|
||||
|
||||
status = vcos_generic_blockpool_init(pool, num_blocks,
|
||||
block_size, mem, size, align, flags, name);
|
||||
|
||||
if (status != VCOS_SUCCESS)
|
||||
goto fail;
|
||||
|
||||
pool->subpools[0].flags |= VCOS_BLOCKPOOL_SUBPOOL_FLAG_OWNS_MEM;
|
||||
return status;
|
||||
|
||||
fail:
|
||||
free(mem);
|
||||
return status;
|
||||
}
|
||||
|
||||
VCOS_STATUS_T vcos_generic_blockpool_extend(VCOS_BLOCKPOOL_T *pool,
|
||||
VCOS_UNSIGNED num_extensions, VCOS_UNSIGNED num_blocks)
|
||||
{
|
||||
VCOS_UNSIGNED i;
|
||||
ASSERT_POOL(pool);
|
||||
|
||||
vcos_log_trace("%s: pool %p num_extensions %d num_blocks %d",
|
||||
VCOS_FUNCTION, pool, num_extensions, num_blocks);
|
||||
|
||||
/* Extend may only be called once */
|
||||
if (pool->num_subpools > 1)
|
||||
return VCOS_EACCESS;
|
||||
|
||||
if (num_extensions < 1 ||
|
||||
num_extensions > VCOS_BLOCKPOOL_MAX_SUBPOOLS - 1)
|
||||
return VCOS_EINVAL;
|
||||
|
||||
if (num_blocks < 1)
|
||||
return VCOS_EINVAL;
|
||||
|
||||
pool->num_subpools += num_extensions;
|
||||
pool->num_extension_blocks = num_blocks;
|
||||
|
||||
/* Mark these subpools as valid but unallocated */
|
||||
for (i = 1; i < pool->num_subpools; ++i)
|
||||
{
|
||||
pool->subpools[i].magic = VCOS_BLOCKPOOL_SUBPOOL_MAGIC;
|
||||
pool->subpools[i].start = NULL;
|
||||
pool->subpools[i].mem = NULL;
|
||||
}
|
||||
|
||||
return VCOS_SUCCESS;
|
||||
}
|
||||
|
||||
void *vcos_generic_blockpool_alloc(VCOS_BLOCKPOOL_T *pool)
|
||||
{
|
||||
VCOS_UNSIGNED i;
|
||||
void* ret = NULL;
|
||||
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = NULL;
|
||||
|
||||
ASSERT_POOL(pool);
|
||||
vcos_mutex_lock(&pool->mutex);
|
||||
|
||||
/* Starting with the main pool try and find a free block */
|
||||
for (i = 0; i < pool->num_subpools; ++i)
|
||||
{
|
||||
if (pool->subpools[i].start && pool->subpools[i].available_blocks > 0)
|
||||
{
|
||||
subpool = &pool->subpools[i];
|
||||
break; /* Found a subpool with free blocks */
|
||||
}
|
||||
}
|
||||
|
||||
if (! subpool)
|
||||
{
|
||||
/* All current subpools are full, try to allocate a new one */
|
||||
for (i = 1; i < pool->num_subpools; ++i)
|
||||
{
|
||||
if (! pool->subpools[i].start)
|
||||
{
|
||||
VCOS_BLOCKPOOL_SUBPOOL_T *s = &pool->subpools[i];
|
||||
size_t size = VCOS_BLOCKPOOL_SIZE(pool->num_extension_blocks,
|
||||
pool->block_data_size, pool->align);
|
||||
void *mem = vcos_malloc(size, pool->name);
|
||||
if (mem)
|
||||
{
|
||||
vcos_log_trace("%s: Allocated subpool %d", VCOS_FUNCTION, i);
|
||||
vcos_generic_blockpool_subpool_init(pool, s, mem, size,
|
||||
pool->num_extension_blocks,
|
||||
pool->align,
|
||||
VCOS_BLOCKPOOL_SUBPOOL_FLAG_OWNS_MEM |
|
||||
VCOS_BLOCKPOOL_SUBPOOL_FLAG_EXTENSION);
|
||||
subpool = s;
|
||||
break; /* Created a subpool */
|
||||
}
|
||||
else
|
||||
{
|
||||
vcos_log_warn("%s: Failed to allocate subpool", VCOS_FUNCTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (subpool)
|
||||
{
|
||||
/* Remove from free list */
|
||||
VCOS_BLOCKPOOL_HEADER_T* nb = subpool->free_list;
|
||||
|
||||
vcos_assert(subpool->free_list);
|
||||
subpool->free_list = nb->owner.next;
|
||||
|
||||
/* Owner is pool so free can be called without passing pool
|
||||
* as a parameter */
|
||||
nb->owner.subpool = subpool;
|
||||
|
||||
ret = nb + 1; /* Return pointer to block data */
|
||||
--(subpool->available_blocks);
|
||||
}
|
||||
vcos_mutex_unlock(&pool->mutex);
|
||||
VCOS_BLOCKPOOL_DEBUG_LOG("pool %p subpool %p ret %p", pool, subpool, ret);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
vcos_assert(ret > subpool->start);
|
||||
vcos_assert(ret < subpool->end);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *vcos_generic_blockpool_calloc(VCOS_BLOCKPOOL_T *pool)
|
||||
{
|
||||
void* ret = vcos_generic_blockpool_alloc(pool);
|
||||
if (ret)
|
||||
memset(ret, 0, pool->block_data_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vcos_generic_blockpool_free(void *block)
|
||||
{
|
||||
VCOS_BLOCKPOOL_DEBUG_LOG("block %p", block);
|
||||
if (block)
|
||||
{
|
||||
VCOS_BLOCKPOOL_HEADER_T* hdr = (VCOS_BLOCKPOOL_HEADER_T*) block - 1;
|
||||
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = hdr->owner.subpool;
|
||||
VCOS_BLOCKPOOL_T *pool = NULL;
|
||||
|
||||
ASSERT_SUBPOOL(subpool);
|
||||
pool = subpool->owner;
|
||||
ASSERT_POOL(pool);
|
||||
|
||||
vcos_mutex_lock(&pool->mutex);
|
||||
vcos_assert((unsigned) subpool->available_blocks < subpool->num_blocks);
|
||||
|
||||
/* Change ownership of block to be the free list */
|
||||
hdr->owner.next = subpool->free_list;
|
||||
subpool->free_list = hdr;
|
||||
++(subpool->available_blocks);
|
||||
|
||||
if (VCOS_BLOCKPOOL_OVERWRITE_ON_FREE)
|
||||
memset(block, 0xBD, pool->block_data_size); /* For debugging */
|
||||
|
||||
if ( (subpool->flags & VCOS_BLOCKPOOL_SUBPOOL_FLAG_EXTENSION) &&
|
||||
subpool->available_blocks == subpool->num_blocks)
|
||||
{
|
||||
VCOS_BLOCKPOOL_DEBUG_LOG("%s: freeing subpool %p mem %p", VCOS_FUNCTION,
|
||||
subpool, subpool->mem);
|
||||
/* Free the sub-pool if it was dynamically allocated */
|
||||
vcos_free(subpool->mem);
|
||||
subpool->mem = NULL;
|
||||
subpool->start = NULL;
|
||||
}
|
||||
vcos_mutex_unlock(&pool->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
VCOS_UNSIGNED vcos_generic_blockpool_available_count(VCOS_BLOCKPOOL_T *pool)
|
||||
{
|
||||
VCOS_UNSIGNED ret = 0;
|
||||
VCOS_UNSIGNED i;
|
||||
|
||||
ASSERT_POOL(pool);
|
||||
vcos_mutex_lock(&pool->mutex);
|
||||
for (i = 0; i < pool->num_subpools; ++i)
|
||||
{
|
||||
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = &pool->subpools[i];
|
||||
ASSERT_SUBPOOL(subpool);
|
||||
|
||||
/* Assume the malloc of sub pool would succeed */
|
||||
if (subpool->start)
|
||||
ret += subpool->available_blocks;
|
||||
else
|
||||
ret += pool->num_extension_blocks;
|
||||
}
|
||||
vcos_mutex_unlock(&pool->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
VCOS_UNSIGNED vcos_generic_blockpool_used_count(VCOS_BLOCKPOOL_T *pool)
|
||||
{
|
||||
VCOS_UNSIGNED ret = 0;
|
||||
VCOS_UNSIGNED i;
|
||||
|
||||
ASSERT_POOL(pool);
|
||||
vcos_mutex_lock(&pool->mutex);
|
||||
|
||||
for (i = 0; i < pool->num_subpools; ++i)
|
||||
{
|
||||
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = &pool->subpools[i];
|
||||
ASSERT_SUBPOOL(subpool);
|
||||
if (subpool->start)
|
||||
ret += (subpool->num_blocks - subpool->available_blocks);
|
||||
}
|
||||
vcos_mutex_unlock(&pool->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vcos_generic_blockpool_delete(VCOS_BLOCKPOOL_T *pool)
|
||||
{
|
||||
vcos_log_trace("%s: pool %p", VCOS_FUNCTION, pool);
|
||||
|
||||
if (pool)
|
||||
{
|
||||
VCOS_UNSIGNED i;
|
||||
|
||||
ASSERT_POOL(pool);
|
||||
for (i = 0; i < pool->num_subpools; ++i)
|
||||
{
|
||||
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = &pool->subpools[i];
|
||||
ASSERT_SUBPOOL(subpool);
|
||||
if (subpool->mem)
|
||||
{
|
||||
/* For debugging */
|
||||
memset(subpool->mem,
|
||||
0xBE,
|
||||
VCOS_BLOCKPOOL_SIZE(subpool->num_blocks,
|
||||
pool->block_data_size, pool->align));
|
||||
|
||||
if (subpool->flags & VCOS_BLOCKPOOL_SUBPOOL_FLAG_OWNS_MEM)
|
||||
vcos_free(subpool->mem);
|
||||
subpool->mem = NULL;
|
||||
subpool->start = NULL;
|
||||
}
|
||||
}
|
||||
vcos_mutex_delete(&pool->mutex);
|
||||
memset(pool, 0xBE, sizeof(VCOS_BLOCKPOOL_T)); /* For debugging */
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t vcos_generic_blockpool_elem_to_handle(void *block)
|
||||
{
|
||||
uint32_t ret = -1;
|
||||
uint32_t index = -1;
|
||||
VCOS_BLOCKPOOL_HEADER_T *hdr = NULL;
|
||||
VCOS_BLOCKPOOL_T *pool = NULL;
|
||||
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = NULL;
|
||||
uint32_t subpool_id;
|
||||
|
||||
vcos_assert(block);
|
||||
hdr = (VCOS_BLOCKPOOL_HEADER_T*) block - 1;
|
||||
subpool = hdr->owner.subpool;
|
||||
ASSERT_SUBPOOL(subpool);
|
||||
|
||||
pool = subpool->owner;
|
||||
ASSERT_POOL(pool);
|
||||
vcos_mutex_lock(&pool->mutex);
|
||||
|
||||
/* The handle is the index into the array of blocks combined
|
||||
* with the subpool id.
|
||||
*/
|
||||
index = ((size_t) hdr - (size_t) subpool->start) / pool->block_size;
|
||||
vcos_assert(index < subpool->num_blocks);
|
||||
|
||||
subpool_id = ((char*) subpool - (char*) &pool->subpools[0]) /
|
||||
sizeof(VCOS_BLOCKPOOL_SUBPOOL_T);
|
||||
|
||||
vcos_assert(subpool_id < VCOS_BLOCKPOOL_MAX_SUBPOOLS);
|
||||
vcos_assert(subpool_id < pool->num_subpools);
|
||||
ret = VCOS_BLOCKPOOL_HANDLE_CREATE(index, subpool_id);
|
||||
|
||||
vcos_log_trace("%s: index %d subpool_id %d handle 0x%08x",
|
||||
VCOS_FUNCTION, index, subpool_id, ret);
|
||||
|
||||
vcos_mutex_unlock(&pool->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *vcos_generic_blockpool_elem_from_handle(
|
||||
VCOS_BLOCKPOOL_T *pool, uint32_t handle)
|
||||
{
|
||||
VCOS_BLOCKPOOL_SUBPOOL_T *subpool;
|
||||
uint32_t subpool_id;
|
||||
uint32_t index;
|
||||
void *ret = NULL;
|
||||
|
||||
|
||||
ASSERT_POOL(pool);
|
||||
vcos_mutex_lock(&pool->mutex);
|
||||
subpool_id = VCOS_BLOCKPOOL_HANDLE_GET_SUBPOOL(handle);
|
||||
|
||||
if (subpool_id < pool->num_subpools)
|
||||
{
|
||||
index = VCOS_BLOCKPOOL_HANDLE_GET_INDEX(handle);
|
||||
subpool = &pool->subpools[subpool_id];
|
||||
if (pool->subpools[subpool_id].magic == VCOS_BLOCKPOOL_SUBPOOL_MAGIC &&
|
||||
pool->subpools[subpool_id].mem && index < subpool->num_blocks)
|
||||
{
|
||||
VCOS_BLOCKPOOL_HEADER_T *hdr = (VCOS_BLOCKPOOL_HEADER_T*)
|
||||
((size_t) subpool->start + (index * pool->block_size));
|
||||
|
||||
if (hdr->owner.subpool == subpool) /* Check block is allocated */
|
||||
ret = hdr + 1;
|
||||
}
|
||||
}
|
||||
vcos_mutex_unlock(&pool->mutex);
|
||||
|
||||
vcos_log_trace("%s: pool %p handle 0x%08x elem %p", VCOS_FUNCTION, pool,
|
||||
handle, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t vcos_generic_blockpool_is_valid_elem(
|
||||
VCOS_BLOCKPOOL_T *pool, const void *block)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
const char *pool_end;
|
||||
VCOS_UNSIGNED i = 0;
|
||||
|
||||
ASSERT_POOL(pool);
|
||||
if (((size_t) block) & 0x3)
|
||||
return 0;
|
||||
|
||||
vcos_mutex_lock(&pool->mutex);
|
||||
|
||||
for (i = 0; i < pool->num_subpools; ++i)
|
||||
{
|
||||
VCOS_BLOCKPOOL_SUBPOOL_T *subpool = &pool->subpools[i];
|
||||
ASSERT_SUBPOOL(subpool);
|
||||
|
||||
if (subpool->mem && subpool->start)
|
||||
{
|
||||
pool_end = (const char*)subpool->start +
|
||||
(subpool->num_blocks * pool->block_size);
|
||||
|
||||
if ((const char*)block > (const char*)subpool->start &&
|
||||
(const char*)block < pool_end)
|
||||
{
|
||||
const VCOS_BLOCKPOOL_HEADER_T *hdr = (
|
||||
const VCOS_BLOCKPOOL_HEADER_T*) block - 1;
|
||||
|
||||
/* If the block has a header where the owner points to the pool then
|
||||
* it's a valid block. */
|
||||
ret = (hdr->owner.subpool == subpool && subpool->owner == pool);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
vcos_mutex_unlock(&pool->mutex);
|
||||
return ret;
|
||||
}
|
||||
+294
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - event flags implemented via a semaphore
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef VCOS_GENERIC_BLOCKPOOL_H
|
||||
#define VCOS_GENERIC_BLOCKPOOL_H
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This provides a generic, thread safe implementation of a VCOS block pool
|
||||
* fixed size memory allocator.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vcos_types.h"
|
||||
|
||||
/** Bits 0 to (VCOS_BLOCKPOOL_SUBPOOL_BITS - 1) are used to store the
|
||||
* subpool id. */
|
||||
#define VCOS_BLOCKPOOL_SUBPOOL_BITS 3
|
||||
#define VCOS_BLOCKPOOL_MAX_SUBPOOLS (1 << VCOS_BLOCKPOOL_SUBPOOL_BITS)
|
||||
|
||||
/* Make zero an invalid handle at the cost of decreasing the maximum
|
||||
* number of blocks (2^28) by 1. Alternatively, a spare bit could be
|
||||
* used to indicated valid blocks but there are likely to be better
|
||||
* uses for spare bits. e.g. allowing more subpools
|
||||
*/
|
||||
#define INDEX_OFFSET 1
|
||||
|
||||
#define VCOS_BLOCKPOOL_HANDLE_GET_INDEX(h) \
|
||||
(((h) >> VCOS_BLOCKPOOL_SUBPOOL_BITS) - INDEX_OFFSET)
|
||||
|
||||
#define VCOS_BLOCKPOOL_HANDLE_GET_SUBPOOL(h) \
|
||||
((h) & ((1 << VCOS_BLOCKPOOL_SUBPOOL_BITS) - 1))
|
||||
|
||||
#define VCOS_BLOCKPOOL_HANDLE_CREATE(i,s) \
|
||||
((((i) + INDEX_OFFSET) << VCOS_BLOCKPOOL_SUBPOOL_BITS) | (s))
|
||||
|
||||
#define VCOS_BLOCKPOOL_INVALID_HANDLE 0
|
||||
#define VCOS_BLOCKPOOL_ALIGN_DEFAULT sizeof(unsigned long)
|
||||
#define VCOS_BLOCKPOOL_FLAG_NONE 0
|
||||
|
||||
typedef struct VCOS_BLOCKPOOL_HEADER_TAG
|
||||
{
|
||||
/* Blocks either refer to to the pool if they are allocated
|
||||
* or the free list if they are available.
|
||||
*/
|
||||
union {
|
||||
struct VCOS_BLOCKPOOL_HEADER_TAG *next;
|
||||
struct VCOS_BLOCKPOOL_SUBPOOL_TAG* subpool;
|
||||
} owner;
|
||||
} VCOS_BLOCKPOOL_HEADER_T;
|
||||
|
||||
typedef struct VCOS_BLOCKPOOL_SUBPOOL_TAG
|
||||
{
|
||||
/** VCOS_BLOCKPOOL_SUBPOOL_MAGIC */
|
||||
uint32_t magic;
|
||||
VCOS_BLOCKPOOL_HEADER_T* free_list;
|
||||
/* The start of the pool memory */
|
||||
void *mem;
|
||||
/* Address of the first block header */
|
||||
void *start;
|
||||
/* The end of the subpool */
|
||||
void *end;
|
||||
/** The number of blocks in this sub-pool */
|
||||
VCOS_UNSIGNED num_blocks;
|
||||
/** Current number of available blocks in this sub-pool */
|
||||
VCOS_UNSIGNED available_blocks;
|
||||
/** Pointers to the pool that owns this sub-pool */
|
||||
struct VCOS_BLOCKPOOL_TAG* owner;
|
||||
/** Define properties such as memory ownership */
|
||||
uint32_t flags;
|
||||
} VCOS_BLOCKPOOL_SUBPOOL_T;
|
||||
|
||||
typedef struct VCOS_BLOCKPOOL_TAG
|
||||
{
|
||||
/** VCOS_BLOCKPOOL_MAGIC */
|
||||
uint32_t magic;
|
||||
/** Thread safety for Alloc, Free, Delete, Stats */
|
||||
VCOS_MUTEX_T mutex;
|
||||
/** Alignment of block data pointers */
|
||||
VCOS_UNSIGNED align;
|
||||
/** Flags for future use e.g. cache options */
|
||||
VCOS_UNSIGNED flags;
|
||||
/** The size of the block data */
|
||||
size_t block_data_size;
|
||||
/** Block size inc overheads */
|
||||
size_t block_size;
|
||||
/** Name for debugging */
|
||||
const char *name;
|
||||
/* The number of subpools that may be used */
|
||||
VCOS_UNSIGNED num_subpools;
|
||||
/** Number of blocks in each dynamically allocated subpool */
|
||||
VCOS_UNSIGNED num_extension_blocks;
|
||||
/** Array of subpools. Subpool zero is is not deleted until the pool is
|
||||
* destroed. If the index of the pool is < num_subpools and
|
||||
* subpool[index.mem] is null then the subpool entry is valid but
|
||||
* "not currently allocated" */
|
||||
VCOS_BLOCKPOOL_SUBPOOL_T subpools[VCOS_BLOCKPOOL_MAX_SUBPOOLS];
|
||||
} VCOS_BLOCKPOOL_T;
|
||||
|
||||
#define VCOS_BLOCKPOOL_ROUND_UP(x,s) (((x) + ((s) - 1)) & ~((s) - 1))
|
||||
/**
|
||||
* Calculates the size in bytes required for a block pool containing
|
||||
* num_blocks of size block_size plus any overheads.
|
||||
*
|
||||
* The block pool header (VCOS_BLOCKPOOL_T) is allocated separately
|
||||
*
|
||||
* Overheads:
|
||||
* block_size + header must be rounded up to meet the required alignment
|
||||
* The start of the first block may need to be up to align bytes
|
||||
* into the given buffer because statically allocated buffers within structures
|
||||
* are not guaranteed to be aligned as required.
|
||||
*/
|
||||
#define VCOS_BLOCKPOOL_SIZE(num_blocks, block_size, align) \
|
||||
((VCOS_BLOCKPOOL_ROUND_UP((block_size) + (align >= 4096 ? 32 : 0) + sizeof(VCOS_BLOCKPOOL_HEADER_T), \
|
||||
(align)) * (num_blocks)) + (align))
|
||||
|
||||
/**
|
||||
* Sanity check to verify whether a handle is potentially a blockpool handle
|
||||
* when the pool pointer is not available.
|
||||
*
|
||||
* If the pool pointer is availabe use vcos_blockpool_elem_to_handle instead.
|
||||
*
|
||||
* @param handle the handle to verify
|
||||
* @param max_blocks the expected maximum number of block in the pool
|
||||
* that the handle belongs to.
|
||||
*/
|
||||
#define VCOS_BLOCKPOOL_IS_VALID_HANDLE_FORMAT(handle, max_blocks) \
|
||||
((handle) != VCOS_BLOCKPOOL_INVALID_HANDLE \
|
||||
&& VCOS_BLOCKPOOL_HANDLE_GET_INDEX((handle)) < (max_blocks))
|
||||
|
||||
VCOSPRE_
|
||||
VCOS_STATUS_T VCOSPOST_ vcos_generic_blockpool_init(VCOS_BLOCKPOOL_T *pool,
|
||||
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
|
||||
void *start, VCOS_UNSIGNED pool_size,
|
||||
VCOS_UNSIGNED align, VCOS_UNSIGNED flags,
|
||||
const char *name);
|
||||
|
||||
VCOSPRE_
|
||||
VCOS_STATUS_T VCOSPOST_ vcos_generic_blockpool_create_on_heap(
|
||||
VCOS_BLOCKPOOL_T *pool, VCOS_UNSIGNED num_blocks,
|
||||
VCOS_UNSIGNED block_size,
|
||||
VCOS_UNSIGNED align, VCOS_UNSIGNED flags,
|
||||
const char *name);
|
||||
|
||||
VCOSPRE_
|
||||
VCOS_STATUS_T VCOSPOST_ vcos_generic_blockpool_extend(VCOS_BLOCKPOOL_T *pool,
|
||||
VCOS_UNSIGNED num_extensions, VCOS_UNSIGNED num_blocks);
|
||||
|
||||
VCOSPRE_ void VCOSPOST_ *vcos_generic_blockpool_alloc(VCOS_BLOCKPOOL_T *pool);
|
||||
|
||||
VCOSPRE_ void VCOSPOST_ *vcos_generic_blockpool_calloc(VCOS_BLOCKPOOL_T *pool);
|
||||
|
||||
VCOSPRE_ void VCOSPOST_ vcos_generic_blockpool_free(void *block);
|
||||
|
||||
VCOSPRE_
|
||||
VCOS_UNSIGNED VCOSPOST_ vcos_generic_blockpool_available_count(
|
||||
VCOS_BLOCKPOOL_T *pool);
|
||||
|
||||
VCOSPRE_
|
||||
VCOS_UNSIGNED VCOSPOST_ vcos_generic_blockpool_used_count(
|
||||
VCOS_BLOCKPOOL_T *pool);
|
||||
|
||||
VCOSPRE_ void VCOSPOST_ vcos_generic_blockpool_delete(VCOS_BLOCKPOOL_T *pool);
|
||||
|
||||
VCOSPRE_ uint32_t VCOSPOST_ vcos_generic_blockpool_elem_to_handle(void *block);
|
||||
|
||||
VCOSPRE_ void VCOSPOST_
|
||||
*vcos_generic_blockpool_elem_from_handle(
|
||||
VCOS_BLOCKPOOL_T *pool, uint32_t handle);
|
||||
|
||||
VCOSPRE_ uint32_t VCOSPOST_
|
||||
vcos_generic_blockpool_is_valid_elem(
|
||||
VCOS_BLOCKPOOL_T *pool, const void *block);
|
||||
#if defined(VCOS_INLINE_BODIES)
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_blockpool_init(VCOS_BLOCKPOOL_T *pool,
|
||||
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
|
||||
void *start, VCOS_UNSIGNED pool_size,
|
||||
VCOS_UNSIGNED align, VCOS_UNSIGNED flags, const char *name)
|
||||
{
|
||||
return vcos_generic_blockpool_init(pool, num_blocks, block_size,
|
||||
start, pool_size, align, flags, name);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_blockpool_create_on_heap(VCOS_BLOCKPOOL_T *pool,
|
||||
VCOS_UNSIGNED num_blocks, VCOS_UNSIGNED block_size,
|
||||
VCOS_UNSIGNED align, VCOS_UNSIGNED flags, const char *name)
|
||||
{
|
||||
return vcos_generic_blockpool_create_on_heap(
|
||||
pool, num_blocks, block_size, align, flags, name);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T VCOSPOST_ vcos_blockpool_extend(VCOS_BLOCKPOOL_T *pool,
|
||||
VCOS_UNSIGNED num_extensions, VCOS_UNSIGNED num_blocks)
|
||||
{
|
||||
return vcos_generic_blockpool_extend(pool, num_extensions, num_blocks);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void *vcos_blockpool_alloc(VCOS_BLOCKPOOL_T *pool)
|
||||
{
|
||||
return vcos_generic_blockpool_alloc(pool);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void *vcos_blockpool_calloc(VCOS_BLOCKPOOL_T *pool)
|
||||
{
|
||||
return vcos_generic_blockpool_calloc(pool);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_blockpool_free(void *block)
|
||||
{
|
||||
vcos_generic_blockpool_free(block);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_UNSIGNED vcos_blockpool_available_count(VCOS_BLOCKPOOL_T *pool)
|
||||
{
|
||||
return vcos_generic_blockpool_available_count(pool);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_UNSIGNED vcos_blockpool_used_count(VCOS_BLOCKPOOL_T *pool)
|
||||
{
|
||||
return vcos_generic_blockpool_used_count(pool);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_blockpool_delete(VCOS_BLOCKPOOL_T *pool)
|
||||
{
|
||||
vcos_generic_blockpool_delete(pool);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
uint32_t vcos_blockpool_elem_to_handle(void *block)
|
||||
{
|
||||
return vcos_generic_blockpool_elem_to_handle(block);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void *vcos_blockpool_elem_from_handle(VCOS_BLOCKPOOL_T *pool, uint32_t handle)
|
||||
{
|
||||
return vcos_generic_blockpool_elem_from_handle(pool, handle);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
uint32_t vcos_blockpool_is_valid_elem(VCOS_BLOCKPOOL_T *pool, const void *block)
|
||||
{
|
||||
return vcos_generic_blockpool_is_valid_elem(pool, block);
|
||||
}
|
||||
#endif /* VCOS_INLINE_BODIES */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* VCOS_GENERIC_BLOCKPOOL_H */
|
||||
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - event flags implemented via mutexes
|
||||
=============================================================================*/
|
||||
|
||||
#include "interface/vcos/vcos.h"
|
||||
#include "interface/vcos/generic/vcos_generic_event_flags.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/** A structure created by a thread that waits on the event flags
|
||||
* for a particular combination of flags to arrive.
|
||||
*/
|
||||
typedef struct VCOS_EVENT_WAITER_T
|
||||
{
|
||||
VCOS_UNSIGNED requested_events; /**< The events wanted */
|
||||
VCOS_UNSIGNED actual_events; /**< Actual events found */
|
||||
VCOS_UNSIGNED op; /**< The event operation to be used */
|
||||
VCOS_STATUS_T return_status; /**< The return status the waiter should pass back */
|
||||
VCOS_EVENT_FLAGS_T *flags; /**< Pointer to the original 'flags' structure */
|
||||
VCOS_THREAD_T *thread; /**< Thread waiting */
|
||||
struct VCOS_EVENT_WAITER_T *next;
|
||||
} VCOS_EVENT_WAITER_T;
|
||||
|
||||
#ifndef NDEBUG
|
||||
static int waiter_list_valid(VCOS_EVENT_FLAGS_T *flags);
|
||||
#endif
|
||||
static void event_flags_timer_expired(void *cxt);
|
||||
|
||||
VCOS_STATUS_T vcos_generic_event_flags_create(VCOS_EVENT_FLAGS_T *flags, const char *name)
|
||||
{
|
||||
VCOS_STATUS_T rc;
|
||||
if ((rc=vcos_mutex_create(&flags->lock, name)) != VCOS_SUCCESS)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
flags->events = 0;
|
||||
flags->waiters.head = flags->waiters.tail = 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
void vcos_generic_event_flags_set(VCOS_EVENT_FLAGS_T *flags,
|
||||
VCOS_UNSIGNED bitmask,
|
||||
VCOS_OPTION op)
|
||||
{
|
||||
vcos_assert(flags);
|
||||
vcos_mutex_lock(&flags->lock);
|
||||
if (op == VCOS_OR)
|
||||
{
|
||||
flags->events |= bitmask;
|
||||
}
|
||||
else if (op == VCOS_AND)
|
||||
{
|
||||
flags->events &= bitmask;
|
||||
}
|
||||
else
|
||||
{
|
||||
vcos_assert(0);
|
||||
}
|
||||
|
||||
/* Now wake up any threads that have now become signalled. */
|
||||
if (flags->waiters.head != NULL)
|
||||
{
|
||||
VCOS_UNSIGNED consumed_events = 0;
|
||||
VCOS_EVENT_WAITER_T **pcurrent_waiter = &flags->waiters.head;
|
||||
VCOS_EVENT_WAITER_T *prev_waiter = NULL;
|
||||
|
||||
/* Walk the chain of tasks suspend on this event flag group to determine
|
||||
* if any of their requests can be satisfied.
|
||||
*/
|
||||
while ((*pcurrent_waiter) != NULL)
|
||||
{
|
||||
VCOS_EVENT_WAITER_T *curr_waiter = *pcurrent_waiter;
|
||||
|
||||
/* Determine if this request has been satisfied */
|
||||
|
||||
/* First, find the event flags in common. */
|
||||
VCOS_UNSIGNED waiter_satisfied = flags->events & curr_waiter->requested_events;
|
||||
|
||||
/* Second, determine if all the event flags must match */
|
||||
if (curr_waiter->op & VCOS_AND)
|
||||
{
|
||||
/* All requested events must be present */
|
||||
waiter_satisfied = (waiter_satisfied == curr_waiter->requested_events);
|
||||
}
|
||||
|
||||
/* Wake this one up? */
|
||||
if (waiter_satisfied)
|
||||
{
|
||||
|
||||
if (curr_waiter->op & VCOS_CONSUME)
|
||||
{
|
||||
consumed_events |= curr_waiter->requested_events;
|
||||
}
|
||||
|
||||
/* remove this block from the list, taking care at the end */
|
||||
*pcurrent_waiter = curr_waiter->next;
|
||||
if (curr_waiter->next == NULL)
|
||||
flags->waiters.tail = prev_waiter;
|
||||
|
||||
vcos_assert(waiter_list_valid(flags));
|
||||
|
||||
curr_waiter->return_status = VCOS_SUCCESS;
|
||||
curr_waiter->actual_events = flags->events;
|
||||
|
||||
_vcos_thread_sem_post(curr_waiter->thread);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* move to next element in the list */
|
||||
prev_waiter = *pcurrent_waiter;
|
||||
pcurrent_waiter = &(curr_waiter->next);
|
||||
}
|
||||
}
|
||||
|
||||
flags->events &= ~consumed_events;
|
||||
|
||||
}
|
||||
|
||||
vcos_mutex_unlock(&flags->lock);
|
||||
}
|
||||
|
||||
void vcos_generic_event_flags_delete(VCOS_EVENT_FLAGS_T *flags)
|
||||
{
|
||||
vcos_mutex_delete(&flags->lock);
|
||||
}
|
||||
|
||||
extern VCOS_STATUS_T vcos_generic_event_flags_get(VCOS_EVENT_FLAGS_T *flags,
|
||||
VCOS_UNSIGNED bitmask,
|
||||
VCOS_OPTION op,
|
||||
VCOS_UNSIGNED suspend,
|
||||
VCOS_UNSIGNED *retrieved_bits)
|
||||
{
|
||||
VCOS_EVENT_WAITER_T waitreq;
|
||||
VCOS_STATUS_T rc = VCOS_EAGAIN;
|
||||
int satisfied = 0;
|
||||
|
||||
vcos_assert(flags);
|
||||
|
||||
/* default retrieved bits to 0 */
|
||||
*retrieved_bits = 0;
|
||||
|
||||
vcos_mutex_lock(&flags->lock);
|
||||
switch (op & VCOS_EVENT_FLAG_OP_MASK)
|
||||
{
|
||||
case VCOS_AND:
|
||||
if ((flags->events & bitmask) == bitmask)
|
||||
{
|
||||
*retrieved_bits = flags->events;
|
||||
rc = VCOS_SUCCESS;
|
||||
satisfied = 1;
|
||||
if (op & VCOS_CONSUME)
|
||||
flags->events &= ~bitmask;
|
||||
}
|
||||
break;
|
||||
|
||||
case VCOS_OR:
|
||||
if (flags->events & bitmask)
|
||||
{
|
||||
*retrieved_bits = flags->events;
|
||||
rc = VCOS_SUCCESS;
|
||||
satisfied = 1;
|
||||
if (op & VCOS_CONSUME)
|
||||
flags->events &= ~bitmask;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
vcos_assert(0);
|
||||
rc = VCOS_EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!satisfied && suspend)
|
||||
{
|
||||
/* Have to go to sleep.
|
||||
*
|
||||
* Append to tail so we get FIFO ordering.
|
||||
*/
|
||||
waitreq.requested_events = bitmask;
|
||||
waitreq.op = op;
|
||||
waitreq.return_status = VCOS_EAGAIN;
|
||||
waitreq.flags = flags;
|
||||
waitreq.actual_events = 0;
|
||||
waitreq.thread = vcos_thread_current();
|
||||
waitreq.next = 0;
|
||||
vcos_assert(waitreq.thread != (VCOS_THREAD_T*)-1);
|
||||
VCOS_QUEUE_APPEND_TAIL(&flags->waiters, &waitreq);
|
||||
|
||||
if (suspend != (VCOS_UNSIGNED)-1)
|
||||
_vcos_task_timer_set(event_flags_timer_expired, &waitreq, suspend);
|
||||
|
||||
vcos_mutex_unlock(&flags->lock);
|
||||
/* go to sleep and wait to be signalled or timeout */
|
||||
|
||||
_vcos_thread_sem_wait();
|
||||
|
||||
*retrieved_bits = waitreq.actual_events;
|
||||
rc = waitreq.return_status;
|
||||
|
||||
/* cancel the timer - do not do this while holding the mutex as it
|
||||
* might be waiting for the timeout function to complete, which will
|
||||
* try to take the mutex.
|
||||
*/
|
||||
if (suspend != (VCOS_UNSIGNED)-1)
|
||||
_vcos_task_timer_cancel();
|
||||
}
|
||||
else
|
||||
{
|
||||
vcos_mutex_unlock(&flags->lock);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/** Called when a get call times out. Remove this thread's
|
||||
* entry from the waiting queue, then resume the thread.
|
||||
*/
|
||||
static void event_flags_timer_expired(void *cxt)
|
||||
{
|
||||
VCOS_EVENT_WAITER_T *waitreq = (VCOS_EVENT_WAITER_T *)cxt;
|
||||
VCOS_EVENT_FLAGS_T *flags = waitreq->flags;
|
||||
VCOS_EVENT_WAITER_T **plist;
|
||||
VCOS_EVENT_WAITER_T *prev = NULL;
|
||||
VCOS_THREAD_T *thread = 0;
|
||||
|
||||
vcos_assert(flags);
|
||||
|
||||
vcos_mutex_lock(&flags->lock);
|
||||
|
||||
/* walk the list of waiting threads on this event group, and remove
|
||||
* the one that has expired.
|
||||
*
|
||||
* FIXME: could use doubly-linked list if lots of threads are found
|
||||
* to be waiting on a single event flag instance.
|
||||
*/
|
||||
plist = &flags->waiters.head;
|
||||
while (*plist != NULL)
|
||||
{
|
||||
if (*plist == waitreq)
|
||||
{
|
||||
int at_end;
|
||||
/* found it */
|
||||
thread = (*plist)->thread;
|
||||
at_end = ((*plist)->next == NULL);
|
||||
|
||||
/* link past */
|
||||
*plist = (*plist)->next;
|
||||
if (at_end)
|
||||
flags->waiters.tail = prev;
|
||||
|
||||
break;
|
||||
}
|
||||
prev = *plist;
|
||||
plist = &(*plist)->next;
|
||||
}
|
||||
vcos_assert(waiter_list_valid(flags));
|
||||
|
||||
vcos_mutex_unlock(&flags->lock);
|
||||
|
||||
if (thread)
|
||||
{
|
||||
_vcos_thread_sem_post(thread);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
static int waiter_list_valid(VCOS_EVENT_FLAGS_T *flags)
|
||||
{
|
||||
int valid;
|
||||
/* Either both head and tail are NULL, or neither are NULL */
|
||||
if (flags->waiters.head == NULL)
|
||||
{
|
||||
valid = (flags->waiters.tail == NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = (flags->waiters.tail != NULL);
|
||||
}
|
||||
|
||||
/* If head and tail point at the same non-NULL element, then there
|
||||
* is only one element in the list.
|
||||
*/
|
||||
if (flags->waiters.head && (flags->waiters.head == flags->waiters.tail))
|
||||
{
|
||||
valid = (flags->waiters.head->next == NULL);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
#endif
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - event flags implemented via a semaphore
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef VCOS_GENERIC_EVENT_FLAGS_H
|
||||
#define VCOS_GENERIC_EVENT_FLAGS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vcos_types.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* This provides event flags (as per Nucleus Event Groups) based on a
|
||||
* mutex, a semaphore (per waiting thread) and a timer (per waiting
|
||||
* thread).
|
||||
*
|
||||
* The data structure is a 32 bit unsigned int (the current set of
|
||||
* flags) and a linked list of clients waiting to be 'satisfied'.
|
||||
*
|
||||
* The mutex merely locks access to the data structure. If a client
|
||||
* calls vcos_event_flags_get() and the requested bits are not already
|
||||
* present, it then sleeps on its per-thread semaphore after adding
|
||||
* this semaphore to the queue waiting. It also sets up a timer.
|
||||
*
|
||||
* The per-thread semaphore and timer are actually stored in the
|
||||
* thread context (joinable thread). In future it may become necessary
|
||||
* to support non-VCOS threads by using thread local storage to
|
||||
* create these objects and associate them with the thread.
|
||||
*/
|
||||
|
||||
struct VCOS_EVENT_WAITER_T;
|
||||
|
||||
typedef struct VCOS_EVENT_FLAGS_T
|
||||
{
|
||||
VCOS_UNSIGNED events; /**< Events currently set */
|
||||
VCOS_MUTEX_T lock; /**< Serialize access */
|
||||
struct
|
||||
{
|
||||
struct VCOS_EVENT_WAITER_T *head; /**< List of threads waiting */
|
||||
struct VCOS_EVENT_WAITER_T *tail; /**< List of threads waiting */
|
||||
} waiters;
|
||||
} VCOS_EVENT_FLAGS_T;
|
||||
|
||||
#define VCOS_OR 1
|
||||
#define VCOS_AND 2
|
||||
#define VCOS_CONSUME 4
|
||||
#define VCOS_OR_CONSUME (VCOS_OR | VCOS_CONSUME)
|
||||
#define VCOS_AND_CONSUME (VCOS_AND | VCOS_CONSUME)
|
||||
#define VCOS_EVENT_FLAG_OP_MASK (VCOS_OR|VCOS_AND)
|
||||
|
||||
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_generic_event_flags_create(VCOS_EVENT_FLAGS_T *flags, const char *name);
|
||||
VCOSPRE_ void VCOSPOST_ vcos_generic_event_flags_set(VCOS_EVENT_FLAGS_T *flags,
|
||||
VCOS_UNSIGNED events,
|
||||
VCOS_OPTION op);
|
||||
VCOSPRE_ void VCOSPOST_ vcos_generic_event_flags_delete(VCOS_EVENT_FLAGS_T *);
|
||||
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_generic_event_flags_get(VCOS_EVENT_FLAGS_T *flags,
|
||||
VCOS_UNSIGNED requested_events,
|
||||
VCOS_OPTION op,
|
||||
VCOS_UNSIGNED suspend,
|
||||
VCOS_UNSIGNED *retrieved_events);
|
||||
|
||||
#ifdef VCOS_INLINE_BODIES
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_event_flags_create(VCOS_EVENT_FLAGS_T *flags, const char *name) {
|
||||
return vcos_generic_event_flags_create(flags, name);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_event_flags_set(VCOS_EVENT_FLAGS_T *flags,
|
||||
VCOS_UNSIGNED events,
|
||||
VCOS_OPTION op) {
|
||||
vcos_generic_event_flags_set(flags, events, op);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_event_flags_delete(VCOS_EVENT_FLAGS_T *f) {
|
||||
vcos_generic_event_flags_delete(f);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_event_flags_get(VCOS_EVENT_FLAGS_T *flags,
|
||||
VCOS_UNSIGNED requested_events,
|
||||
VCOS_OPTION op,
|
||||
VCOS_UNSIGNED suspend,
|
||||
VCOS_UNSIGNED *retrieved_events) {
|
||||
return vcos_generic_event_flags_get(flags, requested_events, op, suspend, retrieved_events);
|
||||
}
|
||||
|
||||
#endif /* VCOS_INLINE_BODIES */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
+268
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define VCOS_LOG_CATEGORY (&vcos_named_sem_log_cat)
|
||||
|
||||
#include "interface/vcos/vcos.h"
|
||||
#include "interface/vcos/generic/vcos_generic_named_sem.h"
|
||||
#include "interface/vcos/vcos_blockpool.h"
|
||||
|
||||
#if defined(VCOS_LOGGING_ENABLED)
|
||||
static VCOS_LOG_CAT_T vcos_named_sem_log_cat =
|
||||
VCOS_LOG_INIT("vcos_named_sem", VCOS_LOG_ERROR);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Named semaphores, primarily for VCFW.
|
||||
*
|
||||
* Does not actually work across processes; merely emulate the API.
|
||||
*
|
||||
* The client initialises a VCOS_NAMED_SEMAPHORE_T, but this merely
|
||||
* points at the real underlying VCOS_NAMED_SEMAPHORE_IMPL_T.
|
||||
*
|
||||
* semaphore_t ---\
|
||||
* ----- semaphore_impl_t
|
||||
* semaphore_t ---/
|
||||
* /
|
||||
* semaphore_t -/
|
||||
*
|
||||
*/
|
||||
|
||||
/* Maintain a block pool of semaphore implementations */
|
||||
#define NUM_SEMS 16
|
||||
|
||||
/* Allow the pool to expand to MAX_SEMS in size */
|
||||
#define MAX_SEMS 512
|
||||
|
||||
/** Each actual real semaphore is stored in one of these. Clients just
|
||||
* get a structure with a pointer to this in it.
|
||||
*
|
||||
* It also contains a doubly linked list tracking the semaphores in-use.
|
||||
*/
|
||||
typedef struct VCOS_NAMED_SEMAPHORE_IMPL_T
|
||||
{
|
||||
VCOS_SEMAPHORE_T sem; /**< Actual underlying semaphore */
|
||||
char name[VCOS_NAMED_SEMAPHORE_NAMELEN]; /**< Name of semaphore, copied */
|
||||
unsigned refs; /**< Reference count */
|
||||
struct VCOS_NAMED_SEMAPHORE_IMPL_T *next; /**< Next in the in-use list */
|
||||
struct VCOS_NAMED_SEMAPHORE_IMPL_T *prev; /**< Previous in the in-use list */
|
||||
} VCOS_NAMED_SEMAPHORE_IMPL_T;
|
||||
|
||||
static VCOS_MUTEX_T lock;
|
||||
static VCOS_NAMED_SEMAPHORE_IMPL_T* sems_in_use = NULL;
|
||||
static int sems_in_use_count = 0;
|
||||
static int sems_total_ref_count = 0;
|
||||
|
||||
static VCOS_BLOCKPOOL_T sems_pool;
|
||||
static char pool_mem[VCOS_BLOCKPOOL_SIZE(
|
||||
NUM_SEMS, sizeof(VCOS_NAMED_SEMAPHORE_IMPL_T), VCOS_BLOCKPOOL_ALIGN_DEFAULT)];
|
||||
|
||||
VCOS_STATUS_T _vcos_named_semaphore_init()
|
||||
{
|
||||
VCOS_STATUS_T status;
|
||||
|
||||
status = vcos_blockpool_init(&sems_pool,
|
||||
NUM_SEMS, sizeof(VCOS_NAMED_SEMAPHORE_IMPL_T),
|
||||
pool_mem, sizeof(pool_mem),
|
||||
VCOS_BLOCKPOOL_ALIGN_DEFAULT, 0, "vcos named semaphores");
|
||||
|
||||
if (status != VCOS_SUCCESS)
|
||||
goto fail_blockpool;
|
||||
|
||||
status = vcos_blockpool_extend(&sems_pool, VCOS_BLOCKPOOL_MAX_SUBPOOLS - 1,
|
||||
(MAX_SEMS - NUM_SEMS) / (VCOS_BLOCKPOOL_MAX_SUBPOOLS - 1));
|
||||
if (status != VCOS_SUCCESS)
|
||||
goto fail_extend;
|
||||
|
||||
status = vcos_mutex_create(&lock, "vcosnmsem");
|
||||
if (status != VCOS_SUCCESS)
|
||||
goto fail_mutex;
|
||||
|
||||
return status;
|
||||
|
||||
fail_mutex:
|
||||
fail_extend:
|
||||
vcos_blockpool_delete(&sems_pool);
|
||||
fail_blockpool:
|
||||
return status;
|
||||
}
|
||||
|
||||
void _vcos_named_semaphore_deinit(void)
|
||||
{
|
||||
vcos_blockpool_delete(&sems_pool);
|
||||
vcos_mutex_delete(&lock);
|
||||
sems_in_use = NULL;
|
||||
}
|
||||
|
||||
VCOS_STATUS_T
|
||||
vcos_generic_named_semaphore_create(VCOS_NAMED_SEMAPHORE_T *sem,
|
||||
const char *name, VCOS_UNSIGNED count)
|
||||
{
|
||||
VCOS_STATUS_T status = VCOS_ENOSPC;
|
||||
int name_len, cmp = -1;
|
||||
VCOS_NAMED_SEMAPHORE_IMPL_T *impl;
|
||||
VCOS_NAMED_SEMAPHORE_IMPL_T *new_impl;
|
||||
|
||||
vcos_log_trace("%s: sem %p name %s count %d", __FUNCTION__,
|
||||
sem, (name ? name : "null"), count);
|
||||
|
||||
vcos_assert(name);
|
||||
|
||||
vcos_mutex_lock(&lock);
|
||||
name_len = vcos_strlen(name);
|
||||
if (name_len >= VCOS_NAMED_SEMAPHORE_NAMELEN)
|
||||
{
|
||||
vcos_assert(0);
|
||||
status = VCOS_EINVAL;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* do we already have this semaphore? */
|
||||
impl = sems_in_use;
|
||||
while (impl && (cmp = vcos_strcmp(name, impl->name)) < 0)
|
||||
impl = impl->next;
|
||||
|
||||
if (impl && cmp == 0)
|
||||
{
|
||||
/* Semaphore is already in use so just increase the ref count */
|
||||
impl->refs++;
|
||||
sems_total_ref_count++;
|
||||
sem->actual = impl;
|
||||
sem->sem = &impl->sem;
|
||||
status = VCOS_SUCCESS;
|
||||
vcos_log_trace(
|
||||
"%s: ref count %d name %s total refs %d num sems %d",
|
||||
__FUNCTION__, impl->refs, impl->name,
|
||||
sems_total_ref_count, sems_in_use_count);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* search for unused semaphore */
|
||||
new_impl = vcos_blockpool_calloc(&sems_pool);
|
||||
if (new_impl)
|
||||
{
|
||||
status = vcos_semaphore_create(&new_impl->sem, name, count);
|
||||
if (status == VCOS_SUCCESS)
|
||||
{
|
||||
new_impl->refs = 1;
|
||||
sems_total_ref_count++;
|
||||
sems_in_use_count++;
|
||||
memcpy(new_impl->name, name, name_len + 1); /* already checked length! */
|
||||
sem->actual = new_impl;
|
||||
sem->sem = &new_impl->sem;
|
||||
|
||||
/* Insert into the sorted list
|
||||
* impl is either NULL or the first element where
|
||||
* name > impl->name.
|
||||
*/
|
||||
if (impl)
|
||||
{
|
||||
new_impl->prev = impl->prev;
|
||||
impl->prev = new_impl;
|
||||
new_impl->next = impl;
|
||||
|
||||
if (new_impl->prev)
|
||||
new_impl->prev->next = new_impl;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Appending to the tail of the list / empty list */
|
||||
VCOS_NAMED_SEMAPHORE_IMPL_T *tail = sems_in_use;
|
||||
while(tail && tail->next)
|
||||
tail = tail->next;
|
||||
|
||||
if (tail)
|
||||
{
|
||||
tail->next = new_impl;
|
||||
new_impl->prev = tail;
|
||||
}
|
||||
}
|
||||
|
||||
if (sems_in_use == impl)
|
||||
{
|
||||
/* Inserted at head or list was empty */
|
||||
sems_in_use = new_impl;
|
||||
}
|
||||
|
||||
vcos_log_trace(
|
||||
"%s: new ref actual %p prev %p next %p count %d name %s " \
|
||||
"total refs %d num sems %d",
|
||||
__FUNCTION__,
|
||||
new_impl, new_impl->prev, new_impl->next,
|
||||
new_impl->refs, new_impl->name,
|
||||
sems_total_ref_count, sems_in_use_count);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
vcos_mutex_unlock(&lock);
|
||||
if (status != VCOS_SUCCESS)
|
||||
{
|
||||
vcos_log_error("%s: failed to create named semaphore name %s status %d " \
|
||||
"total refs %d num sems %d",
|
||||
__FUNCTION__, (name ? name : "NULL"), status,
|
||||
sems_total_ref_count, sems_in_use_count);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void vcos_named_semaphore_delete(VCOS_NAMED_SEMAPHORE_T *sem)
|
||||
{
|
||||
VCOS_NAMED_SEMAPHORE_IMPL_T *actual = sem->actual;
|
||||
vcos_mutex_lock(&lock);
|
||||
|
||||
/* if this fires, the semaphore has already been deleted */
|
||||
vcos_assert(actual->refs);
|
||||
|
||||
vcos_log_trace(
|
||||
"%s: actual %p ref count %d name %s prev %p next %p total refs %d num sems %d",
|
||||
__FUNCTION__, actual, actual->refs, actual->name,
|
||||
actual->prev, actual->next,
|
||||
sems_total_ref_count, sems_in_use_count);
|
||||
|
||||
sems_total_ref_count--;
|
||||
if (--actual->refs == 0)
|
||||
{
|
||||
sems_in_use_count--;
|
||||
if (actual->prev)
|
||||
actual->prev->next = actual->next;
|
||||
|
||||
if (actual->next)
|
||||
actual->next->prev = actual->prev;
|
||||
|
||||
if (sems_in_use == actual)
|
||||
sems_in_use = actual->next;
|
||||
|
||||
vcos_semaphore_delete(&actual->sem);
|
||||
sem->actual = NULL;
|
||||
sem->sem = NULL;
|
||||
vcos_blockpool_free(actual);
|
||||
}
|
||||
vcos_mutex_unlock(&lock);
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - named semaphores
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef VCOS_GENERIC_NAMED_SEM_H
|
||||
#define VCOS_GENERIC_NAMED_SEM_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vcos_types.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Generic support for named semaphores, using regular ones. This is only
|
||||
* suitable for emulating them on an embedded MMUless system, since there is
|
||||
* no support for opening semaphores across process boundaries.
|
||||
*
|
||||
*/
|
||||
|
||||
#define VCOS_NAMED_SEMAPHORE_NAMELEN 64
|
||||
|
||||
/* In theory we could use the name facility provided within Nucleus. However, this
|
||||
* is hard to do as semaphores are constantly being created and destroyed; we
|
||||
* would need to stop everything while allocating the memory for the semaphore
|
||||
* list and then walking it. So keep our own list.
|
||||
*/
|
||||
typedef struct VCOS_NAMED_SEMAPHORE_T
|
||||
{
|
||||
struct VCOS_NAMED_SEMAPHORE_IMPL_T *actual; /**< There are 'n' named semaphores per 1 actual semaphore */
|
||||
VCOS_SEMAPHORE_T *sem; /**< Pointer to actual underlying semaphore */
|
||||
} VCOS_NAMED_SEMAPHORE_T;
|
||||
|
||||
VCOSPRE_ VCOS_STATUS_T VCOSPOST_
|
||||
vcos_generic_named_semaphore_create(VCOS_NAMED_SEMAPHORE_T *sem, const char *name, VCOS_UNSIGNED count);
|
||||
|
||||
VCOSPRE_ void VCOSPOST_ vcos_named_semaphore_delete(VCOS_NAMED_SEMAPHORE_T *sem);
|
||||
|
||||
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ _vcos_named_semaphore_init(void);
|
||||
VCOSPRE_ void VCOSPOST_ _vcos_named_semaphore_deinit(void);
|
||||
|
||||
#if defined(VCOS_INLINE_BODIES)
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_named_semaphore_create(VCOS_NAMED_SEMAPHORE_T *sem, const char *name, VCOS_UNSIGNED count) {
|
||||
return vcos_generic_named_semaphore_create(sem, name, count);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_named_semaphore_wait(VCOS_NAMED_SEMAPHORE_T *sem) {
|
||||
vcos_semaphore_wait(sem->sem);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_named_semaphore_trywait(VCOS_NAMED_SEMAPHORE_T *sem) {
|
||||
return vcos_semaphore_trywait(sem->sem);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_named_semaphore_post(VCOS_NAMED_SEMAPHORE_T *sem) {
|
||||
vcos_semaphore_post(sem->sem);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - reentrant mutexes created from regular ones.
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef VCOS_GENERIC_QUICKSLOW_MUTEX_H
|
||||
#define VCOS_GENERIC_QUICKSLOW_MUTEX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vcos_types.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Quickslow Mutexes implemented as regular ones (i.e. quick and slow modes are the same).
|
||||
*
|
||||
*/
|
||||
|
||||
typedef VCOS_MUTEX_T VCOS_QUICKSLOW_MUTEX_T;
|
||||
|
||||
#if defined(VCOS_INLINE_BODIES)
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_quickslow_mutex_create(VCOS_QUICKSLOW_MUTEX_T *m, const char *name)
|
||||
{
|
||||
return vcos_mutex_create(m, name);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_quickslow_mutex_delete(VCOS_QUICKSLOW_MUTEX_T *m)
|
||||
{
|
||||
vcos_mutex_delete(m);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_quickslow_mutex_lock(VCOS_QUICKSLOW_MUTEX_T *m)
|
||||
{
|
||||
while (vcos_mutex_lock(m) == VCOS_EAGAIN);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_quickslow_mutex_unlock(VCOS_QUICKSLOW_MUTEX_T *m)
|
||||
{
|
||||
vcos_mutex_unlock(m);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_quickslow_mutex_lock_quick(VCOS_QUICKSLOW_MUTEX_T *m)
|
||||
{
|
||||
while (vcos_mutex_lock(m) == VCOS_EAGAIN);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_quickslow_mutex_unlock_quick(VCOS_QUICKSLOW_MUTEX_T *m)
|
||||
{
|
||||
vcos_mutex_unlock(m);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "interface/vcos/vcos.h"
|
||||
#include "interface/vcos/vcos_reentrant_mutex.h"
|
||||
|
||||
VCOS_STATUS_T vcos_generic_reentrant_mutex_create(VCOS_REENTRANT_MUTEX_T *m, const char *name)
|
||||
{
|
||||
m->count = 0;
|
||||
m->owner = 0;
|
||||
return vcos_mutex_create(&m->mutex, name);
|
||||
}
|
||||
|
||||
void vcos_generic_reentrant_mutex_delete(VCOS_REENTRANT_MUTEX_T *m)
|
||||
{
|
||||
vcos_assert(m->count == 0);
|
||||
vcos_mutex_delete(&m->mutex);
|
||||
}
|
||||
|
||||
void vcos_generic_reentrant_mutex_lock(VCOS_REENTRANT_MUTEX_T *m)
|
||||
{
|
||||
VCOS_THREAD_T *thread = vcos_thread_current();
|
||||
vcos_assert(m);
|
||||
|
||||
vcos_assert(thread != 0);
|
||||
|
||||
if (m->owner != thread)
|
||||
{
|
||||
vcos_mutex_lock(&m->mutex);
|
||||
m->owner = thread;
|
||||
vcos_assert(m->count == 0);
|
||||
}
|
||||
m->count++;
|
||||
}
|
||||
|
||||
void vcos_generic_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m)
|
||||
{
|
||||
vcos_assert(m->count != 0);
|
||||
vcos_assert(m->owner == vcos_thread_current());
|
||||
m->count--;
|
||||
if (m->count == 0)
|
||||
{
|
||||
m->owner = 0;
|
||||
vcos_mutex_unlock(&m->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - reentrant mutexes created from regular ones.
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef VCOS_GENERIC_REENTRANT_MUTEX_H
|
||||
#define VCOS_GENERIC_REENTRANT_MUTEX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "vcos_types.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Reentrant Mutexes from regular ones.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct VCOS_REENTRANT_MUTEX_T
|
||||
{
|
||||
VCOS_MUTEX_T mutex;
|
||||
VCOS_THREAD_T *owner;
|
||||
unsigned count;
|
||||
} VCOS_REENTRANT_MUTEX_T;
|
||||
|
||||
/* Extern definitions of functions that do the actual work */
|
||||
|
||||
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_generic_reentrant_mutex_create(VCOS_REENTRANT_MUTEX_T *m, const char *name);
|
||||
|
||||
VCOSPRE_ void VCOSPOST_ vcos_generic_reentrant_mutex_delete(VCOS_REENTRANT_MUTEX_T *m);
|
||||
|
||||
VCOSPRE_ void VCOSPOST_ vcos_generic_reentrant_mutex_lock(VCOS_REENTRANT_MUTEX_T *m);
|
||||
|
||||
VCOSPRE_ void VCOSPOST_ vcos_generic_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m);
|
||||
|
||||
/* Inline forwarding functions */
|
||||
|
||||
#if defined(VCOS_INLINE_BODIES)
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_reentrant_mutex_create(VCOS_REENTRANT_MUTEX_T *m, const char *name) {
|
||||
return vcos_generic_reentrant_mutex_create(m,name);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_reentrant_mutex_delete(VCOS_REENTRANT_MUTEX_T *m) {
|
||||
vcos_generic_reentrant_mutex_delete(m);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_reentrant_mutex_lock(VCOS_REENTRANT_MUTEX_T *m) {
|
||||
vcos_generic_reentrant_mutex_lock(m);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m) {
|
||||
vcos_generic_reentrant_mutex_unlock(m);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*****************************************************************************
|
||||
* Copyright 2012 Broadcom Corporation. All rights reserved.
|
||||
*
|
||||
* This program is the proprietary software of Broadcom Corporation and/or
|
||||
* its licensors, and may only be used, duplicated, modified or distributed
|
||||
* pursuant to the terms and conditions of a separate, written license
|
||||
* agreement executed between you and Broadcom (an "Authorized License").
|
||||
* Except as set forth in an Authorized License, Broadcom grants no license
|
||||
* (express or implied), right to use, or waiver of any kind with respect to
|
||||
* the Software, and Broadcom expressly reserves all rights in and to the
|
||||
* Software and all intellectual property rights therein. IF YOU HAVE NO
|
||||
* AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY
|
||||
* WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE ALL USE OF
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* Except as expressly set forth in the Authorized License,
|
||||
* 1. This program, including its structure, sequence and organization,
|
||||
* constitutes the valuable trade secrets of Broadcom, and you shall use
|
||||
* all reasonable efforts to protect the confidentiality thereof, and to
|
||||
* use this information only in connection with your use of Broadcom
|
||||
* integrated circuit products.
|
||||
* 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
|
||||
* AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
|
||||
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
|
||||
* RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL
|
||||
* IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS,
|
||||
* QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. YOU
|
||||
* ASSUME THE ENTIRE RISK ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE.
|
||||
* 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS
|
||||
* LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT,
|
||||
* OR EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO
|
||||
* YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS
|
||||
* OF THE AMOUNT ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER
|
||||
* IS GREATER. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF
|
||||
* ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "interface/vcos/vcos.h"
|
||||
|
||||
#if defined( __KERNEL__ )
|
||||
#include <linux/string.h>
|
||||
#include <linux/module.h>
|
||||
#else
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
/** Like vsnprintf, except it places the output at the specified offset.
|
||||
* Output is truncated to fit in buflen bytes, and is guaranteed to be NUL-terminated.
|
||||
* Returns the string length before/without truncation.
|
||||
*/
|
||||
size_t vcos_safe_vsprintf(char *buf, size_t buflen, size_t offset, const char *fmt, va_list ap)
|
||||
{
|
||||
size_t space = (offset < buflen) ? (buflen - offset) : 0;
|
||||
|
||||
offset += vcos_vsnprintf(buf ? (buf + offset) : NULL, space, fmt, ap);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/** Like snprintf, except it places the output at the specified offset.
|
||||
* Output is truncated to fit in buflen bytes, and is guaranteed to be NUL-terminated.
|
||||
* Returns the string length before/without truncation.
|
||||
*/
|
||||
size_t vcos_safe_sprintf(char *buf, size_t buflen, size_t offset, const char *fmt, ...)
|
||||
{
|
||||
size_t space = (offset < buflen) ? (buflen - offset) : 0;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
offset += vcos_vsnprintf(buf ? (buf + offset) : NULL, space, fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/** Copies string src to dst at the specified offset.
|
||||
* Output is truncated to fit in dstlen bytes, i.e. the string is at most
|
||||
* (buflen - 1) characters long. Unlike strncpy, exactly one NUL is written
|
||||
* to dst, which is always NUL-terminated.
|
||||
* Returns the string length before/without truncation.
|
||||
*/
|
||||
size_t vcos_safe_strcpy(char *dst, const char *src, size_t dstlen, size_t offset)
|
||||
{
|
||||
if (offset < dstlen)
|
||||
{
|
||||
const char *p = src;
|
||||
char *endp = dst + dstlen -1;
|
||||
|
||||
dst += offset;
|
||||
|
||||
for (; *p!='\0' && dst != endp; dst++, p++)
|
||||
*dst = *p;
|
||||
*dst = '\0';
|
||||
}
|
||||
offset += strlen(src);
|
||||
|
||||
return offset;
|
||||
}
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - generic thread local storage
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef VCOS_GENERIC_TLS_H
|
||||
#define VCOS_GENERIC_TLS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "interface/vcos/vcos_types.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Do an emulation of Thread Local Storage. The platform needs to
|
||||
* provide a way to set and get a per-thread pointer which is
|
||||
* where the TLS data itself is stored.
|
||||
*
|
||||
*
|
||||
* Each thread that wants to join in this scheme needs to call
|
||||
* vcos_tls_thread_register().
|
||||
*
|
||||
* The platform needs to support the macros/functions
|
||||
* _vcos_tls_thread_ptr_set() and _vcos_tls_thread_ptr_get().
|
||||
*/
|
||||
|
||||
#ifndef VCOS_WANT_TLS_EMULATION
|
||||
#error Should not be included unless TLS emulation is defined
|
||||
#endif
|
||||
|
||||
/** Number of slots to reserve per thread. This results in an overhead
|
||||
* of this many words per thread.
|
||||
*/
|
||||
#define VCOS_TLS_MAX_SLOTS 4
|
||||
|
||||
/** TLS key. Allocating one of these reserves the client one of the
|
||||
* available slots.
|
||||
*/
|
||||
typedef VCOS_UNSIGNED VCOS_TLS_KEY_T;
|
||||
|
||||
/** TLS per-thread structure. Each thread gets one of these
|
||||
* if TLS emulation (rather than native TLS support) is
|
||||
* being used.
|
||||
*/
|
||||
typedef struct VCOS_TLS_THREAD_T
|
||||
{
|
||||
void *slots[VCOS_TLS_MAX_SLOTS];
|
||||
} VCOS_TLS_THREAD_T;
|
||||
|
||||
/*
|
||||
* Internal APIs
|
||||
*/
|
||||
|
||||
/** Register this thread's TLS storage area. */
|
||||
VCOSPRE_ void VCOSPOST_ vcos_tls_thread_register(VCOS_TLS_THREAD_T *);
|
||||
|
||||
/** Create a new TLS key */
|
||||
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_generic_tls_create(VCOS_TLS_KEY_T *key);
|
||||
|
||||
/** Delete a TLS key */
|
||||
VCOSPRE_ void VCOSPOST_ vcos_generic_tls_delete(VCOS_TLS_KEY_T tls);
|
||||
|
||||
/** Initialise the TLS library */
|
||||
VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_tls_init(void);
|
||||
|
||||
/** Deinitialise the TLS library */
|
||||
VCOSPRE_ void VCOSPOST_ vcos_tls_deinit(void);
|
||||
|
||||
#if defined(VCOS_INLINE_BODIES)
|
||||
|
||||
#undef VCOS_ASSERT_LOGGING_DISABLE
|
||||
#define VCOS_ASSERT_LOGGING_DISABLE 1
|
||||
|
||||
/*
|
||||
* Implementations of public API functions
|
||||
*/
|
||||
|
||||
/** Set the given value. Since everything is per-thread, there is no need
|
||||
* for any locking.
|
||||
*/
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_tls_set(VCOS_TLS_KEY_T tls, void *v) {
|
||||
VCOS_TLS_THREAD_T *tlsdata = _vcos_tls_thread_ptr_get();
|
||||
vcos_assert(tlsdata); /* Fires if this thread has not been registered */
|
||||
if (tls<VCOS_TLS_MAX_SLOTS)
|
||||
{
|
||||
tlsdata->slots[tls] = v;
|
||||
return VCOS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
vcos_assert(0);
|
||||
return VCOS_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/** Get the given value. No locking required.
|
||||
*/
|
||||
VCOS_INLINE_IMPL
|
||||
void *vcos_tls_get(VCOS_TLS_KEY_T tls) {
|
||||
VCOS_TLS_THREAD_T *tlsdata = _vcos_tls_thread_ptr_get();
|
||||
vcos_assert(tlsdata); /* Fires if this thread has not been registered */
|
||||
if (tls<VCOS_TLS_MAX_SLOTS)
|
||||
{
|
||||
return tlsdata->slots[tls];
|
||||
}
|
||||
else
|
||||
{
|
||||
vcos_assert(0);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_tls_create(VCOS_TLS_KEY_T *key) {
|
||||
return vcos_generic_tls_create(key);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_tls_delete(VCOS_TLS_KEY_T tls) {
|
||||
vcos_generic_tls_delete(tls);
|
||||
}
|
||||
|
||||
#undef VCOS_ASSERT_LOGGING_DISABLE
|
||||
#define VCOS_ASSERT_LOGGING_DISABLE 0
|
||||
|
||||
#endif /* VCOS_INLINE_BODIES */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
The following header is included in order to provide one instance of the symbol vcos_deprecated_code.
|
||||
Any other inclusions of this header (or "vcos_deprecated_code.inc" for assembly language) will cause the linker to warn
|
||||
about multiple definitions of vcos_deprecated_code.
|
||||
The idea is to include this header file for the source files which are deprecated.
|
||||
Therefore the above warnning in a build indicates that the build is using deprecated code!
|
||||
Contact the person named in the accompanying comment for advice - do not remove the inclusion.
|
||||
*/
|
||||
#include "vcos_deprecated.h"
|
||||
|
||||
#include "interface/vcos/vcos.h"
|
||||
|
||||
static int init_refcount;
|
||||
|
||||
VCOS_STATUS_T vcos_init(void)
|
||||
{
|
||||
VCOS_STATUS_T st = VCOS_SUCCESS;
|
||||
|
||||
vcos_global_lock();
|
||||
|
||||
if (init_refcount++ == 0)
|
||||
st = vcos_platform_init();
|
||||
|
||||
vcos_global_unlock();
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
void vcos_deinit(void)
|
||||
{
|
||||
vcos_global_lock();
|
||||
|
||||
vcos_assert(init_refcount > 0);
|
||||
|
||||
if (init_refcount > 0 && --init_refcount == 0)
|
||||
vcos_platform_deinit();
|
||||
|
||||
vcos_global_unlock();
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 2)
|
||||
|
||||
void vcos_ctor(void) __attribute__((constructor, used));
|
||||
|
||||
void vcos_ctor(void)
|
||||
{
|
||||
vcos_init();
|
||||
}
|
||||
|
||||
void vcos_dtor(void) __attribute__((destructor, used));
|
||||
|
||||
void vcos_dtor(void)
|
||||
{
|
||||
vcos_deinit();
|
||||
}
|
||||
|
||||
#endif
|
||||
Vendored
+229
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - implementation: joinable thread from plain
|
||||
=============================================================================*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* Header file for platforms creating the joinable thread from a lowlevel
|
||||
* thread.
|
||||
*
|
||||
* In addition to the actual thread, the following are also created:
|
||||
*
|
||||
* - a semaphore to wait on when joining the thread
|
||||
* - a semaphore to support counted suspend/resume (used by event group)
|
||||
* - a per-thread timer (used by event group, but could be removed)
|
||||
*/
|
||||
|
||||
#ifndef VCOS_JOINABLE_THREAD_FROM_PLAIN_H
|
||||
#define VCOS_JOINABLE_THREAD_FROM_PLAIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef VCOS_SEMAPHORE_H
|
||||
#include "interface/vcos/vcos_semaphore.h"
|
||||
#endif
|
||||
#ifndef VCOS_LOWLEVEL_THREAD_H
|
||||
#include "interface/vcos/vcos_lowlevel_thread.h"
|
||||
#endif
|
||||
#ifndef VCOS_TIMER_H
|
||||
#include "interface/vcos/vcos_timer.h"
|
||||
#endif
|
||||
|
||||
#ifdef VCOS_WANT_TLS_EMULATION
|
||||
#include "interface/vcos/generic/vcos_generic_tls.h"
|
||||
#endif
|
||||
|
||||
#define VCOS_THREAD_MAGIC 0x56436a74
|
||||
|
||||
#define VCOS_THREAD_VALID(t) (t->magic == VCOS_THREAD_MAGIC)
|
||||
#define VCOS_HAVE_THREAD_AT_EXIT 1
|
||||
|
||||
/** Thread attribute structure. Clients should not manipulate this directly, but
|
||||
* should instead use the provided functions.
|
||||
*/
|
||||
typedef struct VCOS_THREAD_ATTR_T
|
||||
{
|
||||
void *ta_stackaddr;
|
||||
VCOS_UNSIGNED ta_stacksz;
|
||||
VCOS_UNSIGNED ta_priority;
|
||||
VCOS_UNSIGNED ta_affinity;
|
||||
VCOS_UNSIGNED ta_timeslice;
|
||||
VCOS_UNSIGNED legacy;
|
||||
VCOS_UNSIGNED ta_autostart;
|
||||
} VCOS_THREAD_ATTR_T;
|
||||
|
||||
/** Each thread gets a timer, which is for internal VCOS use.
|
||||
*/
|
||||
typedef struct _VCOS_THREAD_TIMER_T
|
||||
{
|
||||
VCOS_TIMER_T timer;
|
||||
void (*pfn)(void *);
|
||||
void *cxt;
|
||||
} _VCOS_THREAD_TIMER_T;
|
||||
|
||||
typedef void (*VCOS_THREAD_EXIT_HANDLER_T)(void *);
|
||||
/** Called at thread exit.
|
||||
*/
|
||||
typedef struct VCOS_THREAD_EXIT_T
|
||||
{
|
||||
VCOS_THREAD_EXIT_HANDLER_T pfn;
|
||||
void *cxt;
|
||||
} VCOS_THREAD_EXIT_T;
|
||||
#define VCOS_MAX_EXIT_HANDLERS 8
|
||||
|
||||
/* The name field isn't used for anything, so we can just copy the
|
||||
* the pointer. Nucleus makes its own copy.
|
||||
*/
|
||||
typedef const char * VCOS_LLTHREAD_T_NAME;
|
||||
#define _VCOS_LLTHREAD_NAME(dst,src) (dst)=(src)
|
||||
|
||||
/*
|
||||
* Simulated TLS support
|
||||
*/
|
||||
|
||||
|
||||
/** Thread structure.
|
||||
*
|
||||
* \warning Do not access the members of this structure directly!
|
||||
*/
|
||||
typedef struct VCOS_THREAD_T
|
||||
{
|
||||
VCOS_LLTHREAD_T thread; /**< The underlying thread */
|
||||
char name[16]; /**< The name */
|
||||
unsigned int magic; /**< For debug */
|
||||
void *exit_data; /**< Exit data passed out in vcos_joinable_thread_exit() */
|
||||
void *stack; /**< Stack, if not supplied by caller */
|
||||
VCOS_SEMAPHORE_T wait; /**< Semaphore to wait on at join */
|
||||
VCOS_SEMAPHORE_T suspend; /**< Semaphore to wait on for counted suspend */
|
||||
int16_t joined; /**< Joined yet? For debug. */
|
||||
VCOS_UNSIGNED legacy; /**< Use (argc,argv) for entry point arguments */
|
||||
void *(*entry)(void*); /**< Entry point */
|
||||
void *arg; /**< Argument passed to entry point */
|
||||
void *(*term)(void*); /**< Termination function, used by reaper */
|
||||
void *term_arg; /**< Argument passed to termination function */
|
||||
_VCOS_THREAD_TIMER_T _timer; /**< Internal timer, mainly for event groups */
|
||||
#ifdef VCOS_WANT_TLS_EMULATION
|
||||
VCOS_TLS_THREAD_T _tls; /**< TLS data when native TLS not available, or NULL */
|
||||
#endif
|
||||
/** Array of functions to call at thread exit */
|
||||
VCOS_THREAD_EXIT_T at_exit[VCOS_MAX_EXIT_HANDLERS];
|
||||
|
||||
struct VCOS_THREAD_T *next; /**< For linked lists of threads */
|
||||
} VCOS_THREAD_T;
|
||||
|
||||
#if defined(VCOS_INLINE_BODIES)
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_thread_attr_setstack(VCOS_THREAD_ATTR_T *attrs, void *addr, VCOS_UNSIGNED stacksz) {
|
||||
attrs->ta_stackaddr = addr;
|
||||
attrs->ta_stacksz = stacksz;
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_thread_attr_setstacksize(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED stacksz) {
|
||||
attrs->ta_stacksz = stacksz;
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_thread_attr_setpriority(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED pri) {
|
||||
attrs->ta_priority = pri;
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_thread_attr_setaffinity(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED affinity) {
|
||||
attrs->ta_affinity = affinity;
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_thread_attr_settimeslice(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED ts) {
|
||||
attrs->ta_timeslice = ts;
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void _vcos_thread_attr_setlegacyapi(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED legacy) {
|
||||
attrs->legacy = legacy;
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_thread_attr_setautostart(VCOS_THREAD_ATTR_T *attrs, VCOS_UNSIGNED autostart) {
|
||||
attrs->ta_autostart = autostart;
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_THREAD_T *vcos_thread_current(void) {
|
||||
VCOS_THREAD_T *ret = (VCOS_THREAD_T*)vcos_llthread_current();
|
||||
/*If we're called from a non-vcos thread, this assert will fail.
|
||||
*XXX FIXME why is this commented out?
|
||||
*vcos_assert(ret->magic == VCOS_THREAD_MAGIC);
|
||||
*/
|
||||
return ret;
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
int vcos_thread_running(VCOS_THREAD_T *thread) {
|
||||
return vcos_llthread_running(&thread->thread);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_thread_resume(VCOS_THREAD_T *thread) {
|
||||
vcos_llthread_resume(&thread->thread);
|
||||
}
|
||||
|
||||
#endif /* VCOS_INLINE_BODIES */
|
||||
|
||||
/**
|
||||
* \brief Create a VCOS_THREAD_T for the current thread. This is so we can have
|
||||
* VCOS_THREAD_Ts even for threads not originally created by VCOS (eg the
|
||||
* thread that calls vcos_init)
|
||||
*/
|
||||
extern VCOS_STATUS_T _vcos_thread_create_attach(VCOS_THREAD_T *thread,
|
||||
const char *name);
|
||||
|
||||
/**
|
||||
* \brief Deletes the VCOS_THREAD_T, but does not wait for the underlying
|
||||
* thread to exit. This will cleanup everything created by
|
||||
* _vcos_thread_create_attach
|
||||
*/
|
||||
extern void _vcos_thread_delete(VCOS_THREAD_T *thread);
|
||||
|
||||
/** Register a function to be called when the current thread exits.
|
||||
*/
|
||||
extern VCOS_STATUS_T vcos_thread_at_exit(void (*pfn)(void*), void *cxt);
|
||||
|
||||
/** Deregister a previously registered at-exit function.
|
||||
*/
|
||||
extern void vcos_thread_deregister_at_exit(void (*pfn)(void*), void *cxt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* VCOS_JOINABLE_THREAD_FROM_PLAIN_H */
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - Construct a latch from a semaphore
|
||||
=============================================================================*/
|
||||
|
||||
/** FIXME: rename to vcos_mutex_from_sem.c
|
||||
*/
|
||||
|
||||
typedef struct VCOS_MUTEX_T {
|
||||
VCOS_SEMAPHORE_T sem;
|
||||
struct VCOS_THREAD_T *owner;
|
||||
} VCOS_MUTEX_T;
|
||||
|
||||
extern VCOS_STATUS_T vcos_generic_mutex_create(VCOS_MUTEX_T *latch, const char *name);
|
||||
extern void vcos_generic_mutex_delete(VCOS_MUTEX_T *latch);
|
||||
extern VCOS_STATUS_T vcos_generic_mutex_lock(VCOS_MUTEX_T *latch);
|
||||
extern void vcos_generic_mutex_unlock(VCOS_MUTEX_T *latch);
|
||||
|
||||
#if defined(VCOS_INLINE_BODIES)
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_mutex_create(VCOS_MUTEX_T *latch, const char *name) {
|
||||
return vcos_generic_mutex_create(latch,name);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_mutex_delete(VCOS_MUTEX_T *latch) {
|
||||
vcos_generic_mutex_delete(latch);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_mutex_lock(VCOS_MUTEX_T *latch) {
|
||||
return vcos_generic_mutex_lock(latch);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_mutex_unlock(VCOS_MUTEX_T *latch) {
|
||||
vcos_generic_mutex_unlock(latch);
|
||||
}
|
||||
|
||||
#endif /* VCOS_INLINE_BODIES */
|
||||
|
||||
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
Categorized logging for VCOS - a generic implementation.
|
||||
=============================================================================*/
|
||||
|
||||
#include "interface/vcos/vcos.h"
|
||||
#include "interface/vcos/vcos_ctype.h"
|
||||
#include "interface/vcos/vcos_string.h"
|
||||
#include "interface/vcos/vcos_inttypes.h"
|
||||
|
||||
static VCOS_MUTEX_T lock;
|
||||
static int warned_loglevel; /* only warn about invalid log level once */
|
||||
static VCOS_VLOG_IMPL_FUNC_T vcos_vlog_impl_func = vcos_vlog_default_impl;
|
||||
|
||||
#define VCOS_LOG_CATEGORY (&dflt_log_category)
|
||||
static VCOS_LOG_CAT_T dflt_log_category;
|
||||
VCOS_LOG_CAT_T *vcos_logging_categories = NULL;
|
||||
static int inited;
|
||||
|
||||
#if VCOS_HAVE_CMD
|
||||
|
||||
/*
|
||||
* For kernel or videocore purposes, we generally want the log command. For
|
||||
* user-space apps, they might want to provide their own log command, so we
|
||||
* don't include the built in on.
|
||||
*
|
||||
* So pthreads/vcos_platform.h defines VCOS_WANT_LOG_CMD to be 0. It is
|
||||
* undefined elsewhere.
|
||||
*/
|
||||
|
||||
# if !defined( VCOS_WANT_LOG_CMD )
|
||||
# define VCOS_WANT_LOG_CMD 1
|
||||
# endif
|
||||
#else
|
||||
# define VCOS_WANT_LOG_CMD 0
|
||||
#endif
|
||||
|
||||
/* For now, do not link logging categories into linked lists
|
||||
* as it breaks when people unload shared libraries without
|
||||
* getting the counts right.
|
||||
*/
|
||||
#ifdef __VIDEOCORE__
|
||||
#define REGISTER_CATEGORIES 1
|
||||
#else
|
||||
#define REGISTER_CATEGORIES 0
|
||||
#endif
|
||||
|
||||
#if VCOS_WANT_LOG_CMD
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Does a vcos_assert(0), which is useful to test logging.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
VCOS_STATUS_T vcos_log_assert_cmd( VCOS_CMD_PARAM_T *param )
|
||||
{
|
||||
(void)param;
|
||||
|
||||
#if defined( NDEBUG ) && !defined( VCOS_RELEASE_ASSERTS )
|
||||
vcos_log_error( "vcos_asserts have been compiled out" );
|
||||
vcos_cmd_printf( param, "vcos_asserts have been compiled out - did a vcos_log_error instead\n" );
|
||||
#else
|
||||
vcos_assert(0);
|
||||
vcos_cmd_printf( param, "Executed vcos_assert(0)\n" );
|
||||
#endif
|
||||
|
||||
return VCOS_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Sets a vcos logging level
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
VCOS_STATUS_T vcos_log_set_cmd( VCOS_CMD_PARAM_T *param )
|
||||
{
|
||||
VCOS_LOG_CAT_T *cat;
|
||||
char *name;
|
||||
char *levelStr;
|
||||
VCOS_LOG_LEVEL_T level;
|
||||
VCOS_STATUS_T status;
|
||||
|
||||
if ( param->argc != 3 )
|
||||
{
|
||||
vcos_cmd_usage( param );
|
||||
return VCOS_EINVAL;
|
||||
}
|
||||
|
||||
name = param->argv[1];
|
||||
levelStr = param->argv[2];
|
||||
|
||||
if ( vcos_string_to_log_level( levelStr, &level ) != VCOS_SUCCESS )
|
||||
{
|
||||
vcos_cmd_printf( param, "Unrecognized logging level: '%s'\n", levelStr );
|
||||
return VCOS_EINVAL;
|
||||
}
|
||||
|
||||
vcos_mutex_lock(&lock);
|
||||
|
||||
status = VCOS_SUCCESS;
|
||||
for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next )
|
||||
{
|
||||
if ( vcos_strcmp( name, cat->name ) == 0 )
|
||||
{
|
||||
cat->level = level;
|
||||
vcos_cmd_printf( param, "Category %s level set to %s\n", name, levelStr );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( cat == NULL )
|
||||
{
|
||||
vcos_cmd_printf( param, "Unrecognized category: '%s'\n", name );
|
||||
status = VCOS_ENOENT;
|
||||
}
|
||||
|
||||
vcos_mutex_unlock(&lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Prints out the current settings for a given category (or all cvategories)
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
VCOS_STATUS_T vcos_log_status_cmd( VCOS_CMD_PARAM_T *param )
|
||||
{
|
||||
VCOS_LOG_CAT_T *cat;
|
||||
VCOS_STATUS_T status;
|
||||
|
||||
vcos_mutex_lock(&lock);
|
||||
|
||||
if ( param->argc == 1)
|
||||
{
|
||||
int nw;
|
||||
int nameWidth = 0;
|
||||
|
||||
/* Print information about all of the categories. */
|
||||
|
||||
for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next )
|
||||
{
|
||||
nw = (int)strlen( cat->name );
|
||||
|
||||
if ( nw > nameWidth )
|
||||
{
|
||||
nameWidth = nw;
|
||||
}
|
||||
}
|
||||
|
||||
for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next )
|
||||
{
|
||||
vcos_cmd_printf( param, "%-*s - %s\n", nameWidth, cat->name, vcos_log_level_to_string( cat->level ));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Print information about a particular category */
|
||||
|
||||
for ( cat = vcos_logging_categories; cat != NULL; cat = cat->next )
|
||||
{
|
||||
if ( vcos_strcmp( cat->name, param->argv[1] ) == 0 )
|
||||
{
|
||||
vcos_cmd_printf( param, "%s - %s\n", cat->name, vcos_log_level_to_string( cat->level ));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( cat == NULL )
|
||||
{
|
||||
vcos_cmd_printf( param, "Unrecognized logging category: '%s'\n", param->argv[1] );
|
||||
status = VCOS_ENOENT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
status = VCOS_SUCCESS;
|
||||
out:
|
||||
vcos_mutex_unlock(&lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Prints out the current settings for a given category (or all cvategories)
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
VCOS_STATUS_T vcos_log_test_cmd( VCOS_CMD_PARAM_T *param )
|
||||
{
|
||||
if ( param->argc == 1 )
|
||||
{
|
||||
static int seq_num = 100;
|
||||
|
||||
/* No additional arguments - generate a message with an incrementing number */
|
||||
|
||||
vcos_log_error( "Test message %d", seq_num );
|
||||
|
||||
seq_num++;
|
||||
vcos_cmd_printf( param, "Logged 'Test message %d'\n", seq_num );
|
||||
}
|
||||
else
|
||||
{
|
||||
int arg_idx;
|
||||
|
||||
/* Arguments supplied - log these */
|
||||
|
||||
for ( arg_idx = 0; arg_idx < param->argc; arg_idx++ )
|
||||
{
|
||||
vcos_log_error( "argv[%d] = '%s'", arg_idx, param->argv[arg_idx] );
|
||||
}
|
||||
vcos_cmd_printf( param, "Logged %d line(s) of test data\n", param->argc );
|
||||
}
|
||||
return VCOS_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* Internal commands
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static VCOS_CMD_T log_cmd_entry[] =
|
||||
{
|
||||
{ "assert", "", vcos_log_assert_cmd, NULL, "Does a vcos_assert(0) to test logging" },
|
||||
{ "set", "category level", vcos_log_set_cmd, NULL, "Sets the vcos logging level for a category" },
|
||||
{ "status", "[category]", vcos_log_status_cmd, NULL, "Prints the vcos log status for a (or all) categories" },
|
||||
{ "test", "[arbitrary text]", vcos_log_test_cmd, NULL, "Does a vcos_log to test logging" },
|
||||
|
||||
{ NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
static VCOS_CMD_T cmd_log =
|
||||
{ "log", "command [args]", NULL, log_cmd_entry, "Commands related to vcos logging" };
|
||||
|
||||
#endif
|
||||
|
||||
void vcos_logging_init(void)
|
||||
{
|
||||
if (inited)
|
||||
{
|
||||
/* FIXME: should print a warning or something here */
|
||||
return;
|
||||
}
|
||||
vcos_mutex_create(&lock, "vcos_log");
|
||||
|
||||
vcos_log_platform_init();
|
||||
|
||||
vcos_log_register("default", &dflt_log_category);
|
||||
|
||||
#if VCOS_WANT_LOG_CMD
|
||||
vcos_cmd_register( &cmd_log );
|
||||
#endif
|
||||
|
||||
vcos_assert(!inited);
|
||||
inited = 1;
|
||||
}
|
||||
|
||||
/** Read an alphanumeric token, returning True if we succeeded.
|
||||
*/
|
||||
|
||||
static int read_tok(char *tok, size_t toklen, const char **pstr, char sep)
|
||||
{
|
||||
const char *str = *pstr;
|
||||
size_t n = 0;
|
||||
char ch;
|
||||
|
||||
/* skip past any whitespace */
|
||||
while (str[0] && isspace((int)(str[0])))
|
||||
str++;
|
||||
|
||||
while ((ch = *str) != '\0' &&
|
||||
ch != sep &&
|
||||
(isalnum((int)ch) || (ch == '_')) &&
|
||||
n != toklen-1)
|
||||
{
|
||||
tok[n++] = ch;
|
||||
str++;
|
||||
}
|
||||
|
||||
/* did it work out? */
|
||||
if (ch == '\0' || ch == sep)
|
||||
{
|
||||
if (ch) str++; /* move to next token if not at end */
|
||||
/* yes */
|
||||
tok[n] = '\0';
|
||||
*pstr = str;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const char *vcos_log_level_to_string( VCOS_LOG_LEVEL_T level )
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case VCOS_LOG_UNINITIALIZED: return "uninit";
|
||||
case VCOS_LOG_NEVER: return "never";
|
||||
case VCOS_LOG_ERROR: return "error";
|
||||
case VCOS_LOG_WARN: return "warn";
|
||||
case VCOS_LOG_INFO: return "info";
|
||||
case VCOS_LOG_TRACE: return "trace";
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
|
||||
VCOS_STATUS_T vcos_string_to_log_level( const char *str, VCOS_LOG_LEVEL_T *level )
|
||||
{
|
||||
if (strcmp(str,"error") == 0)
|
||||
*level = VCOS_LOG_ERROR;
|
||||
else if (strcmp(str,"never") == 0)
|
||||
*level = VCOS_LOG_NEVER;
|
||||
else if (strcmp(str,"warn") == 0)
|
||||
*level = VCOS_LOG_WARN;
|
||||
else if (strcmp(str,"warning") == 0)
|
||||
*level = VCOS_LOG_WARN;
|
||||
else if (strcmp(str,"info") == 0)
|
||||
*level = VCOS_LOG_INFO;
|
||||
else if (strcmp(str,"trace") == 0)
|
||||
*level = VCOS_LOG_TRACE;
|
||||
else
|
||||
return VCOS_EINVAL;
|
||||
|
||||
return VCOS_SUCCESS;
|
||||
}
|
||||
|
||||
static int read_level(VCOS_LOG_LEVEL_T *level, const char **pstr, char sep)
|
||||
{
|
||||
char buf[16];
|
||||
int ret = 1;
|
||||
if (read_tok(buf,sizeof(buf),pstr,sep))
|
||||
{
|
||||
if (vcos_string_to_log_level(buf,level) != VCOS_SUCCESS)
|
||||
{
|
||||
vcos_log("Invalid trace level '%s'\n", buf);
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vcos_log_register(const char *name, VCOS_LOG_CAT_T *category)
|
||||
{
|
||||
const char *env;
|
||||
VCOS_LOG_CAT_T *i;
|
||||
|
||||
category->name = name;
|
||||
if ( category->level == VCOS_LOG_UNINITIALIZED )
|
||||
{
|
||||
category->level = VCOS_LOG_ERROR;
|
||||
}
|
||||
category->flags.want_prefix = (category != &dflt_log_category );
|
||||
|
||||
if (!REGISTER_CATEGORIES)
|
||||
return;
|
||||
|
||||
vcos_mutex_lock(&lock);
|
||||
|
||||
/* is it already registered? */
|
||||
for (i = vcos_logging_categories; i ; i = i->next )
|
||||
{
|
||||
if (i == category)
|
||||
{
|
||||
i->refcount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!i)
|
||||
{
|
||||
/* not yet registered */
|
||||
category->next = vcos_logging_categories;
|
||||
vcos_logging_categories = category;
|
||||
category->refcount++;
|
||||
|
||||
vcos_log_platform_register(category);
|
||||
}
|
||||
|
||||
vcos_mutex_unlock(&lock);
|
||||
|
||||
/* Check to see if this log level has been enabled. Look for
|
||||
* (<category:level>,)*
|
||||
*
|
||||
* VC_LOGLEVEL=ilcs:info,vchiq:warn
|
||||
*/
|
||||
|
||||
env = _VCOS_LOG_LEVEL();
|
||||
if (env)
|
||||
{
|
||||
do
|
||||
{
|
||||
char env_name[64];
|
||||
VCOS_LOG_LEVEL_T level;
|
||||
if (read_tok(env_name, sizeof(env_name), &env, ':') &&
|
||||
read_level(&level, &env, ','))
|
||||
{
|
||||
if (strcmp(env_name, name) == 0)
|
||||
{
|
||||
category->level = level;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!warned_loglevel)
|
||||
{
|
||||
vcos_log("VC_LOGLEVEL format invalid at %s\n", env);
|
||||
warned_loglevel = 1;
|
||||
}
|
||||
return;
|
||||
}
|
||||
} while (env[0] != '\0');
|
||||
}
|
||||
|
||||
vcos_log_info( "Registered log category '%s' with level %s",
|
||||
category->name,
|
||||
vcos_log_level_to_string( category->level ));
|
||||
}
|
||||
|
||||
void vcos_log_unregister(VCOS_LOG_CAT_T *category)
|
||||
{
|
||||
VCOS_LOG_CAT_T **pcat;
|
||||
|
||||
if (!REGISTER_CATEGORIES)
|
||||
return;
|
||||
|
||||
vcos_mutex_lock(&lock);
|
||||
category->refcount--;
|
||||
if (category->refcount == 0)
|
||||
{
|
||||
pcat = &vcos_logging_categories;
|
||||
while (*pcat != category)
|
||||
{
|
||||
if (!*pcat)
|
||||
break; /* possibly deregistered twice? */
|
||||
if ((*pcat)->next == NULL)
|
||||
{
|
||||
vcos_assert(0); /* already removed! */
|
||||
vcos_mutex_unlock(&lock);
|
||||
return;
|
||||
}
|
||||
pcat = &(*pcat)->next;
|
||||
}
|
||||
if (*pcat)
|
||||
*pcat = category->next;
|
||||
|
||||
vcos_log_platform_unregister(category);
|
||||
}
|
||||
vcos_mutex_unlock(&lock);
|
||||
}
|
||||
|
||||
VCOSPRE_ const VCOS_LOG_CAT_T * VCOSPOST_ vcos_log_get_default_category(void)
|
||||
{
|
||||
return &dflt_log_category;
|
||||
}
|
||||
|
||||
void vcos_set_log_options(const char *opt)
|
||||
{
|
||||
(void)opt;
|
||||
}
|
||||
|
||||
void vcos_log_dump_mem_impl( const VCOS_LOG_CAT_T *cat,
|
||||
const char *label,
|
||||
uint32_t addr,
|
||||
const void *voidMem,
|
||||
size_t numBytes )
|
||||
{
|
||||
const uint8_t *mem = (const uint8_t *)voidMem;
|
||||
size_t offset;
|
||||
char lineBuf[ 100 ];
|
||||
char *s;
|
||||
|
||||
while ( numBytes > 0 )
|
||||
{
|
||||
s = lineBuf;
|
||||
|
||||
for ( offset = 0; offset < 16; offset++ )
|
||||
{
|
||||
if ( offset < numBytes )
|
||||
{
|
||||
s += vcos_snprintf( s, 4, "%02x ", mem[ offset ]);
|
||||
}
|
||||
else
|
||||
{
|
||||
s += vcos_snprintf( s, 4, " " );
|
||||
}
|
||||
}
|
||||
|
||||
for ( offset = 0; offset < 16; offset++ )
|
||||
{
|
||||
if ( offset < numBytes )
|
||||
{
|
||||
uint8_t ch = mem[ offset ];
|
||||
|
||||
if (( ch < ' ' ) || ( ch > '~' ))
|
||||
{
|
||||
ch = '.';
|
||||
}
|
||||
*s++ = (char)ch;
|
||||
}
|
||||
}
|
||||
*s++ = '\0';
|
||||
|
||||
if (( label != NULL ) && ( *label != '\0' ))
|
||||
{
|
||||
vcos_log_impl( cat, VCOS_LOG_INFO, "%s: %08" PRIx32 ": %s", label, addr, lineBuf );
|
||||
}
|
||||
else
|
||||
{
|
||||
vcos_log_impl( cat, VCOS_LOG_INFO, "%08" PRIx32 ": %s", addr, lineBuf );
|
||||
}
|
||||
|
||||
addr += 16;
|
||||
mem += 16;
|
||||
if ( numBytes > 16 )
|
||||
{
|
||||
numBytes -= 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
numBytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void vcos_log_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap,fmt);
|
||||
vcos_vlog_impl( cat, _level, fmt, ap );
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void vcos_vlog_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args)
|
||||
{
|
||||
vcos_vlog_impl_func( cat, _level, fmt, args );
|
||||
}
|
||||
|
||||
void vcos_set_vlog_impl( VCOS_VLOG_IMPL_FUNC_T vlog_impl_func )
|
||||
{
|
||||
if ( vlog_impl_func == NULL )
|
||||
{
|
||||
vcos_vlog_impl_func = vcos_vlog_default_impl;
|
||||
}
|
||||
else
|
||||
{
|
||||
vcos_vlog_impl_func = vlog_impl_func;
|
||||
}
|
||||
}
|
||||
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - memory alloc implementation
|
||||
=============================================================================*/
|
||||
|
||||
#include "interface/vcos/vcos.h"
|
||||
|
||||
#ifndef _vcos_platform_malloc
|
||||
#include <stdlib.h>
|
||||
#define _vcos_platform_malloc malloc
|
||||
#define _vcos_platform_free free
|
||||
#endif
|
||||
|
||||
typedef struct malloc_header_s {
|
||||
uint32_t guardword;
|
||||
uint32_t size;
|
||||
const char *description;
|
||||
void *ptr;
|
||||
} MALLOC_HEADER_T;
|
||||
|
||||
|
||||
#define MIN_ALIGN sizeof(MALLOC_HEADER_T)
|
||||
|
||||
#define GUARDWORDHEAP 0xa55a5aa5
|
||||
|
||||
void *vcos_generic_mem_alloc_aligned(VCOS_UNSIGNED size, VCOS_UNSIGNED align, const char *desc)
|
||||
{
|
||||
int local_align = align == 0 ? 1 : align;
|
||||
int required_size = size + local_align + sizeof(MALLOC_HEADER_T);
|
||||
void *ptr = _vcos_platform_malloc(required_size);
|
||||
void *ret = NULL;
|
||||
MALLOC_HEADER_T *h;
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
ret = (void *)VCOS_ALIGN_UP(((char *)ptr)+sizeof(MALLOC_HEADER_T), local_align);
|
||||
h = ((MALLOC_HEADER_T *)ret)-1;
|
||||
h->size = size;
|
||||
h->description = desc;
|
||||
h->guardword = GUARDWORDHEAP;
|
||||
h->ptr = ptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *vcos_generic_mem_alloc(VCOS_UNSIGNED size, const char *desc)
|
||||
{
|
||||
return vcos_generic_mem_alloc_aligned(size,MIN_ALIGN,desc);
|
||||
}
|
||||
|
||||
void *vcos_generic_mem_calloc(VCOS_UNSIGNED count, VCOS_UNSIGNED sz, const char *desc)
|
||||
{
|
||||
uint32_t size = count*sz;
|
||||
void *ptr = vcos_generic_mem_alloc_aligned(size,MIN_ALIGN,desc);
|
||||
if (ptr)
|
||||
{
|
||||
memset(ptr, 0, size);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void vcos_generic_mem_free(void *ptr)
|
||||
{
|
||||
MALLOC_HEADER_T *h;
|
||||
if (! ptr) return;
|
||||
|
||||
h = ((MALLOC_HEADER_T *)ptr)-1;
|
||||
vcos_assert(h->guardword == GUARDWORDHEAP);
|
||||
_vcos_platform_free(h->ptr);
|
||||
}
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
Create the vcos_malloc API from the regular system malloc/free
|
||||
=============================================================================*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Create the vcos malloc API from a regular system malloc/free library.
|
||||
*
|
||||
* The API lets callers specify an alignment.
|
||||
*
|
||||
* Under VideoCore this is not needed, as we can simply use the rtos_malloc routines.
|
||||
* But on host platforms that won't be the case.
|
||||
*
|
||||
*/
|
||||
|
||||
VCOSPRE_ void * VCOSPOST_ vcos_generic_mem_alloc(VCOS_UNSIGNED sz, const char *desc);
|
||||
VCOSPRE_ void * VCOSPOST_ vcos_generic_mem_calloc(VCOS_UNSIGNED count, VCOS_UNSIGNED sz, const char *descr);
|
||||
VCOSPRE_ void VCOSPOST_ vcos_generic_mem_free(void *ptr);
|
||||
VCOSPRE_ void * VCOSPOST_ vcos_generic_mem_alloc_aligned(VCOS_UNSIGNED sz, VCOS_UNSIGNED align, const char *desc);
|
||||
|
||||
#ifdef VCOS_INLINE_BODIES
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void *vcos_malloc(VCOS_UNSIGNED size, const char *description) {
|
||||
return vcos_generic_mem_alloc(size, description);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void *vcos_calloc(VCOS_UNSIGNED num, VCOS_UNSIGNED size, const char *description) {
|
||||
return vcos_generic_mem_calloc(num, size, description);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_free(void *ptr) {
|
||||
vcos_generic_mem_free(ptr);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void * vcos_malloc_aligned(VCOS_UNSIGNED size, VCOS_UNSIGNED align, const char *description) {
|
||||
return vcos_generic_mem_alloc_aligned(size, align, description);
|
||||
}
|
||||
|
||||
|
||||
#endif /* VCOS_INLINE_BODIES */
|
||||
|
||||
|
||||
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "vcos.h"
|
||||
#include "vcos_msgqueue.h"
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define MAGIC VCOS_MSGQ_MAGIC
|
||||
|
||||
/* Probably a good idea for MSG_T to be multiple of 8 so that doubles
|
||||
* are naturally aligned without problem.
|
||||
*/
|
||||
vcos_static_assert((sizeof(VCOS_MSG_T) & 7) == 0);
|
||||
|
||||
static void vcos_msgq_pool_on_reply(VCOS_MSG_WAITER_T *waiter,
|
||||
VCOS_MSG_T *msg);
|
||||
static void vcos_msgq_queue_waiter_on_reply(VCOS_MSG_WAITER_T *waiter,
|
||||
VCOS_MSG_T *msg);
|
||||
|
||||
/** Simple reply protocol. The client creates a semaphore and waits
|
||||
* for it. No queuing of multiple replies is possible but nothing needs
|
||||
* to be setup in advance. Because creating semaphores is very fast on
|
||||
* VideoCore there's no need to do anything elaborate to optimize create
|
||||
* time - this might need revisiting on other platforms.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
VCOS_MSG_WAITER_T waiter;
|
||||
VCOS_SEMAPHORE_T waitsem;
|
||||
} VCOS_MSG_SIMPLE_WAITER_T;
|
||||
|
||||
static void vcos_msgq_simple_waiter_on_reply(VCOS_MSG_WAITER_T *waiter,
|
||||
VCOS_MSG_T *msg)
|
||||
{
|
||||
VCOS_MSG_SIMPLE_WAITER_T *self;
|
||||
(void)msg;
|
||||
self = (VCOS_MSG_SIMPLE_WAITER_T*)waiter;
|
||||
vcos_semaphore_post(&self->waitsem);
|
||||
}
|
||||
|
||||
static VCOS_STATUS_T vcos_msgq_simple_waiter_init(VCOS_MSG_SIMPLE_WAITER_T *waiter)
|
||||
{
|
||||
VCOS_STATUS_T status;
|
||||
status = vcos_semaphore_create(&waiter->waitsem, "waiter", 0);
|
||||
waiter->waiter.on_reply = vcos_msgq_simple_waiter_on_reply;
|
||||
return status;
|
||||
}
|
||||
|
||||
static void vcos_msgq_simple_waiter_deinit(VCOS_MSG_SIMPLE_WAITER_T *waiter)
|
||||
{
|
||||
vcos_semaphore_delete(&waiter->waitsem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Message queues
|
||||
*/
|
||||
|
||||
static VCOS_STATUS_T vcos_msgq_create_internal(VCOS_MSGQUEUE_T *q, const char *name)
|
||||
{
|
||||
VCOS_STATUS_T st;
|
||||
|
||||
memset(q, 0, sizeof(*q));
|
||||
|
||||
q->waiter.on_reply = vcos_msgq_queue_waiter_on_reply;
|
||||
st = vcos_semaphore_create(&q->sem, name, 0);
|
||||
if (st != VCOS_SUCCESS)
|
||||
goto fail_sem;
|
||||
|
||||
st = vcos_mutex_create(&q->lock, name);
|
||||
if (st != VCOS_SUCCESS)
|
||||
goto fail_mtx;
|
||||
|
||||
return st;
|
||||
|
||||
fail_mtx:
|
||||
vcos_semaphore_delete(&q->sem);
|
||||
fail_sem:
|
||||
return st;
|
||||
}
|
||||
|
||||
static void vcos_msgq_delete_internal(VCOS_MSGQUEUE_T *q)
|
||||
{
|
||||
vcos_semaphore_delete(&q->sem);
|
||||
vcos_mutex_delete(&q->lock);
|
||||
}
|
||||
|
||||
VCOS_STATUS_T vcos_msgq_create(VCOS_MSGQUEUE_T *q, const char *name)
|
||||
{
|
||||
VCOS_STATUS_T st;
|
||||
|
||||
st = vcos_msgq_create_internal(q, name);
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
void vcos_msgq_delete(VCOS_MSGQUEUE_T *q)
|
||||
{
|
||||
vcos_msgq_delete_internal(q);
|
||||
}
|
||||
|
||||
/* append a message to a message queue */
|
||||
static _VCOS_INLINE void msgq_append(VCOS_MSGQUEUE_T *q, VCOS_MSG_T *msg)
|
||||
{
|
||||
vcos_mutex_lock(&q->lock);
|
||||
if (q->head == NULL)
|
||||
{
|
||||
q->head = q->tail = msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
q->tail->next = msg;
|
||||
q->tail = msg;
|
||||
}
|
||||
vcos_mutex_unlock(&q->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* A waiter for a message queue. Just appends the message to the
|
||||
* queue, waking up the waiting thread.
|
||||
*/
|
||||
static void vcos_msgq_queue_waiter_on_reply(VCOS_MSG_WAITER_T *waiter,
|
||||
VCOS_MSG_T *msg)
|
||||
{
|
||||
VCOS_MSGQUEUE_T *queue = (VCOS_MSGQUEUE_T*)waiter;
|
||||
msgq_append(queue, msg);
|
||||
vcos_semaphore_post(&queue->sem);
|
||||
}
|
||||
|
||||
/* initialise this library */
|
||||
|
||||
VCOS_STATUS_T vcos_msgq_init(void)
|
||||
{
|
||||
return VCOS_SUCCESS;
|
||||
}
|
||||
|
||||
void vcos_msgq_deinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
static _VCOS_INLINE
|
||||
void vcos_msg_send_helper(VCOS_MSG_WAITER_T *waiter,
|
||||
VCOS_MSGQUEUE_T *dest,
|
||||
uint32_t code,
|
||||
VCOS_MSG_T *msg)
|
||||
{
|
||||
vcos_assert(msg);
|
||||
vcos_assert(dest);
|
||||
|
||||
msg->code = code;
|
||||
if (waiter)
|
||||
msg->waiter = waiter;
|
||||
msg->next = NULL;
|
||||
msg->src_thread = vcos_thread_current();
|
||||
|
||||
msgq_append(dest, msg);
|
||||
vcos_semaphore_post(&dest->sem);
|
||||
}
|
||||
|
||||
/* wait on a queue for a message */
|
||||
VCOS_MSG_T *vcos_msg_wait(VCOS_MSGQUEUE_T *queue)
|
||||
{
|
||||
VCOS_MSG_T *msg;
|
||||
vcos_semaphore_wait(&queue->sem);
|
||||
vcos_mutex_lock(&queue->lock);
|
||||
|
||||
msg = queue->head;
|
||||
vcos_assert(msg); /* should always be a message here! */
|
||||
|
||||
queue->head = msg->next;
|
||||
if (queue->head == NULL)
|
||||
queue->tail = NULL;
|
||||
|
||||
vcos_mutex_unlock(&queue->lock);
|
||||
return msg;
|
||||
}
|
||||
|
||||
/* peek on a queue for a message */
|
||||
VCOS_MSG_T *vcos_msg_peek(VCOS_MSGQUEUE_T *queue)
|
||||
{
|
||||
VCOS_MSG_T *msg;
|
||||
vcos_mutex_lock(&queue->lock);
|
||||
|
||||
msg = queue->head;
|
||||
|
||||
/* if there's a message, remove it from the queue */
|
||||
if (msg)
|
||||
{
|
||||
queue->head = msg->next;
|
||||
if (queue->head == NULL)
|
||||
queue->tail = NULL;
|
||||
|
||||
/* keep the semaphore count consistent */
|
||||
|
||||
/* coverity[lock_order]
|
||||
* the semaphore must have a non-zero count so cannot block here.
|
||||
*/
|
||||
vcos_semaphore_wait(&queue->sem);
|
||||
}
|
||||
|
||||
vcos_mutex_unlock(&queue->lock);
|
||||
return msg;
|
||||
}
|
||||
|
||||
void vcos_msg_send(VCOS_MSGQUEUE_T *dest, uint32_t code, VCOS_MSG_T *msg)
|
||||
{
|
||||
vcos_assert(msg->magic == MAGIC);
|
||||
vcos_msg_send_helper(NULL, dest, code, msg);
|
||||
}
|
||||
|
||||
/** Send on to the target queue, then wait on a simple waiter for the reply
|
||||
*/
|
||||
VCOS_STATUS_T vcos_msg_sendwait(VCOS_MSGQUEUE_T *dest, uint32_t code, VCOS_MSG_T *msg)
|
||||
{
|
||||
VCOS_STATUS_T st;
|
||||
VCOS_MSG_SIMPLE_WAITER_T waiter;
|
||||
|
||||
vcos_assert(msg->magic == MAGIC);
|
||||
|
||||
/* if this fires, you've set a waiter up but are now about to obliterate it
|
||||
* with the 'wait for a reply' waiter.
|
||||
*/
|
||||
vcos_assert(msg->waiter == NULL);
|
||||
|
||||
if ((st=vcos_msgq_simple_waiter_init(&waiter)) != VCOS_SUCCESS)
|
||||
return st;
|
||||
|
||||
vcos_msg_send_helper(&waiter.waiter, dest, code, msg);
|
||||
vcos_semaphore_wait(&waiter.waitsem);
|
||||
vcos_msgq_simple_waiter_deinit(&waiter);
|
||||
|
||||
return VCOS_SUCCESS;
|
||||
}
|
||||
|
||||
/** Send a reply to a message
|
||||
*/
|
||||
void vcos_msg_reply(VCOS_MSG_T *msg)
|
||||
{
|
||||
vcos_assert(msg->magic == MAGIC);
|
||||
msg->code |= MSG_REPLY_BIT;
|
||||
if (msg->waiter)
|
||||
{
|
||||
msg->waiter->on_reply(msg->waiter, msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
VCOS_ALERT("%s: reply to non-reply message id %d",
|
||||
VCOS_FUNCTION,
|
||||
msg->code);
|
||||
vcos_assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void vcos_msg_set_source(VCOS_MSG_T *msg, VCOS_MSGQUEUE_T *queue)
|
||||
{
|
||||
vcos_assert(msg);
|
||||
vcos_assert(msg->magic == MAGIC);
|
||||
vcos_assert(queue);
|
||||
msg->waiter = &queue->waiter;
|
||||
}
|
||||
|
||||
/*
|
||||
* Message pools
|
||||
*/
|
||||
|
||||
VCOS_STATUS_T vcos_msgq_pool_create(VCOS_MSGQ_POOL_T *pool,
|
||||
size_t count,
|
||||
size_t payload_size,
|
||||
const char *name)
|
||||
{
|
||||
VCOS_STATUS_T status;
|
||||
int bp_size = payload_size + sizeof(VCOS_MSG_T);
|
||||
status = vcos_blockpool_create_on_heap(&pool->blockpool,
|
||||
count, bp_size,
|
||||
VCOS_BLOCKPOOL_ALIGN_DEFAULT,
|
||||
0,
|
||||
name);
|
||||
if (status != VCOS_SUCCESS)
|
||||
goto fail_pool;
|
||||
|
||||
status = vcos_semaphore_create(&pool->sem, name, count);
|
||||
if (status != VCOS_SUCCESS)
|
||||
goto fail_sem;
|
||||
|
||||
pool->waiter.on_reply = vcos_msgq_pool_on_reply;
|
||||
pool->magic = MAGIC;
|
||||
return status;
|
||||
|
||||
fail_sem:
|
||||
vcos_blockpool_delete(&pool->blockpool);
|
||||
fail_pool:
|
||||
return status;
|
||||
}
|
||||
|
||||
void vcos_msgq_pool_delete(VCOS_MSGQ_POOL_T *pool)
|
||||
{
|
||||
vcos_blockpool_delete(&pool->blockpool);
|
||||
vcos_semaphore_delete(&pool->sem);
|
||||
}
|
||||
|
||||
/** Called when a message from a pool is replied-to. Just returns
|
||||
* the message back to the blockpool.
|
||||
*/
|
||||
static void vcos_msgq_pool_on_reply(VCOS_MSG_WAITER_T *waiter,
|
||||
VCOS_MSG_T *msg)
|
||||
{
|
||||
vcos_unused(waiter);
|
||||
vcos_assert(msg->magic == MAGIC);
|
||||
vcos_msgq_pool_free(msg);
|
||||
}
|
||||
|
||||
VCOS_MSG_T *vcos_msgq_pool_alloc(VCOS_MSGQ_POOL_T *pool)
|
||||
{
|
||||
VCOS_MSG_T *msg;
|
||||
if (vcos_semaphore_trywait(&pool->sem) == VCOS_SUCCESS)
|
||||
{
|
||||
msg = vcos_blockpool_calloc(&pool->blockpool);
|
||||
vcos_assert(msg);
|
||||
msg->magic = MAGIC;
|
||||
msg->waiter = &pool->waiter;
|
||||
msg->pool = pool;
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = NULL;
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
void vcos_msgq_pool_free(VCOS_MSG_T *msg)
|
||||
{
|
||||
if (msg)
|
||||
{
|
||||
VCOS_MSGQ_POOL_T *pool;
|
||||
vcos_assert(msg->pool);
|
||||
|
||||
pool = msg->pool;
|
||||
vcos_assert(msg->pool->magic == MAGIC);
|
||||
|
||||
vcos_blockpool_free(msg);
|
||||
vcos_semaphore_post(&pool->sem);
|
||||
}
|
||||
}
|
||||
|
||||
VCOS_MSG_T *vcos_msgq_pool_wait(VCOS_MSGQ_POOL_T *pool)
|
||||
{
|
||||
VCOS_MSG_T *msg;
|
||||
vcos_semaphore_wait(&pool->sem);
|
||||
msg = vcos_blockpool_calloc(&pool->blockpool);
|
||||
vcos_assert(msg);
|
||||
msg->magic = MAGIC;
|
||||
msg->waiter = &pool->waiter;
|
||||
msg->pool = pool;
|
||||
return msg;
|
||||
}
|
||||
|
||||
void vcos_msg_init(VCOS_MSG_T *msg)
|
||||
{
|
||||
msg->magic = MAGIC;
|
||||
msg->next = NULL;
|
||||
msg->waiter = NULL;
|
||||
msg->pool = NULL;
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - reentrant mutexes mapped directly to regular ones
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef VCOS_GENERIC_REENTRANT_MUTEX_H
|
||||
#define VCOS_GENERIC_REENTRANT_MUTEX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "interface/vcos/vcos_types.h"
|
||||
#include "interface/vcos/vcos_mutex.h"
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Reentrant Mutexes directly using the native re-entrant mutex.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef VCOS_MUTEX_T VCOS_REENTRANT_MUTEX_T;
|
||||
|
||||
/* Inline forwarding functions */
|
||||
|
||||
#if defined(VCOS_INLINE_BODIES)
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
VCOS_STATUS_T vcos_reentrant_mutex_create(VCOS_REENTRANT_MUTEX_T *m, const char *name) {
|
||||
return vcos_mutex_create(m,name);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_reentrant_mutex_delete(VCOS_REENTRANT_MUTEX_T *m) {
|
||||
vcos_mutex_delete(m);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_reentrant_mutex_lock(VCOS_REENTRANT_MUTEX_T *m) {
|
||||
vcos_mutex_lock(m);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
void vcos_reentrant_mutex_unlock(VCOS_REENTRANT_MUTEX_T *m) {
|
||||
vcos_mutex_unlock(m);
|
||||
}
|
||||
|
||||
VCOS_INLINE_IMPL
|
||||
int vcos_reentrant_mutex_is_locked(VCOS_REENTRANT_MUTEX_T *m) {
|
||||
return vcos_mutex_is_locked(m);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright (c) 2012, Broadcom Europe Ltd
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*=============================================================================
|
||||
VideoCore OS Abstraction Layer - thread reaping
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef VCOS_THREAD_REAPER_H
|
||||
#define VCOS_THREAD_REAPER_H
|
||||
|
||||
#define VCOS_HAVE_THREAD_REAPER
|
||||
|
||||
/** Initialise the thread reaper.
|
||||
*/
|
||||
VCOS_STATUS_T vcos_thread_reaper_init(void);
|
||||
|
||||
/** Reap a thread. Arranges for the thread to be automatically
|
||||
* joined.
|
||||
*
|
||||
* @sa vcos_thread_join().
|
||||
*
|
||||
* @param thread the thread to terminate
|
||||
* @param on_terminated called after the thread has exited
|
||||
* @param cxt pass back to the callback
|
||||
*
|
||||
*/
|
||||
void vcos_thread_reap(VCOS_THREAD_T *thread, void (*on_terminated)(void*), void *cxt);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user