Commit 748ed827 authored by Jan Kiszka's avatar Jan Kiszka
Browse files

cobalt: Move common cleanup code out of pipeline diversion again



Same pattern as for previous changes: All that code it common, no need
to duplicate it. The only difference between the two versions of
handle_cleanup_event was what is now encapsulated in
pipeline_cleanup_process.
Signed-off-by: Jan Kiszka's avatarJan Kiszka <jan.kiszka@siemens.com>
parent 926b795b
......@@ -31,4 +31,6 @@ int pipeline_trap_kevents(void);
void pipeline_enable_kevents(void);
void pipeline_cleanup_process(void);
#endif /* !_COBALT_KERNEL_DOVETAIL_KEVENTS_H */
......@@ -31,4 +31,6 @@ int pipeline_trap_kevents(void);
void pipeline_enable_kevents(void);
void pipeline_cleanup_process(void);
#endif /* !_COBALT_KERNEL_IPIPE_KEVENTS_H */
......@@ -22,8 +22,6 @@
#include "../posix/thread.h"
#include "../posix/memory.h"
static void detach_current(void);
void arch_inband_task_init(struct task_struct *tsk)
{
struct cobalt_threadinfo *p = dovetail_task_state(tsk);
......@@ -99,56 +97,9 @@ static inline int handle_setaffinity_event(struct dovetail_migration_data *d)
return cobalt_handle_setaffinity_event(d->task);
}
static void __handle_taskexit_event(struct task_struct *p)
{
struct cobalt_ppd *sys_ppd;
struct xnthread *thread;
spl_t s;
/*
* We are called for both kernel and user shadows over the
* root thread.
*/
secondary_mode_only();
thread = xnthread_current();
XENO_BUG_ON(COBALT, thread == NULL);
trace_cobalt_shadow_unmap(thread);
xnlock_get_irqsave(&nklock, s);
if (xnthread_test_state(thread, XNSSTEP))
cobalt_unregister_debugged_thread(thread);
xnsched_run();
xnlock_put_irqrestore(&nklock, s);
xnthread_run_handler_stack(thread, exit_thread);
if (xnthread_test_state(thread, XNUSER)) {
cobalt_umm_free(&cobalt_kernel_ppd.umm, thread->u_window);
thread->u_window = NULL;
sys_ppd = cobalt_ppd_get(0);
if (atomic_dec_and_test(&sys_ppd->refcnt))
cobalt_remove_process(cobalt_current_process());
}
}
static int handle_taskexit_event(struct task_struct *p) /* p == current */
static inline int handle_taskexit_event(struct task_struct *p)
{
__handle_taskexit_event(p);
/*
* __xnthread_cleanup() -> ... -> finalize_thread
* handler. From that point, the TCB is dropped. Be careful of
* not treading on stale memory within @thread.
*/
__xnthread_cleanup(xnthread_current());
detach_current();
return KEVENT_PROPAGATE;
return cobalt_handle_taskexit_event(p);
}
static int handle_user_return(struct task_struct *task)
......@@ -238,55 +189,14 @@ out:
return KEVENT_PROPAGATE;
}
static int handle_cleanup_event(struct mm_struct *mm)
static inline int handle_cleanup_event(struct mm_struct *mm)
{
struct cobalt_process *old, *process;
struct cobalt_ppd *sys_ppd;
struct xnthread *curr;
/*
* We are NOT called for exiting kernel shadows.
* cobalt_current_process() is cleared if we get there after
* handle_task_exit(), so we need to restore this context
* pointer temporarily.
*/
process = cobalt_search_process(mm);
old = cobalt_set_process(process);
sys_ppd = cobalt_ppd_get(0);
if (sys_ppd != &cobalt_kernel_ppd) {
bool running_exec;
/*
* Detect a userland shadow running exec(), i.e. still
* attached to the current linux task (no prior
* detach_current). In this case, we emulate a task
* exit, since the Xenomai binding shall not survive
* the exec() syscall. Since the process will keep on
* running though, we have to disable the event
* notifier manually for it.
*/
curr = xnthread_current();
running_exec = curr && (current->flags & PF_EXITING) == 0;
if (running_exec) {
__handle_taskexit_event(current);
dovetail_stop_altsched();
}
if (atomic_dec_and_test(&sys_ppd->refcnt))
cobalt_remove_process(process);
if (running_exec) {
__xnthread_cleanup(curr);
detach_current();
}
}
/*
* CAUTION: Do not override a state change caused by
* cobalt_remove_process().
*/
if (cobalt_current_process() == process)
cobalt_set_process(old);
return cobalt_handle_cleanup_event(mm);
}
return KEVENT_PROPAGATE;
void pipeline_cleanup_process(void)
{
dovetail_stop_altsched();
}
int handle_ptrace_resume(struct task_struct *tracee)
......@@ -456,14 +366,6 @@ void pipeline_attach_current(struct xnthread *thread)
dovetail_init_altsched(&xnthread_archtcb(thread)->altsched);
}
static void detach_current(void)
{
struct cobalt_threadinfo *p = pipeline_current();
p->thread = NULL;
p->process = NULL;
}
int pipeline_trap_kevents(void)
{
dovetail_start();
......
......@@ -24,8 +24,6 @@
#include "../posix/thread.h"
#include "../posix/memory.h"
static void detach_current(void);
static inline int handle_exception(struct ipipe_trap_data *d)
{
struct xnthread *thread;
......@@ -156,6 +154,11 @@ static inline int handle_setaffinity_event(struct ipipe_cpu_migration_data *d)
return cobalt_handle_setaffinity_event(d->task);
}
static inline int handle_taskexit_event(struct task_struct *p)
{
return cobalt_handle_taskexit_event(p);
}
void ipipe_migration_hook(struct task_struct *p) /* hw IRQs off */
{
struct xnthread *thread = xnthread_from_task(p);
......@@ -242,58 +245,6 @@ static inline void init_hostrt(void) { }
#endif /* !CONFIG_IPIPE_HAVE_HOSTRT */
static void __handle_taskexit_event(struct task_struct *p)
{
struct cobalt_ppd *sys_ppd;
struct xnthread *thread;
spl_t s;
/*
* We are called for both kernel and user shadows over the
* root thread.
*/
secondary_mode_only();
thread = xnthread_current();
XENO_BUG_ON(COBALT, thread == NULL);
trace_cobalt_shadow_unmap(thread);
xnlock_get_irqsave(&nklock, s);
if (xnthread_test_state(thread, XNSSTEP))
cobalt_unregister_debugged_thread(thread);
xnsched_run();
xnlock_put_irqrestore(&nklock, s);
xnthread_run_handler_stack(thread, exit_thread);
if (xnthread_test_state(thread, XNUSER)) {
cobalt_umm_free(&cobalt_kernel_ppd.umm, thread->u_window);
thread->u_window = NULL;
sys_ppd = cobalt_ppd_get(0);
if (atomic_dec_and_test(&sys_ppd->refcnt))
cobalt_remove_process(cobalt_current_process());
}
}
static int handle_taskexit_event(struct task_struct *p) /* p == current */
{
__handle_taskexit_event(p);
/*
* __xnthread_cleanup() -> ... -> finalize_thread
* handler. From that point, the TCB is dropped. Be careful of
* not treading on stale memory within @thread.
*/
__xnthread_cleanup(xnthread_current());
detach_current();
return KEVENT_PROPAGATE;
}
static int handle_schedule_event(struct task_struct *next_task)
{
struct task_struct *prev_task;
......@@ -431,55 +382,14 @@ out:
return KEVENT_PROPAGATE;
}
static int handle_cleanup_event(struct mm_struct *mm)
static inline int handle_cleanup_event(struct mm_struct *mm)
{
struct cobalt_process *old, *process;
struct cobalt_ppd *sys_ppd;
struct xnthread *curr;
/*
* We are NOT called for exiting kernel shadows.
* cobalt_current_process() is cleared if we get there after
* handle_task_exit(), so we need to restore this context
* pointer temporarily.
*/
process = cobalt_search_process(mm);
old = cobalt_set_process(process);
sys_ppd = cobalt_ppd_get(0);
if (sys_ppd != &cobalt_kernel_ppd) {
bool running_exec;
/*
* Detect a userland shadow running exec(), i.e. still
* attached to the current linux task (no prior
* detach_current). In this case, we emulate a task
* exit, since the Xenomai binding shall not survive
* the exec() syscall. Since the process will keep on
* running though, we have to disable the event
* notifier manually for it.
*/
curr = xnthread_current();
running_exec = curr && (current->flags & PF_EXITING) == 0;
if (running_exec) {
__handle_taskexit_event(current);
ipipe_disable_notifier(current);
}
if (atomic_dec_and_test(&sys_ppd->refcnt))
cobalt_remove_process(process);
if (running_exec) {
__xnthread_cleanup(curr);
detach_current();
}
}
/*
* CAUTION: Do not override a state change caused by
* cobalt_remove_process().
*/
if (cobalt_current_process() == process)
cobalt_set_process(old);
return cobalt_handle_cleanup_event(mm);
}
return KEVENT_PROPAGATE;
void pipeline_cleanup_process(void)
{
ipipe_disable_notifier(current);
}
static inline int handle_clockfreq_event(unsigned int *p)
......@@ -642,13 +552,6 @@ void pipeline_attach_current(struct xnthread *thread)
p->process = cobalt_search_process(current->mm);
}
static void detach_current(void)
{
struct cobalt_threadinfo *p = pipeline_current();
p->thread = NULL;
p->process = NULL;
}
int pipeline_trap_kevents(void)
{
init_hostrt();
......
......@@ -834,6 +834,117 @@ bool cobalt_affinity_ok(struct task_struct *task) /* nklocked, IRQs off */
}
#endif /* CONFIG_SMP */
static void __handle_taskexit_event(struct task_struct *p)
{
struct cobalt_ppd *sys_ppd;
struct xnthread *thread;
spl_t s;
/*
* We are called for both kernel and user shadows over the
* root thread.
*/
secondary_mode_only();
thread = xnthread_current();
XENO_BUG_ON(COBALT, thread == NULL);
trace_cobalt_shadow_unmap(thread);
xnlock_get_irqsave(&nklock, s);
if (xnthread_test_state(thread, XNSSTEP))
cobalt_unregister_debugged_thread(thread);
xnsched_run();
xnlock_put_irqrestore(&nklock, s);
xnthread_run_handler_stack(thread, exit_thread);
if (xnthread_test_state(thread, XNUSER)) {
cobalt_umm_free(&cobalt_kernel_ppd.umm, thread->u_window);
thread->u_window = NULL;
sys_ppd = cobalt_ppd_get(0);
if (atomic_dec_and_test(&sys_ppd->refcnt))
cobalt_remove_process(cobalt_current_process());
}
}
static void detach_current(void)
{
struct cobalt_threadinfo *p = pipeline_current();
p->thread = NULL;
p->process = NULL;
}
int cobalt_handle_taskexit_event(struct task_struct *task) /* task == current */
{
__handle_taskexit_event(task);
/*
* __xnthread_cleanup() -> ... -> finalize_thread
* handler. From that point, the TCB is dropped. Be careful of
* not treading on stale memory within @thread.
*/
__xnthread_cleanup(xnthread_current());
detach_current();
return KEVENT_PROPAGATE;
}
int cobalt_handle_cleanup_event(struct mm_struct *mm)
{
struct cobalt_process *old, *process;
struct cobalt_ppd *sys_ppd;
struct xnthread *curr;
/*
* We are NOT called for exiting kernel shadows.
* cobalt_current_process() is cleared if we get there after
* handle_task_exit(), so we need to restore this context
* pointer temporarily.
*/
process = cobalt_search_process(mm);
old = cobalt_set_process(process);
sys_ppd = cobalt_ppd_get(0);
if (sys_ppd != &cobalt_kernel_ppd) {
bool running_exec;
/*
* Detect a userland shadow running exec(), i.e. still
* attached to the current linux task (no prior
* detach_current). In this case, we emulate a task
* exit, since the Xenomai binding shall not survive
* the exec() syscall. Since the process will keep on
* running though, we have to disable the event
* notifier manually for it.
*/
curr = xnthread_current();
running_exec = curr && (current->flags & PF_EXITING) == 0;
if (running_exec) {
__handle_taskexit_event(current);
pipeline_cleanup_process();
}
if (atomic_dec_and_test(&sys_ppd->refcnt))
cobalt_remove_process(process);
if (running_exec) {
__xnthread_cleanup(curr);
detach_current();
}
}
/*
* CAUTION: Do not override a state change caused by
* cobalt_remove_process().
*/
if (cobalt_current_process() == process)
cobalt_set_process(old);
return KEVENT_PROPAGATE;
}
static int attach_process(struct cobalt_process *process)
{
struct cobalt_ppd *p = &process->sys_ppd;
......
......@@ -169,4 +169,8 @@ bool cobalt_affinity_ok(struct task_struct *task);
#define cobalt_affinity_ok(task) (true)
#endif
int cobalt_handle_taskexit_event(struct task_struct *task);
int cobalt_handle_cleanup_event(struct mm_struct *mm);
#endif /* !_COBALT_POSIX_PROCESS_H */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment