diff options
| author | HubretXie <[email protected]> | 2019-05-16 10:22:41 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2019-05-16 10:22:41 +0800 |
| commit | 9de2942b159b7d08bc79aa370008bc42eeafc1e0 (patch) | |
| tree | c6ed31f70123415e96da63973a8184e96eaad824 /src | |
| parent | fd05ad76d69e02ee2c36e8eb73781a5654073be4 (diff) | |
| parent | 4539172f5c97306a322ac1768c5c8eb4f878ea3c (diff) | |
Merge pull request #4 from RT-Thread/master
sync
Diffstat (limited to 'src')
| -rw-r--r-- | src/cpu.c | 10 | ||||
| -rw-r--r-- | src/idle.c | 4 | ||||
| -rw-r--r-- | src/ipc.c | 4 | ||||
| -rw-r--r-- | src/scheduler.c | 92 | ||||
| -rw-r--r-- | src/signal.c | 179 | ||||
| -rw-r--r-- | src/thread.c | 2 |
6 files changed, 220 insertions, 71 deletions
@@ -42,12 +42,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_uint16_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 +65,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/idle.c b/src/idle.c index e685a7ddfc..77b0424892 100644 --- a/src/idle.c +++ b/src/idle.c @@ -228,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 @@ -255,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 } } @@ -753,8 +753,8 @@ __again: if (thread->error != RT_EOK) { - /* interrupt by signal, try it again */ - if (thread->error == -RT_EINTR) goto __again; + /* interrupt by signal, try it again */ + if (thread->error == -RT_EINTR) goto __again; /* return error */ return thread->error; diff --git a/src/scheduler.c b/src/scheduler.c index be29d9a7e0..b487bd4b60 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -128,17 +128,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; @@ -322,8 +314,23 @@ void rt_schedule(void) if (pcpu->irq_nest) { pcpu->irq_switch_flag = 1; + rt_hw_interrupt_enable(level); + goto __exit; } - else if (current_thread->scheduler_lock_nest == 1) /* whether lock scheduler */ + +#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 (current_thread->scheduler_lock_nest == 1) /* whether lock scheduler */ { rt_ubase_t highest_ready_priority; @@ -366,27 +373,32 @@ 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); } } } +#ifdef RT_USING_SIGNALS + 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); + } +#else /* enable interrupt */ rt_hw_interrupt_enable(level); +#endif __exit: return ; @@ -465,13 +477,25 @@ void rt_schedule(void) rt_hw_context_switch((rt_ubase_t)&from_thread->sp, (rt_ubase_t)&to_thread->sp); +#ifdef RT_USING_SIGNALS + 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); + } +#else /* enable interrupt */ rt_hw_interrupt_enable(level); - -#ifdef RT_USING_SIGNALS - /* check signal status */ - rt_thread_handle_sig(RT_TRUE); #endif goto __exit; } @@ -519,6 +543,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); diff --git a/src/signal.c b/src/signal.c index 06c2055d26..bea3615d34 100644 --- a/src/signal.c +++ b/src/signal.c @@ -23,7 +23,7 @@ #endif #define DBG_TAG "SIGN" -#define DBG_LVL DBG_INFO +#define DBG_LVL DBG_WARNING #include <rtdbg.h> #define sig_mask(sig_no) (1u << sig_no) @@ -52,17 +52,28 @@ static void _signal_entry(void *parameter) /* 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*/ @@ -82,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); @@ -108,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); @@ -133,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); @@ -154,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; } @@ -272,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); @@ -281,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: @@ -320,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 */ @@ -335,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); } @@ -364,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); } @@ -418,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); @@ -452,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/thread.c b/src/thread.c index 0f2e1dc3d0..276bba9938 100644 --- a/src/thread.c +++ b/src/thread.c @@ -191,7 +191,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 |
