Proc refcnting wrappers
authorBarret Rhoden <brho@cs.berkeley.edu>
Mon, 28 Feb 2011 23:41:45 +0000 (15:41 -0800)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:59 +0000 (17:35 -0700)
Uses proc_incref() and proc_decref() for help with debugging.  Note that
not all sources of incref are via proc_incref() (specifically,
pid2proc()), and other places can still access the kref directly.

14 files changed:
kern/arch/i686/process.c
kern/arch/i686/trap.c
kern/arch/sparc/process.c
kern/arch/sparc/trap.c
kern/include/env.h
kern/include/process.h
kern/src/arsc.c
kern/src/kthread.c
kern/src/manager.c
kern/src/monitor.c
kern/src/process.c
kern/src/resource.c
kern/src/schedule.c
kern/src/syscall.c

index 3b82308..ddae33d 100644 (file)
@@ -59,6 +59,6 @@ void __abandon_core(void)
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        asm volatile ("movw %%ax,%%gs; lldt %%ax" :: "a"(0));
        lcr3(boot_cr3);
-       kref_put(&pcpui->cur_proc->kref);
+       proc_decref(pcpui->cur_proc);
        pcpui->cur_proc = 0;
 }
index ce7a407..b61011d 100644 (file)
@@ -249,7 +249,7 @@ trap_dispatch(trapframe_t *tf)
                                panic("Damn Damn!  Unhandled trap in the kernel!");
                        else {
                                warn("Unexpected trap from userspace");
-                               kref_get(&current->kref, 1);
+                               proc_incref(current, 1);
                                proc_destroy(current);
                                return;
                        }
@@ -374,7 +374,7 @@ void page_fault_handler(struct trapframe *tf)
                       current->pid, prot & PROT_READ ? "READ" : "WRITE", fault_va,
                       tf->tf_eip, core_id(), err);
                print_trapframe(tf);
-               kref_get(&current->kref, 1);
+               proc_incref(current, 1);
                proc_destroy(current);
        }
 }
index e7ccceb..b70ffda 100644 (file)
@@ -42,6 +42,6 @@ void __abandon_core(void)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        lcr3(boot_cr3);
-       kref_put(&pcpui->cur_proc->kref);
+       proc_decref(pcpui->cur_proc);
        pcpui->cur_proc = 0;
 }
index 3dc0144..cc743ff 100644 (file)
@@ -331,7 +331,7 @@ unhandled_trap(trapframe_t* state)
                spin_unlock(&screwup_lock);
 
                assert(current);
-               kref_get(&current->kref, 1);
+               proc_incref(current, 1);
                proc_destroy(current);
 
                panic("I shouldn't have gotten here!");
