当前位置:   article > 正文

协程基础_context系列函数_sverilog pure函数和context函数

sverilog pure函数和context函数
  最近想看看协程,对这个的具体实现不太了解,查了下,协程最常规的做法就是基于makecontext,getcontext,swapcontext这类函数在用户空间切换用户上下文。

所以在这通过例子代码尽量把context相关的函数弄清楚先。

  1. #include <ucontext.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. static ucontext_t uctx_main, uctx_func1, uctx_func2;
  5. #define handle_error(msg) \
  6. do { perror(msg); exit(EXIT_FAILURE); } while (0)
  7. static void
  8. func1(void)
  9. {
  10. printf("func1: started\n"); //4
  11. printf("func1: swapcontext(&uctx_func1, &uctx_func2)\n"); //5
  12. if (swapcontext(&uctx_func1, &uctx_func2) == -1) //切换回func2执行
  13. handle_error("swapcontext");
  14. printf("func1: returning\n"); //7
  15. }
  16. static void
  17. func2(void)
  18. {
  19. printf("func2: started\n"); //2
  20. printf("func2: swapcontext(&uctx_func2, &uctx_func1)\n"); //3
  21. if (swapcontext(&uctx_func2, &uctx_func1) == -1) //切换到func1执行
  22. handle_error("swapcontext");
  23. printf("func2: returning\n"); //6
  24. }
  25. int
  26. main(int argc, char *argv[])
  27. {
  28. //注意在实际中要注意stack大小,否则可能会出现溢出.
  29. char func1_stack[16384];
  30. char func2_stack[16384];
  31. //获取当前进程/线程上下文信息,存储到uctx_func1中
  32. if (getcontext(&uctx_func1) == -1)
  33. handle_error("getcontext");
  34. //uc_stack: 分配保存协程数据的堆栈空间
  35. uctx_func1.uc_stack.ss_sp = func1_stack; //栈头指针
  36. uctx_func1.uc_stack.ss_size = sizeof(func1_stack); //栈大小
  37. uctx_func1.uc_link = &uctx_main; //协程后续的context
  38. makecontext(&uctx_func1, func1, 0); //依修改得到一个新的centext
  39. if (getcontext(&uctx_func2) == -1)
  40. handle_error("getcontext");
  41. uctx_func2.uc_stack.ss_sp = func2_stack;
  42. uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
  43. /* Successor context is f1(), unless argc > 1 */
  44. //如果argc有传参数进来,则uc_link置为空.后续代码将不再执行
  45. uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1;
  46. makecontext(&uctx_func2, func2, 0);
  47. printf("main: swapcontext(&uctx_main, &uctx_func2)\n"); //1
  48. //swapcontext(ucontext_t *oucp, ucontext_t *ucp)
  49. // 进行上下文切换,将当前上下文保存到oucp中,切换到ucp
  50. //将当前上下文保存到uctx_main, 并切换到uctx_func2
  51. if (swapcontext(&uctx_main, &uctx_func2) == -1)
  52. handle_error("swapcontext");
  53. printf("main: exiting\n"); //8 : 如argc不为空则这不会执行.
  54. exit(EXIT_SUCCESS);
  55. }

例子运行结果:

  1. suora:/test # ./co1 5
  2. main: swapcontext(&uctx_main, &uctx_func2)
  3. func2: started
  4. func2: swapcontext(&uctx_func2, &uctx_func1)
  5. func1: started
  6. func1: swapcontext(&uctx_func1, &uctx_func2)
  7. func2: returning
  8. suora:/test # ./co1
  9. main: swapcontext(&uctx_main, &uctx_func2)
  10. func2: started
  11. func2: swapcontext(&uctx_func2, &uctx_func1)
  12. func1: started
  13. func1: swapcontext(&uctx_func1, &uctx_func2)
  14. func2: returning
  15. func1: returning
  16. main: exiting
