====== Trocas de contexto ====== {{:so:ppos_01_contextos.mkv |Vídeo deste projeto}} Implementar tarefas simultâneas dentro de um processo de usuário não é uma tarefa difícil, embora alguns detalhes de baixo nível possam assustar os iniciantes, como a manipulação de registradores para as trocas de contexto. Felizmente, algumas chamadas de sistema POSIX permitem simplificar a manipulação de contextos, eliminando as operações com registradores e tornando o código portável: * ''getcontext(&a)'' : salva o contexto atual na variável ''a''. * ''setcontext(&a)'' : restaura um contexto salvo anteriormente na variável ''a''. * ''swapcontext(&a,&b)'' : salva o contexto atual em ''a'' e restaura o contexto salvo anteriormente em ''b''. * ''makecontext(&a, ...)'' : ajusta alguns valores internos do contexto salvo em ''a''. * as variáveis ''a'' e ''b'' são do tipo ''ucontext_t'' e armazenam contextos de execução. Mais informações sobre essas funções podem ser obtidas em suas respectivas páginas de manual (''man getcontext'', etc.). Estude o código presente no arquivo {{contexts.c}}, execute-o e explique seu funcionamento. A depuração passo-a-passo desse código pode apresentar alguma dificuldade, devido às trocas de contexto. Sugere-se inserir pontos de parada (//breakpoints//) nos trechos mais críticos e depurar "saltando" de um ponto ao próximo. Elabore um relatório (no [[teaching:regras das atividades de laboratorio#relatórios|formato correto]]) cobrindo pelo menos os seguintes pontos: Após estudar o código do arquivo, faça as seguintes atividades: - Explique o objetivo e os parâmetros de cada uma das quatro funções acima. - Explique o significado dos campos da estrutura ''ucontext_t'' que foram utilizados no código. - Explique cada linha do código de ''contexts.c'' que chame uma dessas funções ou que manipule estruturas do tipo ''ucontext_t''. - Para visualizar melhor as trocas de contexto, desenhe o [[diagrama de tempo]] dessa execução. ===== Curiosidade ===== Trocas de contexto são implementadas dentro do núcleo, por código sucinto mas geralmente complexo. Veja um [[https://en.wikipedia.org/wiki/A_Commentary_on_the_UNIX_Operating_System#%E2%80%9CYou_are_not_expected_to_understand_this%E2%80%9D|comentário do código de troca de contexto]] de uma versão inicial do UNIX (anos 1970): /* * Switch to stack of the new process and set up * his segmentation registers. */ retu(rp->p_addr); sureg(); /* * If the new process paused because it was * swapped out, set the stack level to the last call * to savu(u_ssav). This means that the return * which is executed immediately after the call to aretu * actually returns from the last routine which did * the savu. * * You are not expected to understand this. <----------------- */ if(rp->p_flag&SSWAP) { rp->p_flag =& ~SSWAP; aretu(u.u_ssav); } /* * The value returned here has many subtle implications. * See the newproc comments. */ return(1); ===== Outras informações ===== * Duração estimada: 2 horas.