index cdc08b2..9510853 100644 (file)
@@ -31,7 +31,7 @@ struct proc {
        pid_t ppid;                 // Parent's PID
        pid_t exitcode;                         // exit() param or main() return value
        uint32_t state;                         // Status of the process
-       struct kref kref;               /* Refcnt */
+       struct kref p_kref;             /* Refcnt */
        uint32_t env_flags;
        uint32_t env_entry;
 
index 21f661d..ee159c9 100644 (file)
@@ -76,6 +76,8 @@ struct proc *proc_create(struct file *prog, char **argv, char **envp);
 int __proc_set_state(struct proc *p, uint32_t state) WRITES(p->state);
 struct proc *pid2proc(pid_t pid);
 bool proc_controls(struct proc *SAFE actor, struct proc *SAFE target);
+void proc_incref(struct proc *p, unsigned int val);
+void proc_decref(struct proc *p);
 void proc_run(struct proc *SAFE p);
 void proc_restartcore(void);
 void proc_destroy(struct proc *SAFE p);
index 7487556..6fed271 100644 (file)
@@ -34,7 +34,7 @@ intreg_t inline syscall_async(struct proc *p, syscall_req_t *call)
 
 intreg_t sys_init_arsc(struct proc *p)
 {
-       kref_get(&p->kref, 1);          /* we're storing an external ref here */
+       proc_incref(p, 1);              /* we're storing an external ref here */
        spin_lock_irqsave(&arsc_proc_lock);
        TAILQ_INSERT_TAIL(&arsc_proc_list, p, proc_arsc_link);
        spin_unlock_irqsave(&arsc_proc_lock);
@@ -55,7 +55,7 @@ void arsc_server(struct trapframe *tf)
                        process_generic_syscalls (p, MAX_ASRC_BATCH); 
                        if (p->state == PROC_DYING) {
                                TAILQ_REMOVE(&arsc_proc_list, p, proc_arsc_link);
-                               kref_put(&p->kref);
+                               proc_decref(p);
                                /* Need to break out, so the TAILQ_FOREACH doesn't flip out.
                                 * It's not fair, but we're not dealing with that yet anyway */
                                break;
index aa27a6d..4c58310 100644 (file)
@@ -73,7 +73,7 @@ void sleep_on(struct semaphore *sem)
        kthread->sysc = pcpui->cur_sysc;
        pcpui->cur_sysc = 0;                            /* catch bugs */
        if (kthread->proc)
-               kref_get(&kthread->proc->kref, 1);
+               proc_incref(kthread->proc, 1);
        /* Save the context, toggle blocking for the reactivation */
        save_kernel_tf(&kthread->context);
        if (!blocking)
@@ -106,7 +106,7 @@ unwind_sleep_prep:
        /* Restore the core's current and default stacktop */
        current = kthread->proc;                        /* arguably unnecessary */
        if (kthread->proc)
-               kref_put(&kthread->proc->kref);
+               proc_decref(kthread->proc);
        set_stack_top(kthread->stacktop);
        /* Save the allocs as the spare */
        assert(!pcpui->spare);
@@ -151,7 +151,7 @@ void restart_kthread(struct kthread *kthread)
                /* __launch_kthread() should have abandoned if it was diff */
                assert(current == kthread->proc);
                /* no longer need this ref, current holds it */
-               kref_put(&kthread->proc->kref);
+               proc_decref(kthread->proc);
        } else {
                /* ref gets transfered (or it was 0 (no ref held)) */
                current = kthread->proc;
index 72a858c..af4476d 100644 (file)
@@ -67,7 +67,7 @@ char *p_envp[] = {"LD_LIBRARY_PATH=/lib", 0};
        __proc_set_state((p), PROC_RUNNABLE_S);                                      \
        spin_unlock(&(p)->proc_lock);                                                \
        proc_run((p));                                                               \
-       kref_put(&(p)->kref);
+       proc_decref((p));
 
 #define quick_proc_create(x, p, f)                                               \
        (f) = do_file_open((x), 0, 0);                                               \
@@ -92,7 +92,7 @@ char *p_envp[] = {"LD_LIBRARY_PATH=/lib", 0};
        for (int i = 0; i < (c); i++)                                                \
                cache_color_alloc(llc_cache, p->cache_colors_map);                       \
        proc_run((p));                                                               \
-       kref_put(&(p)->kref);
+       proc_decref((p));
 
 #define quick_proc_color_create(x, p, c, f)                                      \
        (f) = do_file_open((x), 0, 0);                                               \
index 83393a0..8d129dd 100644 (file)
@@ -300,7 +300,7 @@ int mon_bin_run(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
        __proc_set_state(p, PROC_RUNNABLE_S);
        schedule_proc(p);
        spin_unlock(&p->proc_lock);
-       kref_put(&p->kref); /* let go of the reference created in proc_create() */
+       proc_decref(p); /* let go of the reference created in proc_create() */
        kref_put(&program->f_kref);
        /* Should never return from schedule (env_pop in there) also note you may
         * not get the process you created, in the event there are others floating
@@ -358,7 +358,7 @@ int mon_procinfo(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                        return 1;
                }
                proc_destroy(p);
-               kref_put(&p->kref);
+               proc_decref(p);
        } else {
                printk("Bad option\n");
                return 1;
@@ -461,7 +461,7 @@ int mon_notify(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                /* o/w, try and do what they want */
                send_kernel_event(p, &msg, 0);
        }
-       kref_put(&p->kref);
+       proc_decref(p);
        return 0;
 }
 
@@ -497,14 +497,14 @@ int mon_measure(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                begin = start_timing();
 #ifdef __CONFIG_APPSERVER__
                printk("Warning: this will be inaccurate due to the appserver.\n");
-               end_refcnt = kref_refcnt(&p->kref) - p->procinfo->num_vcores - 1;
+               end_refcnt = kref_refcnt(&p->p_kref) - p->procinfo->num_vcores - 1;
 #endif /* __CONFIG_APPSERVER__ */
                proc_destroy(p);
-               kref_put(&p->kref);
+               proc_decref(p);
 #ifdef __CONFIG_APPSERVER__
                /* Won't be that accurate, since it's not actually going through the
                 * __proc_free() path. */
-               spin_on(kref_refcnt(&p->kref) != end_refcnt);   
+               spin_on(kref_refcnt(&p->p_kref) != end_refcnt); 
 #else
                /* this is a little ghetto. it's not fully free yet, but we are also
                 * slowing it down by messing with it, esp with the busy waiting on a
@@ -531,14 +531,14 @@ int mon_measure(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                        spin_on(p->procinfo->pcoremap[pcoreid].valid);
                        diff = stop_timing(begin);
                } else { /* preempt all cores, warned but no delay */
-                       end_refcnt = kref_refcnt(&p->kref) - p->procinfo->num_vcores;
+                       end_refcnt = kref_refcnt(&p->p_kref) - p->procinfo->num_vcores;
                        begin = start_timing();
                        proc_preempt_all(p, 1000000);
                        /* a little ghetto, implies no one is using p */
-                       spin_on(kref_refcnt(&p->kref) != end_refcnt);
+                       spin_on(kref_refcnt(&p->p_kref) != end_refcnt);
                        diff = stop_timing(begin);
                }
-               kref_put(&p->kref);
+               proc_decref(p);
        } else if (!strcmp(argv[1], "preempt-warn")) {
                if (argc < 3) {
                        printk("Give me a pid number.\n");
@@ -576,7 +576,7 @@ int mon_measure(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                        spin_on(p->procinfo->num_vcores > 1);
                        diff = stop_timing(begin);
                }
-               kref_put(&p->kref);
+               proc_decref(p);
        } else if (!strcmp(argv[1], "preempt-raw")) {
                if (argc < 3) {
                        printk("Give me a pid number.\n");
@@ -605,17 +605,17 @@ int mon_measure(int argc, char *NTS *NT COUNT(argc) argv, trapframe_t *tf)
                        /* TODO: (RMS), if num_vcores == 0, RUNNABLE_M, schedule */
                } else { /* preempt all cores, no warning or waiting */
                        spin_lock(&p->proc_lock);
-                       end_refcnt = kref_refcnt(&p->kref) - p->procinfo->num_vcores;
+                       end_refcnt = kref_refcnt(&p->p_kref) - p->procinfo->num_vcores;
                        begin = start_timing();
                        self_ipi_pending = __proc_preempt_all(p);
                        /* TODO: (RMS), RUNNABLE_M, schedule */
                        spin_unlock(&p->proc_lock);
                        __proc_kmsg_pending(p, self_ipi_pending);
                        /* a little ghetto, implies no one else is using p */
-                       spin_on(kref_refcnt(&p->kref) != end_refcnt);
+                       spin_on(kref_refcnt(&p->p_kref) != end_refcnt);
                        diff = stop_timing(begin);
                }
-               kref_put(&p->kref);
+               proc_decref(p);
        } else {
                printk("Bad option\n");
                return 1;
index 3fb5a7d..4c0bc46 100644 (file)
@@ -173,7 +173,7 @@ struct proc *pid2proc(pid_t pid)
        spin_lock(&pid_hash_lock);
        struct proc *p = hashtable_search(pid_hash, (void*)pid);
        if (p)
-               if (!kref_get_not_zero(&p->kref, 1))
+               if (!kref_get_not_zero(&p->p_kref, 1))
                        p = 0;
        spin_unlock(&pid_hash_lock);
        return p;
@@ -273,7 +273,7 @@ error_t proc_alloc(struct proc **pp, struct proc *parent)
        { INITSTRUCT(*p)
 
        /* one reference for the proc existing, and one for the ref we pass back. */
-       kref_init(&p->kref, __proc_free, 2);
+       kref_init(&p->p_kref, __proc_free, 2);
        // Setup the default map of where to get cache colors from
        p->cache_colors_map = global_cache_colors_map;
        p->next_cache_color = 0;
@@ -376,12 +376,12 @@ struct proc *proc_create(struct file *prog, char **argv, char **envp)
  * address space and deallocate any other used memory. */
 static void __proc_free(struct kref *kref)
 {
-       struct proc *p = container_of(kref, struct proc, kref);
+       struct proc *p = container_of(kref, struct proc, p_kref);
        physaddr_t pa;
 
        printd("[PID %d] freeing proc: %d\n", current ? current->pid : 0, p->pid);
        // All parts of the kernel should have decref'd before __proc_free is called
-       assert(kref_refcnt(&p->kref) == 0);
+       assert(kref_refcnt(&p->p_kref) == 0);
 
        kref_put(&p->fs_env.root->d_kref);
        kref_put(&p->fs_env.pwd->d_kref);
@@ -422,6 +422,19 @@ bool proc_controls(struct proc *actor, struct proc *target)
        return ((actor == target) || (target->ppid == actor->pid));
 }
 
+/* Helper to incref by val.  Using the helper to help debug/interpose on proc
+ * ref counting.  Note that pid2proc doesn't use this interface. */
+void proc_incref(struct proc *p, unsigned int val)
+{
+       kref_get(&p->p_kref, val);
+}
+
+/* Helper to decref for debugging.  Don't directly kref_put() for now. */
+void proc_decref(struct proc *p)
+{
+       kref_put(&p->p_kref);
+}
+
 /* Helper, makes p the 'current' process, dropping the old current/cr3.  Don't
  * incref - this assumes the passed in reference already counted 'current'. */
 static void __set_proc_current(struct proc *p)
@@ -439,7 +452,7 @@ static void __set_proc_current(struct proc *p)
                 * rarely happen, since we usually proactively leave process context,
                 * but this is the fallback. */
                if (pcpui->cur_proc)
-                       kref_put(&pcpui->cur_proc->kref);
+                       proc_decref(pcpui->cur_proc);
                pcpui->cur_proc = p;
        }
 }
@@ -486,7 +499,7 @@ void proc_run(struct proc *p)
                         * current.  Decref if current is already properly set, otherwise
                         * ensure current is set. */
                        if (p == current)
-                               kref_put(&p->kref);
+                               proc_decref(p);
                        else
                                __set_proc_current(p);
                        /* We restartcore, instead of startcore, since startcore is a bit
@@ -504,7 +517,7 @@ void proc_run(struct proc *p)
                                __proc_set_state(p, PROC_RUNNING_M);
                                /* Up the refcnt, since num_vcores are going to start using this
                                 * process and have it loaded in their 'current'. */
-                               kref_get(&p->kref, p->procinfo->num_vcores);
+                               proc_incref(p, p->procinfo->num_vcores);
                                /* If the core we are running on is in the vcoremap, we will get
                                 * an IPI (once we reenable interrupts) and never return. */
                                if (is_mapped_vcore(p, core_id()))
@@ -645,7 +658,7 @@ void proc_destroy(struct proc *p)
                        // here's how to do it manually
                        if (current == p) {
                                lcr3(boot_cr3);
-                               kref_put(&p->kref);             /* this decref is for the cr3 */
+                               proc_decref(p);         /* this decref is for the cr3 */
                                current = NULL;
                        }
                        #endif
@@ -680,8 +693,8 @@ void proc_destroy(struct proc *p)
         * will help if these files (or similar objects in the future) hold
         * references to p (preventing a __proc_free()). */
        close_all_files(&p->open_files, FALSE);
-       /* This kref_put() is for the process's existence. */
-       kref_put(&p->kref);
+       /* This decref is for the process's existence. */
+       proc_decref(p);
        /* Unlock and possible decref and wait.  A death IPI should be on its way,
         * either from the RUNNING_S one, or from proc_take_cores with a __death.
         * in general, interrupts should be on when you call proc_destroy locally,
@@ -832,7 +845,7 @@ void proc_yield(struct proc *SAFE p, bool being_nice)
                              __FUNCTION__);
        }
        spin_unlock(&p->proc_lock);
-       kref_put(&p->kref);                     /* need to eat the ref passed in */
+       proc_decref(p);                 /* need to eat the ref passed in */
        /* TODO: (RMS) If there was a change to the idle cores, try and give our
         * core to someone who was preempted. */
        /* Clean up the core and idle.  For mgmt cores, they will ultimately call
@@ -1105,7 +1118,7 @@ bool __proc_give_cores(struct proc *SAFE p, uint32_t *pcorelist, size_t num)
                case (PROC_RUNNING_M):
                        /* Up the refcnt, since num cores are going to start using this
                         * process and have it loaded in their 'current'. */
-                       kref_get(&p->kref, num);
+                       proc_incref(p, num);
                        __seq_start_write(&p->procinfo->coremap_seqctr);
                        for (int i = 0; i < num; i++) {
                                free_vcoreid = get_free_vcoreid(p, free_vcoreid);
@@ -1264,7 +1277,7 @@ bool __proc_take_allcores(struct proc *SAFE p, amr_t message,
 void __proc_kmsg_pending(struct proc *p, bool ipi_pending)
 {
        if (ipi_pending) {
-               kref_put(&p->kref);
+               proc_decref(p);
                process_routine_kmsg(0);
                panic("stack-killing kmsg not found in %s!!!", __FUNCTION__);
        }
@@ -1352,7 +1365,7 @@ void __startcore(trapframe_t *tf, uint32_t srcid, void *a0, void *a1, void *a2)
        assert(p_to_run);
        /* the sender of the amsg increfed, thinking we weren't running current. */
        if (p_to_run == current)
-               kref_put(&p_to_run->kref);
+               proc_decref(p_to_run);
        vcoreid = get_vcoreid(p_to_run, pcoreid);
        vcpd = &p_to_run->procdata->vcore_preempt_data[vcoreid];
        printd("[kernel] startcore on physical core %d for process %d's vcore %d\n",
@@ -1521,7 +1534,7 @@ void print_proc_info(pid_t pid)
        printk("PID: %d\n", p->pid);
        printk("PPID: %d\n", p->ppid);
        printk("State: 0x%08x\n", p->state);
-       printk("Refcnt: %d\n", atomic_read(&p->kref.refcount) - 1);
+       printk("Refcnt: %d\n", atomic_read(&p->p_kref.refcount) - 1);
        printk("Flags: 0x%08x\n", p->env_flags);
        printk("CR3(phys): 0x%08x\n", p->env_cr3);
        printk("Num Vcores: %d\n", p->procinfo->num_vcores);
@@ -1550,5 +1563,5 @@ void print_proc_info(pid_t pid)
        //print_trapframe(&p->env_tf);
        /* no locking / unlocking or refcnting */
        // spin_unlock(&p->proc_lock);
-       kref_put(&p->kref);
+       proc_decref(p);
 }
index 52d5ed5..48a83d9 100644 (file)
@@ -169,7 +169,7 @@ ssize_t core_request(struct proc *p)
                 * (just like in proc_destroy).  it also needs to decref, to consume the
                 * reference that came into this function (since we don't return).  */
                if (need_to_idle) {
-                       kref_put(&p->kref);
+                       proc_decref(p);
                        abandon_core();
                        smp_idle();
                }
index ad6a094..fe68161 100644 (file)
@@ -33,7 +33,7 @@ void schedule_init(void)
 void schedule_proc(struct proc *p)
 {
        /* up the refcnt since we are storing the reference */
-       kref_get(&p->kref, 1);
+       proc_incref(p, 1);
        spin_lock_irqsave(&runnablelist_lock);
        printd("Scheduling PID: %d\n", p->pid);
        TAILQ_INSERT_TAIL(&proc_runnablelist, p, proc_link);
@@ -52,7 +52,7 @@ void deschedule_proc(struct proc *p)
        TAILQ_REMOVE(&proc_runnablelist, p, proc_link);
        spin_unlock_irqsave(&runnablelist_lock);
        /* down the refcnt, since its no longer stored */
-       kref_put(&p->kref);
+       proc_decref(p);
        return;
 }
 
@@ -73,7 +73,7 @@ void schedule(void)
                printd("PID of proc i'm running: %d\n", p->pid);
                /* proc_run will either eat the ref, or we'll decref manually. */
                proc_run(p);
-               kref_put(&p->kref);
+               proc_decref(p);
        } else {
                spin_unlock_irqsave(&runnablelist_lock);
        }
index 0bfd7da..cfb9812 100644 (file)
@@ -306,7 +306,7 @@ static int sys_proc_create(struct proc *p, char *path, size_t path_l,
        assert(insert_file(&new_p->open_files, dev_stderr, 0) == 2);
        __proc_ready(new_p);
        pid = new_p->pid;
-       kref_put(&new_p->kref); /* give up the reference created in proc_create() */
+       proc_decref(new_p);     /* give up the reference created in proc_create() */
        return pid;
 late_error:
        proc_destroy(new_p);
@@ -327,17 +327,17 @@ static error_t sys_proc_run(struct proc *p, unsigned pid)
        spin_lock(&p->proc_lock);
        // make sure we have access and it's in the right state to be activated
        if (!proc_controls(p, target)) {
-               kref_put(&target->kref);
+               proc_decref(target);
                retval = -EPERM;
        } else if (target->state != PROC_CREATED) {
-               kref_put(&target->kref);
+               proc_decref(target);
                retval = -EINVAL;
        } else {
                __proc_set_state(target, PROC_RUNNABLE_S);
                schedule_proc(target);
        }
        spin_unlock(&p->proc_lock);
-       kref_put(&target->kref);
+       proc_decref(target);
        return retval;
 }
 
@@ -355,7 +355,7 @@ static error_t sys_proc_destroy(struct proc *p, pid_t pid, int exitcode)
                return -1;
        }
        if (!proc_controls(p, p_to_die)) {
-               kref_put(&p_to_die->kref);
+               proc_decref(p_to_die);
                set_errno(EPERM);
                return -1;
        }
@@ -367,7 +367,7 @@ static error_t sys_proc_destroy(struct proc *p, pid_t pid, int exitcode)
        }
        proc_destroy(p_to_die);
        /* we only get here if we weren't the one to die */
-       kref_put(&p_to_die->kref);
+       proc_decref(p_to_die);
        return ESUCCESS;
 }
 
@@ -377,9 +377,9 @@ static int sys_proc_yield(struct proc *p, bool being_nice)
         * early.  If it doesn't return, it expects to eat our reference (for now).
         */
        signal_current_sc(0);
-       kref_get(&p->kref, 1);
+       proc_incref(p, 1);
        proc_yield(p, being_nice);
-       kref_put(&p->kref);
+       proc_decref(p);
        return 0;
 }
 
@@ -607,8 +607,8 @@ static ssize_t sys_trywait(env_t* e, pid_t pid, int* status)
 
                // if the wait succeeded, decref twice
                if (ret == 0)
-                       kref_put(&p->kref);
-               kref_put(&p->kref);
+                       proc_decref(p);
+               proc_decref(p);
                return ret;
        }
 
@@ -655,9 +655,9 @@ static int sys_resource_req(struct proc *p, int type, unsigned int amt_wanted,
        int retval;
        signal_current_sc(0);
        /* this might not return (if it's a _S -> _M transition) */
-       kref_get(&p->kref, 1);
+       proc_incref(p, 1);
        retval = resource_req(p, type, amt_wanted, amt_wanted_min, flags);
-       kref_put(&p->kref);
+       proc_decref(p);
        return retval;
 }
 
@@ -673,20 +673,20 @@ static int sys_notify(struct proc *p, int target_pid, unsigned int ev_type,
                return -1;
        }
        if (!proc_controls(p, target)) {
-               kref_put(&target->kref);
+               proc_decref(target);
                set_errno(EPERM);
                return -1;
        }
        /* if the user provided an ev_msg, copy it in and use that */
        if (u_msg) {
                if (memcpy_from_user(p, &local_msg, u_msg, sizeof(struct event_msg))) {
-                       kref_put(&target->kref);
+                       proc_decref(target);
                        set_errno(EINVAL);
                        return -1;
                }
        }
        send_kernel_event(target, &local_msg, 0);
-       kref_put(&target->kref);
+       proc_decref(target);
        return 0;
 }