Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #957, move async console option #959

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions default_config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,31 @@ set(OSAL_CONFIG_DEBUG_PRINTF FALSE
CACHE BOOL "Controls inclusion of OS_DEBUG statements in the code"
)

#
# OS_CONFIG_CONSOLE_ASYNC
# ----------------------------------
#
# Controls whether the console device writes (OS_printf) will be deferred
# to a separate utility task or handled directly by the calling task.
#
# If set FALSE, the utility task WILL NOT be spawned, and all OS_printf()
# calls will be synchronously written to the console device.
#
# If set TRUE, an extra utility task WILL be spawned, and the data from
# all OS_printf() calls will be written to an output queue which is then
# transferred to the console device by the utility task.
#
# When this is TRUE (default), it may improve real time performance by not
# requiring the caller to delay on a potentially slow console device output.
#
# However decoupling in this manner requires creation of an extra task and
# stack to handle the output, and a side effect is that the OS_printf() output
# can become decoupled from the event/task where it actually occurred, or
# messages might appear in a different order than they originally occurred.
#
set(OSAL_CONFIG_CONSOLE_ASYNC TRUE
CACHE BOOL "Controls spawning of a separate utility task for OS_printf"
)

#############################################
# Resource Limits for the OS API
Expand Down
1 change: 1 addition & 0 deletions osconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#cmakedefine OSAL_CONFIG_INCLUDE_SHELL
#cmakedefine OSAL_CONFIG_DEBUG_PRINTF
#cmakedefine OSAL_CONFIG_DEBUG_PERMISSIVE_MODE
#cmakedefine OSAL_CONFIG_CONSOLE_ASYNC

#cmakedefine OSAL_CONFIG_BUGCHECK_DISABLE
#cmakedefine OSAL_CONFIG_BUGCHECK_STRICT
Expand Down
1 change: 0 additions & 1 deletion src/os/posix/inc/os-impl-console.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
/* Console device */
typedef struct
{
bool is_async;
sem_t data_sem;
} OS_impl_console_internal_record_t;

Expand Down
22 changes: 8 additions & 14 deletions src/os/posix/src/os-impl-console.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,9 @@ void OS_ConsoleWakeup_Impl(const OS_object_token_t *token)

local = OS_OBJECT_TABLE_GET(OS_impl_console_table, *token);

if (local->is_async)
{
/* post the sem for the utility task to run */
sem_post(&local->data_sem);
}
else
{
/* output directly */
OS_ConsoleOutput_Impl(token);
}
/* post the sem for the utility task to run */
sem_post(&local->data_sem);

} /* end OS_ConsoleWakeup_Impl */

/*----------------------------------------------------------------
Expand Down Expand Up @@ -121,18 +114,19 @@ static void *OS_ConsoleTask_Entry(void *arg)
int32 OS_ConsoleCreate_Impl(const OS_object_token_t *token)
{
OS_impl_console_internal_record_t *local;
OS_console_internal_record_t * console;
pthread_t consoletask;
int32 return_code;
OS_VoidPtrValueWrapper_t local_arg = {0};

local = OS_OBJECT_TABLE_GET(OS_impl_console_table, *token);
console = OS_OBJECT_TABLE_GET(OS_console_table, *token);
local = OS_OBJECT_TABLE_GET(OS_impl_console_table, *token);

if (token->obj_idx == 0)
{
return_code = OS_SUCCESS;
local->is_async = OS_CONSOLE_ASYNC;
return_code = OS_SUCCESS;

if (local->is_async)
if (console->IsAsync)
{
if (sem_init(&local->data_sem, 0, 0) < 0)
{
Expand Down
1 change: 0 additions & 1 deletion src/os/rtems/inc/os-impl-console.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
/* Console device */
typedef struct
{
bool is_async;
sem_t data_sem;
} OS_impl_console_internal_record_t;

