struct pid *find_pid_ns(int nr, struct pid_namespace *ns) { struct hlist_node *elem; struct upid *pnr; #ifndef NOTC struct hlist_head *head = &pid_hash[pid_hashfn(nr, ns)]; int level = ns->level; #endif #ifdef NOTC hlist_for_each_entry_rcu(pnr, elem, &pid_hash[pid_hashfn(nr, ns)], pid_chain) #else hlist_for_each_entry_rcu(pnr, elem, head, pid_chain) #endif if (pnr->nr == nr && pnr->ns == ns) #ifdef NOTC return container_of(pnr, struct pid, numbers[ns->level]); #else { size_t off = (size_t)((struct pid *)0)->numbers + sizeof(struct upid) * ns->level; return (struct pid *)((char *)pnr - off); } #endif return NULL; }
struct pid *alloc_pid(struct pid_namespace *ns) { struct pid *pid; enum pid_type type; int i, nr; struct pid_namespace *tmp; struct upid *upid; pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL); if (!pid) goto out; tmp = ns; pid->level = ns->level; for (i = ns->level; i >= 0; i--) { nr = alloc_pidmap(tmp); if (nr < 0) goto out_free; pid->numbers[i].nr = nr; pid->numbers[i].ns = tmp; tmp = tmp->parent; } if (unlikely(is_child_reaper(pid))) { if (pid_ns_prepare_proc(ns)) goto out_free; } get_pid_ns(ns); atomic_set(&pid->count, 1); for (type = 0; type < PIDTYPE_MAX; ++type) INIT_HLIST_HEAD(&pid->tasks[type]); upid = pid->numbers + ns->level; spin_lock_irq(&pidmap_lock); if (!(ns->nr_hashed & PIDNS_HASH_ADDING)) goto out_unlock; for ( ; upid >= pid->numbers; --upid) { hlist_add_head_rcu(&upid->pid_chain, &pid_hash[pid_hashfn(upid->nr, upid->ns)]); upid->ns->nr_hashed++; } spin_unlock_irq(&pidmap_lock); out: return pid; out_unlock: spin_unlock_irq(&pidmap_lock); put_pid_ns(ns); out_free: while (++i <= ns->level) free_pidmap(pid->numbers + i); kmem_cache_free(ns->pid_cachep, pid); pid = NULL; goto out; }
static struct proc *pid_lookup(int pid) { struct proc *procp; for (procp = pidhash[pid_hashfn(pid)]; procp && procp->pid != pid; procp = procp->pidhash_next) ; return procp; }
int remove_process(struct process_group *pgroup, int pid) { int hashkey = pid_hashfn(pid); if (pgroup->proctable[hashkey] == NULL) return 1; //nothing to delete struct list_node *node = (struct list_node*)locate_node(pgroup->proctable[hashkey], &pid); if (node == NULL) return 2; delete_node(pgroup->proctable[hashkey], node); return 0; }
struct pid *find_pid_ns(int nr, struct pid_namespace *ns) { struct upid *pnr; hlist_for_each_entry_rcu(pnr, &pid_hash[pid_hashfn(nr, ns)], pid_chain) if (pnr->nr == nr && pnr->ns == ns) return container_of(pnr, struct pid, numbers[ns->level]); return NULL; }
// find_proc - find proc frome proc hash_list according to pid struct proc_struct * find_proc(int pid) { if (0 < pid && pid < MAX_PID) { list_entry_t *list = hash_list + pid_hashfn(pid), *le = list; while ((le = list_next(le)) != list) { struct proc_struct *proc = le2proc(le, hash_link); if (proc->pid == pid) { return proc; } } } return NULL; }
struct pid *alloc_pid(struct pid_namespace *ns) { struct pid *pid; enum pid_type type; int i, nr; struct pid_namespace *tmp; struct upid *upid; pid = kmem_cache_alloc(ns->pid_cachep, GFP_KERNEL); if (!pid) goto out; tmp = ns; for (i = ns->level; i >= 0; i--) { nr = alloc_pidmap(tmp); if (nr < 0) goto out_free; pid->numbers[i].nr = nr; pid->numbers[i].ns = tmp; tmp = tmp->parent; } get_pid_ns(ns); pid->level = ns->level; atomic_set(&pid->count, 1); for (type = 0; type < PIDTYPE_MAX; ++type) INIT_HLIST_HEAD(&pid->tasks[type]); spin_lock_irq(&pidmap_lock); for (i = ns->level; i >= 0; i--) { upid = &pid->numbers[i]; hlist_add_head_rcu(&upid->pid_chain, &pid_hash[pid_hashfn(upid->nr, upid->ns)]); } spin_unlock_irq(&pidmap_lock); out: return pid; out_free: for (i++; i <= ns->level; i++) free_pidmap(pid->numbers[i].ns, pid->numbers[i].nr); kmem_cache_free(ns->pid_cachep, pid); pid = NULL; goto out; }
// hash_proc - add proc into proc hash_list static void hash_proc(struct proc_struct *proc) { list_add(hash_list + pid_hashfn(proc->pid), &(proc->hash_link)); }
/* Hmm, same thing for find_task_by_pid? Something's odd here... */ static struct task_struct *find_task_by_pid(int pid) { struct task_struct *p, **htable = &pidhash[pid_hashfn(pid)]; for(p = *htable; p && p->pid != pid; p = p->pidhash_next) ; return p; }
void update_process_group(struct process_group *pgroup) { struct process_iterator it; struct process tmp_process; struct process_filter filter; struct timeval now; gettimeofday(&now, NULL); //time elapsed from previous sample (in ms) long dt = timediff(&now, &pgroup->last_update) / 1000; filter.pid = pgroup->target_pid; filter.include_children = pgroup->include_children; init_process_iterator(&it, &filter); clear_list(pgroup->proclist); init_list(pgroup->proclist, 4); while (get_next_process(&it, &tmp_process) != -1) { // struct timeval t; // gettimeofday(&t, NULL); // printf("T=%ld.%ld PID=%d PPID=%d START=%d CPUTIME=%d\n", t.tv_sec, t.tv_usec, tmp_process.pid, tmp_process.ppid, tmp_process.starttime, tmp_process.cputime); int hashkey = pid_hashfn(tmp_process.pid); if (pgroup->proctable[hashkey] == NULL) { //empty bucket pgroup->proctable[hashkey] = malloc(sizeof(struct list)); struct process *new_process = malloc(sizeof(struct process)); tmp_process.cpu_usage = -1; memcpy(new_process, &tmp_process, sizeof(struct process)); init_list(pgroup->proctable[hashkey], 4); add_elem(pgroup->proctable[hashkey], new_process); add_elem(pgroup->proclist, new_process); } else { //existing bucket struct process *p = (struct process*)locate_elem(pgroup->proctable[hashkey], &tmp_process); if (p == NULL) { //process is new. add it struct process *new_process = malloc(sizeof(struct process)); tmp_process.cpu_usage = -1; memcpy(new_process, &tmp_process, sizeof(struct process)); add_elem(pgroup->proctable[hashkey], new_process); add_elem(pgroup->proclist, new_process); } else { assert(tmp_process.pid == p->pid); assert(tmp_process.ppid == p->ppid); assert(tmp_process.starttime == p->starttime); add_elem(pgroup->proclist, p); if (dt < MIN_DT) continue; //process exists. update CPU usage double sample = 1.0 * (tmp_process.cputime - p->cputime) / dt; if (p->cpu_usage == -1) { //initialization p->cpu_usage = sample; } else { //usage adjustment p->cpu_usage = (1.0-ALFA) * p->cpu_usage + ALFA * sample; } p->cputime = tmp_process.cputime; } } } close_process_iterator(&it); if (dt < MIN_DT) return; pgroup->last_update = now; }