00001 // =================================================================== 00002 // Basic_Consumer.cc 00003 // Scott F. H. Kaplan -- sfkaplan@cs.amherst.edu 00004 // October 2002 00005 00006 // A subclass of Consumer that emits a basic page-level reference 00007 // trace with no extra information about shared space or multiple 00008 // processes. Logical page numbers are emitted, however, so that 00009 // shared pages are not multiply counted. The trace takes the 00010 // following form: 00011 // 00012 // R 14fe3 00013 // 00014 // The first field is the ``type tag'': A single character, either 00015 // 'R' or 'W', to indicate whether or not the reference is a read or a 00016 // write. Note that this trace format does not distinguish between 00017 // kernel and user references. Instruction references are considered 00018 // read operations. 00019 // 00020 // The second field is the page number: A hexidecimal value giving the 00021 // logical page number being referenced. 00022 // =================================================================== 00023 00024 00025 00026 // =================================================================== 00027 // INCLUDES 00028 00029 #include "Basic_Consumer.hh" 00030 // =================================================================== 00031 00032 00033 00034 // =================================================================== 00035 Basic_Consumer::Basic_Consumer (const char* const reference_pathname, 00036 const char* const kernel_pathname) : 00037 Consumer(reference_pathname, kernel_pathname) { 00038 00039 // Nothing to do after calling the parent's constructor. 00040 00041 } // Basic_Consumer 00042 // =================================================================== 00043 00044 00045 00046 // =================================================================== 00047 Basic_Consumer::~Basic_Consumer () { 00048 00049 // Nothing to do here; the parent's destructor is called 00050 // automatically. 00051 00052 } // ~Basic_Consumer 00053 // =================================================================== 00054 00055 00056 00057 // =================================================================== 00058 void 00059 Basic_Consumer::act_on_reference_record () { 00060 00061 // Convert the input record's tag to a valid output tag. 00062 tag_t output_tag = 0; 00063 switch (reference_record->tag) { 00064 00065 case TAG_USER_READ: 00066 case TAG_KERNEL_READ: 00067 00068 output_tag = TAG_OUTPUT_READ; 00069 break; 00070 00071 case TAG_USER_WRITE: 00072 case TAG_KERNEL_WRITE: 00073 00074 output_tag = TAG_OUTPUT_WRITE; 00075 break; 00076 00077 default: 00078 fprintf(stderr, 00079 "act_on_reference_record(): Invalid tag %c(%d)\n", 00080 reference_record->tag, 00081 (int)reference_record->tag); 00082 exit(1); 00083 00084 } 00085 00086 // Iff the page referenced is in the kernel's address range, we need 00087 // to use the kernel's context. 00088 virtual_to_logical_map_t* map = 0; 00089 if (reference_record->virtual_page.page < 00090 kernel_virtual_page_offset) { 00091 00092 map = safe_context_to_V2L_map(reference_record->virtual_page.context); 00093 00094 } else { 00095 00096 map = safe_context_to_V2L_map(kernel_context); 00097 00098 } 00099 00100 // Lookup the logical page ID if one exists. 00101 bool V2L_mapping_exists; 00102 logical_page_ID_t logical_page_ID; 00103 lookup_logical_page_ID(&V2L_mapping_exists, 00104 &logical_page_ID, 00105 map, 00106 reference_record->virtual_page.page); 00107 00108 // Emit the new record only if a mapping was found (that is, if this 00109 // is not a reference to a buffer cache page). 00110 if (V2L_mapping_exists) { 00111 printf("%c %lx\n", output_tag, logical_page_ID); 00112 } 00113 00114 } // act_on_reference_record 00115 // =================================================================== 00116 00117 00118 00119 // =================================================================== 00120 void 00121 Basic_Consumer::lookup_logical_page_ID 00122 (bool* return_V2L_mapping_exists, 00123 logical_page_ID_t* const return_logical_page_ID, 00124 const virtual_to_logical_map_t* const map, 00125 const virtual_page_ID_t virtual_page_ID) { 00126 00127 // Assume initially that if the virtual page is valid, its mapping 00128 // into logical space will exist. 00129 *return_V2L_mapping_exists = true; 00130 00131 // Attempt to lookup the page in the context's map. 00132 const virtual_to_logical_map_t::const_iterator i = 00133 (*map).find(virtual_page_ID); 00134 00135 // Was the lookup successful? 00136 if (i != (*map).end()) { 00137 00138 // Yes. Is the logical page a buffer cache page? 00139 if ((*i).second->type == TYPE_BUFFER_CACHE) { 00140 00141 // It is a buffer cache page, and so no mapping into logical 00142 // space really exists. 00143 *return_V2L_mapping_exists = false; 00144 00145 } else { 00146 00147 // It is not a buffer cache page, so return the logical page's 00148 // ID. 00149 *return_logical_page_ID = (*i).second->page; 00150 00151 } 00152 00153 // The lookup failed. Is the virtual address in the kernel's 00154 // address space? 00155 } else if (virtual_page_ID >= kernel_virtual_page_offset) { 00156 00157 // Yes. The upper 1 GB of the logical space is reserved to 00158 // correspond to the upper 1 GB of kernel virtual address 00159 // space. [Linux specific] Calculate the logical page ID. 00160 *return_logical_page_ID = 00161 kernel_logical_page_offset + (virtual_page_ID - 00162 kernel_virtual_page_offset); 00163 00164 } else { 00165 00166 // There was no mapping into logical space found, and the virtual 00167 // address is not in the kernel space. Therefore, this is an 00168 // invalid virtual address. Emit the error and exit. 00169 fprintf(stderr, "lookup_logical_page_ID(): Failed lookup\n"); 00170 exit(1); 00171 00172 } 00173 } // lookup_logical_page_ID 00174 // ===================================================================