从运行结果看,大致弄清这几个函数了,不过我对stack大小还是没弄清楚应当怎么估算,但我把这个例子再实现了下。
弄了个动态分配内存的试了试。

  1. /*************************************************
  2. Author: xiongchuanliang
  3. Description: coroutine
  4. suora:/test # gcc -o co2 co2.c
  5. suora:/test # ./co2
  6. main: swapcontext(&uctx_main, &uctx_func2)
  7. func2: started
  8. func2: swapcontext(&uctx_func2, &uctx_func1)
  9. func1: started
  10. func1: swapcontext(&uctx_func1, &uctx_func2)
  11. func2: returning
  12. func1: returning
  13. main: exiting
  14. suora:/test # ./co2 3 5
  15. main: swapcontext(&uctx_main, &uctx_func2)
  16. func2: started
  17. func2: swapcontext(&uctx_func2, &uctx_func1)
  18. func1: started
  19. func1: swapcontext(&uctx_func1, &uctx_func2)
  20. func2: returning
  21. suora:/test #
  22. **************************************************/
  23. #include <ucontext.h>
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. ucontext_t uctx_main, uctx_func1, uctx_func2;
  27. #define handle_error(msg) \
  28. do { perror(msg); exit(EXIT_FAILURE); } while (0)
  29. #define CONTEXT_STACK (1024*64) // 64kB
  30. typedef void (*context_func)(void);
  31. void func1(void);
  32. void func2(void);
  33. int ctx_create(ucontext_t *ctx,
  34. context_func func,
  35. ucontext_t *ctx_link,
  36. void *ss_sp,
  37. size_t ss_size);
  38. int main(int argc, char *argv[])
  39. {
  40. if(ctx_create(&uctx_func1,func1,&uctx_main,
  41. malloc(CONTEXT_STACK),CONTEXT_STACK) == 1)
  42. return EXIT_FAILURE;
  43. if(ctx_create(&uctx_func2,func2,
  44. (argc > 1) ? NULL : &uctx_func1 , //&uctx_func1
  45. malloc(CONTEXT_STACK),CONTEXT_STACK) == 1)
  46. {
  47. free( uctx_func1.uc_stack.ss_sp );
  48. return EXIT_FAILURE;
  49. }
  50. printf("main: swapcontext(&uctx_main, &uctx_func2)\n");
  51. if (swapcontext(&uctx_main, &uctx_func2) == -1)
  52. handle_error("swapcontext");
  53. free( uctx_func1.uc_stack.ss_sp );
  54. free( uctx_func2.uc_stack.ss_sp );
  55. printf("main: exiting\n");
  56. exit(EXIT_SUCCESS);
  57. }
  58. int ctx_create(ucontext_t *ctx,
  59. context_func func,
  60. ucontext_t *ctx_link,
  61. void *ss_sp,
  62. size_t ss_size)
  63. {
  64. if(getcontext(ctx) == -1)
  65. {
  66. handle_error("getcontext");
  67. return 1;
  68. }
  69. ctx->uc_link = ctx_link;
  70. ctx->uc_stack.ss_sp = ss_sp;
  71. ctx->uc_stack.ss_size = ss_size;
  72. ctx->uc_stack.ss_flags = 0;
  73. makecontext(ctx, func, 0);
  74. return 0;
  75. }
  76. void func1(void)
  77. {
  78. printf("func1: started\n");
  79. printf("func1: swapcontext(&uctx_func1, &uctx_func2)\n");
  80. if (swapcontext(&uctx_func1, &uctx_func2) == -1)
  81. handle_error("swapcontext");
  82. printf("func1: returning\n");
  83. }
  84. void func2(void)
  85. {
  86. printf("func2: started\n");
  87. printf("func2: swapcontext(&uctx_func2, &uctx_func1)\n");
  88. if (swapcontext(&uctx_func2, &uctx_func1) == -1)
  89. handle_error("swapcontext");
  90. printf("func2: returning\n");
  91. }

今天先弄到这.


MAIL: xcl_168@aliyun.com
BLOG: blog.csdn.net/xcl168


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/845081?site
推荐阅读
相关标签
  

闽ICP备14008679号