Skip to content

Commit

Permalink
CCB 20191030: Merge #257 #276 #277 #278
Browse files Browse the repository at this point in the history
Fixes #271 #272 #273 #274
Code reviewed and approved at 20191030 CCB
  • Loading branch information
skliper committed Oct 31, 2019
2 parents 342422a + 6357c2d commit 58d4d74
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 76 deletions.
63 changes: 20 additions & 43 deletions src/os/posix/ostimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ void OS_TimeBaseUnlock_Impl(uint32 local_id)
* Purpose: Local helper routine, not part of OSAL API.
*
*-----------------------------------------------------------------*/
static uint32 OS_TimeBase_SoftWaitImpl(uint32 timer_id)
static uint32 OS_TimeBase_SigWaitImpl(uint32 timer_id)
{
int ret;
OS_impl_timebase_internal_record_t *local;
Expand All @@ -144,57 +144,34 @@ static uint32 OS_TimeBase_SoftWaitImpl(uint32 timer_id)

local = &OS_impl_timebase_table[timer_id];

if (local->reset_flag == 0)
{
interval_time = OS_timebase_table[timer_id].nominal_interval_time;
}
else
ret = sigwait(&local->sigset, &sig);

if (ret != 0)
{
interval_time = OS_timebase_table[timer_id].nominal_start_time;
local->reset_flag = 0;
/*
* the sigwait call failed.
* returning 0 will cause the process to repeat.
*/
interval_time = 0;
}

if (local->assigned_signal == 0)
else if (local->reset_flag == 0)
{
/*
* If no signal is in use and this function got called,
* just implement it using a software delay. This is the
* least accurate option, but it always works.
* Normal steady-state behavior.
* interval_time reflects the configured interval time.
*/
if (interval_time == 0)
{
/*
* Protect against a zero interval time causing a "spin loop"
* In this case sleep for 10ms.
*/
interval_time = 10000;
}
local->softsleep.tv_nsec += 1000 * (interval_time % 1000000);
local->softsleep.tv_sec += interval_time / 1000000;
if (local->softsleep.tv_nsec > 1000000000)
{
local->softsleep.tv_nsec -= 1000000000;
++local->softsleep.tv_sec;
}
interval_time = OS_timebase_table[timer_id].nominal_interval_time;
}


do
else
{
/*
* Note that either of these calls can be interrupted by OTHER signals,
* so it needs to be repeated until it actually returns the proper code.
* Reset/First interval behavior.
* timer_set() was invoked since the previous interval occurred (if any).
* interval_time reflects the configured start time.
*/
if (local->assigned_signal == 0)
{
ret = clock_nanosleep(OS_PREFERRED_CLOCK, TIMER_ABSTIME, &local->softsleep, NULL);
}
else
{
ret = sigwait(&local->sigset, &sig);
}
interval_time = OS_timebase_table[timer_id].nominal_start_time;
local->reset_flag = 0;
}
while (ret != 0);

return interval_time;
} /* end OS_TimeBase_SoftWaitImpl */
Expand Down Expand Up @@ -453,7 +430,7 @@ int32 OS_TimeBaseCreate_Impl(uint32 timer_id)
break;
}

OS_timebase_table[timer_id].external_sync = OS_TimeBase_SoftWaitImpl;
OS_timebase_table[timer_id].external_sync = OS_TimeBase_SigWaitImpl;
}
while (0);

Expand Down
2 changes: 1 addition & 1 deletion src/os/rtems/osfilesys.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ int32 OS_FileSysStartVolume_Impl (uint32 filesys_id)
impl->mount_fstype = RTEMS_FILESYSTEM_TYPE_RFS;

OS_DEBUG("OSAL: RAM disk initialized: volume=%s device=%s address=0x%08lX\n",
local->volume_name, impl->blockdev_name, local->address);
local->volume_name, impl->blockdev_name, (unsigned long)local->address);

return_code = OS_SUCCESS;
break;
Expand Down
49 changes: 36 additions & 13 deletions src/os/rtems/ostimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ typedef struct
uint8 simulate_flag;
uint8 reset_flag;
rtems_interval interval_ticks;
uint32 configured_start_time;
uint32 configured_interval_time;
} OS_impl_timebase_internal_record_t;

