summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Kconfig29
-rw-r--r--src/SConscript17
-rw-r--r--src/clock.c24
-rw-r--r--src/components.c15
-rw-r--r--src/cpu.c107
-rw-r--r--src/device.c16
-rw-r--r--src/idle.c20
-rw-r--r--src/ipc.c369
-rw-r--r--src/irq.c2
-rw-r--r--src/kservice.c132
-rw-r--r--src/mem.c8
-rw-r--r--src/memheap.c6
-rw-r--r--src/mempool.c39
-rw-r--r--src/object.c112
-rw-r--r--src/scheduler.c201
-rw-r--r--src/signal.c185
-rw-r--r--src/slab.c44
-rw-r--r--src/thread.c135
-rw-r--r--src/timer.c137
19 files changed, 1191 insertions, 407 deletions
diff --git a/src/Kconfig b/src/Kconfig
index 9ae655c670..63a7a67887 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -8,10 +8,19 @@ config RT_NAME_MAX
Each kernel object, such as thread, timer, semaphore etc, has a name,
the RT_NAME_MAX is the maximal size of this object name.
+config RT_USING_ARCH_DATA_TYPE
+ bool "Use the data types defined in ARCH_CPU"
+ default n
+ help
+ For the data type like, `rt_uint8/int8_t, rt_uint16/int16_t, rt_uint32/int32_t`,
+ BSP can define these basic data types in ARCH_CPU level.
+
+ Please re-define these data types in rtconfig_project.h file.
+
config RT_USING_SMP
bool "Enable SMP(Symmetric multiprocessing)"
default n
- help
+ help
This option should be selected by machines which have an SMP-
capable CPU.
The only effect of this option is to make the SMP-related
@@ -19,10 +28,10 @@ config RT_USING_SMP
config RT_CPUS_NR
int "Number of CPUs"
- default 2
- depends on RT_USING_SMP
+ default 2
+ depends on RT_USING_SMP
help
- Number of CPUs in the system
+ Number of CPUs in the system
config RT_ALIGN_SIZE
int "Alignment size for CPU architecture data access"
@@ -77,8 +86,8 @@ config RT_USING_IDLE_HOOK
default y if RT_USING_HOOK
if RT_USING_IDLE_HOOK
- config RT_IDEL_HOOK_LIST_SIZE
- int "The max size of idel hook list"
+ config RT_IDLE_HOOK_LIST_SIZE
+ int "The max size of idle hook list"
default 4
range 1 16
help
@@ -91,7 +100,7 @@ config IDLE_THREAD_STACK_SIZE
config RT_USING_TIMER_SOFT
bool "Enable software timer with a timer thread"
- default n
+ default y
help
the timeout function context of soft-timer is under a high priority timer
thread.
@@ -113,6 +122,10 @@ menuconfig RT_DEBUG
if RT_DEBUG
+config RT_DEBUG_COLOR
+ bool "Enable color debugging log"
+ default n
+
config RT_DEBUG_INIT_CONFIG
bool "Enable debugging of components initialization"
default n
@@ -318,7 +331,7 @@ endmenu
config RT_VER_NUM
hex
- default 0x40000
+ default 0x40003
help
RT-Thread version number
diff --git a/src/SConscript b/src/SConscript
index bb38baa6bd..82c3b8aaf1 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -5,18 +5,6 @@ from building import *
src = Glob('*.c')
CPPPATH = [RTT_ROOT + '/include']
-if rtconfig.CROSS_TOOL == 'keil':
- # add more link flags for module and components_init.
- LINKFLAGS = ''
- if GetDepend('RT_USING_MODULE'):
- LINKFLAGS += ' --keep *.o(RTMSymTab) '
- if GetDepend('RT_USING_COMPONENTS_INIT'):
- LINKFLAGS += ' --keep *.o(.rti_fn.*) '
-else:
- LINKFLAGS = ''
-
-if GetDepend('RT_USING_COMPONENTS_INIT') == False:
- SrcRemove(src, ['components.c'])
if GetDepend('RT_USING_MODULE') == False:
SrcRemove(src, ['module.c'])
@@ -38,6 +26,9 @@ if GetDepend('RT_USING_MEMHEAP') == False:
if GetDepend('RT_USING_DEVICE') == False:
SrcRemove(src, ['device.c'])
-group = DefineGroup('Kernel', src, depend = [''], CPPPATH = CPPPATH, LINKFLAGS = LINKFLAGS)
+if GetDepend('RT_USING_SMP') == False:
+ SrcRemove(src, ['cpu.c'])
+
+group = DefineGroup('Kernel', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
diff --git a/src/clock.c b/src/clock.c
index 1bedb4e06a..a91cd829b6 100644
--- a/src/clock.c
+++ b/src/clock.c
@@ -24,10 +24,8 @@
static rt_tick_t rt_tick = 0;
#endif
-extern void rt_timer_check(void);
-
/**
- * This function will init system tick and set it to zero.
+ * This function will initialize system tick and set it to zero.
* @ingroup SystemInit
*
* @deprecated since 1.1.0, this function does not need to be invoked
@@ -91,8 +89,9 @@ void rt_tick_increase(void)
/* change to initialized tick */
thread->remaining_tick = thread->init_tick;
- /* yield */
- rt_thread_yield();
+ thread->stat |= RT_THREAD_STAT_YIELD;
+
+ rt_schedule();
}
/* check timer */
@@ -109,15 +108,20 @@ void rt_tick_increase(void)
*
* @return the calculated tick
*/
-int rt_tick_from_millisecond(rt_int32_t ms)
+rt_tick_t rt_tick_from_millisecond(rt_int32_t ms)
{
- int tick;
+ rt_tick_t tick;
if (ms < 0)
- tick = RT_WAITING_FOREVER;
+ {
+ tick = (rt_tick_t)RT_WAITING_FOREVER;
+ }
else
- tick = (RT_TICK_PER_SECOND * ms + 999) / 1000;
-
+ {
+ tick = RT_TICK_PER_SECOND * (ms / 1000);
+ tick += (RT_TICK_PER_SECOND * (ms % 1000) + 999) / 1000;
+ }
+
/* return the calculated tick */
return tick;
}
diff --git a/src/components.c b/src/components.c
index d77ef8300f..e7824b65ef 100644
--- a/src/components.c
+++ b/src/components.c
@@ -92,7 +92,7 @@ void rt_components_board_init(void)
rt_kprintf(":%d done\n", result);
}
#else
- const init_fn_t *fn_ptr;
+ volatile const init_fn_t *fn_ptr;
for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
{
@@ -118,7 +118,7 @@ void rt_components_init(void)
rt_kprintf(":%d done\n", result);
}
#else
- const init_fn_t *fn_ptr;
+ volatile const init_fn_t *fn_ptr;
for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++)
{
@@ -126,6 +126,7 @@ void rt_components_init(void)
}
#endif
}
+#endif /* RT_USING_COMPONENTS_INIT */
#ifdef RT_USING_USER_MAIN
@@ -138,7 +139,6 @@ extern int $Super$$main(void);
/* re-define main function */
int $Sub$$main(void)
{
- rt_hw_interrupt_disable();
rtthread_startup();
return 0;
}
@@ -150,16 +150,13 @@ int __low_level_init(void)
{
// call IAR table copy function.
__iar_data_init3();
- rt_hw_interrupt_disable();
rtthread_startup();
return 0;
}
#elif defined(__GNUC__)
-extern int main(void);
/* Add -eentry to arm-none-eabi-gcc argument */
int entry(void)
{
- rt_hw_interrupt_disable();
rtthread_startup();
return 0;
}
@@ -178,9 +175,10 @@ void main_thread_entry(void *parameter)
extern int main(void);
extern int $Super$$main(void);
+#ifdef RT_USING_COMPONENTS_INIT
/* RT-Thread components initialization */
rt_components_init();
-
+#endif
#ifdef RT_USING_SMP
rt_hw_secondary_cpu_up();
#endif
@@ -207,7 +205,7 @@ void rt_application_init(void)
result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
RT_ASSERT(result == RT_EOK);
-
+
/* if not define RT_USING_HEAP, using to eliminate the warning */
(void)result;
#endif
@@ -258,4 +256,3 @@ int rtthread_startup(void)
return 0;
}
#endif
-#endif
diff --git a/src/cpu.c b/src/cpu.c
index 3e2d65dfb9..96e585713b 100644
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -7,15 +7,106 @@
* Date Author Notes
* 2018-10-30 Bernard The first version
*/
-
-#include <rtthread.h>
#include <rthw.h>
+#include <rtthread.h>
#ifdef RT_USING_SMP
-
static struct rt_cpu rt_cpus[RT_CPUS_NR];
rt_hw_spinlock_t _cpus_lock;
+/*
+ * disable scheduler
+ */
+static void rt_preempt_disable(void)
+{
+ register rt_base_t level;
+ struct rt_thread *current_thread;
+
+ /* disable interrupt */
+ level = rt_hw_local_irq_disable();
+
+ current_thread = rt_thread_self();
+ if (!current_thread)
+ {
+ rt_hw_local_irq_enable(level);
+ return;
+ }
+
+ /* lock scheduler for local cpu */
+ current_thread->scheduler_lock_nest ++;
+
+ /* enable interrupt */
+ rt_hw_local_irq_enable(level);
+}
+
+/*
+ * enable scheduler
+ */
+static void rt_preempt_enable(void)
+{
+ register rt_base_t level;
+ struct rt_thread *current_thread;
+
+ /* disable interrupt */
+ level = rt_hw_local_irq_disable();
+
+ current_thread = rt_thread_self();
+ if (!current_thread)
+ {
+ rt_hw_local_irq_enable(level);
+ return;
+ }
+
+ /* unlock scheduler for local cpu */
+ current_thread->scheduler_lock_nest --;
+
+ rt_schedule();
+ /* enable interrupt */
+ rt_hw_local_irq_enable(level);
+}
+
+void rt_spin_lock_init(struct rt_spinlock *lock)
+{
+ rt_hw_spin_lock_init(&lock->lock);
+}
+RTM_EXPORT(rt_spin_lock_init)
+
+void rt_spin_lock(struct rt_spinlock *lock)
+{
+ rt_preempt_disable();
+ rt_hw_spin_lock(&lock->lock);
+}
+RTM_EXPORT(rt_spin_lock)
+
+void rt_spin_unlock(struct rt_spinlock *lock)
+{
+ rt_hw_spin_unlock(&lock->lock);
+ rt_preempt_enable();
+}
+RTM_EXPORT(rt_spin_unlock)
+
+rt_base_t rt_spin_lock_irqsave(struct rt_spinlock *lock)
+{
+ unsigned long level;
+
+ rt_preempt_disable();
+
+ level = rt_hw_local_irq_disable();
+ rt_hw_spin_lock(&lock->lock);
+
+ return level;
+}
+RTM_EXPORT(rt_spin_lock_irqsave)
+
+void rt_spin_unlock_irqrestore(struct rt_spinlock *lock, rt_base_t level)
+{
+ rt_hw_spin_unlock(&lock->lock);
+ rt_hw_local_irq_enable(level);
+
+ rt_preempt_enable();
+}
+RTM_EXPORT(rt_spin_unlock_irqrestore)
+
/**
* This fucntion will return current cpu.
*/
@@ -42,12 +133,16 @@ rt_base_t rt_cpus_lock(void)
pcpu = rt_cpu_self();
if (pcpu->current_thread != RT_NULL)
{
- if (pcpu->current_thread->cpus_lock_nest++ == 0)
+ register rt_ubase_t lock_nest = pcpu->current_thread->cpus_lock_nest;
+
+ pcpu->current_thread->cpus_lock_nest++;
+ if (lock_nest == 0)
{
pcpu->current_thread->scheduler_lock_nest++;
rt_hw_spin_lock(&_cpus_lock);
}
}
+
return level;
}
RTM_EXPORT(rt_cpus_lock);
@@ -61,7 +156,9 @@ void rt_cpus_unlock(rt_base_t level)
if (pcpu->current_thread != RT_NULL)
{
- if (--pcpu->current_thread->cpus_lock_nest == 0)
+ pcpu->current_thread->cpus_lock_nest--;
+
+ if (pcpu->current_thread->cpus_lock_nest == 0)
{
pcpu->current_thread->scheduler_lock_nest--;
rt_hw_spin_unlock(&_cpus_lock);
diff --git a/src/device.c b/src/device.c
index 51fc6176a6..32c06b380c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -95,7 +95,7 @@ RTM_EXPORT(rt_device_unregister);
* @return the error code, RT_EOK on successfully.
*
* @deprecated since 1.2.x, this function is not needed because the initialization
- * of a device is performed when applicaiton opens it.
+ * of a device is performed when application opens it.
*/
rt_err_t rt_device_init_all(void)
{
@@ -162,7 +162,7 @@ rt_device_t rt_device_create(int type, int attach_size)
size = RT_ALIGN(sizeof(struct rt_device), RT_ALIGN_SIZE);
attach_size = RT_ALIGN(attach_size, RT_ALIGN_SIZE);
- /* use the totoal size */
+ /* use the total size */
size += attach_size;
device = (rt_device_t)rt_malloc(size);
@@ -208,7 +208,7 @@ rt_err_t rt_device_init(rt_device_t dev)
RT_ASSERT(dev != RT_NULL);
- /* get device init handler */
+ /* get device_init handler */
if (device_init != RT_NULL)
{
if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
@@ -269,7 +269,7 @@ rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag)
return -RT_EBUSY;
}
- /* call device open interface */
+ /* call device_open interface */
if (device_open != RT_NULL)
{
result = device_open(dev, oflag);
@@ -317,7 +317,7 @@ rt_err_t rt_device_close(rt_device_t dev)
if (dev->ref_count != 0)
return RT_EOK;
- /* call device close interface */
+ /* call device_close interface */
if (device_close != RT_NULL)
{
result = device_close(dev);
@@ -357,7 +357,7 @@ rt_size_t rt_device_read(rt_device_t dev,
return 0;
}
- /* call device read interface */
+ /* call device_read interface */
if (device_read != RT_NULL)
{
return device_read(dev, pos, buffer, size);
@@ -396,7 +396,7 @@ rt_size_t rt_device_write(rt_device_t dev,
return 0;
}
- /* call device write interface */
+ /* call device_write interface */
if (device_write != RT_NULL)
{
return device_write(dev, pos, buffer, size);
@@ -423,7 +423,7 @@ rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg)
RT_ASSERT(dev != RT_NULL);
RT_ASSERT(rt_object_get_type(&dev->parent) == RT_Object_Class_Device);
- /* call device write interface */
+ /* call device_write interface */
if (device_control != RT_NULL)
{
return device_control(dev, cmd, arg);
diff --git a/src/idle.c b/src/idle.c
index d02b199f32..99db64f571 100644
--- a/src/idle.c
+++ b/src/idle.c
@@ -51,11 +51,11 @@ ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t rt_thread_stack[_CPUS_NR][IDLE_THREAD_STACK_SIZE];
#ifdef RT_USING_IDLE_HOOK
-#ifndef RT_IDEL_HOOK_LIST_SIZE
-#define RT_IDEL_HOOK_LIST_SIZE 4
+#ifndef RT_IDLE_HOOK_LIST_SIZE
+#define RT_IDLE_HOOK_LIST_SIZE 4
#endif
-static void (*idle_hook_list[RT_IDEL_HOOK_LIST_SIZE])();
+static void (*idle_hook_list[RT_IDLE_HOOK_LIST_SIZE])(void);
/**
* @ingroup Hook
@@ -78,7 +78,7 @@ rt_err_t rt_thread_idle_sethook(void (*hook)(void))
/* disable interrupt */
level = rt_hw_interrupt_disable();
- for (i = 0; i < RT_IDEL_HOOK_LIST_SIZE; i++)
+ for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++)
{
if (idle_hook_list[i] == RT_NULL)
{
@@ -110,7 +110,7 @@ rt_err_t rt_thread_idle_delhook(void (*hook)(void))
/* disable interrupt */
level = rt_hw_interrupt_disable();
- for (i = 0; i < RT_IDEL_HOOK_LIST_SIZE; i++)
+ for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++)
{
if (idle_hook_list[i] == hook)
{
@@ -193,6 +193,8 @@ void rt_thread_idle_excute(void)
/* if it's a system object, not delete it */
if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
{
+ /* detach this object */
+ rt_object_detach((rt_object_t)thread);
/* unlock scheduler */
rt_exit_critical();
@@ -226,6 +228,7 @@ void rt_thread_idle_excute(void)
}
}
+extern void rt_system_power_manager(void);
static void rt_thread_idle_entry(void *parameter)
{
#ifdef RT_USING_SMP
@@ -243,7 +246,7 @@ static void rt_thread_idle_entry(void *parameter)
#ifdef RT_USING_IDLE_HOOK
rt_size_t i;
- for (i = 0; i < RT_IDEL_HOOK_LIST_SIZE; i++)
+ for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++)
{
if (idle_hook_list[i] != RT_NULL)
{
@@ -253,6 +256,9 @@ static void rt_thread_idle_entry(void *parameter)
#endif
rt_thread_idle_excute();
+#ifdef RT_USING_PM
+ rt_system_power_manager();
+#endif
}
}
@@ -265,7 +271,7 @@ static void rt_thread_idle_entry(void *parameter)
*/
void rt_thread_idle_init(void)
{
- int i;
+ rt_ubase_t i;
char tidle_name[RT_NAME_MAX];
for (i = 0; i < _CPUS_NR; i++)
diff --git a/src/ipc.c b/src/ipc.c
index 7f603cfc4d..454fcb5439 100644
--- a/src/ipc.c
+++ b/src/ipc.c
@@ -33,6 +33,10 @@
* 2011-12-18 Bernard add more parameter checking in message queue
* 2013-09-14 Grissiom add an option check in rt_event_recv
* 2018-10-02 Bernard add 64bit support for mailbox
+ * 2019-09-16 tyx add send wait support for message queue
+ * 2020-07-29 Meco Man fix thread->event_set/event_info when received an
+ * event without pending
+ * 2020-10-11 Meco Man add value overflow-check code
*/
#include <rtthread.h>
@@ -59,7 +63,7 @@ extern void (*rt_object_put_hook)(struct rt_object *object);
*/
rt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc)
{
- /* init ipc object */
+ /* initialize ipc object */
rt_list_init(&(ipc->suspend_thread));
return RT_EOK;
@@ -116,6 +120,9 @@ rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list,
rt_list_insert_before(list, &(thread->tlist));
}
break;
+
+ default:
+ break;
}
return RT_EOK;
@@ -158,13 +165,13 @@ rt_inline rt_err_t rt_ipc_list_resume_all(rt_list_t *list)
struct rt_thread *thread;
register rt_ubase_t temp;
- /* wakeup all suspend threads */
+ /* wakeup all suspended threads */
while (!rt_list_isempty(list))
{
/* disable interrupt */
temp = rt_hw_interrupt_disable();
- /* get next suspend thread */
+ /* get next suspended thread */
thread = rt_list_entry(list->next, struct rt_thread, tlist);
/* set error code to RT_ERROR */
thread->error = -RT_ERROR;
@@ -172,7 +179,7 @@ rt_inline rt_err_t rt_ipc_list_resume_all(rt_list_t *list)
/*
* resume thread
* In rt_thread_resume function, it will remove current thread from
- * suspend list
+ * suspended list
*/
rt_thread_resume(thread);
@@ -190,7 +197,7 @@ rt_inline rt_err_t rt_ipc_list_resume_all(rt_list_t *list)
*
* @param sem the semaphore object
* @param name the name of semaphore
- * @param value the init value of semaphore
+ * @param value the initial value of semaphore
* @param flag the flag of semaphore
*
* @return the operation status, RT_EOK on successful
@@ -201,15 +208,16 @@ rt_err_t rt_sem_init(rt_sem_t sem,
rt_uint8_t flag)
{
RT_ASSERT(sem != RT_NULL);
+ RT_ASSERT(value < 0x10000U);
- /* init object */
+ /* initialize object */
rt_object_init(&(sem->parent.parent), RT_Object_Class_Semaphore, name);
- /* init ipc object */
+ /* initialize ipc object */
rt_ipc_object_init(&(sem->parent));
- /* set init value */
- sem->value = value;
+ /* set initial value */
+ sem->value = (rt_uint16_t)value;
/* set parent */
sem->parent.parent.flag = flag;
@@ -234,7 +242,7 @@ rt_err_t rt_sem_detach(rt_sem_t sem)
RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);
RT_ASSERT(rt_object_is_systemobject(&sem->parent.parent));
- /* wakeup all suspend threads */
+ /* wakeup all suspended threads */
rt_ipc_list_resume_all(&(sem->parent.suspend_thread));
/* detach semaphore object */
@@ -249,7 +257,7 @@ RTM_EXPORT(rt_sem_detach);
* This function will create a semaphore from system resource
*
* @param name the name of semaphore
- * @param value the init value of semaphore
+ * @param value the initial value of semaphore
* @param flag the flag of semaphore
*
* @return the created semaphore, RT_NULL on error happen
@@ -261,16 +269,17 @@ rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag)
rt_sem_t sem;
RT_DEBUG_NOT_IN_INTERRUPT;
+ RT_ASSERT(value < 0x10000U);
/* allocate object */
sem = (rt_sem_t)rt_object_allocate(RT_Object_Class_Semaphore, name);
if (sem == RT_NULL)
return sem;
- /* init ipc object */
+ /* initialize ipc object */
rt_ipc_object_init(&(sem->parent));
- /* set init value */
+ /* set initial value */
sem->value = value;
/* set parent */
@@ -298,7 +307,7 @@ rt_err_t rt_sem_delete(rt_sem_t sem)
RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);
RT_ASSERT(rt_object_is_systemobject(&sem->parent.parent) == RT_FALSE);
- /* wakeup all suspend threads */
+ /* wakeup all suspended threads */
rt_ipc_list_resume_all(&(sem->parent.suspend_thread));
/* delete semaphore object */
@@ -455,7 +464,17 @@ rt_err_t rt_sem_release(rt_sem_t sem)
need_schedule = RT_TRUE;
}
else
- sem->value ++; /* increase value */
+ {
+ if(sem->value < RT_SEM_VALUE_MAX)
+ {
+ sem->value ++; /* increase value */
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+ }
/* enable interrupt */
rt_hw_interrupt_enable(temp);
@@ -529,10 +548,10 @@ rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag)
/* parameter check */
RT_ASSERT(mutex != RT_NULL);
- /* init object */
+ /* initialize object */
rt_object_init(&(mutex->parent.parent), RT_Object_Class_Mutex, name);
- /* init ipc object */
+ /* initialize ipc object */
rt_ipc_object_init(&(mutex->parent));
mutex->value = 1;
@@ -563,7 +582,7 @@ rt_err_t rt_mutex_detach(rt_mutex_t mutex)
RT_ASSERT(rt_object_get_type(&mutex->parent.parent) == RT_Object_Class_Mutex);
RT_ASSERT(rt_object_is_systemobject(&mutex->parent.parent));
- /* wakeup all suspend threads */
+ /* wakeup all suspended threads */
rt_ipc_list_resume_all(&(mutex->parent.suspend_thread));
/* detach semaphore object */
@@ -595,7 +614,7 @@ rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag)
if (mutex == RT_NULL)
return mutex;
- /* init ipc object */
+ /* initialize ipc object */
rt_ipc_object_init(&(mutex->parent));
mutex->value = 1;
@@ -628,10 +647,10 @@ rt_err_t rt_mutex_delete(rt_mutex_t mutex)
RT_ASSERT(rt_object_get_type(&mutex->parent.parent) == RT_Object_Class_Mutex);
RT_ASSERT(rt_object_is_systemobject(&mutex->parent.parent) == RT_FALSE);
- /* wakeup all suspend threads */
+ /* wakeup all suspended threads */
rt_ipc_list_resume_all(&(mutex->parent.suspend_thread));
- /* delete semaphore object */
+ /* delete mutex object */
rt_object_delete(&(mutex->parent.parent));
return RT_EOK;
@@ -677,12 +696,22 @@ rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
if (mutex->owner == thread)
{
- /* it's the same thread */
- mutex->hold ++;
+ if(mutex->hold < RT_MUTEX_HOLD_MAX)
+ {
+ /* it's the same thread */
+ mutex->hold ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
}
else
{
+#ifdef RT_USING_SIGNALS
__again:
+#endif /* end of RT_USING_SIGNALS */
/* The value of mutex is 1 in initial status. Therefore, if the
* value is great than 0, it indicates the mutex is avaible.
*/
@@ -694,7 +723,15 @@ __again:
/* set mutex owner and original priority */
mutex->owner = thread;
mutex->original_priority = thread->current_priority;
- mutex->hold ++;
+ if(mutex->hold < RT_MUTEX_HOLD_MAX)
+ {
+ mutex->hold ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
}
else
{
@@ -751,8 +788,10 @@ __again:
if (thread->error != RT_EOK)
{
- /* interrupt by signal, try it again */
- if (thread->error == -RT_EINTR) goto __again;
+#ifdef RT_USING_SIGNALS
+ /* interrupt by signal, try it again */
+ if (thread->error == -RT_EINTR) goto __again;
+#endif /* end of RT_USING_SIGNALS */
/* return error */
return thread->error;
@@ -849,7 +888,15 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
/* set new owner and priority */
mutex->owner = thread;
mutex->original_priority = thread->current_priority;
- mutex->hold ++;
+ if(mutex->hold < RT_MUTEX_HOLD_MAX)
+ {
+ mutex->hold ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
/* resume thread */
rt_ipc_list_resume(&(mutex->parent.suspend_thread));
@@ -858,9 +905,17 @@ rt_err_t rt_mutex_release(rt_mutex_t mutex)
}
else
{
- /* increase value */
- mutex->value ++;
-
+ if(mutex->value < RT_MUTEX_VALUE_MAX)
+ {
+ /* increase value */
+ mutex->value ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+
/* clear owner */
mutex->owner = RT_NULL;
mutex->original_priority = 0xff;
@@ -914,16 +969,16 @@ rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag)
/* parameter check */
RT_ASSERT(event != RT_NULL);
- /* init object */
+ /* initialize object */
rt_object_init(&(event->parent.parent), RT_Object_Class_Event, name);
/* set parent flag */
event->parent.parent.flag = flag;
- /* init ipc object */
+ /* initialize ipc object */
rt_ipc_object_init(&(event->parent));
- /* init event */
+ /* initialize event */
event->set = 0;
return RT_EOK;
@@ -977,10 +1032,10 @@ rt_event_t rt_event_create(const char *name, rt_uint8_t flag)
/* set parent */
event->parent.parent.flag = flag;
- /* init ipc object */
+ /* initialize ipc object */
rt_ipc_object_init(&(event->parent));
- /* init event */
+ /* initialize event */
event->set = 0;
return event;
@@ -1047,7 +1102,7 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)
event->set |= set;
RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(event->parent.parent)));
-
+
if (!rt_list_isempty(&event->parent.suspend_thread))
{
/* search thread list to resume thread */
@@ -1070,13 +1125,20 @@ rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set)
{
if (thread->event_set & event->set)
{
- /* save recieved event set */
+ /* save the received event set */
thread->event_set = thread->event_set & event->set;
/* received an OR event */
status = RT_EOK;
}
}
+ else
+ {
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return -RT_EINVAL;
+ }
/* move node to the next */
n = n->next;
@@ -1140,7 +1202,7 @@ rt_err_t rt_event_recv(rt_event_t event,
if (set == 0)
return -RT_ERROR;
- /* init status */
+ /* initialize status */
status = -RT_ERROR;
/* get current thread */
thread = rt_thread_self();
@@ -1174,7 +1236,11 @@ rt_err_t rt_event_recv(rt_event_t event,
/* set received event */
if (recved)
*recved = (event->set & set);
-
+
+ /* fill thread event info */
+ thread->event_set = (event->set & set);
+ thread->event_info = option;
+
/* received event */
if (option & RT_EVENT_FLAG_CLEAR)
event->set &= ~set;
@@ -1183,6 +1249,11 @@ rt_err_t rt_event_recv(rt_event_t event,
{
/* no waiting */
thread->error = -RT_ETIMEOUT;
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return -RT_ETIMEOUT;
}
else
{
@@ -1250,7 +1321,7 @@ rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg)
/* parameter check */
RT_ASSERT(event != RT_NULL);
RT_ASSERT(rt_object_get_type(&event->parent.parent) == RT_Object_Class_Event);
-
+
if (cmd == RT_IPC_CMD_RESET)
{
/* disable interrupt */
@@ -1259,7 +1330,7 @@ rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg)
/* resume all waiting thread */
rt_ipc_list_resume_all(&event->parent.suspend_thread);
- /* init event set */
+ /* initialize event set */
event->set = 0;
/* enable interrupt */
@@ -1296,23 +1367,23 @@ rt_err_t rt_mb_init(rt_mailbox_t mb,
{
RT_ASSERT(mb != RT_NULL);
- /* init object */
+ /* initialize object */
rt_object_init(&(mb->parent.parent), RT_Object_Class_MailBox, name);
/* set parent flag */
mb->parent.parent.flag = flag;
- /* init ipc object */
+ /* initialize ipc object */
rt_ipc_object_init(&(mb->parent));
- /* init mailbox */
- mb->msg_pool = msgpool;
+ /* initialize mailbox */
+ mb->msg_pool = (rt_ubase_t *)msgpool;
mb->size = size;
mb->entry = 0;
mb->in_offset = 0;
mb->out_offset = 0;
- /* init an additional list of sender suspend thread */
+ /* initialize an additional list of sender suspend thread */
rt_list_init(&(mb->suspend_sender_thread));
return RT_EOK;
@@ -1369,12 +1440,12 @@ rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag)
/* set parent */
mb->parent.parent.flag = flag;
- /* init ipc object */
+ /* initialize ipc object */
rt_ipc_object_init(&(mb->parent));
- /* init mailbox */
+ /* initialize mailbox */
mb->size = size;
- mb->msg_pool = RT_KERNEL_MALLOC(mb->size * sizeof(rt_ubase_t));
+ mb->msg_pool = (rt_ubase_t *)RT_KERNEL_MALLOC(mb->size * sizeof(rt_ubase_t));
if (mb->msg_pool == RT_NULL)
{
/* delete mailbox object */
@@ -1386,7 +1457,7 @@ rt_mailbox_t rt_mb_create(const char *name, rt_size_t size, rt_uint8_t flag)
mb->in_offset = 0;
mb->out_offset = 0;
- /* init an additional list of sender suspend thread */
+ /* initialize an additional list of sender suspend thread */
rt_list_init(&(mb->suspend_sender_thread));
return mb;
@@ -1535,9 +1606,18 @@ rt_err_t rt_mb_send_wait(rt_mailbox_t mb,
++ mb->in_offset;
if (mb->in_offset >= mb->size)
mb->in_offset = 0;
- /* increase message entry */
- mb->entry ++;
-
+
+ if(mb->entry < RT_MB_ENTRY_MAX)
+ {
+ /* increase message entry */
+ mb->entry ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+
/* resume suspended thread */
if (!rt_list_isempty(&mb->parent.suspend_thread))
{
@@ -1788,39 +1868,42 @@ rt_err_t rt_mq_init(rt_mq_t mq,
/* parameter check */
RT_ASSERT(mq != RT_NULL);
- /* init object */
+ /* initialize object */
rt_object_init(&(mq->parent.parent), RT_Object_Class_MessageQueue, name);
/* set parent flag */
mq->parent.parent.flag = flag;
- /* init ipc object */
+ /* initialize ipc object */
rt_ipc_object_init(&(mq->parent));
- /* set messasge pool */
+ /* set message pool */
mq->msg_pool = msgpool;
/* get correct message size */
mq->msg_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE);
mq->max_msgs = pool_size / (mq->msg_size + sizeof(struct rt_mq_message));
- /* init message list */
+ /* initialize message list */
mq->msg_queue_head = RT_NULL;
mq->msg_queue_tail = RT_NULL;
- /* init message empty list */
+ /* initialize message empty list */
mq->msg_queue_free = RT_NULL;
for (temp = 0; temp < mq->max_msgs; temp ++)
{
head = (struct rt_mq_message *)((rt_uint8_t *)mq->msg_pool +
temp * (mq->msg_size + sizeof(struct rt_mq_message)));
- head->next = mq->msg_queue_free;
+ head->next = (struct rt_mq_message *)mq->msg_queue_free;
mq->msg_queue_free = head;
}
/* the initial entry is zero */
mq->entry = 0;
+ /* initialize an additional list of sender suspend thread */
+ rt_list_init(&(mq->suspend_sender_thread));
+
return RT_EOK;
}
RTM_EXPORT(rt_mq_init);
@@ -1841,6 +1924,8 @@ rt_err_t rt_mq_detach(rt_mq_t mq)
/* resume all suspended thread */
rt_ipc_list_resume_all(&mq->parent.suspend_thread);
+ /* also resume all message queue private suspended thread */
+ rt_ipc_list_resume_all(&(mq->suspend_sender_thread));
/* detach message queue object */
rt_object_detach(&(mq->parent.parent));
@@ -1879,10 +1964,10 @@ rt_mq_t rt_mq_create(const char *name,
/* set parent */
mq->parent.parent.flag = flag;
- /* init ipc object */
+ /* initialize ipc object */
rt_ipc_object_init(&(mq->parent));
- /* init message queue */
+ /* initialize message queue */
/* get correct message size */
mq->msg_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE);
@@ -1892,28 +1977,31 @@ rt_mq_t rt_mq_create(const char *name,
mq->msg_pool = RT_KERNEL_MALLOC((mq->msg_size + sizeof(struct rt_mq_message)) * mq->max_msgs);
if (mq->msg_pool == RT_NULL)
{
- rt_mq_delete(mq);
+ rt_object_delete(&(mq->parent.parent));
return RT_NULL;
}
- /* init message list */
+ /* initialize message list */
mq->msg_queue_head = RT_NULL;
mq->msg_queue_tail = RT_NULL;
- /* init message empty list */
+ /* initialize message empty list */
mq->msg_queue_free = RT_NULL;
for (temp = 0; temp < mq->max_msgs; temp ++)
{
head = (struct rt_mq_message *)((rt_uint8_t *)mq->msg_pool +
temp * (mq->msg_size + sizeof(struct rt_mq_message)));
- head->next = mq->msg_queue_free;
+ head->next = (struct rt_mq_message *)mq->msg_queue_free;
mq->msg_queue_free = head;
}
/* the initial entry is zero */
mq->entry = 0;
+ /* initialize an additional list of sender suspend thread */
+ rt_list_init(&(mq->suspend_sender_thread));
+
return mq;
}
RTM_EXPORT(rt_mq_create);
@@ -1936,6 +2024,8 @@ rt_err_t rt_mq_delete(rt_mq_t mq)
/* resume all suspended thread */
rt_ipc_list_resume_all(&(mq->parent.suspend_thread));
+ /* also resume all message queue private suspended thread */
+ rt_ipc_list_resume_all(&(mq->suspend_sender_thread));
/* free message queue pool */
RT_KERNEL_FREE(mq->msg_pool);
@@ -1949,19 +2039,25 @@ RTM_EXPORT(rt_mq_delete);
#endif
/**
- * This function will send a message to message queue object, if there are
- * threads suspended on message queue object, it will be waked up.
+ * This function will send a message to message queue object. If the message queue is full,
+ * current thread will be suspended until timeout.
*
* @param mq the message queue object
* @param buffer the message
* @param size the size of buffer
+ * @param timeout the waiting time
*
* @return the error code
*/
-rt_err_t rt_mq_send(rt_mq_t mq, void *buffer, rt_size_t size)
+rt_err_t rt_mq_send_wait(rt_mq_t mq,
+ const void *buffer,
+ rt_size_t size,
+ rt_int32_t timeout)
{
register rt_ubase_t temp;
struct rt_mq_message *msg;
+ rt_uint32_t tick_delta;
+ struct rt_thread *thread;
/* parameter check */
RT_ASSERT(mq != RT_NULL);
@@ -1973,6 +2069,11 @@ rt_err_t rt_mq_send(rt_mq_t mq, void *buffer, rt_size_t size)
if (size > mq->msg_size)
return -RT_ERROR;
+ /* initialize delta tick */
+ tick_delta = 0;
+ /* get current thread */
+ thread = rt_thread_self();
+
RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mq->parent.parent)));
/* disable interrupt */
@@ -1980,14 +2081,78 @@ rt_err_t rt_mq_send(rt_mq_t mq, void *buffer, rt_size_t size)
/* get a free list, there must be an empty item */
msg = (struct rt_mq_message *)mq->msg_queue_free;
- /* message queue is full */
- if (msg == RT_NULL)
+ /* for non-blocking call */
+ if (msg == RT_NULL && timeout == 0)
{
/* enable interrupt */
rt_hw_interrupt_enable(temp);
return -RT_EFULL;
}
+
+ /* message queue is full */
+ while ((msg = mq->msg_queue_free) == RT_NULL)
+ {
+ /* reset error number in thread */
+ thread->error = RT_EOK;
+
+ /* no waiting, return timeout */
+ if (timeout == 0)
+ {
+ /* enable interrupt */
+ rt_hw_interrupt_enable(temp);
+
+ return -RT_EFULL;
+ }
+
+ RT_DEBUG_IN_THREAD_CONTEXT;
+ /* suspend current thread */
+ rt_ipc_list_suspend(&(mq->suspend_sender_thread),
+ thread,
+ mq->parent.parent.flag);
+
+ /* has waiting time, start thread timer */
+ if (timeout > 0)
+ {
+ /* get the start tick of timer */
+ tick_delta = rt_tick_get();
+
+ RT_DEBUG_LOG(RT_DEBUG_IPC, ("mq_send_wait: start timer of thread:%s\n",
+ thread->name));
+
+ /* reset the timeout of thread timer and start it */
+ rt_timer_control(&(thread->thread_timer),
+ RT_TIMER_CTRL_SET_TIME,
+ &timeout);
+ rt_timer_start(&(thread->thread_timer));
+ }
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(temp);
+
+ /* re-schedule */
+ rt_schedule();
+
+ /* resume from suspend state */
+ if (thread->error != RT_EOK)
+ {
+ /* return error */
+ return thread->error;
+ }
+
+ /* disable interrupt */
+ temp = rt_hw_interrupt_disable();
+
+ /* if it's not waiting forever and then re-calculate timeout tick */
+ if (timeout > 0)
+ {
+ tick_delta = rt_tick_get() - tick_delta;
+ timeout -= tick_delta;
+ if (timeout < 0)
+ timeout = 0;
+ }
+ }
+
/* move free list pointer */
mq->msg_queue_free = msg->next;
@@ -2014,8 +2179,16 @@ rt_err_t rt_mq_send(rt_mq_t mq, void *buffer, rt_size_t size)
if (mq->msg_queue_head == RT_NULL)
mq->msg_queue_head = msg;
- /* increase message entry */
- mq->entry ++;
+ if(mq->entry < RT_MQ_ENTRY_MAX)
+ {
+ /* increase message entry */
+ mq->entry ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
/* resume suspended thread */
if (!rt_list_isempty(&mq->parent.suspend_thread))
@@ -2035,6 +2208,22 @@ rt_err_t rt_mq_send(rt_mq_t mq, void *buffer, rt_size_t size)
return RT_EOK;
}
+RTM_EXPORT(rt_mq_send_wait)
+
+/**
+ * This function will send a message to message queue object, if there are
+ * threads suspended on message queue object, it will be waked up.
+ *
+ * @param mq the message queue object
+ * @param buffer the message
+ * @param size the size of buffer
+ *
+ * @return the error code
+ */
+rt_err_t rt_mq_send(rt_mq_t mq, const void *buffer, rt_size_t size)
+{
+ return rt_mq_send_wait(mq, buffer, size, 0);
+}
RTM_EXPORT(rt_mq_send);
/**
@@ -2048,7 +2237,7 @@ RTM_EXPORT(rt_mq_send);
*
* @return the error code
*/
-rt_err_t rt_mq_urgent(rt_mq_t mq, void *buffer, rt_size_t size)
+rt_err_t rt_mq_urgent(rt_mq_t mq, const void *buffer, rt_size_t size)
{
register rt_ubase_t temp;
struct rt_mq_message *msg;
@@ -2091,16 +2280,24 @@ rt_err_t rt_mq_urgent(rt_mq_t mq, void *buffer, rt_size_t size)
temp = rt_hw_interrupt_disable();
/* link msg to the beginning of message queue */
- msg->next = mq->msg_queue_head;
+ msg->next = (struct rt_mq_message *)mq->msg_queue_head;
mq->msg_queue_head = msg;
/* if there is no tail */
if (mq->msg_queue_tail == RT_NULL)
mq->msg_queue_tail = msg;
- /* increase message entry */
- mq->entry ++;
-
+ if(mq->entry < RT_MQ_ENTRY_MAX)
+ {
+ /* increase message entry */
+ mq->entry ++;
+ }
+ else
+ {
+ rt_hw_interrupt_enable(temp); /* enable interrupt */
+ return -RT_EFULL; /* value overflowed */
+ }
+
/* resume suspended thread */
if (!rt_list_isempty(&mq->parent.suspend_thread))
{
@@ -2255,6 +2452,22 @@ rt_err_t rt_mq_recv(rt_mq_t mq,
/* put message to free list */
msg->next = (struct rt_mq_message *)mq->msg_queue_free;
mq->msg_queue_free = msg;
+
+ /* resume suspended thread */
+ if (!rt_list_isempty(&(mq->suspend_sender_thread)))
+ {
+ rt_ipc_list_resume(&(mq->suspend_sender_thread));
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(temp);
+
+ RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(mq->parent.parent)));
+
+ rt_schedule();
+
+ return RT_EOK;
+ }
+
/* enable interrupt */
rt_hw_interrupt_enable(temp);
@@ -2290,6 +2503,8 @@ rt_err_t rt_mq_control(rt_mq_t mq, int cmd, void *arg)
/* resume all waiting thread */
rt_ipc_list_resume_all(&mq->parent.suspend_thread);
+ /* also resume all message queue private suspended thread */
+ rt_ipc_list_resume_all(&(mq->suspend_sender_thread));
/* release all message in the queue */
while (mq->msg_queue_head != RT_NULL)
diff --git a/src/irq.c b/src/irq.c
index 78ad586064..311d297bfe 100644
--- a/src/irq.c
+++ b/src/irq.c
@@ -105,7 +105,7 @@ RTM_EXPORT(rt_interrupt_leave);
*
* @return the number of nested interrupts.
*/
-rt_uint8_t rt_interrupt_get_nest(void)
+RT_WEAK rt_uint8_t rt_interrupt_get_nest(void)
{
rt_uint8_t ret;
rt_base_t level;
diff --git a/src/kservice.c b/src/kservice.c
index c938f4110a..0a74f05268 100644
--- a/src/kservice.c
+++ b/src/kservice.c
@@ -316,7 +316,7 @@ RTM_EXPORT(rt_memmove);
* This function will compare two areas of memory
*
* @param cs one area of memory
- * @param ct znother area of memory
+ * @param ct another area of memory
* @param count the size of the area
*
* @return the result
@@ -326,7 +326,7 @@ rt_int32_t rt_memcmp(const void *cs, const void *ct, rt_ubase_t count)
const unsigned char *su1, *su2;
int res = 0;
- for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ for (su1 = (const unsigned char *)cs, su2 = (const unsigned char *)ct; 0 < count; ++su1, ++su2, count--)
if ((res = *su1 - *su2) != 0)
break;
@@ -370,7 +370,7 @@ RTM_EXPORT(rt_strstr);
*
* @return the result
*/
-rt_uint32_t rt_strcasecmp(const char *a, const char *b)
+rt_int32_t rt_strcasecmp(const char *a, const char *b)
{
int ca, cb;
@@ -456,11 +456,15 @@ RTM_EXPORT(rt_strncmp);
rt_int32_t rt_strcmp(const char *cs, const char *ct)
{
while (*cs && *cs == *ct)
- cs++, ct++;
+ {
+ cs++;
+ ct++;
+ }
return (*cs - *ct);
}
RTM_EXPORT(rt_strcmp);
+
/**
* The strnlen() function returns the number of characters in the
* string pointed to by s, excluding the terminating null byte ('\0'),
@@ -476,11 +480,13 @@ rt_size_t rt_strnlen(const char *s, rt_ubase_t maxlen)
{
const char *sc;
- for (sc = s; *sc != '\0' && sc - s < maxlen; ++sc) /* nothing */
+ for (sc = s; *sc != '\0' && (rt_ubase_t)(sc - s) < maxlen; ++sc) /* nothing */
;
return sc - s;
}
+RTM_EXPORT(rt_strnlen);
+
/**
* This function will return the length of a string, which terminate will
* null character.
@@ -535,13 +541,33 @@ void rt_show_version(void)
rt_kprintf("- RT - Thread Operating System\n");
rt_kprintf(" / | \\ %d.%d.%d build %s\n",
RT_VERSION, RT_SUBVERSION, RT_REVISION, __DATE__);
- rt_kprintf(" 2006 - 2018 Copyright by rt-thread team\n");
+ rt_kprintf(" 2006 - 2020 Copyright by rt-thread team\n");
}
RTM_EXPORT(rt_show_version);
/* private function */
-#define isdigit(c) ((unsigned)((c) - '0') < 10)
+#define _ISDIGIT(c) ((unsigned)((c) - '0') < 10)
+
+#ifdef RT_PRINTF_LONGLONG
+rt_inline int divide(long long *n, int base)
+{
+ int res;
+
+ /* optimized for processor which does not support divide instructions. */
+ if (base == 10)
+ {
+ res = (int)(((unsigned long long)*n) % 10U);
+ *n = (long long)(((unsigned long long)*n) / 10U);
+ }
+ else
+ {
+ res = (int)(((unsigned long long)*n) % 16U);
+ *n = (long long)(((unsigned long long)*n) / 16U);
+ }
+ return res;
+}
+#else
rt_inline int divide(long *n, int base)
{
int res;
@@ -560,11 +586,12 @@ rt_inline int divide(long *n, int base)
return res;
}
+#endif
rt_inline int skip_atoi(const char **s)
{
register int i = 0;
- while (isdigit(**s))
+ while (_ISDIGIT(**s))
i = i * 10 + *((*s)++) - '0';
return i;
@@ -581,7 +608,11 @@ rt_inline int skip_atoi(const char **s)
#ifdef RT_PRINTF_PRECISION
static char *print_number(char *buf,
char *end,
+#ifdef RT_PRINTF_LONGLONG
+ long long num,
+#else
long num,
+#endif
int base,
int s,
int precision,
@@ -589,7 +620,11 @@ static char *print_number(char *buf,
#else
static char *print_number(char *buf,
char *end,
+#ifdef RT_PRINTF_LONGLONG
+ long long num,
+#else
long num,
+#endif
int base,
int s,
int type)
@@ -601,6 +636,7 @@ static char *print_number(char *buf,
#else
char tmp[16];
#endif
+ int precision_bak = precision;
const char *digits;
static const char small_digits[] = "0123456789abcdef";
static const char large_digits[] = "0123456789ABCDEF";
@@ -664,7 +700,7 @@ static char *print_number(char *buf,
while (size-- > 0)
{
- if (buf <= end)
+ if (buf < end)
*buf = ' ';
++ buf;
}
@@ -672,11 +708,11 @@ static char *print_number(char *buf,
if (sign)
{
- if (buf <= end)
+ if (buf < end)
{
*buf = sign;
- -- size;
}
+ -- size;
++ buf;
}
@@ -685,16 +721,16 @@ static char *print_number(char *buf,
{
if (base == 8)
{
- if (buf <= end)
+ if (buf < end)
*buf = '0';
++ buf;
}
else if (base == 16)
{
- if (buf <= end)
+ if (buf < end)
*buf = '0';
++ buf;
- if (buf <= end)
+ if (buf < end)
{
*buf = type & LARGE ? 'X' : 'x';
}
@@ -708,7 +744,7 @@ static char *print_number(char *buf,
{
while (size-- > 0)
{
- if (buf <= end)
+ if (buf < end)
*buf = c;
++ buf;
}
@@ -717,23 +753,23 @@ static char *print_number(char *buf,
#ifdef RT_PRINTF_PRECISION
while (i < precision--)
{
- if (buf <= end)
+ if (buf < end)
*buf = '0';
++ buf;
}
#endif
/* put number in the temporary buffer */
- while (i-- > 0)
+ while (i-- > 0 && (precision_bak != 0))
{
- if (buf <= end)
+ if (buf < end)
*buf = tmp[i];
++ buf;
}
while (size-- > 0)
{
- if (buf <= end)
+ if (buf < end)
*buf = ' ';
++ buf;
}
@@ -765,7 +801,7 @@ rt_int32_t rt_vsnprintf(char *buf,
#endif
str = buf;
- end = buf + size - 1;
+ end = buf + size;
/* Make sure end is always >= buf */
if (end < buf)
@@ -778,7 +814,7 @@ rt_int32_t rt_vsnprintf(char *buf,
{
if (*fmt != '%')
{
- if (str <= end)
+ if (str < end)
*str = *fmt;
++ str;
continue;
@@ -801,7 +837,7 @@ rt_int32_t rt_vsnprintf(char *buf,
/* get field width */
field_width = -1;
- if (isdigit(*fmt)) field_width = skip_atoi(&fmt);
+ if (_ISDIGIT(*fmt)) field_width = skip_atoi(&fmt);
else if (*fmt == '*')
{
++ fmt;
@@ -820,7 +856,7 @@ rt_int32_t rt_vsnprintf(char *buf,
if (*fmt == '.')
{
++ fmt;
- if (isdigit(*fmt)) precision = skip_atoi(&fmt);
+ if (_ISDIGIT(*fmt)) precision = skip_atoi(&fmt);
else if (*fmt == '*')
{
++ fmt;
@@ -859,20 +895,20 @@ rt_int32_t rt_vsnprintf(char *buf,
{
while (--field_width > 0)
{
- if (str <= end) *str = ' ';
+ if (str < end) *str = ' ';
++ str;
}
}
/* get character */
c = (rt_uint8_t)va_arg(args, int);
- if (str <= end) *str = c;
+ if (str < end) *str = c;
++ str;
/* put width */
while (--field_width > 0)
{
- if (str <= end) *str = ' ';
+ if (str < end) *str = ' ';
++ str;
}
continue;
@@ -890,21 +926,21 @@ rt_int32_t rt_vsnprintf(char *buf,
{
while (len < field_width--)
{
- if (str <= end) *str = ' ';
+ if (str < end) *str = ' ';
++ str;
}
}
for (i = 0; i < len; ++i)
{
- if (str <= end) *str = *s;
+ if (str < end) *str = *s;
++ str;
++ s;
}
while (len < field_width--)
{
- if (str <= end) *str = ' ';
+ if (str < end) *str = ' ';
++ str;
}
continue;
@@ -927,7 +963,7 @@ rt_int32_t rt_vsnprintf(char *buf,
continue;
case '%':
- if (str <= end) *str = '%';
+ if (str < end) *str = '%';
++ str;
continue;
@@ -949,12 +985,12 @@ rt_int32_t rt_vsnprintf(char *buf,
break;
default:
- if (str <= end) *str = '%';
+ if (str < end) *str = '%';
++ str;
if (*fmt)
{
- if (str <= end) *str = *fmt;
+ if (str < end) *str = *fmt;
++ str;
}
else
@@ -991,8 +1027,14 @@ rt_int32_t rt_vsnprintf(char *buf,
#endif
}
- if (str <= end) *str = '\0';
- else *end = '\0';
+ if (size > 0)
+ {
+ if (str < end) *str = '\0';
+ else
+ {
+ end[-1] = '\0';
+ }
+ }
/* the trailing null byte doesn't count towards the total
* ++str;
@@ -1074,18 +1116,22 @@ RTM_EXPORT(rt_console_get_device);
*
* @param name the name of new console device
*
- * @return the old console device handler
+ * @return the old console device handler on successful, or RT_NULL on failure.
*/
rt_device_t rt_console_set_device(const char *name)
{
- rt_device_t new, old;
+ rt_device_t new_device, old_device;
/* save old device */
- old = _console_device;
+ old_device = _console_device;
/* find new console device */
- new = rt_device_find(name);
- if (new != RT_NULL)
+ new_device = rt_device_find(name);
+
+ /* check whether it's a same device */
+ if (new_device == old_device) return RT_NULL;
+
+ if (new_device != RT_NULL)
{
if (_console_device != RT_NULL)
{
@@ -1094,11 +1140,11 @@ rt_device_t rt_console_set_device(const char *name)
}
/* set new console device */
- rt_device_open(new, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
- _console_device = new;
+ rt_device_open(new_device, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_STREAM);
+ _console_device = new_device;
}
- return old;
+ return old_device;
}
RTM_EXPORT(rt_console_set_device);
#endif
@@ -1293,7 +1339,9 @@ int __rt_ffs(int value)
#ifdef RT_DEBUG
/* RT_ASSERT(EX)'s hook */
+
void (*rt_assert_hook)(const char *ex, const char *func, rt_size_t line);
+
/**
* This function will set a hook function to RT_ASSERT(EX). It will run when the expression is false.
*
diff --git a/src/mem.c b/src/mem.c
index ca5329404e..c03c8b3452 100644
--- a/src/mem.c
+++ b/src/mem.c
@@ -489,6 +489,12 @@ void *rt_realloc(void *rmem, rt_size_t newsize)
{
((struct heap_mem *)&heap_ptr[mem2->next])->prev = ptr2;
}
+
+ if (mem2 < lfree)
+ {
+ /* the splited struct is now the lowest */
+ lfree = mem2;
+ }
plug_holes(mem2);
@@ -644,7 +650,7 @@ int memcheck(void)
{
position = (rt_ubase_t)mem - (rt_ubase_t)heap_ptr;
if (position < 0) goto __exit;
- if (position > mem_size_aligned) goto __exit;
+ if (position > (int)mem_size_aligned) goto __exit;
if (mem->magic != HEAP_MAGIC) goto __exit;
if (mem->used != 0 && mem->used != 1) goto __exit;
}
diff --git a/src/memheap.c b/src/memheap.c
index eb5d710029..0ff6925696 100644
--- a/src/memheap.c
+++ b/src/memheap.c
@@ -34,7 +34,7 @@
#define RT_MEMHEAP_MINIALLOC 12
#define RT_MEMHEAP_SIZE RT_ALIGN(sizeof(struct rt_memheap_item), RT_ALIGN_SIZE)
-#define MEMITEM_SIZE(item) ((rt_uint32_t)item->next - (rt_uint32_t)item - RT_MEMHEAP_SIZE)
+#define MEMITEM_SIZE(item) ((rt_ubase_t)item->next - (rt_ubase_t)item - RT_MEMHEAP_SIZE)
/*
* The initialized memory pool will be:
@@ -126,8 +126,8 @@ rt_err_t rt_memheap_detach(struct rt_memheap *heap)
RT_ASSERT(heap);
RT_ASSERT(rt_object_get_type(&heap->parent) == RT_Object_Class_MemHeap);
RT_ASSERT(rt_object_is_systemobject(&heap->parent));
-
- rt_object_detach(&(heap->lock.parent.parent));
+
+ rt_sem_detach(&heap->lock);
rt_object_detach(&(heap->parent));
/* Return a successful completion. */
diff --git a/src/mempool.c b/src/mempool.c
index 2184586aba..db614032aa 100644
--- a/src/mempool.c
+++ b/src/mempool.c
@@ -85,6 +85,9 @@ rt_err_t rt_mp_init(struct rt_mempool *mp,
/* parameter check */
RT_ASSERT(mp != RT_NULL);
+ RT_ASSERT(name != RT_NULL);
+ RT_ASSERT(start != RT_NULL);
+ RT_ASSERT(size > 0 && block_size > 0);
/* initialize object */
rt_object_init(&(mp->parent), RT_Object_Class_MemPool, name);
@@ -103,7 +106,6 @@ rt_err_t rt_mp_init(struct rt_mempool *mp,
/* initialize suspended thread list */
rt_list_init(&(mp->suspend_thread));
- mp->suspend_thread_count = 0;
/* initialize free block list */
block_ptr = (rt_uint8_t *)mp->start_address;
@@ -132,7 +134,7 @@ RTM_EXPORT(rt_mp_init);
rt_err_t rt_mp_detach(struct rt_mempool *mp)
{
struct rt_thread *thread;
- register rt_ubase_t temp;
+ register rt_ubase_t level;
/* parameter check */
RT_ASSERT(mp != RT_NULL);
@@ -143,7 +145,7 @@ rt_err_t rt_mp_detach(struct rt_mempool *mp)
while (!rt_list_isempty(&(mp->suspend_thread)))
{
/* disable interrupt */
- temp = rt_hw_interrupt_disable();
+ level = rt_hw_interrupt_disable();
/* get next suspend thread */
thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);
@@ -157,11 +159,8 @@ rt_err_t rt_mp_detach(struct rt_mempool *mp)
*/
rt_thread_resume(thread);
- /* decrease suspended thread count */
- mp->suspend_thread_count --;
-
/* enable interrupt */
- rt_hw_interrupt_enable(temp);
+ rt_hw_interrupt_enable(level);
}
/* detach object */
@@ -192,6 +191,10 @@ rt_mp_t rt_mp_create(const char *name,
RT_DEBUG_NOT_IN_INTERRUPT;
+ /* parameter check */
+ RT_ASSERT(name != RT_NULL);
+ RT_ASSERT(block_count > 0 && block_size > 0);
+
/* allocate object */
mp = (struct rt_mempool *)rt_object_allocate(RT_Object_Class_MemPool, name);
/* allocate object failed */
@@ -219,7 +222,6 @@ rt_mp_t rt_mp_create(const char *name,
/* initialize suspended thread list */
rt_list_init(&(mp->suspend_thread));
- mp->suspend_thread_count = 0;
/* initialize free block list */
block_ptr = (rt_uint8_t *)mp->start_address;
@@ -248,7 +250,7 @@ RTM_EXPORT(rt_mp_create);
rt_err_t rt_mp_delete(rt_mp_t mp)
{
struct rt_thread *thread;
- register rt_ubase_t temp;
+ register rt_ubase_t level;
RT_DEBUG_NOT_IN_INTERRUPT;
@@ -261,7 +263,7 @@ rt_err_t rt_mp_delete(rt_mp_t mp)
while (!rt_list_isempty(&(mp->suspend_thread)))
{
/* disable interrupt */
- temp = rt_hw_interrupt_disable();
+ level = rt_hw_interrupt_disable();
/* get next suspend thread */
thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);
@@ -275,11 +277,8 @@ rt_err_t rt_mp_delete(rt_mp_t mp)
*/
rt_thread_resume(thread);
- /* decrease suspended thread count */
- mp->suspend_thread_count --;
-
/* enable interrupt */
- rt_hw_interrupt_enable(temp);
+ rt_hw_interrupt_enable(level);
}
/* release allocated room */
@@ -308,6 +307,9 @@ void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time)
struct rt_thread *thread;
rt_uint32_t before_sleep = 0;
+ /* parameter check */
+ RT_ASSERT(mp != RT_NULL);
+
/* get current thread */
thread = rt_thread_self();
@@ -334,7 +336,6 @@ void *rt_mp_alloc(rt_mp_t mp, rt_int32_t time)
/* need suspend thread */
rt_thread_suspend(thread);
rt_list_insert_after(&(mp->suspend_thread), &(thread->tlist));
- mp->suspend_thread_count++;
if (time > 0)
{
@@ -402,6 +403,9 @@ void rt_mp_free(void *block)
struct rt_thread *thread;
register rt_base_t level;
+ /* parameter check */
+ if (block == RT_NULL) return;
+
/* get the control block of pool which the block belongs to */
block_ptr = (rt_uint8_t **)((rt_uint8_t *)block - sizeof(rt_uint8_t *));
mp = (struct rt_mempool *)*block_ptr;
@@ -418,7 +422,7 @@ void rt_mp_free(void *block)
*block_ptr = mp->block_list;
mp->block_list = (rt_uint8_t *)block_ptr;
- if (mp->suspend_thread_count > 0)
+ if (!rt_list_isempty(&(mp->suspend_thread)))
{
/* get the suspended thread */
thread = rt_list_entry(mp->suspend_thread.next,
@@ -431,9 +435,6 @@ void rt_mp_free(void *block)
/* resume thread */
rt_thread_resume(thread);
- /* decrease suspended thread count */
- mp->suspend_thread_count --;
-
/* enable interrupt */
rt_hw_interrupt_enable(level);
diff --git a/src/object.c b/src/object.c
index 70b9a5c04e..6866d805ca 100644
--- a/src/object.c
+++ b/src/object.c
@@ -212,7 +212,9 @@ void rt_system_object_init(void)
/**
* This function will return the specified type of object information.
*
- * @param type the type of object
+ * @param type the type of object, which can be
+ * RT_Object_Class_Thread/Semaphore/Mutex... etc
+ *
* @return the object type information or RT_NULL
*/
struct rt_object_information *
@@ -228,6 +230,77 @@ rt_object_get_information(enum rt_object_class_type type)
RTM_EXPORT(rt_object_get_information);
/**
+ * This function will return the length of object list in object container.
+ *
+ * @param type the type of object, which can be
+ * RT_Object_Class_Thread/Semaphore/Mutex... etc
+ * @return the length of object list
+ */
+int rt_object_get_length(enum rt_object_class_type type)
+{
+ int count = 0;
+ rt_ubase_t level;
+ struct rt_list_node *node = RT_NULL;
+ struct rt_object_information *information = RT_NULL;
+
+ information = rt_object_get_information((enum rt_object_class_type)type);
+ if (information == RT_NULL) return 0;
+
+ level = rt_hw_interrupt_disable();
+ /* get the count of objects */
+ rt_list_for_each(node, &(information->object_list))
+ {
+ count ++;
+ }
+ rt_hw_interrupt_enable(level);
+
+ return count;
+}
+RTM_EXPORT(rt_object_get_length);
+
+/**
+ * This function will copy the object pointer of the specified type,
+ * with the maximum size specified by maxlen.
+ *
+ * @param type the type of object, which can be
+ * RT_Object_Class_Thread/Semaphore/Mutex... etc
+ * @param pointers the pointers will be saved to
+ * @param maxlen the maximum number of pointers can be saved
+ *
+ * @return the copied number of object pointers
+ */
+int rt_object_get_pointers(enum rt_object_class_type type, rt_object_t *pointers, int maxlen)
+{
+ int index = 0;
+ rt_ubase_t level;
+
+ struct rt_object *object;
+ struct rt_list_node *node = RT_NULL;
+ struct rt_object_information *information = RT_NULL;
+
+ if (maxlen <= 0) return 0;
+
+ information = rt_object_get_information((enum rt_object_class_type)type);
+ if (information == RT_NULL) return 0;
+
+ level = rt_hw_interrupt_disable();
+ /* retrieve pointer of object */
+ rt_list_for_each(node, &(information->object_list))
+ {
+ object = rt_list_entry(node, struct rt_object, list);
+
+ pointers[index] = object;
+ index ++;
+
+ if (index >= maxlen) break;
+ }
+ rt_hw_interrupt_enable(level);
+
+ return index;
+}
+RTM_EXPORT(rt_object_get_pointers);
+
+/**
* This function will initialize an object and add it to object system
* management.
*
@@ -240,6 +313,7 @@ void rt_object_init(struct rt_object *object,
const char *name)
{
register rt_base_t temp;
+ struct rt_list_node *node = RT_NULL;
struct rt_object_information *information;
#ifdef RT_USING_MODULE
struct rt_dlmodule *module = dlmodule_self();
@@ -249,11 +323,29 @@ void rt_object_init(struct rt_object *object,
information = rt_object_get_information(type);
RT_ASSERT(information != RT_NULL);
- /* initialize object's parameters */
+ /* check object type to avoid re-initialization */
+
+ /* enter critical */
+ rt_enter_critical();
+ /* try to find object */
+ for (node = information->object_list.next;
+ node != &(information->object_list);
+ node = node->next)
+ {
+ struct rt_object *obj;
+ obj = rt_list_entry(node, struct rt_object, list);
+ if (obj) /* skip warning when disable debug */
+ {
+ RT_ASSERT(obj != object);
+ }
+ }
+ /* leave critical */
+ rt_exit_critical();
+
+ /* initialize object's parameters */
/* set object type to static */
object->type = type | RT_Object_Class_Static;
-
/* copy name */
rt_strncpy(object->name, name, RT_NAME_MAX);
@@ -463,9 +555,10 @@ rt_object_t rt_object_find(const char *name, rt_uint8_t type)
struct rt_list_node *node = RT_NULL;
struct rt_object_information *information = RT_NULL;
+ information = rt_object_get_information((enum rt_object_class_type)type);
+
/* parameter check */
- if ((name == RT_NULL) || (type > RT_Object_Class_Unknown))
- return RT_NULL;
+ if ((name == RT_NULL) || (information == RT_NULL)) return RT_NULL;
/* which is invoke in interrupt status */
RT_DEBUG_NOT_IN_INTERRUPT;
@@ -474,14 +567,7 @@ rt_object_t rt_object_find(const char *name, rt_uint8_t type)
rt_enter_critical();
/* try to find object */
- if (information == RT_NULL)
- {
- information = rt_object_get_information((enum rt_object_class_type)type);
- RT_ASSERT(information != RT_NULL);
- }
- for (node = information->object_list.next;
- node != &(information->object_list);
- node = node->next)
+ rt_list_for_each(node, &(information->object_list))
{
object = rt_list_entry(node, struct rt_object, list);
if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
diff --git a/src/scheduler.c b/src/scheduler.c
index aafa1f4529..2250c4a006 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -33,10 +33,6 @@
#include <rtthread.h>
#include <rthw.h>
-#ifdef RT_USING_SMP
-rt_hw_spinlock_t _rt_critical_lock;
-#endif /*RT_USING_SMP*/
-
rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
rt_uint32_t rt_thread_ready_priority_group;
#if RT_THREAD_PRIORITY_MAX > 32
@@ -82,7 +78,11 @@ static void _rt_scheduler_stack_check(struct rt_thread *thread)
{
RT_ASSERT(thread != RT_NULL);
+#if defined(ARCH_CPU_STACK_GROWS_UPWARD)
+ if (*((rt_uint8_t *)((rt_ubase_t)thread->stack_addr + thread->stack_size - 1)) != '#' ||
+#else
if (*((rt_uint8_t *)thread->stack_addr) != '#' ||
+#endif
(rt_ubase_t)thread->sp <= (rt_ubase_t)thread->stack_addr ||
(rt_ubase_t)thread->sp >
(rt_ubase_t)thread->stack_addr + (rt_ubase_t)thread->stack_size)
@@ -124,17 +124,9 @@ static struct rt_thread* _get_highest_priority_thread(rt_ubase_t *highest_prio)
register struct rt_thread *highest_priority_thread;
register rt_ubase_t highest_ready_priority, local_highest_ready_priority;
struct rt_cpu* pcpu = rt_cpu_self();
-
#if RT_THREAD_PRIORITY_MAX > 32
register rt_ubase_t number;
- if (rt_thread_ready_priority_group == 0 && pcpu->priority_group == 0)
- {
- *highest_prio = pcpu->current_thread->current_priority;
- /* only local IDLE is readly */
- return pcpu->current_thread;
- }
-
number = __rt_ffs(rt_thread_ready_priority_group) - 1;
highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1;
number = __rt_ffs(pcpu->priority_group) - 1;
@@ -261,12 +253,13 @@ void rt_system_scheduler_start(void)
#endif /*RT_USING_SMP*/
rt_schedule_remove_thread(to_thread);
+ to_thread->stat = RT_THREAD_RUNNING;
/* switch to new thread */
#ifdef RT_USING_SMP
- rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp, to_thread);
+ rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp, to_thread);
#else
- rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp);
+ rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp);
#endif /*RT_USING_SMP*/
/* never come back */
@@ -307,7 +300,7 @@ void rt_schedule(void)
int cpu_id;
/* disable interrupt */
- level = rt_hw_interrupt_disable();
+ level = rt_hw_interrupt_disable();
cpu_id = rt_hw_cpu_id();
pcpu = rt_cpu_index(cpu_id);
@@ -317,8 +310,23 @@ void rt_schedule(void)
if (pcpu->irq_nest)
{
pcpu->irq_switch_flag = 1;
+ rt_hw_interrupt_enable(level);
+ goto __exit;
+ }
+
+#ifdef RT_USING_SIGNALS
+ if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
+ {
+ /* if current_thread signal is in pending */
+
+ if ((current_thread->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL_PENDING)
+ {
+ rt_thread_resume(current_thread);
+ }
}
- else if (current_thread->scheduler_lock_nest == 1) /* whether lock scheduler */
+#endif
+
+ if (current_thread->scheduler_lock_nest == 1) /* whether lock scheduler */
{
rt_ubase_t highest_ready_priority;
@@ -326,16 +334,21 @@ void rt_schedule(void)
{
to_thread = _get_highest_priority_thread(&highest_ready_priority);
current_thread->oncpu = RT_CPU_DETACHED;
- if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY)
+ if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)
{
if (current_thread->current_priority < highest_ready_priority)
{
to_thread = current_thread;
}
+ else if (current_thread->current_priority == highest_ready_priority && (current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
+ {
+ to_thread = current_thread;
+ }
else
{
rt_schedule_insert_thread(current_thread);
}
+ current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
}
to_thread->oncpu = cpu_id;
if (to_thread != current_thread)
@@ -346,6 +359,7 @@ void rt_schedule(void)
RT_OBJECT_HOOK_CALL(rt_scheduler_hook, (current_thread, to_thread));
rt_schedule_remove_thread(to_thread);
+ to_thread->stat = RT_THREAD_RUNNING | (to_thread->stat & ~RT_THREAD_STAT_MASK);
/* switch to new thread */
RT_DEBUG_LOG(RT_DEBUG_SCHEDULER,
@@ -360,21 +374,8 @@ void rt_schedule(void)
_rt_scheduler_stack_check(to_thread);
#endif
- {
- extern void rt_thread_handle_sig(rt_bool_t clean_state);
-
- rt_hw_context_switch((rt_ubase_t)&current_thread->sp,
- (rt_ubase_t)&to_thread->sp, to_thread);
-
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
-
-#ifdef RT_USING_SIGNALS
- /* check signal status */
- rt_thread_handle_sig(RT_TRUE);
-#endif
- goto __exit;
- }
+ rt_hw_context_switch((rt_ubase_t)&current_thread->sp,
+ (rt_ubase_t)&to_thread->sp, to_thread);
}
}
}
@@ -382,6 +383,26 @@ void rt_schedule(void)
/* enable interrupt */
rt_hw_interrupt_enable(level);
+#ifdef RT_USING_SIGNALS
+ /* check stat of thread for signal */
+ level = rt_hw_interrupt_disable();
+ if (current_thread->stat & RT_THREAD_STAT_SIGNAL_PENDING)
+ {
+ extern void rt_thread_handle_sig(rt_bool_t clean_state);
+
+ current_thread->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
+
+ rt_hw_interrupt_enable(level);
+
+ /* check signal status */
+ rt_thread_handle_sig(RT_TRUE);
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
+#endif
+
__exit:
return ;
}
@@ -406,20 +427,26 @@ void rt_schedule(void)
if (rt_thread_ready_priority_group != 0)
{
+ /* need_insert_from_thread: need to insert from_thread to ready queue */
int need_insert_from_thread = 0;
to_thread = _get_highest_priority_thread(&highest_ready_priority);
- if ((rt_current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY)
+ if ((rt_current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)
{
if (rt_current_thread->current_priority < highest_ready_priority)
{
to_thread = rt_current_thread;
}
+ else if (rt_current_thread->current_priority == highest_ready_priority && (rt_current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
+ {
+ to_thread = rt_current_thread;
+ }
else
{
need_insert_from_thread = 1;
}
+ rt_current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
}
if (to_thread != rt_current_thread)
@@ -437,12 +464,13 @@ void rt_schedule(void)
}
rt_schedule_remove_thread(to_thread);
+ to_thread->stat = RT_THREAD_RUNNING | (to_thread->stat & ~RT_THREAD_STAT_MASK);
/* switch to new thread */
RT_DEBUG_LOG(RT_DEBUG_SCHEDULER,
("[%d]switch to priority#%d "
- "thread:%.*s(sp:0x%p), "
- "from thread:%.*s(sp: 0x%p)\n",
+ "thread:%.*s(sp:0x%08x), "
+ "from thread:%.*s(sp: 0x%08x)\n",
rt_interrupt_nest, highest_ready_priority,
RT_NAME_MAX, to_thread->name, to_thread->sp,
RT_NAME_MAX, from_thread->name, from_thread->sp));
@@ -462,8 +490,23 @@ void rt_schedule(void)
rt_hw_interrupt_enable(level);
#ifdef RT_USING_SIGNALS
- /* check signal status */
- rt_thread_handle_sig(RT_TRUE);
+ /* check stat of thread for signal */
+ level = rt_hw_interrupt_disable();
+ if (rt_current_thread->stat & RT_THREAD_STAT_SIGNAL_PENDING)
+ {
+ extern void rt_thread_handle_sig(rt_bool_t clean_state);
+
+ rt_current_thread->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
+
+ rt_hw_interrupt_enable(level);
+
+ /* check signal status */
+ rt_thread_handle_sig(RT_TRUE);
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
#endif
goto __exit;
}
@@ -478,6 +521,7 @@ void rt_schedule(void)
else
{
rt_schedule_remove_thread(rt_current_thread);
+ rt_current_thread->stat = RT_THREAD_RUNNING | (rt_current_thread->stat & ~RT_THREAD_STAT_MASK);
}
}
}
@@ -510,6 +554,18 @@ void rt_scheduler_do_irq_switch(void *context)
pcpu = rt_cpu_index(cpu_id);
current_thread = pcpu->current_thread;
+#ifdef RT_USING_SIGNALS
+ if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
+ {
+ /* if current_thread signal is in pending */
+
+ if ((current_thread->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL_PENDING)
+ {
+ rt_thread_resume(current_thread);
+ }
+ }
+#endif
+
if (pcpu->irq_switch_flag == 0)
{
rt_hw_interrupt_enable(level);
@@ -527,16 +583,21 @@ void rt_scheduler_do_irq_switch(void *context)
{
to_thread = _get_highest_priority_thread(&highest_ready_priority);
current_thread->oncpu = RT_CPU_DETACHED;
- if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY)
+ if ((current_thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_RUNNING)
{
if (current_thread->current_priority < highest_ready_priority)
{
to_thread = current_thread;
}
+ else if (current_thread->current_priority == highest_ready_priority && (current_thread->stat & RT_THREAD_STAT_YIELD_MASK) == 0)
+ {
+ to_thread = current_thread;
+ }
else
{
rt_schedule_insert_thread(current_thread);
}
+ current_thread->stat &= ~RT_THREAD_STAT_YIELD_MASK;
}
to_thread->oncpu = cpu_id;
if (to_thread != current_thread)
@@ -548,6 +609,7 @@ void rt_scheduler_do_irq_switch(void *context)
RT_OBJECT_HOOK_CALL(rt_scheduler_hook, (current_thread, to_thread));
rt_schedule_remove_thread(to_thread);
+ to_thread->stat = RT_THREAD_RUNNING | (to_thread->stat & ~RT_THREAD_STAT_MASK);
#ifdef RT_USING_OVERFLOW_CHECK
_rt_scheduler_stack_check(to_thread);
@@ -586,14 +648,16 @@ void rt_schedule_insert_thread(struct rt_thread *thread)
/* disable interrupt */
level = rt_hw_interrupt_disable();
- /* change stat */
- thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);
-
+ /* it should be RUNNING thread */
if (thread->oncpu != RT_CPU_DETACHED)
{
+ thread->stat = RT_THREAD_RUNNING | (thread->stat & ~RT_THREAD_STAT_MASK);
goto __exit;
}
+ /* READY thread, insert to ready queue */
+ thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);
+
cpu_id = rt_hw_cpu_id();
bind_cpu = thread->bind_cpu ;
@@ -608,7 +672,7 @@ void rt_schedule_insert_thread(struct rt_thread *thread)
rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
&(thread->tlist));
cpu_mask = RT_CPU_MASK ^ (1 << cpu_id);
- rt_hw_ipi_send(RT_SCHEDULE_IPI_IRQ, cpu_mask);
+ rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask);
}
else
{
@@ -625,7 +689,7 @@ void rt_schedule_insert_thread(struct rt_thread *thread)
if (cpu_id != bind_cpu)
{
cpu_mask = 1 << bind_cpu;
- rt_hw_ipi_send(RT_SCHEDULE_IPI_IRQ, cpu_mask);
+ rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask);
}
}
@@ -646,14 +710,15 @@ void rt_schedule_insert_thread(struct rt_thread *thread)
/* disable interrupt */
temp = rt_hw_interrupt_disable();
- /* change stat */
- thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);
-
+ /* it's current thread, it should be RUNNING thread */
if (thread == rt_current_thread)
{
+ thread->stat = RT_THREAD_RUNNING | (thread->stat & ~RT_THREAD_STAT_MASK);
goto __exit;
}
+ /* READY thread, insert to ready queue */
+ thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);
/* insert thread to ready list */
rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
&(thread->tlist));
@@ -719,7 +784,7 @@ void rt_schedule_remove_thread(struct rt_thread *thread)
{
#if RT_THREAD_PRIORITY_MAX > 32
pcpu->ready_table[thread->number] &= ~thread->high_mask;
- if (rt_thread_ready_table[thread->number] == 0)
+ if (pcpu->ready_table[thread->number] == 0)
{
pcpu->priority_group &= ~thread->number_mask;
}
@@ -779,16 +844,28 @@ void rt_enter_critical(void)
level = rt_hw_local_irq_disable();
current_thread = rt_cpu_self()->current_thread;
+ if (!current_thread)
+ {
+ rt_hw_local_irq_enable(level);
+ return;
+ }
+
/*
* the maximal number of nest is RT_UINT16_MAX, which is big
* enough and does not check here
*/
- /* lock scheduler for all cpus */
- if (current_thread->scheduler_lock_nest == !!current_thread->cpus_lock_nest)
{
- rt_hw_spin_lock(&_rt_critical_lock);
+ register rt_uint16_t lock_nest = current_thread->cpus_lock_nest;
+ current_thread->cpus_lock_nest++;
+ if (lock_nest == 0)
+ {
+ current_thread->scheduler_lock_nest ++;
+ rt_hw_spin_lock(&_cpus_lock);
+ }
}
+ /* critical for local cpu */
+ current_thread->critical_lock_nest ++;
/* lock scheduler for local cpu */
current_thread->scheduler_lock_nest ++;
@@ -829,12 +906,21 @@ void rt_exit_critical(void)
level = rt_hw_local_irq_disable();
current_thread = rt_cpu_self()->current_thread;
+ if (!current_thread)
+ {
+ rt_hw_local_irq_enable(level);
+ return;
+ }
current_thread->scheduler_lock_nest --;
- if (current_thread->scheduler_lock_nest == !!current_thread->cpus_lock_nest)
+ current_thread->critical_lock_nest --;
+
+ current_thread->cpus_lock_nest--;
+ if (current_thread->cpus_lock_nest == 0)
{
- rt_hw_spin_unlock(&_rt_critical_lock);
+ current_thread->scheduler_lock_nest --;
+ rt_hw_spin_unlock(&_cpus_lock);
}
if (current_thread->scheduler_lock_nest <= 0)
@@ -860,14 +946,17 @@ void rt_exit_critical(void)
level = rt_hw_interrupt_disable();
rt_scheduler_lock_nest --;
-
if (rt_scheduler_lock_nest <= 0)
{
rt_scheduler_lock_nest = 0;
/* enable interrupt */
rt_hw_interrupt_enable(level);
- rt_schedule();
+ if (rt_current_thread)
+ {
+ /* if scheduler is started, do a schedule */
+ rt_schedule();
+ }
}
else
{
@@ -888,9 +977,9 @@ rt_uint16_t rt_critical_level(void)
#ifdef RT_USING_SMP
struct rt_thread *current_thread = rt_cpu_self()->current_thread;
- return current_thread->scheduler_lock_nest;
+ return current_thread->critical_lock_nest;
#else
- return rt_scheduler_lock_nest;
+ return rt_scheduler_lock_nest;
#endif /*RT_USING_SMP*/
}
RTM_EXPORT(rt_critical_level);
diff --git a/src/signal.c b/src/signal.c
index 05632b2c4a..bb9339ab6c 100644
--- a/src/signal.c
+++ b/src/signal.c
@@ -22,10 +22,8 @@
#define RT_SIG_INFO_MAX 32
#endif
-// #define DBG_ENABLE
-#define DBG_SECTION_NAME "SIGN"
-#define DBG_COLOR
-#define DBG_LEVEL DBG_LOG
+#define DBG_TAG "SIGN"
+#define DBG_LVL DBG_WARNING
#include <rtdbg.h>
#define sig_mask(sig_no) (1u << sig_no)
@@ -51,22 +49,31 @@ static void _signal_entry(void *parameter)
{
rt_thread_t tid = rt_thread_self();
- dbg_enter;
-
/* handle signal */
rt_thread_handle_sig(RT_FALSE);
- /* never come back... */
- rt_hw_interrupt_disable();
+#ifdef RT_USING_SMP
+ {
+ struct rt_cpu* pcpu = rt_cpu_self();
+
+ pcpu->current_thread->cpus_lock_nest--;
+ if (pcpu->current_thread->cpus_lock_nest == 0)
+ {
+ pcpu->current_thread->scheduler_lock_nest--;
+ }
+
+ }
+#else
/* return to thread */
tid->sp = tid->sig_ret;
tid->sig_ret = RT_NULL;
+#endif
LOG_D("switch back to: 0x%08x\n", tid->sp);
tid->stat &= ~RT_THREAD_STAT_SIGNAL;
#ifdef RT_USING_SMP
- rt_hw_context_switch_to((rt_ubase_t)&(tid->sp), tid);
+ rt_hw_context_switch_to((rt_base_t)&parameter, tid);
#else
rt_hw_context_switch_to((rt_ubase_t)&(tid->sp));
#endif /*RT_USING_SMP*/
@@ -86,16 +93,21 @@ static void _signal_deliver(rt_thread_t tid)
{
rt_ubase_t level;
+ level = rt_hw_interrupt_disable();
+
/* thread is not interested in pended signals */
- if (!(tid->sig_pending & tid->sig_mask)) return;
+ if (!(tid->sig_pending & tid->sig_mask))
+ {
+ rt_hw_interrupt_enable(level);
+ return;
+ }
- level = rt_hw_interrupt_disable();
if ((tid->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND)
{
/* resume thread to handle signal */
rt_thread_resume(tid);
/* add signal state */
- tid->stat |= RT_THREAD_STAT_SIGNAL;
+ tid->stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);
rt_hw_interrupt_enable(level);
@@ -112,17 +124,36 @@ static void _signal_deliver(rt_thread_t tid)
rt_hw_interrupt_enable(level);
/* do signal action in self thread context */
- rt_thread_handle_sig(RT_TRUE);
+ if (rt_interrupt_get_nest() == 0)
+ {
+ rt_thread_handle_sig(RT_TRUE);
+ }
}
else if (!((tid->stat & RT_THREAD_STAT_SIGNAL_MASK) & RT_THREAD_STAT_SIGNAL))
{
/* add signal state */
- tid->stat |= RT_THREAD_STAT_SIGNAL;
+ tid->stat |= (RT_THREAD_STAT_SIGNAL | RT_THREAD_STAT_SIGNAL_PENDING);
+
+#ifdef RT_USING_SMP
+ {
+ int cpu_id;
+
+ cpu_id = tid->oncpu;
+ if ((cpu_id != RT_CPU_DETACHED) && (cpu_id != rt_hw_cpu_id()))
+ {
+ rt_uint32_t cpu_mask;
+ cpu_mask = RT_CPU_MASK ^ (1 << cpu_id);
+ rt_hw_ipi_send(RT_SCHEDULE_IPI, cpu_mask);
+ }
+ }
+#else
/* point to the signal handle entry */
+ tid->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
tid->sig_ret = tid->sp;
tid->sp = rt_hw_stack_init((void *)_signal_entry, RT_NULL,
(void *)((char *)tid->sig_ret - 32), RT_NULL);
+#endif
rt_hw_interrupt_enable(level);
LOG_D("signal stack pointer @ 0x%08x", tid->sp);
@@ -137,14 +168,53 @@ static void _signal_deliver(rt_thread_t tid)
}
}
+#ifdef RT_USING_SMP
+void *rt_signal_check(void* context)
+{
+ rt_base_t level;
+ int cpu_id;
+ struct rt_cpu* pcpu;
+ struct rt_thread *current_thread;
+
+ level = rt_hw_interrupt_disable();
+ cpu_id = rt_hw_cpu_id();
+ pcpu = rt_cpu_index(cpu_id);
+ current_thread = pcpu->current_thread;
+
+ if (pcpu->irq_nest)
+ {
+ rt_hw_interrupt_enable(level);
+ return context;
+ }
+
+ if (current_thread->cpus_lock_nest == 1)
+ {
+ if (current_thread->stat & RT_THREAD_STAT_SIGNAL_PENDING)
+ {
+ void *sig_context;
+
+ current_thread->stat &= ~RT_THREAD_STAT_SIGNAL_PENDING;
+
+ rt_hw_interrupt_enable(level);
+ sig_context = rt_hw_stack_init((void *)_signal_entry, context,
+ (void *)(context - 32), RT_NULL);
+ return sig_context;
+ }
+ }
+ rt_hw_interrupt_enable(level);
+ return context;
+}
+#endif
+
rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler)
{
+ rt_base_t level;
rt_sighandler_t old = RT_NULL;
rt_thread_t tid = rt_thread_self();
if (!sig_valid(signo)) return SIG_ERR;
- rt_enter_critical();
+ level = rt_hw_interrupt_disable();
if (tid->sig_vectors == RT_NULL)
{
rt_thread_alloc_sig(tid);
@@ -158,7 +228,7 @@ rt_sighandler_t rt_signal_install(int signo, rt_sighandler_t handler)
else if (handler == SIG_DFL) tid->sig_vectors[signo] = _signal_default_handler;
else tid->sig_vectors[signo] = handler;
}
- rt_exit_critical();
+ rt_hw_interrupt_enable(level);
return old;
}
@@ -276,7 +346,20 @@ __done:
LOG_D("sigwait: %d sig raised!", signo);
if (si_prev) si_prev->list.next = si_node->list.next;
- else tid->si_list = si_node->list.next;
+ else
+ {
+ struct siginfo_node *node_next;
+
+ if (si_node->list.next)
+ {
+ node_next = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
+ tid->si_list = node_next;
+ }
+ else
+ {
+ tid->si_list = RT_NULL;
+ }
+ }
/* clear pending */
tid->sig_pending &= ~sig_mask(signo);
@@ -285,7 +368,14 @@ __done:
}
si_prev = si_node;
- si_node = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
+ if (si_node->list.next)
+ {
+ si_node = (void *)rt_slist_entry(si_node->list.next, struct siginfo_node, list);
+ }
+ else
+ {
+ si_node = RT_NULL;
+ }
}
__done_int:
@@ -324,13 +414,13 @@ void rt_thread_handle_sig(rt_bool_t clean_state)
signo = si_node->si.si_signo;
handler = tid->sig_vectors[signo];
+ tid->sig_pending &= ~sig_mask(signo);
rt_hw_interrupt_enable(level);
LOG_D("handle signal: %d, handler 0x%08x", signo, handler);
if (handler) handler(signo);
level = rt_hw_interrupt_disable();
- tid->sig_pending &= ~sig_mask(signo);
error = -RT_EINTR;
rt_mp_free(si_node); /* release this siginfo node */
@@ -339,10 +429,16 @@ void rt_thread_handle_sig(rt_bool_t clean_state)
}
/* whether clean signal status */
- if (clean_state == RT_TRUE) tid->stat &= ~RT_THREAD_STAT_SIGNAL;
+ if (clean_state == RT_TRUE)
+ {
+ tid->stat &= ~RT_THREAD_STAT_SIGNAL;
+ }
+ else
+ {
+ return;
+ }
}
}
-
rt_hw_interrupt_enable(level);
}
@@ -368,30 +464,30 @@ void rt_thread_alloc_sig(rt_thread_t tid)
void rt_thread_free_sig(rt_thread_t tid)
{
rt_base_t level;
- struct siginfo_node *si_list;
+ struct siginfo_node *si_node;
rt_sighandler_t *sig_vectors;
level = rt_hw_interrupt_disable();
- si_list = (struct siginfo_node *)tid->si_list;
+ si_node = (struct siginfo_node *)tid->si_list;
tid->si_list = RT_NULL;
sig_vectors = tid->sig_vectors;
tid->sig_vectors = RT_NULL;
rt_hw_interrupt_enable(level);
- if (si_list)
+ if (si_node)
{
struct rt_slist_node *node;
- struct siginfo_node *si_node;
+ struct rt_slist_node *node_to_free;
LOG_D("free signal info list");
- node = &(si_list->list);
+ node = &(si_node->list);
do
{
- si_node = rt_slist_entry(node, struct siginfo_node, list);
- rt_mp_free(si_node);
-
+ node_to_free = node;
node = node->next;
+ si_node = rt_slist_entry(node_to_free, struct siginfo_node, list);
+ rt_mp_free(si_node);
} while (node);
}
@@ -422,30 +518,23 @@ int rt_thread_kill(rt_thread_t tid, int sig)
struct rt_slist_node *node;
struct siginfo_node *entry;
- node = (struct rt_slist_node *)tid->si_list;
- rt_hw_interrupt_enable(level);
+ si_node = (struct siginfo_node *)tid->si_list;
+ if (si_node)
+ node = (struct rt_slist_node *)&si_node->list;
+ else
+ node = RT_NULL;
/* update sig info */
- rt_enter_critical();
for (; (node) != RT_NULL; node = node->next)
{
entry = rt_slist_entry(node, struct siginfo_node, list);
if (entry->si.si_signo == sig)
{
memcpy(&(entry->si), &si, sizeof(siginfo_t));
- rt_exit_critical();
+ rt_hw_interrupt_enable(level);
return 0;
}
}
- rt_exit_critical();
-
- /* disable interrupt to protect tcb */
- level = rt_hw_interrupt_disable();
- }
- else
- {
- /* a new signal */
- tid->sig_pending |= sig_mask(sig);
}
rt_hw_interrupt_enable(level);
@@ -456,14 +545,22 @@ int rt_thread_kill(rt_thread_t tid, int sig)
memcpy(&(si_node->si), &si, sizeof(siginfo_t));
level = rt_hw_interrupt_disable();
- if (!tid->si_list) tid->si_list = si_node;
- else
+
+ if (tid->si_list)
{
struct siginfo_node *si_list;
si_list = (struct siginfo_node *)tid->si_list;
rt_slist_append(&(si_list->list), &(si_node->list));
}
+ else
+ {
+ tid->si_list = si_node;
+ }
+
+ /* a new signal */
+ tid->sig_pending |= sig_mask(sig);
+
rt_hw_interrupt_enable(level);
}
else
diff --git a/src/slab.c b/src/slab.c
index bf26c84cca..0872ecf092 100644
--- a/src/slab.c
+++ b/src/slab.c
@@ -217,9 +217,9 @@ struct memusage
};
static struct memusage *memusage = RT_NULL;
#define btokup(addr) \
- (&memusage[((rt_uint32_t)(addr) - heap_start) >> RT_MM_PAGE_BITS])
+ (&memusage[((rt_ubase_t)(addr) - heap_start) >> RT_MM_PAGE_BITS])
-static rt_uint32_t heap_start, heap_end;
+static rt_ubase_t heap_start, heap_end;
/* page allocator */
struct rt_page_head
@@ -275,7 +275,7 @@ void rt_page_free(void *addr, rt_size_t npages)
struct rt_page_head **prev;
RT_ASSERT(addr != RT_NULL);
- RT_ASSERT((rt_uint32_t)addr % RT_MM_PAGE_SIZE == 0);
+ RT_ASSERT((rt_ubase_t)addr % RT_MM_PAGE_SIZE == 0);
RT_ASSERT(npages != 0);
n = (struct rt_page_head *)addr;
@@ -348,13 +348,13 @@ void rt_system_heap_init(void *begin_addr, void *end_addr)
RT_DEBUG_NOT_IN_INTERRUPT;
/* align begin and end addr to page */
- heap_start = RT_ALIGN((rt_uint32_t)begin_addr, RT_MM_PAGE_SIZE);
- heap_end = RT_ALIGN_DOWN((rt_uint32_t)end_addr, RT_MM_PAGE_SIZE);
+ heap_start = RT_ALIGN((rt_ubase_t)begin_addr, RT_MM_PAGE_SIZE);
+ heap_end = RT_ALIGN_DOWN((rt_ubase_t)end_addr, RT_MM_PAGE_SIZE);
if (heap_start >= heap_end)
{
rt_kprintf("rt_system_heap_init, wrong address[0x%x - 0x%x]\n",
- (rt_uint32_t)begin_addr, (rt_uint32_t)end_addr);
+ (rt_ubase_t)begin_addr, (rt_ubase_t)end_addr);
return;
}
@@ -391,17 +391,17 @@ void rt_system_heap_init(void *begin_addr, void *end_addr)
memusage = rt_page_alloc(limsize / RT_MM_PAGE_SIZE);
RT_DEBUG_LOG(RT_DEBUG_SLAB, ("memusage 0x%x, size 0x%x\n",
- (rt_uint32_t)memusage, limsize));
+ (rt_ubase_t)memusage, limsize));
}
/*
* Calculate the zone index for the allocation request size and set the
* allocation request size to that particular zone's chunk size.
*/
-rt_inline int zoneindex(rt_uint32_t *bytes)
+rt_inline int zoneindex(rt_size_t *bytes)
{
/* unsigned for shift opt */
- rt_uint32_t n = (rt_uint32_t) * bytes;
+ rt_ubase_t n = (rt_ubase_t)(*bytes);
if (n < 128)
{
@@ -507,7 +507,7 @@ void *rt_malloc(rt_size_t size)
("malloc a large memory 0x%x, page cnt %d, kup %d\n",
size,
size >> RT_MM_PAGE_BITS,
- ((rt_uint32_t)chunk - heap_start) >> RT_MM_PAGE_BITS));
+ ((rt_ubase_t)chunk - heap_start) >> RT_MM_PAGE_BITS));
/* lock heap */
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
@@ -610,7 +610,7 @@ void *rt_malloc(rt_size_t size)
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
RT_DEBUG_LOG(RT_DEBUG_SLAB, ("alloc a new zone: 0x%x\n",
- (rt_uint32_t)z));
+ (rt_ubase_t)z));
/* set message usage */
for (off = 0, kup = btokup(z); off < zone_page_cnt; off ++)
@@ -694,7 +694,7 @@ void *rt_realloc(void *ptr, rt_size_t size)
* Get the original allocation's zone. If the new request winds up
* using the same chunk size we do not have to do anything.
*/
- kup = btokup((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK);
+ kup = btokup((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK);
if (kup->type == PAGE_TYPE_LARGE)
{
rt_size_t osize;
@@ -709,7 +709,7 @@ void *rt_realloc(void *ptr, rt_size_t size)
}
else if (kup->type == PAGE_TYPE_SMALL)
{
- z = (slab_zone *)(((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK) -
+ z = (slab_zone *)(((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK) -
kup->size * RT_MM_PAGE_SIZE);
RT_ASSERT(z->z_magic == ZALLOC_SLAB_MAGIC);
@@ -783,20 +783,20 @@ void rt_free(void *ptr)
/* get memory usage */
#if RT_DEBUG_SLAB
{
- rt_uint32_t addr = ((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK);
+ rt_ubase_t addr = ((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK);
RT_DEBUG_LOG(RT_DEBUG_SLAB,
("free a memory 0x%x and align to 0x%x, kup index %d\n",
- (rt_uint32_t)ptr,
- (rt_uint32_t)addr,
- ((rt_uint32_t)(addr) - heap_start) >> RT_MM_PAGE_BITS));
+ (rt_ubase_t)ptr,
+ (rt_ubase_t)addr,
+ ((rt_ubase_t)(addr) - heap_start) >> RT_MM_PAGE_BITS));
}
#endif
- kup = btokup((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK);
+ kup = btokup((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK);
/* release large allocation */
if (kup->type == PAGE_TYPE_LARGE)
{
- rt_uint32_t size;
+ rt_ubase_t size;
/* lock heap */
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
@@ -811,7 +811,7 @@ void rt_free(void *ptr)
RT_DEBUG_LOG(RT_DEBUG_SLAB,
("free large memory block 0x%x, page count %d\n",
- (rt_uint32_t)ptr, size));
+ (rt_ubase_t)ptr, size));
/* free this page */
rt_page_free(ptr, size);
@@ -823,7 +823,7 @@ void rt_free(void *ptr)
rt_sem_take(&heap_sem, RT_WAITING_FOREVER);
/* zone case. get out zone. */
- z = (slab_zone *)(((rt_uint32_t)ptr & ~RT_MM_PAGE_MASK) -
+ z = (slab_zone *)(((rt_ubase_t)ptr & ~RT_MM_PAGE_MASK) -
kup->size * RT_MM_PAGE_SIZE);
RT_ASSERT(z->z_magic == ZALLOC_SLAB_MAGIC);
@@ -857,7 +857,7 @@ void rt_free(void *ptr)
slab_zone **pz;
RT_DEBUG_LOG(RT_DEBUG_SLAB, ("free zone 0x%x\n",
- (rt_uint32_t)z, z->z_zoneindex));
+ (rt_ubase_t)z, z->z_zoneindex));
/* remove zone from zone array list */
for (pz = &zone_array[z->z_zoneindex]; z != *pz; pz = &(*pz)->z_next)
diff --git a/src/thread.c b/src/thread.c
index df9f151834..49e2022bf7 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -107,11 +107,11 @@ void rt_thread_exit(void)
rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
}
- /* enable interrupt */
- rt_hw_interrupt_enable(level);
-
/* switch to next task */
rt_schedule();
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
}
static rt_err_t _rt_thread_init(struct rt_thread *thread,
@@ -141,7 +141,7 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread,
(void *)rt_thread_exit);
#else
thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
- (void *)((char *)thread->stack_addr + thread->stack_size - sizeof(rt_ubase_t)),
+ (rt_uint8_t *)((char *)thread->stack_addr + thread->stack_size - sizeof(rt_ubase_t)),
(void *)rt_thread_exit);
#endif
@@ -172,13 +172,14 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread,
/* lock init */
thread->scheduler_lock_nest = 0;
thread->cpus_lock_nest = 0;
+ thread->critical_lock_nest = 0;
#endif /*RT_USING_SMP*/
/* initialize cleanup function and user data */
thread->cleanup = 0;
thread->user_data = 0;
- /* init thread timer */
+ /* initialize thread timer */
rt_timer_init(&(thread->thread_timer),
thread->name,
rt_thread_timeout,
@@ -191,7 +192,9 @@ static rt_err_t _rt_thread_init(struct rt_thread *thread,
thread->sig_mask = 0x00;
thread->sig_pending = 0x00;
+#ifndef RT_USING_SMP
thread->sig_ret = RT_NULL;
+#endif
thread->sig_vectors = RT_NULL;
thread->si_list = RT_NULL;
#endif
@@ -239,7 +242,7 @@ rt_err_t rt_thread_init(struct rt_thread *thread,
RT_ASSERT(thread != RT_NULL);
RT_ASSERT(stack_start != RT_NULL);
- /* init thread object */
+ /* initialize thread object */
rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);
return _rt_thread_init(thread,
@@ -290,7 +293,7 @@ rt_err_t rt_thread_startup(rt_thread_t thread)
RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT);
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
- /* set current priority to init priority */
+ /* set current priority to initialize priority */
thread->current_priority = thread->init_priority;
/* calculate priority attribute */
@@ -335,6 +338,9 @@ rt_err_t rt_thread_detach(rt_thread_t thread)
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread));
+ if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
+ return RT_EOK;
+
if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
{
/* remove from schedule */
@@ -347,17 +353,17 @@ rt_err_t rt_thread_detach(rt_thread_t thread)
/* change stat */
thread->stat = RT_THREAD_CLOSE;
- /* detach object */
- rt_object_detach((rt_object_t)thread);
-
- if (thread->cleanup != RT_NULL)
+ if ((rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) &&
+ thread->cleanup == RT_NULL)
+ {
+ rt_object_detach((rt_object_t)thread);
+ }
+ else
{
/* disable interrupt */
lock = rt_hw_interrupt_disable();
-
/* insert to defunct thread list */
rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
-
/* enable interrupt */
rt_hw_interrupt_enable(lock);
}
@@ -366,7 +372,6 @@ rt_err_t rt_thread_detach(rt_thread_t thread)
}
RTM_EXPORT(rt_thread_detach);
-
#ifdef RT_USING_HEAP
/**
* This function will create a thread object and allocate thread object memory
@@ -435,6 +440,9 @@ rt_err_t rt_thread_delete(rt_thread_t thread)
RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread) == RT_FALSE);
+ if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
+ return RT_EOK;
+
if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
{
/* remove from schedule */
@@ -444,12 +452,12 @@ rt_err_t rt_thread_delete(rt_thread_t thread)
/* release thread timer */
rt_timer_detach(&(thread->thread_timer));
- /* change stat */
- thread->stat = RT_THREAD_CLOSE;
-
/* disable interrupt */
lock = rt_hw_interrupt_disable();
+ /* change stat */
+ thread->stat = RT_THREAD_CLOSE;
+
/* insert to defunct thread list */
rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
@@ -470,7 +478,15 @@ RTM_EXPORT(rt_thread_delete);
*/
rt_err_t rt_thread_yield(void)
{
+ struct rt_thread *thread;
+ rt_base_t lock;
+
+ thread = rt_thread_self();
+ lock = rt_hw_interrupt_disable();
+ thread->remaining_tick = thread->init_tick;
+ thread->stat |= RT_THREAD_STAT_YIELD;
rt_schedule();
+ rt_hw_interrupt_enable(lock);
return RT_EOK;
}
@@ -529,9 +545,66 @@ rt_err_t rt_thread_delay(rt_tick_t tick)
RTM_EXPORT(rt_thread_delay);
/**
+ * This function will let current thread delay until (*tick + inc_tick).
+ *
+ * @param tick the tick of last wakeup.
+ * @param inc_tick the increment tick
+ *
+ * @return RT_EOK
+ */
+rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick)
+{
+ register rt_base_t level;
+ struct rt_thread *thread;
+
+ RT_ASSERT(tick != RT_NULL);
+
+ /* set to current thread */
+ thread = rt_thread_self();
+ RT_ASSERT(thread != RT_NULL);
+ RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
+
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ if (rt_tick_get() - *tick < inc_tick)
+ {
+ *tick = *tick + inc_tick - rt_tick_get();
+
+ /* suspend thread */
+ rt_thread_suspend(thread);
+
+ /* reset the timeout of thread timer and start it */
+ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, tick);
+ rt_timer_start(&(thread->thread_timer));
+
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ rt_schedule();
+
+ /* clear error number of this thread to RT_EOK */
+ if (thread->error == -RT_ETIMEOUT)
+ {
+ thread->error = RT_EOK;
+ }
+ }
+ else
+ {
+ rt_hw_interrupt_enable(level);
+ }
+
+ /* get the wakeup tick */
+ *tick = rt_tick_get();
+
+ return RT_EOK;
+}
+RTM_EXPORT(rt_thread_delay_until);
+
+/**
* This function will let current thread delay for some milliseconds.
*
- * @param tick the delay time
+ * @param ms the delay ms time
*
* @return RT_EOK
*/
@@ -614,9 +687,17 @@ rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)
case RT_THREAD_CTRL_STARTUP:
return rt_thread_startup(thread);
-#ifdef RT_USING_HEAP
case RT_THREAD_CTRL_CLOSE:
- return rt_thread_delete(thread);
+
+ if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
+ {
+ return rt_thread_detach(thread);
+ }
+#ifdef RT_USING_HEAP
+ else
+ {
+ return rt_thread_delete(thread);
+ }
#endif
#ifdef RT_USING_SMP
@@ -655,6 +736,7 @@ RTM_EXPORT(rt_thread_control);
*/
rt_err_t rt_thread_suspend(rt_thread_t thread)
{
+ register rt_base_t stat;
register rt_base_t temp;
/* thread check */
@@ -663,22 +745,25 @@ rt_err_t rt_thread_suspend(rt_thread_t thread)
RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: %s\n", thread->name));
- if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_READY)
+ stat = thread->stat & RT_THREAD_STAT_MASK;
+ if ((stat != RT_THREAD_READY) && (stat != RT_THREAD_RUNNING))
{
RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, 0x%2x\n",
thread->stat));
-
return -RT_ERROR;
}
- RT_ASSERT(thread == rt_thread_self());
-
/* disable interrupt */
temp = rt_hw_interrupt_disable();
+ if (stat == RT_THREAD_RUNNING)
+ {
+ /* not suspend running status thread on other core */
+ RT_ASSERT(thread == rt_thread_self());
+ }
/* change thread stat */
- thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK);
rt_schedule_remove_thread(thread);
+ thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK);
/* stop thread timer anyway */
rt_timer_stop(&(thread->thread_timer));
diff --git a/src/timer.c b/src/timer.c
index fd938065db..4b9003794c 100644
--- a/src/timer.c
+++ b/src/timer.c
@@ -25,6 +25,10 @@
static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
#ifdef RT_USING_TIMER_SOFT
+
+#define RT_SOFT_TIMER_IDLE 1
+#define RT_SOFT_TIMER_BUSY 0
+
#ifndef RT_TIMER_THREAD_STACK_SIZE
#define RT_TIMER_THREAD_STACK_SIZE 512
#endif
@@ -33,6 +37,8 @@ static rt_list_t rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
#define RT_TIMER_THREAD_PRIO 0
#endif
+/* soft timer status */
+static rt_uint8_t soft_timer_status = RT_SOFT_TIMER_IDLE;
/* soft timer list */
static rt_list_t rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL];
static struct rt_thread timer_thread;
@@ -108,14 +114,23 @@ static void _rt_timer_init(rt_timer_t timer,
static rt_tick_t rt_timer_list_next_timeout(rt_list_t timer_list[])
{
struct rt_timer *timer;
+ register rt_base_t level;
+ rt_tick_t timeout_tick = RT_TICK_MAX;
- if (rt_list_isempty(&timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
- return RT_TICK_MAX;
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
- timer = rt_list_entry(timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
- struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
+ if (!rt_list_isempty(&timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
+ {
+ timer = rt_list_entry(timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
+ struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
+ timeout_tick = timer->timeout_tick;
+ }
- return timer->timeout_tick;
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
+
+ return timeout_tick;
}
rt_inline void _rt_timer_remove(rt_timer_t timer)
@@ -212,6 +227,8 @@ rt_err_t rt_timer_detach(rt_timer_t timer)
level = rt_hw_interrupt_disable();
_rt_timer_remove(timer);
+ /* stop timer */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
/* enable interrupt */
rt_hw_interrupt_enable(level);
@@ -275,6 +292,8 @@ rt_err_t rt_timer_delete(rt_timer_t timer)
level = rt_hw_interrupt_disable();
_rt_timer_remove(timer);
+ /* stop timer */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
/* enable interrupt */
rt_hw_interrupt_enable(level);
@@ -399,7 +418,8 @@ rt_err_t rt_timer_start(rt_timer_t timer)
if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
{
/* check whether timer thread is ready */
- if ((timer_thread.stat & RT_THREAD_STAT_MASK) != RT_THREAD_READY)
+ if ((soft_timer_status == RT_SOFT_TIMER_IDLE) &&
+ ((timer_thread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND))
{
/* resume timer thread to check soft timer */
rt_thread_resume(&timer_thread);
@@ -436,13 +456,12 @@ rt_err_t rt_timer_stop(rt_timer_t timer)
level = rt_hw_interrupt_disable();
_rt_timer_remove(timer);
+ /* change status */
+ timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
/* enable interrupt */
rt_hw_interrupt_enable(level);
- /* change stat */
- timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
-
return RT_EOK;
}
RTM_EXPORT(rt_timer_stop);
@@ -458,10 +477,13 @@ RTM_EXPORT(rt_timer_stop);
*/
rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
{
+ register rt_base_t level;
+
/* timer check */
RT_ASSERT(timer != RT_NULL);
RT_ASSERT(rt_object_get_type(&timer->parent) == RT_Object_Class_Timer);
+ level = rt_hw_interrupt_disable();
switch (cmd)
{
case RT_TIMER_CTRL_GET_TIME:
@@ -479,7 +501,24 @@ rt_err_t rt_timer_control(rt_timer_t timer, int cmd, void *arg)
case RT_TIMER_CTRL_SET_PERIODIC:
timer->parent.flag |= RT_TIMER_FLAG_PERIODIC;
break;
+
+ case RT_TIMER_CTRL_GET_STATE:
+ if(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
+ {
+ /*timer is start and run*/
+ *(rt_tick_t *)arg = RT_TIMER_FLAG_ACTIVATED;
+ }
+ else
+ {
+ /*timer is stop*/
+ *(rt_tick_t *)arg = RT_TIMER_FLAG_DEACTIVATED;
+ }
+ break;
+
+ default:
+ break;
}
+ rt_hw_interrupt_enable(level);
return RT_EOK;
}
@@ -496,6 +535,7 @@ void rt_timer_check(void)
struct rt_timer *t;
rt_tick_t current_tick;
register rt_base_t level;
+ rt_list_t list = RT_LIST_OBJECT_INIT(list);
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));
@@ -519,7 +559,12 @@ void rt_timer_check(void)
/* remove timer from timer list firstly */
_rt_timer_remove(t);
-
+ if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
+ {
+ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+ }
+ /* add timer to temporary list */
+ rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
/* call timeout function */
t->timeout_func(t->parameter);
@@ -529,6 +574,12 @@ void rt_timer_check(void)
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
+ /* Check whether the timer object is detached or started again */
+ if (rt_list_isempty(&list))
+ {
+ continue;
+ }
+
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
{
@@ -536,14 +587,8 @@ void rt_timer_check(void)
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
rt_timer_start(t);
}
- else
- {
- /* stop timer */
- t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
- }
}
- else
- break;
+ else break;
}
/* enable interrupt */
@@ -564,26 +609,27 @@ rt_tick_t rt_timer_next_timeout_tick(void)
#ifdef RT_USING_TIMER_SOFT
/**
- * This function will check timer list, if a timeout event happens, the
+ * This function will check software-timer list, if a timeout event happens, the
* corresponding timeout function will be invoked.
*/
void rt_soft_timer_check(void)
{
rt_tick_t current_tick;
- rt_list_t *n;
struct rt_timer *t;
+ register rt_base_t level;
+ rt_list_t list = RT_LIST_OBJECT_INIT(list);
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n"));
- current_tick = rt_tick_get();
-
- /* lock scheduler */
- rt_enter_critical();
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
- for (n = rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next;
- n != &(rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]);)
+ while (!rt_list_isempty(&rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
{
- t = rt_list_entry(n, struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
+ t = rt_list_entry(rt_soft_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
+ struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);
+
+ current_tick = rt_tick_get();
/*
* It supposes that the new tick shall less than the half duration of
@@ -593,25 +639,34 @@ void rt_soft_timer_check(void)
{
RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));
- /* move node to the next */
- n = n->next;
-
/* remove timer from timer list firstly */
_rt_timer_remove(t);
+ if (!(t->parent.flag & RT_TIMER_FLAG_PERIODIC))
+ {
+ t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+ }
+ /* add timer to temporary list */
+ rt_list_insert_after(&list, &(t->row[RT_TIMER_SKIP_LIST_LEVEL - 1]));
+
+ soft_timer_status = RT_SOFT_TIMER_BUSY;
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
- /* not lock scheduler when performing timeout function */
- rt_exit_critical();
/* call timeout function */
t->timeout_func(t->parameter);
- /* re-get tick */
- current_tick = rt_tick_get();
-
RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));
- /* lock scheduler */
- rt_enter_critical();
+ /* disable interrupt */
+ level = rt_hw_interrupt_disable();
+
+ soft_timer_status = RT_SOFT_TIMER_IDLE;
+ /* Check whether the timer object is detached or started again */
+ if (rt_list_isempty(&list))
+ {
+ continue;
+ }
if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
@@ -620,17 +675,11 @@ void rt_soft_timer_check(void)
t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
rt_timer_start(t);
}
- else
- {
- /* stop timer */
- t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
- }
}
else break; /* not check anymore */
}
-
- /* unlock scheduler */
- rt_exit_critical();
+ /* enable interrupt */
+ rt_hw_interrupt_enable(level);
RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n"));
}