Projeto final para a disciplina INE5424 - Sistemas Operacionais II. tongOS é um Sistema Operacional baseado em RISC-V e feito em Rust.
Principal referência de implementação: Stephen Marz¹.
0.5
Padrão: https://doc.rust-lang.org/book/ch01-01-installation.html ou https://rustup.rs/
Arch/Manjaro: https://wiki.archlinux.org/index.php/rust#Installation
rustup install nightly
rustup target add riscv64gc-unknown-none-elf
Talvez seja necessário -> (cargo install cargo-binutils)
Para executar, mesmo após qualquer mudança, basta o seguinte comando:
cargo run
Para pontos de entrega e como visualizar, veja entrega e visualização.
Para a segunda entrega do projeto, é necessário cobrir os seguintes tópicos:
- Corretude na execução da política de escalonamento particionado.
- Corretude na migração de threads.
- Corretude na política de migração implementada.
Os testes para a segunda entrega estão apresentados no arquivo assigment.rs, chamados pela função kinit() em main.rs.
Para esta entrega, apresentamos duas novas features de visualização: DEBUG_OUTPUT e PROCESS_TO_RUN, ambas definidas em lib.rs.
Com DEBUG_OUTPUT é possível ativar ou desativar os prints de debug no meio do código (as vezes pode ficar meio difícil de entender o que está acontecendo).
Com PROCESS_TO_RUN você pode escolher qual processo/app executar. As opções são:
- Processos simples de exemplo: impressões e alguns loops com somador.
- Jantar dos Filósofos.
- App simples com input de teclado + sleep.
- Executar todos em sequência.
A execução com 4 harts está hardcoded, por algumas razões. É possível verificar que o qemu chama -smp 4 em .cargo/config.
A inicialização das outras harts já era feito anteriormente no processo de boot. Essa parte está em entry.S. Adicionalmente, adicionamos, na função kinit() em main.rs, a "finalização" do setup das outras harts. Todas as harts, com exceção da 0, esperam até que a hart 0 termine a inicialização do sistema e acorde-as, através da variável MAY_BOOT, permitindo que escalonem algum processo.
Adaptamos o sistema para mostar, ao printar, a hart corrente, a hart anterior e o pid do processo que está realizando essa saída.
Assim como na entrega 4, cada hart possui sua fila de processos. A migração de processos entre harts é realizada sempre que um processo transite de um estado qualquer (running, blocked, sleeping) para ready. Esse procedimento é realizado na função migrate_process, localizada em process.rs. Nela, é invocada uma função que decide para qual hart o processo será migrado: migration_criteria, localizada em scheduler.rs.
Foram implementadas três políticas de migração bem simples: adição via mod, Round Robin e "disponibilidade". É importante ressaltar que a API para adicionar um novo critério é bem simples, bastando apenas criar uma função e adicioná-la na lista de critérios disponíveis, selecionados pela variável CRITERIA, localizada em scheduler.rs. Para a primeira, apenas adicionamos 1 no valor da hart corrente e realizamos a operação de % 4, para que fique no intervalo adequado. Para a segunda, existe uma variável chamada NEXT_HART, compartilhada por todas as harts, que é adicionada de um sempre que chamada, fazendo % 4 no final. Para a terceira, primeiro olha-se se alguma hart está executando IDLE, senão busca a hart com a menor fila ready.
Primeiro terminal: make run_debug -> executa o qemu em forma de debugação.
Segundo terminal: make debug -> inicia o debug, carregando os símbolos e dando target em localhost:1234.
¹ Stephen Marz. Tutorial: https://osblog.stephenmarz.com/ e repositório: https://github.com/sgmarz/osblog. Arquivos ou funções específicas poderão conter referência direta a ele.