Clean up the feedback code.

This commit is contained in:
Enrico Fraccaroli
2023-04-18 17:52:19 +02:00
parent 09aa9a6a39
commit d630fd55f7
4 changed files with 154 additions and 254 deletions
-7
View File
@@ -1,7 +0,0 @@
--PID'S RECORDING SESSION--
MODE:
PID PRIO NAME
+4 -1
View File
@@ -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.
+2 -86
View File
@@ -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++;
}
+148 -160
View File
@@ -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;
}
}
}
}