Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

Per_Task_Consumer.cc

Go to the documentation of this file.
00001 
00010 // ===================================================================
00011 // INCLUDES
00012 
00013 #include <stdio.h>
00014 #include <string.h>
00015 #include "Per_Task_Consumer.hh"
00016 #include "PTC_Task.hh"
00017 // ===================================================================
00018 
00019 
00020 
00021 // ===================================================================
00022 Per_Task_Consumer::Per_Task_Consumer
00023 (Reference_Reader* const reference_reader,
00024  const char* const kernel_pathname,
00025  const char* const output_directory_pathname) :
00026   Consumer(reference_reader, kernel_pathname) {
00027 
00028   // Copy the output directory pathname into this object.
00029   strcpy(this->output_directory_pathname, output_directory_pathname);
00030 
00031   // Create a writer for the kernel task.
00032   PTC_Task* task = (PTC_Task*)kernel_task;
00033   task->writer = new Per_Task_Writer(output_directory_pathname,
00034              task->process->process_ID,
00035              task->task_ID);
00036   if (task->writer == NULL) {
00037     fprintf(stderr, "Per_Task_Consumer::Per_Task_Consumer(): ");
00038     fprintf(stderr, "Failed to allocate kernel task's writer\n");
00039     exit(1);
00040   }
00041 
00042 } // Per_Task_Consumer::Per_Task_Consumer
00043 // ===================================================================
00044 
00045 
00046 
00047 // ===================================================================
00048 Per_Task_Consumer::~Per_Task_Consumer () {
00049 
00050   // Traverse the task_ID->Task table.
00051   task_ID_to_Task_map_t::iterator i = task_ID_to_Task_map.begin();
00052   while (i != task_ID_to_Task_map.end()) {
00053 
00054     // Delete the per-task writer associated with this task, thus
00055     // flushing and closing its output.
00056     PTC_Task* task = (PTC_Task*)(*i).second;
00057     delete task->writer;
00058     task->writer = NULL;
00059 
00060     // Move to the next task.
00061     i++;
00062 
00063   } // task_ID->Task table traversal
00064 
00065 } // Per_Task_Consumer::~Per_Task_Consumer
00066 // ===================================================================
00067 
00068 
00069 
00070 // ===================================================================
00071 void
00072 Per_Task_Consumer::act_on_reference_record () {
00073 
00074   // Lookup the canonical page ID, if one exists, for this reference
00075   // in the current task's context.
00076   bool V2C_mapping_exists;
00077   canonical_page_ID_t canonical_page_ID;
00078   lookup_canonical_page_ID(&V2C_mapping_exists,
00079          &canonical_page_ID,
00080          active_task->process->virtual_to_canonical_map,
00081          reference_record->virtual_page.page_ID);
00082 
00083   // Submit this reference to this task's writer only if a mapping to
00084   // a canonical page really exists (that is, this is not a reference
00085   // to a buffer-cache page).
00086   if (V2C_mapping_exists) {
00087     PTC_Task* active_PTC_task = (PTC_Task*)active_task;
00088     active_PTC_task->writer->
00089       append_reference_record(reference_record,
00090             canonical_page_ID,
00091             active_task->virtual_cycle_time,
00092             active_task->virtual_instruction_time,
00093             active_task->virtual_reference_time);
00094   }
00095 
00096 } // Consumer::act_on_reference_record
00097 // ===================================================================
00098 
00099 
00100 
00101 // ===================================================================
00102 void
00103 Per_Task_Consumer::act_on_kernel_record () {
00104 
00105   // Determine how to react to this record depending on the type of
00106   // kernel event.
00107   PTC_Task* active_PTC_task = NULL;
00108   switch (kernel_record->tag) {
00109 
00110   case TAG_CONTEXT_ASSIGNMENT:
00111 
00112     PTC_handle_context_assignment();
00113     break;
00114 
00115   case TAG_FILE_OPEN:
00116   case TAG_FILE_CLOSE:
00117   case TAG_FILE_READ:
00118   case TAG_FILE_WRITE:
00119   case TAG_ACCEPT:
00120 
00121     // These kernel events should appear in the output trace for the
00122     // current task.  As a sanity check, ensure that the task ID given
00123     // for this record matches the current task's ID.
00124     if (kernel_record->task_ID != active_task->task_ID) {
00125       fprintf(stderr, "Per_Task_Consumer::act_on_kernel_record(): ");
00126       fprintf(stderr, "Record and current task ID mismatch\n");
00127       exit(1);
00128     }
00129 
00130     // Pass the kernel event to the task's writer.
00131     active_PTC_task = (PTC_Task*)active_task;
00132     active_PTC_task->writer->
00133       append_kernel_record(kernel_record,
00134          active_task->virtual_cycle_time,
00135          active_task->virtual_instruction_time,
00136          active_task->virtual_reference_time);
00137     break;
00138 
00139   default:
00140 
00141     // Do nothing -- ignore this kernel record, as it's not relevant
00142     // to the output of these per-task traces.
00143     break;
00144 
00145   }
00146 
00147 } // Consumer::act_on_kernel_record
00148 // ===================================================================
00149 
00150 
00151 
00152 // ===================================================================
00153 Task*
00154 Per_Task_Consumer::allocate_new_task () {
00155 
00156   // Attempt to allocate a PTC_Task, a specific subclass designed for
00157   // use with this class.
00158   Task* task = new PTC_Task;
00159   if (task == NULL) {
00160     fprintf(stderr, "Per_Task_Consumer::allocate_new_task(): ");
00161     fprintf(stderr, "Allocation failure\n");
00162     exit(1);
00163   }
00164 
00165   return task;
00166 
00167 } // Per_Task_Consumer::allocate_new_task
00168 // ===================================================================
00169 
00170 
00171 
00172 // ===================================================================
00173 void
00174 Per_Task_Consumer::PTC_handle_context_assignment () {
00175 
00176   // Look up the task being assigned a context.
00177   PTC_Task* task =
00178     (PTC_Task*)safe_task_ID_to_task(kernel_record->task_ID);
00179 
00180   // Was there a previous writer?  (The existence of one implies that
00181   // the task was previously assigned to some other context, and thus
00182   // some other process.)
00183   if (task->writer != NULL) {
00184 
00185     // Delete (and thus flush and close) the old writer.
00186     delete task->writer;
00187     task->writer = NULL;
00188 
00189   } // Task had previous writer
00190 
00191   // Create a new writer for this task and its newly assigned context
00192   // and process.
00193   task->writer = new Per_Task_Writer(output_directory_pathname,
00194              task->process->process_ID,
00195              task->task_ID);
00196   if (task->writer == NULL) {
00197     fprintf(stderr,
00198       "Per_Task_Consumer::PTC_handle_context_assignment(): ");
00199     fprintf(stderr, "Failed to allocate new per-task writer\n");
00200     exit(1);
00201   }
00202 
00203 } // Per_Task_Consumer::PTC_handle_context_assignment
00204 // ===================================================================

Generated on Fri Jan 31 10:33:34 2003 for Laplace-merge by doxygen1.3-rc2