Created
September 25, 2020 14:10
-
-
Save dulimarta/b55c6d7083b6fecd8a67b027f5f33b97 to your computer and use it in GitHub Desktop.
CS452 ULT swap_conteext
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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