diff options
Diffstat (limited to 'xen')
-rw-r--r-- | xen/common/dom0_ops.c | 4 | ||||
-rw-r--r-- | xen/common/domain.c | 35 | ||||
-rw-r--r-- | xen/common/network.c | 6 | ||||
-rw-r--r-- | xen/include/asm-i386/processor.h | 9 | ||||
-rw-r--r-- | xen/include/xeno/dom0_ops.h | 1 | ||||
-rw-r--r-- | xen/include/xeno/sched.h | 6 |
6 files changed, 38 insertions, 23 deletions
diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index 1d43f641ba..e451a8f3e7 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -81,6 +81,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) wake_up(p); reschedule(p); ret = p->domain; + free_task_struct(p); } break; @@ -113,13 +114,14 @@ long do_dom0_op(dom0_op_t *u_dom0_op) case DOM0_KILLDOMAIN: { unsigned int dom = op.u.killdomain.domain; + int force = op.u.killdomain.force; if ( dom == IDLE_DOMAIN_ID ) { ret = -EPERM; } else { - ret = kill_other_domain(dom); + ret = kill_other_domain(dom, force); } } break; diff --git a/xen/common/domain.c b/xen/common/domain.c index 5e862ada6d..89efe59f64 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -40,6 +40,8 @@ struct task_struct *do_newdomain(unsigned int dom_id, unsigned int cpu) if (!p) goto newdomain_out; memset(p, 0, sizeof(*p)); + atomic_set(&p->refcnt, 1); + p->domain = dom_id; p->processor = cpu; @@ -82,6 +84,7 @@ struct task_struct *find_domain_by_id(unsigned int dom) read_lock_irq(&tasklist_lock); do { if ( (p->domain == dom) ) { + get_task_struct(p); /* increment the refcnt for caller */ read_unlock_irq(&tasklist_lock); return (p); } @@ -117,27 +120,27 @@ void kill_domain(void) } -long kill_other_domain(unsigned int dom) +long kill_other_domain(unsigned int dom, int force) { - struct task_struct *p = &idle0_task; + struct task_struct *p; unsigned long cpu_mask = 0; - long ret = -ESRCH; - read_lock_irq(&tasklist_lock); - do { - if ( p->domain == dom ) - { - cpu_mask = mark_guest_event(p, _EVENT_DIE); - ret = 0; - break; - } - } - while ( (p = p->next_task) != &idle0_task ); - read_unlock_irq(&tasklist_lock); + p = find_domain_by_id(dom); + if ( p == NULL ) return -ESRCH; - hyp_event_notify(cpu_mask); + if ( force ) + { + cpu_mask = mark_hyp_event(p, _HYP_EVENT_DIE); + hyp_event_notify(cpu_mask); + } + else + { + cpu_mask = mark_guest_event(p, _EVENT_DIE); + guest_event_notify(cpu_mask); + } - return ret; + free_task_struct(p); + return 0; } diff --git a/xen/common/network.c b/xen/common/network.c index f761ca9ba2..cd726621f1 100644 --- a/xen/common/network.c +++ b/xen/common/network.c @@ -81,7 +81,7 @@ net_vif_t *create_net_vif(int domain) new_vif->net_ring = new_ring; new_vif->shadow_ring = shadow_ring; - new_vif->domain = find_domain_by_id(domain); + new_vif->domain = dom_task; new_vif->list.next = NULL; @@ -93,6 +93,7 @@ net_vif_t *create_net_vif(int domain) dom_task->net_vif_list[dom_task->num_net_vifs] = new_vif; dom_task->num_net_vifs++; + free_task_struct(dom_task); return new_vif; fail: @@ -103,6 +104,8 @@ fail: if ( shadow_ring->tx_ring ) kfree(shadow_ring->tx_ring); kfree(shadow_ring); } + + free_task_struct(dom_task); return NULL; } @@ -149,6 +152,7 @@ void vif_query(vif_query_t *vq) copy_to_user(vq->buf, buf, strlen(buf) + 1); + free_task_struct(dom_task); } diff --git a/xen/include/asm-i386/processor.h b/xen/include/asm-i386/processor.h index 36a50b2976..e5d2e420ac 100644 --- a/xen/include/asm-i386/processor.h +++ b/xen/include/asm-i386/processor.h @@ -440,9 +440,12 @@ unsigned long get_wchan(struct task_struct *p); #define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1022]) #define THREAD_SIZE (2*PAGE_SIZE) -#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) -#define free_task_struct(p) free_pages((unsigned long) (p), 1) -#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count) +#define alloc_task_struct() \ + ((struct task_struct *) __get_free_pages(GFP_KERNEL,1)) +#define free_task_struct(_p) \ + if ( atomic_dec_and_test(&(_p)->refcnt) ) free_pages((unsigned long)(_p), 1) +#define get_task_struct(_p) \ + atomic_inc(&(_p)->refcnt) #define idle0_task (idle0_task_union.task) #define idle0_stack (idle0_task_union.stack) diff --git a/xen/include/xeno/dom0_ops.h b/xen/include/xeno/dom0_ops.h index 49a5842fab..5e498de1bc 100644 --- a/xen/include/xeno/dom0_ops.h +++ b/xen/include/xeno/dom0_ops.h @@ -27,6 +27,7 @@ typedef struct dom0_newdomain_st typedef struct dom0_killdomain_st { unsigned int domain; + int force; } dom0_killdomain_t; typedef struct dom0_getmemlist_st diff --git a/xen/include/xeno/sched.h b/xen/include/xeno/sched.h index 3cffa46bf1..b0855f7b0a 100644 --- a/xen/include/xeno/sched.h +++ b/xen/include/xeno/sched.h @@ -60,7 +60,7 @@ struct task_struct { int processor; int state; - int hyp_events; + int hyp_events; unsigned int domain; /* An unsafe pointer into a shared data area. */ @@ -101,6 +101,8 @@ struct task_struct { struct task_struct *prev_task, *next_task; unsigned long flags; + + atomic_t refcnt; }; /* @@ -163,7 +165,7 @@ struct task_struct *find_domain_by_id(unsigned int dom); extern void release_task(struct task_struct *); extern void kill_domain(void); extern void kill_domain_with_errmsg(const char *err); -extern long kill_other_domain(unsigned int dom); +extern long kill_other_domain(unsigned int dom, int force); /* arch/process.c */ void new_thread(struct task_struct *p, |