Expand Down
25 changes: 9 additions & 16 deletions src/os/rtems/src/os-impl-console.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
/* Console device */
typedef struct
{
bool is_async;
rtems_id data_sem;
int out_fd;
} OS_impl_console_internal_record_t;
Expand All @@ -93,16 +92,9 @@ void OS_ConsoleWakeup_Impl(const OS_object_token_t *token)

local = OS_OBJECT_TABLE_GET(OS_impl_console_table, *token);

if (local->is_async)
{
/* post the sem for the utility task to run */
rtems_semaphore_release(local->data_sem);
}
else
{
/* output directly */
OS_ConsoleOutput_Impl(token);
}
/* post the sem for the utility task to run */
rtems_semaphore_release(local->data_sem);

} /* end OS_ConsoleWakeup_Impl */

/*----------------------------------------------------------------
Expand Down Expand Up @@ -143,20 +135,21 @@ static void OS_ConsoleTask_Entry(rtems_task_argument arg)
int32 OS_ConsoleCreate_Impl(const OS_object_token_t *token)
{
OS_impl_console_internal_record_t *local;
OS_console_internal_record_t * console;
int32 return_code;
rtems_name r_name;
rtems_id r_task_id;
rtems_status_code status;

local = OS_OBJECT_TABLE_GET(OS_impl_console_table, *token);
local = OS_OBJECT_TABLE_GET(OS_impl_console_table, *token);
console = OS_OBJECT_TABLE_GET(OS_console_table, *token);

if (OS_ObjectIndexFromToken(token) == 0)
{
return_code = OS_SUCCESS;
local->is_async = OS_CONSOLE_ASYNC;
local->out_fd = OSAL_CONSOLE_FILENO;
return_code = OS_SUCCESS;
local->out_fd = OSAL_CONSOLE_FILENO;

if (local->is_async)
if (console->IsAsync)
{
OS_DEBUG("%s(): Starting Async Console Handler\n", __func__);
/*
Expand Down
9 changes: 4 additions & 5 deletions src/os/shared/inc/os-shared-printf.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ typedef struct
volatile size_t ReadPos; /**< Offset of next byte to read */
volatile size_t WritePos; /**< Offset of next byte to write */
uint32 OverflowEvents; /**< Number of lines dropped due to overflow */
bool IsAsync;

} OS_console_internal_record_t;

Expand Down Expand Up @@ -89,17 +90,15 @@ int32 OS_ConsoleCreate_Impl(const OS_object_token_t *token);
void OS_ConsoleOutput_Impl(const OS_object_token_t *token);

/*----------------------------------------------------------------
Function: OS_ConsoleOutput_Impl
Function: OS_ConsoleWakeup_Impl

Purpose: Console output data notification

This is a notification API that is invoked whenever there
is new data available in the console output buffer.

For a synchronous console service, this may call
OS_ConsoleWrite_Impl() directly. For an async console
service, this should wakeup the actual console servicing
thread.
It is only used of the console is configured for async operation,
and it should wakeup the actual console servicing thread.
------------------------------------------------------------------*/
void OS_ConsoleWakeup_Impl(const OS_object_token_t *token);

Expand Down
22 changes: 21 additions & 1 deletion src/os/shared/src/osapi-printf.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@
#include "os-shared-idmap.h"
#include "os-shared-printf.h"

/*
* The choice of whether to run a separate utility task
* comes from osal compile-time config
*/
#ifdef OSAL_CONFIG_CONSOLE_ASYNC
#define OS_CONSOLE_IS_ASYNC true
#else
#define OS_CONSOLE_IS_ASYNC false
#endif

/* reserve buffer memory for the printf console device */
static char OS_printf_buffer_mem[(sizeof(OS_PRINTF_CONSOLE_NAME) + OS_BUFFER_SIZE) * OS_BUFFER_MSG_DEPTH];

Expand Down Expand Up @@ -99,6 +109,7 @@ int32 OS_ConsoleAPI_Init(void)
*/
console->BufBase = OS_printf_buffer_mem;
console->BufSize = sizeof(OS_printf_buffer_mem);
console->IsAsync = OS_CONSOLE_IS_ASYNC;

