diff options
| author | yangjie11 <[email protected]> | 2020-11-18 09:56:35 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-11-18 09:56:35 +0800 |
| commit | d4a682e8d97fa131e5a8d795f8c5451d55cdd5b0 (patch) | |
| tree | 4773b40cb012475c5daf74bfd55707e141477669 /src | |
| parent | 2b98f4720c827ae1850df78299f6b273d568c8c7 (diff) | |
| parent | 2ef3c9d861f55253620996a94831a4be31ca6620 (diff) | |
Merge pull request #3 from RT-Thread/master
sync
Diffstat (limited to 'src')
| -rw-r--r-- | src/Kconfig | 29 | ||||
| -rw-r--r-- | src/SConscript | 17 | ||||
| -rw-r--r-- | src/clock.c | 24 | ||||
| -rw-r--r-- | src/components.c | 15 | ||||
| -rw-r--r-- | src/cpu.c | 107 | ||||
| -rw-r--r-- | src/device.c | 16 | ||||
| -rw-r--r-- | src/idle.c | 20 | ||||
| -rw-r--r-- | src/ipc.c | 369 | ||||
| -rw-r--r-- | src/irq.c | 2 | ||||
| -rw-r--r-- | src/kservice.c | 132 | ||||
| -rw-r--r-- | src/mem.c | 8 | ||||
| -rw-r--r-- | src/memheap.c | 6 | ||||
| -rw-r--r-- | src/mempool.c | 39 | ||||
| -rw-r--r-- | src/object.c | 112 | ||||
| -rw-r--r-- | src/scheduler.c | 201 | ||||
| -rw-r--r-- | src/signal.c | 185 | ||||
| -rw-r--r-- | src/slab.c | 44 | ||||
| -rw-r--r-- | src/thread.c | 135 | ||||
| -rw-r--r-- | src/timer.c | 137 |
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 @@ -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++) @@ -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) @@ -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. * @@ -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)¤t_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)¤t_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)¶meter, 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")); } |