/****************************************************************************************
Expand Down Expand Up @@ -150,10 +152,15 @@ static rtems_timer_service_routine OS_TimeBase_ISR(rtems_id rtems_timer_id, void
static uint32 OS_TimeBase_WaitImpl(uint32 local_id)
{
OS_impl_timebase_internal_record_t *local;
uint32 interval_time;
uint32 tick_time;

local = &OS_impl_timebase_table[local_id];

/*
* Pend for the tick arrival
*/
rtems_semaphore_obtain(local->tick_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);

/*
* Determine how long this tick was.
* Note that there are plenty of ways this become wrong if the timer
Expand All @@ -163,21 +170,16 @@ static uint32 OS_TimeBase_WaitImpl(uint32 local_id)
*/
if (local->reset_flag == 0)
{
interval_time = OS_timebase_table[local_id].nominal_interval_time;
tick_time = local->configured_interval_time;
}
else
{
interval_time = OS_timebase_table[local_id].nominal_start_time;
tick_time = local->configured_start_time;
local->reset_flag = 0;
}

/*
* Pend for the tick arrival
*/
rtems_semaphore_obtain(local->tick_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);


return interval_time;
return tick_time;
} /* end OS_TimeBase_WaitImpl */


Expand Down Expand Up @@ -469,13 +471,34 @@ int32 OS_TimeBaseSet_Impl(uint32 timer_id, int32 start_time, int32 interval_time
}
else
{
if (local->interval_ticks > 0)
local->configured_start_time = (10000 * start_ticks) / OS_SharedGlobalVars.TicksPerSecond;
local->configured_interval_time = (10000 * local->interval_ticks) / OS_SharedGlobalVars.TicksPerSecond;
local->configured_start_time *= 100;
local->configured_interval_time *= 100;

if (local->configured_start_time != start_time)
{
start_ticks = local->interval_ticks;
OS_DEBUG("WARNING: timer %lu start_time requested=%luus, configured=%luus\n",
(unsigned long)timer_id,
(unsigned long)start_time,
(unsigned long)local->configured_start_time);
}
if (local->configured_interval_time != interval_time)
{
OS_DEBUG("WARNING: timer %lu interval_time requested=%luus, configured=%luus\n",
(unsigned long)timer_id,
(unsigned long)interval_time,
(unsigned long)local->configured_interval_time);
}

OS_timebase_table[timer_id].accuracy_usec = (start_ticks * 100000) / OS_SharedGlobalVars.TicksPerSecond;
OS_timebase_table[timer_id].accuracy_usec *= 10;
if (local->interval_ticks > 0)
{
OS_timebase_table[timer_id].accuracy_usec = local->configured_interval_time;
}
else
{
OS_timebase_table[timer_id].accuracy_usec = local->configured_start_time;
}
}
}
}
Expand Down
10 changes: 9 additions & 1 deletion src/os/shared/osapi-timebase.c
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ void OS_TimeBase_CallbackThread(uint32 timebase_id)
timecb = &OS_timecb_table[curr_cb_local_id];
saved_wait_time = timecb->wait_time;
timecb->wait_time -= tick_time;
if (timecb->wait_time <= 0)
while (timecb->wait_time <= 0)
{
timecb->wait_time += timecb->interval_time;

Expand All @@ -519,6 +519,14 @@ void OS_TimeBase_CallbackThread(uint32 timebase_id)
{
(*timecb->callback_ptr)(curr_cb_public_id, timecb->callback_arg);
}

/*
* Do not repeat the loop unless interval_time is configured.
*/
if (timecb->interval_time <= 0)
{
break;
}
}
curr_cb_local_id = timecb->next_ref;
}
Expand Down
69 changes: 65 additions & 4 deletions src/os/vxworks/ostimer.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ typedef struct
TASK_ID handler_task;
timer_t host_timerid;
enum OS_TimerState timer_state;
uint32 configured_start_time;
uint32 configured_interval_time;
bool reset_flag;
} OS_impl_timebase_internal_record_t;

