Clean up the feedback code.
This commit is contained in:
@@ -1,7 +0,0 @@
|
||||
--PID'S RECORDING SESSION--
|
||||
|
||||
MODE:
|
||||
|
||||
PID PRIO NAME
|
||||
|
||||
|
||||
@@ -5,8 +5,11 @@
|
||||
#pragma once
|
||||
|
||||
#include "sys/types.h"
|
||||
#include "process/process.h"
|
||||
|
||||
void writeFeedback(pid_t pid, char name[], pid_t padre, int mode, int prio);
|
||||
/// @brief Function which is called by scheduler_algorithm after choosing the
|
||||
/// next task, and updates the sceduling statistics.
|
||||
void scheduler_feedback_update(task_struct * next);
|
||||
|
||||
/// @brief Initialize the scheduler feedback system.
|
||||
/// @return 1 on success, 0 on failure.
|
||||
|
||||
@@ -126,9 +126,6 @@ static inline task_struct *__scheduler_priority(runqueue_t *runqueue, bool_t ski
|
||||
}
|
||||
}
|
||||
|
||||
//function to track the scheduler algorithm
|
||||
//writeFeedback(next->pid, next->name, next->parent->pid, 2, (next->se).prio);
|
||||
|
||||
return next;
|
||||
#else
|
||||
return __scheduler_rr(runqueue, skip_periodic);
|
||||
@@ -175,8 +172,6 @@ static inline task_struct *__scheduler_cfs(runqueue_t *runqueue, bool_t skip_per
|
||||
next = entry; // scambio il prossimo processo con quello a priorità piu bassa trovato
|
||||
}
|
||||
}
|
||||
//function to track the scheduler algorithm
|
||||
//writeFeedback(next->pid, next->name, next->parent->pid, 3, (next->se).prio);
|
||||
|
||||
return next;
|
||||
#else
|
||||
@@ -243,8 +238,8 @@ task_struct *scheduler_pick_next_task(runqueue_t *runqueue)
|
||||
|
||||
// Update the last context switch time of the next task.
|
||||
next->se.exec_start = timer_get_ticks();
|
||||
feedback(next->pid, next->name, next->parent->pid, 1, (next->se).prio);
|
||||
writeFeedback(next->pid, next->name, next->parent->pid, 1, (next->se).prio);
|
||||
|
||||
scheduler_feedback_update(next);
|
||||
|
||||
return next;
|
||||
}
|
||||
@@ -286,82 +281,3 @@ static void __update_task_statistics(task_struct *task)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//Nuova funzione per statistiche RunTime
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#define MAX_STORAGE 500000
|
||||
|
||||
typedef struct statistic {
|
||||
pid_t pid;
|
||||
char name[20];
|
||||
int occur;
|
||||
} stat;
|
||||
|
||||
int countPid = 1;
|
||||
int countPid_1 = 1;
|
||||
|
||||
stat arr_stats[MAX_STORAGE] = { 0, "", 0 };
|
||||
|
||||
pid_t PID_BUFFER1[MAX_STORAGE] = { 0 };
|
||||
char PID_NAME1[MAX_STORAGE][40];
|
||||
|
||||
void feedback(pid_t pid, char name[], pid_t padre, int mode, int prio)
|
||||
{
|
||||
//se lasciamo a 600k sono 31 secondi circa, nb -> ovviamente dipende dalla cpu del pc che ospita la macchina
|
||||
if (!(countPid_1 % 500000)) {
|
||||
//printf("PID %i name :%s\n", pid, name);
|
||||
//qui dentro dobbiamo: ordinare senza ripetizioni sia pid_buffer1 sia pid_name1
|
||||
//e in piu ci serve un altro array per contare le occorreze
|
||||
//se facciamo cosi poi possimao permetterci di ciclare un for e semplicemente stampare i tre cosi
|
||||
int end = 0;
|
||||
printf("\nSTATS:\n");
|
||||
|
||||
for (int i = 0; i < MAX_STORAGE && !end; i++) {
|
||||
if (arr_stats[i].pid == 0) {
|
||||
end = 1;
|
||||
} else {
|
||||
printf("Name: %s, Pid: %i, TCPU: %.4f%% \n", arr_stats[i].name, arr_stats[i].pid, arr_stats[i].occur * 100 / (double)MAX_STORAGE);
|
||||
}
|
||||
}
|
||||
end = 0;
|
||||
//resettiamo
|
||||
for (int i = 0; i < MAX_STORAGE && !end; i++) {
|
||||
if (arr_stats[i].pid == 0) { //se trovo che ho finito di ciclare i valori registrati
|
||||
end = 1; //esco dal for
|
||||
}
|
||||
arr_stats[i].pid = 0;
|
||||
arr_stats[i].occur = 0;
|
||||
}
|
||||
|
||||
countPid = 0;
|
||||
countPid_1 = 0;
|
||||
} else {
|
||||
//Opportuno controllo per non sforare il MAX_STORAGE della struttura dati che utilizziamo
|
||||
if (countPid != MAX_STORAGE) {
|
||||
//REGISTRAZIONE PID IN BUFFER
|
||||
int stored = 0;
|
||||
int endArr = 0;
|
||||
int i;
|
||||
for (i = 0; i < MAX_STORAGE && !stored && !endArr; i++) {
|
||||
if (arr_stats[i].pid == pid) {
|
||||
arr_stats[i].occur++;
|
||||
stored = 1;
|
||||
}
|
||||
if (arr_stats[i].pid == 0) { //se trovo che ho finito di ciclpidare i valori registrati
|
||||
endArr = 1; //esco dal for
|
||||
}
|
||||
}
|
||||
if (!stored) { //se non avevo registrato il valore
|
||||
|
||||
i--;
|
||||
arr_stats[i].pid = pid;
|
||||
strcpy(arr_stats[i].name, name);
|
||||
arr_stats[i].occur = 1;
|
||||
}
|
||||
countPid++;
|
||||
}
|
||||
}
|
||||
countPid_1++;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
// Include the kernel log levels.
|
||||
#include "sys/kernel_levels.h"
|
||||
/// Change the header.
|
||||
#define __DEBUG_HEADER__ "[SCHFBK]"
|
||||
/// Set the log level.
|
||||
#define __DEBUG_LEVEL__ LOGLEVEL_DEBUG
|
||||
|
||||
/*
|
||||
HOW TO:
|
||||
all'avvio di MentOS, usa comando start, verrai avvisato su terminale quando la sessione sarà terminata.
|
||||
@@ -18,175 +25,156 @@ Istruzioni relative ai parametri della funzione start (che sono work in progress
|
||||
*/
|
||||
|
||||
#include "process/scheduler_feedback.h"
|
||||
|
||||
#include "hardware/timer.h"
|
||||
#include "strerror.h"
|
||||
#include "io/debug.h"
|
||||
#include "fs/vfs.h"
|
||||
#include "assert.h"
|
||||
#include "string.h"
|
||||
#include "fcntl.h"
|
||||
#include "stdio.h"
|
||||
#include "fs/vfs.h"
|
||||
#include "string.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define FEEDBACK_FILENAME "/feedback2.txt"
|
||||
/// @brief
|
||||
#define FEEDBACK_FILENAME "/var/feedback.txt"
|
||||
/// @brief
|
||||
#define FEEDBACK_HEADER "\nPID PRIO NAME\n\0"
|
||||
/// @brief
|
||||
#define LOG_INTERVAL 3
|
||||
|
||||
// Size of the buffer.
|
||||
#define BUFFER_SIZE 256
|
||||
#if defined(SCHEDULER_RR)
|
||||
#define POLICY_NAME "RR "
|
||||
#elif defined(SCHEDULER_PRIORITY)
|
||||
#define POLICY_NAME "PRIO "
|
||||
#elif defined(SCHEDULER_CFS)
|
||||
#define POLICY_NAME "CFS "
|
||||
#elif defined(SCHEDULER_EDF)
|
||||
#define POLICY_NAME "EDF "
|
||||
#elif defined(SCHEDULER_RM)
|
||||
#define POLICY_NAME "RM "
|
||||
#elif defined(SCHEDULER_AEDF)
|
||||
#define POLICY_NAME "AEDF "
|
||||
#else
|
||||
#error "You should enable a scheduling algorithm!"
|
||||
#endif
|
||||
|
||||
#define MAX_SIZE_NAME 20
|
||||
|
||||
//Variabili Globali
|
||||
#define MAX_STORAGE 10
|
||||
int count = 0;
|
||||
pid_t PID_BUFFER[MAX_STORAGE] = { 0 };
|
||||
int PID_PRIO[MAX_STORAGE] = { 0 };
|
||||
char PID_NAME[MAX_STORAGE][MAX_SIZE_NAME];
|
||||
pid_t oldPid = -1;
|
||||
/// @brief
|
||||
ssize_t offset;
|
||||
int err = 1;
|
||||
int countChar(char[]);
|
||||
void wipe();
|
||||
/// @brief
|
||||
size_t next_log;
|
||||
/// @brief
|
||||
size_t total_occurrences;
|
||||
|
||||
/*
|
||||
PID 1 --> INIT
|
||||
PID 2 --> KTHREADD
|
||||
*/
|
||||
|
||||
/*
|
||||
Funzione che viene chiamata da scheduler_algorithm dopo aver scelto il prossimo processo da eseguire
|
||||
*/
|
||||
void writeFeedback(pid_t pid, char name[], pid_t padre, int mode, int prio)
|
||||
{
|
||||
char start[] = "start";
|
||||
int brake = 0;
|
||||
|
||||
//analizzo se nome del PID passato come argomento corrisponde al comando START
|
||||
for (int i = 0; i < countChar(name) && brake == 0; i++) {
|
||||
if ((start[i] != name[i]) || oldPid == pid || oldPid == padre || countChar(name) != countChar(start)) { //brake a 0 anche se viene rilevata una start che non è stata lanciata da terminale ma è in esecuzione de un po
|
||||
brake = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//questo ci serve per andare a salvare il pid di una nuova start lanciata da terminale
|
||||
//il primissimo start viene detectato OR detecta uno start con un pid nuovo MA con mio padre diverso dal creatore della sessione attuale o finita (oldPid)
|
||||
if ((oldPid == -1 && brake == 0) || (oldPid != -1 && brake == 0 && oldPid != pid && oldPid != padre)) {
|
||||
oldPid = pid;
|
||||
}
|
||||
|
||||
//Se prima volta e' start bene, proseguiamo siccome brake e' zero,
|
||||
//le successive brake NON zero ma count > 0 poiche start passato in precedenza
|
||||
//Opportuno controllo per non sforare il MAX_STORAGE della struttura dati che utilizziamo
|
||||
if (count != MAX_STORAGE && (count != 0 || brake == 0)) {
|
||||
//REGISTRAZIONE PID IN BUFFER in modalita start SENZA parametri
|
||||
PID_BUFFER[count] = pid;
|
||||
PID_PRIO[count] = prio;
|
||||
strcpy(PID_NAME[count], name);
|
||||
count++;
|
||||
}
|
||||
|
||||
//QUI SE BUFFER PIENO SCRIVO SU FILE
|
||||
|
||||
if (count == MAX_STORAGE) {
|
||||
mode_t flag = 000777;
|
||||
char buffer[BUFFER_SIZE];
|
||||
const char *namef = "/home/user/feedback.txt";
|
||||
offset = sizeof(char) * 34; //PER SCRITTURA MODALITA
|
||||
char temp[6]; //max PID 99999
|
||||
char temp_prio[4];
|
||||
char rr[] = "ROUND ROBIN\n";
|
||||
char priority[] = "HIGH PRIORITY FIRST\n";
|
||||
char cfs[] = "FAIR SHARE\n";
|
||||
char testo[] = "\nPID PRIO NAME\n";
|
||||
|
||||
// NOTE: You should check if the file exists, or create it, during the boot
|
||||
// phase of the system. Choose a place where to put it, a location like
|
||||
// `/var/scheduling_feedback.txt`.
|
||||
vfs_file_t *file = vfs_open(namef, O_RDWR, flag);
|
||||
|
||||
if (file == NULL) {
|
||||
printf("Error: Failed to open feedback file.");
|
||||
}
|
||||
|
||||
if (mode == 1) {
|
||||
offset += vfs_write(file, " ", offset, sizeof(char));
|
||||
offset += vfs_write(file, rr, offset, sizeof(char) * countChar(rr));
|
||||
} else if (mode == 2) {
|
||||
offset += vfs_write(file, " ", offset, sizeof(char));
|
||||
offset += vfs_write(file, priority, offset, sizeof(char) * countChar(priority));
|
||||
} else {
|
||||
offset += vfs_write(file, " ", offset, sizeof(char));
|
||||
offset += vfs_write(file, cfs, offset, sizeof(char) * countChar(cfs));
|
||||
}
|
||||
|
||||
/*
|
||||
offset += vfs_write(file, "\n", offset, sizeof(char));
|
||||
offset += vfs_write(file, "\n", offset, sizeof(char));
|
||||
offset += sizeof(char)* (13);*/
|
||||
|
||||
offset += vfs_write(file, testo, offset, sizeof(char) * countChar(testo));
|
||||
|
||||
for (int i = 0; i < MAX_STORAGE; i++) {
|
||||
itoa(temp, PID_BUFFER[i], 10);
|
||||
itoa(temp_prio, PID_PRIO[i], 10);
|
||||
offset += vfs_write(file, temp, offset, sizeof(char) * countChar(temp));
|
||||
offset += vfs_write(file, " ", offset, sizeof(char) * 3);
|
||||
offset += vfs_write(file, temp_prio, offset, sizeof(char) * countChar(temp_prio));
|
||||
offset += vfs_write(file, " ", offset, sizeof(char) * 3);
|
||||
offset += vfs_write(file, PID_NAME[i], offset, sizeof(char) * countChar(PID_NAME[i]));
|
||||
offset += vfs_write(file, "\n", offset, sizeof(char));
|
||||
//ripristino array temp
|
||||
for (int j = 0; j < 5; j++) {
|
||||
temp[j] = 0;
|
||||
}
|
||||
}
|
||||
vfs_close(file);
|
||||
count = 0;
|
||||
err = 1;
|
||||
}
|
||||
|
||||
if (!strcmp(name, "error") && err) {
|
||||
wipe();
|
||||
err--;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Funzione che pulisce la sessione
|
||||
*/
|
||||
void wipe()
|
||||
{
|
||||
mode_t flag = 000777;
|
||||
const char *namef = "/home/user/feedback.txt";
|
||||
vfs_file_t *file = vfs_open(namef, O_RDWR, flag);
|
||||
count = 0;
|
||||
offset += sizeof(char) * 100; //overkill
|
||||
|
||||
for (int i = 34 * sizeof(char); i < offset; i += sizeof(char)) {
|
||||
//NB: se riusciamo a creare un file nostro e scrivere non solo sugli spazi
|
||||
//questo costrutto non funziona, del sovrascrivere finche count non e' zero
|
||||
vfs_write(file, " ", i, sizeof(char));
|
||||
}
|
||||
vfs_close(file);
|
||||
}
|
||||
|
||||
/*
|
||||
Funzione che conta caratteri del array di char passato
|
||||
*/
|
||||
|
||||
int countChar(char name[])
|
||||
{
|
||||
int ct = 0;
|
||||
while (name[ct] != '\0') {
|
||||
ct++;
|
||||
}
|
||||
return ct;
|
||||
}
|
||||
/// @brief
|
||||
struct statistic {
|
||||
pid_t pid;
|
||||
char name[20];
|
||||
unsigned long occur;
|
||||
} arr_stats[PID_MAX_LIMIT];
|
||||
|
||||
int scheduler_feedback_init()
|
||||
{
|
||||
//
|
||||
//mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
//
|
||||
//vfs_file_t *feedback = vfs_creat(FEEDBACK_FILENAME, mode);
|
||||
//if (feedback == NULL)
|
||||
// pr_debug("non va");
|
||||
|
||||
// Create the feedback file, if necessary.
|
||||
int ret = vfs_mkdir("/var", 0644);
|
||||
if ((ret < 0) && (-ret != EEXIST)) {
|
||||
pr_err("Failed to create the `/var` directory.\n");
|
||||
pr_err("Error: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
// Create the feedback file, if necessary.
|
||||
vfs_file_t *feedback = vfs_open(FEEDBACK_FILENAME, O_WRONLY | O_TRUNC | O_CREAT, 0644);
|
||||
if (feedback == NULL) {
|
||||
pr_err("Failed to create the feedback file.\n");
|
||||
pr_err("Error: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
// Get the length of the headr.
|
||||
ssize_t header_len = strlen(FEEDBACK_HEADER);
|
||||
// Reset the offset.
|
||||
offset = 0;
|
||||
// Write the header.
|
||||
vfs_write(feedback, FEEDBACK_HEADER, offset, header_len);
|
||||
// Move the offset.
|
||||
offset += header_len;
|
||||
// Close the file.
|
||||
vfs_close(feedback);
|
||||
// Initialize the stat array.
|
||||
for (size_t i = 0; i < PID_MAX_LIMIT; ++i) {
|
||||
arr_stats[i].pid = -1;
|
||||
arr_stats[i].occur = 0;
|
||||
}
|
||||
// Set when the first logging should happen.
|
||||
next_log = timer_get_seconds() + LOG_INTERVAL;
|
||||
// Initialize the number of occurrences.
|
||||
total_occurrences = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void scheduler_feedback_update(task_struct *next)
|
||||
{
|
||||
assert(next && "Received a NULL task.");
|
||||
|
||||
// ========================================================================
|
||||
|
||||
if (next_log < timer_get_seconds()) {
|
||||
pr_debug("Scheduling Statistics (%s)\n", POLICY_NAME);
|
||||
|
||||
// Open the feedback file.
|
||||
//vfs_file_t *feedback = vfs_open(FEEDBACK_FILENAME, O_WRONLY, 0644);
|
||||
//if (feedback == NULL) {
|
||||
// pr_err("Failed to create the feedback file.\n");
|
||||
// pr_err("Error: %s\n", strerror(errno));
|
||||
// return;
|
||||
//}
|
||||
|
||||
//char buffer[NAME_MAX * 2];
|
||||
//int written = 0;
|
||||
|
||||
for (size_t i = 0; i < PID_MAX_LIMIT; ++i) {
|
||||
if (arr_stats[i].pid == -1) {
|
||||
break;
|
||||
}
|
||||
float tcpu = ((float)arr_stats[i].occur * 100.0) / total_occurrences;
|
||||
pr_debug("[%3d] %-12s -> TCPU: %.2f%% \n",
|
||||
arr_stats[i].pid,
|
||||
arr_stats[i].name,
|
||||
tcpu);
|
||||
|
||||
//written = sprintf(buffer, "[%3d](%s)[%f], ", arr_stats[i].pid, arr_stats[i].name, tcpu);
|
||||
//vfs_write(feedback, buffer, offset, written);
|
||||
//offset += written;
|
||||
}
|
||||
//vfs_write(feedback, "/n", offset, 1);
|
||||
//offset++;
|
||||
|
||||
for (size_t i = 0; i < PID_MAX_LIMIT; ++i) {
|
||||
if (arr_stats[i].pid == -1) {
|
||||
break;
|
||||
}
|
||||
arr_stats[i].pid = -1;
|
||||
arr_stats[i].occur = 0;
|
||||
}
|
||||
// Update when in the future, the logging should happen.
|
||||
next_log = timer_get_seconds() + LOG_INTERVAL;
|
||||
// Reset the number of occurrences.
|
||||
total_occurrences = 0;
|
||||
} else {
|
||||
for (size_t i = 0; i < PID_MAX_LIMIT; ++i) {
|
||||
// If the process we are logging is already in the stat array, increase the occurrences.
|
||||
if (arr_stats[i].pid == next->pid) {
|
||||
arr_stats[i].occur += 1;
|
||||
total_occurrences += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
// If we reached the unused stat entries, it means the current
|
||||
// process is not stored and we need to insert it.
|
||||
if (arr_stats[i].pid == -1) {
|
||||
arr_stats[i].pid = next->pid;
|
||||
strcpy(arr_stats[i].name, next->name);
|
||||
arr_stats[i].occur = 1;
|
||||
total_occurrences += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user