Skip to content

Instantly share code, notes, and snippets.

@dulimarta
Created September 25, 2020 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dulimarta/b55c6d7083b6fecd8a67b027f5f33b97 to your computer and use it in GitHub Desktop.
Save dulimarta/b55c6d7083b6fecd8a67b027f5f33b97 to your computer and use it in GitHub Desktop.
CS452 ULT swap_conteext
/*
* Demonstrate a minimal code to implement thread switching in user
* space
**/
#include <ucontext.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
ucontext_t c1_ctx, c2_ctx, tmp;
ucontext_t *current;
const int STACK_SIZE = 4 * 1024; // 4K bytes
int whose_turn = 0;
char stack1[STACK_SIZE];
char stack2[STACK_SIZE];
// type for a pointer to functions that take zero argument
typedef void (*FuncNoArg)(void);
void one() {
while(1) {
printf("In one...\n");
usleep(100000);
}
}
void two(const char* text) {
while(1) {
printf("In two---%s\n", text);
usleep(300000);
}
}
void wakeup() {
// Flip flop between the two contexts
whose_turn = 1 - whose_turn;
switch(whose_turn) {
case 0:
swapcontext(&tmp, &c1_ctx);
break;
case 1:
swapcontext(&tmp, &c2_ctx);
}
}
int main() {
getcontext(&c1_ctx);
c1_ctx.uc_stack.ss_sp = stack1;
c1_ctx.uc_stack.ss_size = STACK_SIZE;
c1_ctx.uc_link = NULL; // no successor thread
// Function one takes no arguments
makecontext(&c1_ctx, one, 0);
getcontext(&c2_ctx);
c2_ctx.uc_stack.ss_sp = stack2;
c2_ctx.uc_stack.ss_size = STACK_SIZE;
c2_ctx.uc_link = NULL; // no successor thread
// Function two takes 1 string arg
makecontext(&c2_ctx, (FuncNoArg) two, 1, "Hello");
printf("In main\n");
// Setup periodic timer handler
struct sigaction alarm_act;
alarm_act.sa_handler = wakeup;
sigemptyset(&alarm_act.sa_mask);
alarm_act.sa_flags = SA_RESTART;
sigaction(SIGALRM, &alarm_act, NULL);
struct itimerval freq;
// Initial 2-sec delay
freq.it_value.tv_sec = 2;
freq.it_value.tv_usec = 0;
// then periodically every 500 millisec
freq.it_interval.tv_sec = 0;
freq.it_interval.tv_usec = 500000;
setitimer(ITIMER_REAL, &freq, NULL);
while(1) {
printf("In main thread...\n");
pause();
}
return 0;
}
/*
* Demonstrate a minimal code to implement thread switching in user
* space
**/
#include <ucontext.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
ucontext_t c1_ctx, c2_ctx, main_ctx, tmp;
ucontext_t *current;
const int STACK_SIZE = 4 * 1024; // 4K bytes
int whose_turn = 0;
char stack1[STACK_SIZE];
char stack2[STACK_SIZE];
// type for a pointer to functions that take zero argument
typedef void (*FuncNoArg)(void);
void one() {
while(1) {
printf("In one...\n");
usleep(100000);
}
}
void two(const char* text) {
while(1) {
printf("In two---%s\n", text);
usleep(300000);
}
}
void wakeup() {
whose_turn++; // Round robun scheduler
switch(whose_turn) {
case 0:
swapcontext(&tmp, &main_ctx);
break;
case 1:
swapcontext(&tmp, &c1_ctx);
break;
case 2:
swapcontext(&tmp, &c2_ctx);
break;
case 3:
whose_turn = -1;
}
}
int main() {
getcontext(&main_ctx);
getcontext(&c1_ctx);
c1_ctx.uc_stack.ss_sp = stack1;
c1_ctx.uc_stack.ss_size = STACK_SIZE;
c1_ctx.uc_link = NULL; // no successor thread
// Function one takes no arguments
makecontext(&c1_ctx, one, 0);
getcontext(&c2_ctx);
c2_ctx.uc_stack.ss_sp = stack2;
c2_ctx.uc_stack.ss_size = STACK_SIZE;
c2_ctx.uc_link = NULL; // no successor thread
// Function two takes 1 string arg
makecontext(&c2_ctx, (FuncNoArg) two, 1, "Hello");
printf("In main\n");
// Setup periodic timer handler
struct sigaction alarm_act;
alarm_act.sa_handler = wakeup;
sigemptyset(&alarm_act.sa_mask);
alarm_act.sa_flags = SA_RESTART;
sigaction(SIGALRM, &alarm_act, NULL);
struct itimerval freq;
// Initial 2-sec delay
freq.it_value.tv_sec = 2;
freq.it_value.tv_usec = 0;
// then periodically every 500 millisec
freq.it_interval.tv_sec = 0;
freq.it_interval.tv_usec = 500000;
setitimer(ITIMER_REAL, &freq, NULL);
while(1) {
printf("In main thread...\n");
pause();
}
return 0;
}
#include <ucontext.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
ucontext_t c1, c2, main_ctx;
ucontext_t *current;
char stack1[4 * 1024];
char stack2[4 * 1024];
void one() {
while(1) {
printf("In one...\n");
usleep(100000);
}
}
void two() {
while(1) {
printf("In two---\n");
usleep(300000);
}
}
void wakeup(int _) {
if (current == NULL || current == &c2) {
current = &c1;
swapcontext(&main_ctx, &c1);
} else {
current = &c2;
swapcontext(&main_ctx, &c2);
}
}
int main() {
// Prepare context and stack for the first func
getcontext(&c1);
c1.uc_stack = {.ss_sp = stack1, .ss_size = 4 * 1024};
c1.uc_link = NULL;
makecontext(&c1, one, 0);
// Prepare context and stack for the second func
getcontext(&c2);
c2.uc_stack = {.ss_sp = stack2, .ss_size = 4 * 1024};
c2.uc_link = NULL;
makecontext(&c2, two, 0);
printf("In main\n");
// Install periodic timer handler
struct sigaction alarm_act;
alarm_act.sa_handler = wakeup;
sigemptyset(&alarm_act.sa_mask);
alarm_act.sa_flags = SA_RESTART;
sigaction(SIGALRM, &alarm_act, NULL);
itimerval freq;
// Initial 2-sec delay
// then periodically every 500 millisec
freq = {
.it_interval = {.tv_sec = 0, .tv_usec = 500000},
.it_value = {.tv_sec = 2, .tv_usec = 0}
};
// Fire the timer
setitimer(ITIMER_REAL, &freq, NULL);
// Main thread does nothing but pause for SIGALRM
while(1) {
pause();
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment