diff --git a/kernel/behave.c b/kernel/behave.c index f90b5a503ffbcccdc34faf8c12db6fc4bda73972..ffd18d9f7ee71efa5657cdc9805e904d89d1fd25 100644 --- a/kernel/behave.c +++ b/kernel/behave.c @@ -145,13 +145,27 @@ pbm_NODE* task_alloc(void) { return new_task_node; } +/* +* Get the index of a given task (which can then be used as an unambiguous identificator). +* Returns -1 if given NULL. +*/ +static int64_t task_2_index(pbm_NODE* task) { + int64_t res = ((uint64_t)task - (uint64_t)tasks->task_buffer) / sizeof(pbm_NODE); + if (!task || res > PROC_BUF_SIZE) { + return -1; + } else { + return res; + } +} + void debug_print_tasks(void) { size_t i; pbm_NODE t; printk(KERN_WARNING "-----\nTASKS:\n"); for(i = 0; i <= tasks->curr_task_index; i++) { t = tasks->task_buffer[i]; - printk(KERN_WARNING "type: %u, thread_id: %u, count: %llu, children: %llx, next_sib: %llx\n", t.type, t.thread_id, t.count, (uint64_t)t.children, (uint64_t)t.next_sib); + printk(KERN_WARNING "addr: %lu, type: %u, thread_id: %u, count: %llu, children: %lli, next_sib: %lli\n", + i, t.type, t.thread_id, t.count, task_2_index(t.children), task_2_index(t.next_sib)); } printk(KERN_WARNING "^^^^^\n"); } @@ -196,13 +210,28 @@ PBM* proc_alloc(void) { return new_pbm; } +/* +* Get the index of a given PBM (which can then be used as an unambiguous identificator) +* Returns -1 if given NULL. +*/ +static int64_t pbm_2_index(PBM* pbm) { + int64_t res = ((uint64_t)pbm - (uint64_t)procs->process_buffer) / sizeof(PBM); + if (!pbm || res > PROC_BUF_SIZE) { + return -1; + } else { + return res; + } +} + void debug_print_procs(void) { size_t i; PBM p; printk(KERN_WARNING "-----\nPROCS:\n"); for(i = 0; i <= procs->curr_proc_index; i++) { p = procs->process_buffer[i]; - printk(KERN_WARNING "root: %llx, last: %llx, children: %llx, next_sib: %llx\n", (uint64_t)p.root, (uint64_t)p.last, (uint64_t)p.children, (uint64_t)p.next_sib); + printk(KERN_WARNING "index: %lu, root: %lli, last: %lli, children: %lli, next_sib: %lli\n", + // calculate indices instead of using the pointers for more readability and represent NULL-values with -1 + i, task_2_index(p.root), task_2_index(p.last), pbm_2_index(p.children), pbm_2_index(p.next_sib)); } printk(KERN_WARNING "^^^^^\n"); } @@ -395,7 +424,8 @@ int pbm_task_end(PBM* pbm) { /* * Before starting the new task, append the fork-node to the task graph to maintain the correct order - */ + */ + printk(KERN_WARNING ">> CREATE NEW FORK NODE! by %u\n", parent_proc->pid); fork_node = _pbm_create_node(FORK, parent_proc->pid); if(!fork_node) { printk(KERN_WARNING "COULD NOT CREATE NEW FORK NODE!\n"); @@ -408,6 +438,10 @@ int pbm_task_end(PBM* pbm) { } parent_pbm->last = fork_node; // the new node becomes the last inserted one + // any fork-node has exactly two children because a fork creates only one + // copy of an existing process (1 (copy) + 1 (existing) = 2) + fork_node->count = 2; + // start the new task pbm_task_start(parent_pbm, COMP, parent_proc); @@ -422,7 +456,7 @@ int pbm_task_end(PBM* pbm) { * This function must get called in the _do_fork() routine AFTER (!) the child process starts to * run (current == child) otherwise the perf counting will fail! */ -int pbm_fork(struct task_struct* proc, pid_t parent_pid, pbm_NODE* fork_date) { +int pbm_fork(struct task_struct* proc, pid_t parent_pid, pbm_NODE* fork_node) { unsigned long irq_flags; PBM* parent_pbm; @@ -494,11 +528,23 @@ int pbm_fork(struct task_struct* proc, pid_t parent_pid, pbm_NODE* fork_date) { // We have to know WHEN the exit happens relative to the parent. So every child remembers the // current fork-task-node of the parent on exit (so that the join can happen at the correct // position (more or less, may be imperfect due to parallelism)) - child_pbm->fork_date = fork_date; + child_pbm->fork_date = fork_node; // continue performance counting for child (restarting parent counting has already been started pbm_task_start(child_pbm, COMP, proc); + // insert front of child task graph into parent task graph: + // prepend child-task-tree to list of child-nodes in the fork-node + // preconditions: + // * child_pbm->root->next_sib == NULL: since any fork-node has at most two children and + // only one before the join-operation) + // * child_pbm->root != NULL: since the previously called pbm_task_start() should have + // written to that + if (fork_node) { + child_pbm->root->next_sib = fork_node->children; + fork_node->children = child_pbm->root; + } + return 1; } @@ -539,6 +585,7 @@ int pbm_join(PBM* child_pbm) { if(!child_pbm) return 0; + printk(KERN_WARNING "Joining thread %u with fork_node: %lli\n", child_pbm->last->thread_id, task_2_index(child_pbm->fork_date)); fork_node = child_pbm->fork_date; // the child process is used to label the join operation to know which process the join belongs @@ -551,31 +598,20 @@ int pbm_join(PBM* child_pbm) { return 0; } - // any fork-node has exactly two children because a fork creates only one - // copy of an existing process (1 (copy) + 1 (existing) = 2) - fork_node->count = 2; + // any join-node has exactly two children because it is reversing a fork + // which creates only one copy of an existing process (1 (copy) + 1 (existing) = 2) join_node->count = 2; - // insert front of child task graph into parent task graph: - // prepend child-task-tree to list of child-nodes in the fork-node - { - // assumption: child_pbm->root->next_sib == NULL (since any fork-node - // has at most two children and only one before the join-operation) - child_pbm->root->next_sib = fork_node->children; - fork_node->children = child_pbm->root; - } - - // insert back of child task graph with appended join-node into parent task - // graph - { - // assumption: child_pbm->last->children == NULL (since it should be - // the last task the child did before exit) - // append join node to child task-graph - child_pbm->last->children = join_node; - // insert join node directly after the exit-date-node in the parent pbm - join_node->children = child_pbm->exit_date->children; - child_pbm->exit_date->children = join_node->children; - } + // insert back of child task graph with appended join-node into parent task graph + // precondition: + // * child_pbm->last->children == NULL: since it should be the last task the child did + // before exit + // append join node to child task-graph + child_pbm->last->children = join_node; + // insert join node directly after the exit-date-node in the parent pbm + printk(KERN_WARNING "Exit-date: %lli, child: %lli\n", task_2_index(child_pbm->exit_date), task_2_index(child_pbm->exit_date->children)); + join_node->children = child_pbm->exit_date->children; + child_pbm->exit_date->children = join_node; return 1; } @@ -585,6 +621,7 @@ void pbm_post_processing(PBM* pbm) { PBM* sib_pbm; PBM* child_pbm = pbm->children; if(child_pbm) { + printk(KERN_WARNING "Joining child thread %u\n", child_pbm->last->thread_id); pbm_post_processing(child_pbm); pbm_join(child_pbm); // TODO Remove from list of childs or just mark as visited? @@ -592,7 +629,9 @@ void pbm_post_processing(PBM* pbm) { sib_pbm = pbm->next_sib; if(sib_pbm) { + printk(KERN_WARNING "Joining sib thread %u\n", sib_pbm->last->thread_id); pbm_post_processing(sib_pbm); + pbm_join(sib_pbm); // TODO Remove from list of siblings or just mark as visited? } } @@ -611,6 +650,8 @@ void pbm_join_and_print_graph_self(pid_t pid) { pbm = get_pbm_by_pid(pid); if (pbm) { pbm_post_processing(pbm); + printk(KERN_WARNING "After post-processing:\n"); + debug_print_tasks(); pbm_print_graph(pbm, pbm->root); } else { printk(KERN_WARNING "JOIN: PBM not found for: %u\n", pid); @@ -629,17 +670,20 @@ void pbm_print_graph(PBM* pbm, pbm_NODE* node) { return; root = node; - - printk(KERN_WARNING "Node %p: (%s, count = %llu), children:\n", node, types[node->type], node->count); + printk(KERN_WARNING "Node %lli: (%s, pid = %u, count = %llu), children:\n", + task_2_index(node), types[node->type], node->thread_id, node->count); if(node->children) { node = node->children; while(node) { - printk(KERN_WARNING " -- Node %p: (%s, count = %llu), next sibling: %p\n", node, types[node->type], node->count, node->next_sib); + printk(KERN_WARNING " -- Node %lli: (%s, pid = %u, count = %llu), next sibling: %lli\n", + task_2_index(node), types[node->type], node->thread_id, node->count, task_2_index(node->next_sib)); node = node->next_sib; } + } else { + printk(KERN_WARNING " -- Exit (pid = %u)\n", node->thread_id); } if(root->children) diff --git a/kernel/behave.h b/kernel/behave.h index 881970f662dedbf241261bb474334ec4deb5c1cd..e55a10a86fe4a35c55072066aec3b541a93ba2db 100644 --- a/kernel/behave.h +++ b/kernel/behave.h @@ -128,7 +128,7 @@ int pbm_task_end(PBM* pbm); * * The process as an explicit argument is needed since the fork is called by the parent. */ -int pbm_fork(struct task_struct* proc, pid_t parent_pid, pbm_NODE* fork_date); +int pbm_fork(struct task_struct* proc, pid_t parent_pid, pbm_NODE* fork_node); int pbm_exit(pid_t pid, pid_t parent_pid);