diff --git a/Makefile b/Makefile index a6b2736211a854ad0e68d59709a4c5fa50416569..f18490c7ed27dedcde8438fd98d2066753de74ef 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ OPTION=-m32 -all: display_stack try_mul pingpong +all: display_stack try_mul pingpong pingpongpang display_stack : display_stack.o gcc $(OPTION) -o $@ $^ @@ -11,8 +11,11 @@ try_mul : try.o try_mul.o pingpong : try.o pingpong.o gcc $(OPTION) -o $@ $^ +pingpongpang : try.o pingpongpang.o + gcc $(OPTION) -o $@ $^ + %.o:%.c gcc $(OPTION) -c $< clean: - rm -f *.o *.s display_stack try_mul pingpong + rm -f *.o *.s display_stack try_mul pingpong pingpongpang diff --git a/pingpongpang.c b/pingpongpang.c new file mode 100644 index 0000000000000000000000000000000000000000..980f391f18e3e7d4051282f1b4a70812e8b1b93d --- /dev/null +++ b/pingpongpang.c @@ -0,0 +1,48 @@ +#include <stdio.h> +#include <stdlib.h> +#include "try.h" + +#define STACK 16384 + +void f_ping(void *args); +void f_pong(void *args); +void f_pang(void *args); + +int main(int argc, char *argv[]) +{ + ctx_t *pang_ctx = create_ctx(STACK, f_pang, NULL); + ctx_t *pong_ctx = create_ctx(STACK, f_pong, NULL); + ctx_t *ping_ctx = create_ctx(STACK, f_ping, NULL); + printf("Begin \n"); + yield(); + printf("End \n"); + exit(EXIT_SUCCESS); +} + +void f_ping(void *args) +{ + printf("A"); + yield(); + printf("B"); + yield(); + printf("C"); + yield(); +} + +void f_pong(void *args) +{ + printf("1"); + yield(); + printf("2"); + yield(); +} + +void f_pang(void *args) +{ + printf("("); + yield(); + printf(":"); + yield(); + printf(")"); + yield(); +} diff --git a/try.c b/try.c index ea0bbaff473f58cb26af3cf5d664d2d49bbc449a..46c18250f1cc5115921979540562fe5c9c03290c 100644 --- a/try.c +++ b/try.c @@ -2,6 +2,9 @@ #include <assert.h> #include "try.h" +static ctx_t *current_ctx = NULL; +static ctx_t *ring_ctx = NULL; + int try(ctx_t *pctx, func_t *f, int arg) { asm("movl %%esp, %0" @@ -38,7 +41,6 @@ int init_ctx(ctx_t *pctx, int stack_size, funct_t f, void *args) pctx->status = CTX_INIT; } -static ctx_t *current_ctx = NULL; void switch_to_ctx(ctx_t *pctx) { assert(pctx->status != CTX_END); @@ -67,5 +69,33 @@ void start_ctx() current_ctx->status = CTX_EXEC; current_ctx->f(current_ctx->args); current_ctx->status = CTX_END; - free(current_ctx->stack); + yield(); +} + +ctx_t *create_ctx(int stack_size, funct_t f, void *args) +{ + ctx_t *new_ctx = malloc(sizeof(ctx_t)); + + if (ring_ctx == NULL) + { + new_ctx->next_ctx = new_ctx; + ring_ctx = new_ctx; + } + else + { + new_ctx->next_ctx = ring_ctx->next_ctx; + ring_ctx->next_ctx = new_ctx; + } + + init_ctx(new_ctx, stack_size, f, args); + return new_ctx; +} + +void yield() +{ + assert(ring_ctx != NULL || current_ctx != NULL); + if (current_ctx == NULL) + switch_to_ctx(ring_ctx->next_ctx); + else + switch_to_ctx(current_ctx->next_ctx); } \ No newline at end of file diff --git a/try.h b/try.h index 27d015a6c77d518810d5d941d64ee08fdcabca3f..b62722caaa89b943f04a282825b9adda2ba4599f 100644 --- a/try.h +++ b/try.h @@ -11,7 +11,7 @@ typedef enum CTX_END } ctx_status_t; -typedef struct +typedef struct ctx_s { void *esp; void *ebp; @@ -19,6 +19,7 @@ typedef struct funct_t *f; void *args; ctx_status_t status; + struct ctx_s *next_ctx; } ctx_t; int try(ctx_t *, func_t *, int); @@ -31,4 +32,8 @@ void switch_to_ctx(ctx_t *); void start_ctx(); +ctx_t *create_ctx(int, funct_t, void *); + +void yield(); + #endif // TRY