def _get_cpu_model() -> pc.CPUModel: if not os.path.exists('/dev/cpu/0/cpuid'): log.warning( 'cannot detect cpu model (file /dev/cpu/0/cpuid does not exists!) ' '- returning unknown') return pc.CPUModel.UNKNOWN with SetEffectiveRootUid(): with open("/dev/cpu/0/cpuid", "rb") as f: b = f.read(32) eax = int(b[16]) + (int(b[17]) << 8) + (int(b[18]) << 16) + ( int(b[19]) << 24) log.log( logger.TRACE, '16,17,18,19th bytes from /dev/cpu/0/cpuid: %02x %02x %02x %02x', b[16], b[17], b[18], b[19]) model = (eax >> 4) & 0xF family = (eax >> 8) & 0xF extended_model = (eax >> 16) & 0xF extended_family = (eax >> 20) & 0xFF display_family = family if family == 0xF: display_family += extended_family display_model = model if family == 0x6 or family == 0xF: display_model += (extended_model << 4) if display_model in [0x4E, 0x5E, 0x55]: return pc.CPUModel.SKYLAKE elif display_model in [0x3D, 0x47, 0x4F, 0x56]: return pc.CPUModel.BROADWELL else: return pc.CPUModel.UNKNOWN
def remove(self, mongroup_name): """Remove resctrl control directory or just mon_group if this is root or not last container under control. """ # Try to clean itself if I'm the last mon_group and not root. if self.name == RESCTRL_ROOT_NAME: log.debug('resctrl: remove root') dir_to_remove = self._get_mongroup_fullpath(mongroup_name) else: # For non root # Am I last on the remove all. if len(self.get_mon_groups()) == 1: log.debug('resctrl: remove ctrl directory %r', self.name) dir_to_remove = self.fullpath else: log.debug('resctrl: remove just mon_group %r in %r', mongroup_name, self.name) dir_to_remove = self._get_mongroup_fullpath(mongroup_name) # Remove the mongroup directory if exists. with SetEffectiveRootUid(): log.log(logger.TRACE, 'resctrl: rmdir(%r)', dir_to_remove) if os.path.exists(dir_to_remove): os.rmdir(dir_to_remove) else: log.debug("Directory: {} already removed. Ignoring!".format( dir_to_remove))
def _add_pids_to_tasks_file(self, pids, tasks_filepath): """Writes pids to task file. This function is susceptible to races caused by time that passes between read and write. - causing errors like: ProcessLookupError Error handling is based on edge cases available in: https://github.com/torvalds/linux/blob/v4.20/arch/x86/kernel/cpu/intel_rdt_rdtgroup.c#L676 and are mapped to python exceptions https://github.com/python/cpython/blob/v3.6.8/Objects/exceptions.c#L2658 ESRCH -> ProcessLookupError ENOENT -> FileNotFoundError Important note: any writing/flushing error is going the reappear during closing, that is why it is again wrapped by try:except (and why context manager is not used). """ if not pids: return log.log(logger.TRACE, 'resctrl: write(%s): number_of_pids=%r', tasks_filepath, len(pids)) ftasks = None try: ftasks = open(tasks_filepath, 'w') with SetEffectiveRootUid(): for pid in pids: ftasks.write(pid) ftasks.flush() except ProcessLookupError: log.warning( 'Could not write pid to resctrl (%r): ' 'Process probably does not exist. ', tasks_filepath) except FileNotFoundError: log.error( 'Could not write pid to resctrl (%r): ' 'rdt group was not found (moved/deleted - race detected).', tasks_filepath) except OSError as e: if e.errno == errno.EINVAL: # (kstrtoint(strstrip(buf), 0, &pid) || pid < 0) log.error( 'Could not write pid to resctrl (%r): ' 'Invalid argument %r.', tasks_filepath) else: log.error( 'Could not write pid to resctrl (%r): ' 'Unexpected errno %r.', tasks_filepath, e.errno) finally: try: # Try what we can to close the file but it is expected # to fails because the wrong # data is waiting to be flushed if ftasks is not None: ftasks.close() except (ProcessLookupError, FileNotFoundError, OSError): log.warning('Could not close resctrl/tasks file - ignored!' '(side-effect of previous warning!)')