]> wirehaze git hosting - ppos.git/blob - ppos/hardware/cpu.c

wirehaze git hosting

add ppos/
[ppos.git] / ppos / hardware / cpu.c
1 // PingPongOS - PingPong Operating System
2 // Prof. Carlos A. Maziero, DINF UFPR
3 // Versão 2.0 -- Junho de 2025
4
5 // ATENÇÃO: ESTE ARQUIVO NÃO DEVE SER ALTERADO;
6 // ALTERAÇÕES SERÃO DESCARTADAS NA CORREÇÃO.
7
8 // Emula vários mecanismos de uma CPU:
9 // - interrupções virtuais - emuladas com sinais POSIX de tempo real
10 // a partir de SIGRTMIN+1
11 // - desligamento do sistema
12
13 // padrão de API UNIX a usar (para sigaction)
14 #define _XOPEN_SOURCE 700
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <signal.h>
20 #include <time.h>
21 #include <sys/times.h>
22 #include "cpu.h"
23
24 #define NOERROR 0
25 #define ERROR -1
26
27 // para os sinais
28 static struct sigaction action;
29
30 // para o timer
31 static timer_t timer;
32 static struct itimerspec delay;
33 static struct sigevent sigev;
34
35 //----------------------------------------------------------------------
36
37 int hw_irq_handle(int irq, void (*handle)(int))
38 {
39 if (irq < 1)
40 return (ERROR);
41
42 if ((irq + SIGRTMIN) >= SIGRTMAX)
43 return (ERROR);
44
45 if (!handle)
46 return (ERROR);
47
48 // registra a ação para o sinal indicado
49 action.sa_handler = handle;
50 sigemptyset(&action.sa_mask);
51 action.sa_flags = SA_NODEFER;
52 if (sigaction(irq + SIGRTMIN, &action, 0) < 0)
53 {
54 perror("IRQ:");
55 abort();
56 }
57 return (NOERROR);
58 }
59
60 //----------------------------------------------------------------------
61
62 void hw_irq_enable(int enable)
63 {
64 sigset_t mask;
65
66 if (enable)
67 sigemptyset(&mask);
68 else
69 sigfillset(&mask);
70
71 sigprocmask(SIG_SETMASK, &mask, NULL);
72 }
73
74 //----------------------------------------------------------------------
75
76 int hw_timer(int first, int next)
77 {
78 if (first < 0 || next < 0)
79 return (ERROR);
80
81 // cria o timer
82 sigev.sigev_notify = SIGEV_SIGNAL;
83 sigev.sigev_signo = IRQ_TIMER + SIGRTMIN;
84 if (timer_create(CLOCK_REALTIME, &sigev, &timer) == -1)
85 {
86 perror("TIMER:");
87 abort();
88 }
89
90 // configura o timer POSIX
91 delay.it_value.tv_nsec = first * 1000000;
92 delay.it_value.tv_sec = 0;
93 delay.it_interval.tv_nsec = first * 1000000;
94 delay.it_interval.tv_sec = 0;
95
96 // arma o timer POSIX
97 if (timer_settime(timer, 0, &delay, NULL) == -1)
98 {
99 perror("TIMER:");
100 abort();
101 }
102 return (NOERROR);
103 }
104
105 //----------------------------------------------------------------------
106
107 void hw_wfi()
108 {
109 // A syscall pause permite emular o comportamento da instrução HLT
110 // (halt) ou WFI (wait for interrupt), que suspendem a CPU até a
111 // próxima interrupção de hardware, para economizar energia.
112 // Neste caso, pause() suspende este processo até o próximo sinal
113 // UNIX, que emula uma interrupção.
114 pause();
115 }
116
117 //----------------------------------------------------------------------
118
119 void hw_poweroff(int error)
120 {
121 //struct tms time;
122
123 // print CPU usage
124 //times(&time);
125 //printf("Hardware shutdown, cpu active for %ld ms\n",
126 // 10 * (time.tms_utime + time.tms_stime));
127
128 // encerra com erro, GDB pode ver o call stack
129 if (error)
130 abort();
131
132 exit(0);
133 }
134
135 //----------------------------------------------------------------------