/****************************************************************************************
Expand Down Expand Up @@ -153,14 +156,14 @@ static uint32 OS_VxWorks_SigWait(uint32 local_id)
OS_impl_timebase_internal_record_t *local;
OS_common_record_t *global;
uint32 active_id;
uint32 interval_time;
uint32 tick_time;
int signo;
int ret;

local = &OS_impl_timebase_table[local_id];
global = &OS_global_timebase_table[local_id];
active_id = global->active_id;
interval_time = 0;
tick_time = 0;

if (active_id != 0 && local->assigned_signal > 0)
{
Expand Down Expand Up @@ -190,11 +193,20 @@ static uint32 OS_VxWorks_SigWait(uint32 local_id)
if (ret == OK && signo == local->assigned_signal &&
global->active_id == active_id)
{
interval_time = OS_timebase_table[local_id].nominal_interval_time;
if (local->reset_flag)
{
/* first interval after reset, use start time */
tick_time = local->configured_start_time;
local->reset_flag = false;
}
else
{
tick_time = local->configured_interval_time;
}
}
}

return interval_time;
return tick_time;
} /* end OS_VxWorks_SigWait */


Expand Down Expand Up @@ -354,6 +366,7 @@ int32 OS_TimeBaseCreate_Impl(uint32 timer_id)
local->handler_mutex = (SEM_ID)0;
local->host_timerid = 0;
local->timer_state = OS_TimerRegState_INIT;
local->reset_flag = false;

/*
* Set up the necessary OS constructs
Expand Down Expand Up @@ -543,11 +556,59 @@ int32 OS_TimeBaseSet_Impl(uint32 timer_id, int32 start_time, int32 interval_time
if (status == OK)
{
return_code = OS_SUCCESS;

/*
* VxWorks will round the interval up to the next higher
* system tick interval. Sometimes this can make a substantial
* difference in the actual time, particularly as the error
* accumulates over time.
*
* timer_gettime() will reveal the actual interval programmed,
* after all rounding/adjustments, which can be used to determine
* the actual start_time/interval_time that will be realized.
*
* If this actual interval is different than the intended value,
* it may indicate the need for better tuning on the app/config/bsp
* side, and so a DEBUG message is generated.
*/
status = timer_gettime(local->host_timerid, &timeout);
if (status == OK)
{
local->configured_start_time =
(timeout.it_value.tv_sec * 1000000) +
(timeout.it_value.tv_nsec / 1000);
local->configured_interval_time =
(timeout.it_interval.tv_sec * 1000000) +
(timeout.it_interval.tv_nsec / 1000);

if (local->configured_start_time != start_time)
{
OS_DEBUG("WARNING: timer %lu start_time requested=%luus, configured=%luus\n",
(unsigned long)timer_id,
(unsigned long)start_time,
(unsigned long)local->configured_start_time);
}
if (local->configured_interval_time != interval_time)
{
OS_DEBUG("WARNING: timer %lu interval_time requested=%luus, configured=%luus\n",
(unsigned long)timer_id,
(unsigned long)interval_time,
(unsigned long)local->configured_interval_time);
}

}

}
else
{
return_code = OS_TIMER_ERR_INVALID_ARGS;
}

}

if (!local->reset_flag && return_code == OS_SUCCESS)
{
local->reset_flag = true;
}

return return_code;
Expand Down
4 changes: 2 additions & 2 deletions src/tests/sem-speed-test/sem-speed-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,10 @@ void SemSetup(void)
/*
** Create the tasks
*/
status = OS_TaskCreate( &task_1_id, "Task 1", task_1, NULL, 0, TASK_PRIORITY, 0);
status = OS_TaskCreate( &task_1_id, "Task 1", task_1, NULL, 4096, TASK_PRIORITY, 0);
UtAssert_True(status == OS_SUCCESS, "Task 1 create Id=%u Rc=%d", (unsigned int)task_1_id, (int)status);

status = OS_TaskCreate( &task_2_id, "Task 2", task_2, NULL, 0, TASK_PRIORITY, 0);
status = OS_TaskCreate( &task_2_id, "Task 2", task_2, NULL, 4096, TASK_PRIORITY, 0);
UtAssert_True(status == OS_SUCCESS, "Task 2 create Id=%u Rc=%d", (unsigned int)task_2_id, (int)status);

/* A small delay just to allow the tasks
Expand Down
Loading

0 comments on commit 58d4d74

Please sign in to comment.