DEV Community

Cover image for Dia 21 e 22 - Entendendo contextos em C
Matheus Gomes
Matheus Gomes

Posted on

Dia 21 e 22 - Entendendo contextos em C

Em C, contexto é o estado atual de execução de um programa, incluindo registradores (pequenas áreas de armazenamento dentro da CPU, usadas para armazenar dados e instruções durante a execução de programas), variáveis e o fluxo de instruções, crucial para trocar tarefas.

Troca de contextos para sistemas operacionais

A principal função é permitir a multitarefa. Isso garante que o sistema possa alternar entre processos de forma eficiente.

Aqui foi disponibilizado o arquivo contexts.c. É um demonstrativo de como contextos funcionam.

Logo no topo desse arquivo, percebemos a importação da biblioteca ucontext.h. Ela permite manipular o contexto de execução.

No trecho abaixo vemos que são criados 3 contextos, e esses 3 contextos terão a memória alocada do tamanho de STACKSIZE.

#define STACKSIZE 64 * 1024 /* tamanho de pilha das threads */

ucontext_t ContextPing, ContextPong, ContextMain;
Enter fullscreen mode Exit fullscreen mode

E logo depois, as funções Ping e Pong que serão executadas em seus respectivos contextos:

void BodyPing(void *arg)
{
  int i;

  printf("%s: inicio\n", (char *)arg);

  for (i = 0; i < 4; i++)
  {
    printf("%s: %d\n", (char *)arg, i);
    swapcontext(&ContextPing, &ContextPong);
  }
  printf("%s: fim\n", (char *)arg);

  swapcontext(&ContextPing, &ContextMain);
}

/*****************************************************/

void BodyPong(void *arg)
{
  int i;

  printf("%s: inicio\n", (char *)arg);

  for (i = 0; i < 4; i++)
  {
    printf("%s: %d\n", (char *)arg, i);
    swapcontext(&ContextPong, &ContextPing);
  }
  printf("%s: fim\n", (char *)arg);

  swapcontext(&ContextPong, &ContextMain);
}

/*****************************************************/
Enter fullscreen mode Exit fullscreen mode

Na função main, é utilizado malloc para reservar as stacks, onde posteriormente são atribuidos com uc_stack.ss_sp ao contexto, e swapcontext é usado para alternar entre eles.

int main(int argc, char *argv[])
{
  char *stack;

  printf("main: inicio\n");

  getcontext(&ContextPing);

  stack = malloc(STACKSIZE);
  if (stack)
  {
    ContextPing.uc_stack.ss_sp = stack;
    ContextPing.uc_stack.ss_size = STACKSIZE;
    ContextPing.uc_stack.ss_flags = 0;
    ContextPing.uc_link = 0;
  }
  else
  {
    perror("Erro na criação da pilha: ");
    exit(1);
  }

  makecontext(&ContextPing, (void *)(*BodyPing), 1, "    Ping");

  getcontext(&ContextPong);

  stack = malloc(STACKSIZE);
  if (stack)
  {
    ContextPong.uc_stack.ss_sp = stack;
    ContextPong.uc_stack.ss_size = STACKSIZE;
    ContextPong.uc_stack.ss_flags = 0;
    ContextPong.uc_link = 0;
  }
  else
  {
    perror("Erro na criação da pilha: ");
    exit(1);
  }

  makecontext(&ContextPong, (void *)(*BodyPong), 1, "        Pong");

  swapcontext(&ContextMain, &ContextPing);
  swapcontext(&ContextMain, &ContextPong);

  printf("main: fim\n");

  exit(0);
}
Enter fullscreen mode Exit fullscreen mode

Output do programa executado:

main: inicio
    Ping: inicio
    Ping: 0
        Pong: inicio
        Pong: 0
    Ping: 1
        Pong: 1
    Ping: 2
        Pong: 2
    Ping: 3
        Pong: 3
    Ping: fim
        Pong: fim
main: fim
Enter fullscreen mode Exit fullscreen mode

Com isso, podemos perceber que mesmo alterando os contextos, os valores que "fluem" pela função são mantidos, um exemplo nesse caso é o índice do for.

Você deve ter percebido que existe um malloc para o contexto de Ping e de Pong, mas vemos que existe um contexto para main também, por qual motivo não existe um malloc para ele?

O ContextMain não precisa de uma stack separada porque ele opera na stack do thread principal, enquanto os contextos Ping e Pong têm suas próprias stacks alocadas dinamicamente.

Se crio um contexto e não aloco memória para ele, quando utilizamos o swap, ele vai para a stack principal do programa.

Esse código é do professor Maziero, encontrado no sub-projeto desenvolvido do PingPongOS "Trocas de Contexto".

Image of Datadog

The Essential Toolkit for Front-end Developers

Take a user-centric approach to front-end monitoring that evolves alongside increasingly complex frameworks and single-page applications.

Get The Kit

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more