return_code = OS_ConsoleCreate_Impl(&token);

Expand Down Expand Up @@ -234,7 +245,16 @@ int32 OS_ConsoleWrite(osal_id_t console_id, const char *Str)
* This is done while still locked, so it can support
* either a synchronous or asynchronous implementation.
*/
OS_ConsoleWakeup_Impl(&token);
if (console->IsAsync)
{
/* post the sem for the utility task to run */
OS_ConsoleWakeup_Impl(&token);
}
else
{
/* output directly */
OS_ConsoleOutput_Impl(&token);
}

OS_ObjectIdRelease(&token);
}
Expand Down
1 change: 0 additions & 1 deletion src/os/vxworks/inc/os-impl-console.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
typedef struct
{
VX_COUNTING_SEMAPHORE(cmem);
bool is_async;
SEM_ID datasem;
TASK_ID taskid;
} OS_impl_console_internal_record_t;
Expand Down
20 changes: 6 additions & 14 deletions src/os/vxworks/src/os-impl-console.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,12 @@ void OS_ConsoleWakeup_Impl(const OS_object_token_t *token)

local = OS_OBJECT_TABLE_GET(OS_impl_console_table, *token);

if (local->is_async)
/* post the sem for the utility task to run */
if (semGive(local->datasem) == ERROR)
{
/* post the sem for the utility task to run */
if (semGive(local->datasem) == ERROR)
{
OS_DEBUG("semGive() - vxWorks errno %d\n", errno);
}
}
else
{
/* output directly */
OS_ConsoleOutput_Impl(token);
OS_DEBUG("semGive() - vxWorks errno %d\n", errno);
}

} /* end OS_ConsoleWakeup_Impl */

/*----------------------------------------------------------------
Expand Down Expand Up @@ -142,10 +135,9 @@ int32 OS_ConsoleCreate_Impl(const OS_object_token_t *token)

if (OS_ObjectIndexFromToken(token) == 0)
{
return_code = OS_SUCCESS;
local->is_async = OS_CONSOLE_ASYNC;
return_code = OS_SUCCESS;

if (local->is_async)
if (console->IsAsync)
{
OS_DEBUG("%s(): Starting Async Console Handler\n", __func__);

Expand Down
23 changes: 17 additions & 6 deletions src/unit-test-coverage/shared/src/coveragetest-printf.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ void Test_OS_printf(void)
* void OS_printf_disable(void);
* void OS_printf_enable(void);
*/
uint32 CallCount = 0;

/* catch case where OS_printf called before init */
OS_SharedGlobalVars.PrintfConsoleId = OS_OBJECT_ID_UNDEFINED;
Expand All @@ -80,17 +79,29 @@ void Test_OS_printf(void)
UtAssert_True(OS_console_table[0].WritePos == 0, "WritePos (%lu) >= 0",
(unsigned long)OS_console_table[0].WritePos);

/* normal case */
/* normal case - sync mode */
OS_console_table[0].IsAsync = false;
OS_printf_enable();
OS_printf("UnitTest3");
CallCount = UT_GetStubCount(UT_KEY(OS_ConsoleWakeup_Impl));
UtAssert_True(CallCount == 1, "OS_ConsoleWakeup_Impl() call count (%lu) == 1", (unsigned long)CallCount);
UtAssert_True(OS_console_table[0].WritePos >= 9, "WritePos (%lu) >= 9",
OS_printf("UnitTest3s");
UtAssert_STUB_COUNT(OS_ConsoleWakeup_Impl, 0);
UtAssert_STUB_COUNT(OS_ConsoleOutput_Impl, 1);
UtAssert_True(OS_console_table[0].WritePos >= 10, "WritePos (%lu) >= 10",
(unsigned long)OS_console_table[0].WritePos);

/* normal case - async mode */
OS_console_table[0].IsAsync = true;
OS_console_table[0].WritePos = 0;
OS_printf("UnitTest3a");
UtAssert_STUB_COUNT(OS_ConsoleWakeup_Impl, 1);
UtAssert_STUB_COUNT(OS_ConsoleOutput_Impl, 1);
UtAssert_True(OS_console_table[0].WritePos >= 10, "WritePos (%lu) >= 10",
(unsigned long)OS_console_table[0].WritePos);

/* print a long string that does not fit in the 16-char buffer */
OS_printf_enable();
OS_printf("UnitTest4BufferLengthExceeded");
UtAssert_True(OS_console_table[0].OverflowEvents == 1, "OverflowEvents (%lu) == 1",
(unsigned long)OS_console_table[0].OverflowEvents);

/* test writing with a non-empty console name */
strncpy(OS_console_table[0].device_name, "ut", sizeof(OS_console_table[0].device_name) - 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,4 @@ extern size_t const UT_Ref_OS_impl_console_table_SIZE;
*/
extern void UT_ConsoleTest_TaskEntry(int arg);

/**
* Force the "is_async" field to a given state for coverage testing
*/
extern void UT_ConsoleTest_SetConsoleAsync(osal_index_t local_id, bool is_async);

#endif /* UT_ADAPTOR_CONSOLE_H */
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,3 @@ void UT_ConsoleTest_TaskEntry(int arg)
{
OS_VxWorks_ConsoleTask_Entry(arg);
}

void UT_ConsoleTest_SetConsoleAsync(osal_index_t local_id, bool is_async)
{
OS_impl_console_table[local_id].is_async = is_async;
}
18 changes: 10 additions & 8 deletions src/unit-test-coverage/vxworks/src/coveragetest-console.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,13 @@ void Test_OS_ConsoleWakeup_Impl(void)
*/
OS_object_token_t token = UT_TOKEN_0;

/* no return code - check for coverage */
UT_ConsoleTest_SetConsoleAsync(0, true);
/* this just gives the sem, only called in async mode */
OS_ConsoleWakeup_Impl(&token);
UtAssert_True(UT_GetStubCount(UT_KEY(OCS_semGive)) == 1, "semGive() called in async mode");

/* Failure only causes a debug message to be generated, no error handling here */
UT_SetDefaultReturnValue(UT_KEY(OCS_semGive), -1);
OS_ConsoleWakeup_Impl(&token);

UT_ConsoleTest_SetConsoleAsync(0, false);
OS_console_table[0].WritePos = 1;
OS_ConsoleWakeup_Impl(&token);
UtAssert_True(UT_GetStubCount(UT_KEY(OS_ConsoleOutput_Impl)) == 1, "OS_ConsoleOutput_Impl() called in sync mode");
}

void Test_OS_ConsoleCreate_Impl(void)
Expand All @@ -63,8 +58,15 @@ void Test_OS_ConsoleCreate_Impl(void)

memset(&token, 0, sizeof(token));

/* Verify coverage when configured for sync mode */
OS_console_table[0].IsAsync = false;
OSAPI_TEST_FUNCTION_RC(OS_ConsoleCreate_Impl(&token), OS_SUCCESS);
UtAssert_STUB_COUNT(OCS_taskSpawn, 0); /* Task _was not_ spawned */

/* Verify coverage when configured for async mode */
OS_console_table[0].IsAsync = true;
OSAPI_TEST_FUNCTION_RC(OS_ConsoleCreate_Impl(&token), OS_SUCCESS);
UtAssert_True(UT_GetStubCount(UT_KEY(OCS_taskSpawn)) == 1, "taskSpawn() called");
UtAssert_STUB_COUNT(OCS_taskSpawn, 1); /* Task _was_ spawned */

UT_SetDefaultReturnValue(UT_KEY(OCS_semCInitialize), OCS_ERROR);
OSAPI_TEST_FUNCTION_RC(OS_ConsoleCreate_Impl(&token), OS_SEM_FAILURE);
Expand Down