General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

99 lines
2.5 KiB

  1. #pragma once
  2. #include "gp/system/system.hpp"
  3. // TODO: implement unsafe_bottleneck to use in the locked list
  4. namespace gp{
  5. namespace system {
  6. class simple_scheduling : public gp::system::scheduling_scheme {
  7. struct locked_circular_buffer {
  8. std::atomic_bool lock;
  9. gp::array<gp::system::task_queue::node_ptr, gp_config::limits::max_processes> processes;
  10. size_t read_idx = 0;
  11. size_t write_idx = 0;
  12. void push(gp::system::task_queue::node_ptr node) {
  13. bool t = true;
  14. bool f = false;
  15. while(not lock.compare_exchange_strong(f,t)){}
  16. {
  17. gp_config::assertion((write_idx + 1)%processes.size() != read_idx, "bad push to circular buffer");
  18. processes[write_idx] = node;
  19. write_idx=(write_idx+1)%processes.size();
  20. }
  21. while(not lock.compare_exchange_strong(t,f)){}
  22. }
  23. gp::system::task_queue::node_ptr pop() {
  24. bool t = true;
  25. bool f = false;
  26. gp::system::task_queue::node_ptr ret;
  27. while(not lock.compare_exchange_strong(f,t)){}
  28. {
  29. if(read_idx == write_idx) {
  30. ret = nullptr;
  31. } else {
  32. ret = processes[read_idx];
  33. read_idx=(read_idx+1)%processes.size();
  34. }
  35. }
  36. while(not lock.compare_exchange_strong(t,f)){}
  37. return ret;
  38. }
  39. };
  40. locked_circular_buffer running;
  41. locked_circular_buffer waiting;
  42. locked_circular_buffer to_clean;
  43. locked_circular_buffer naughty;
  44. system* sys = nullptr;
  45. public:
  46. simple_scheduling()
  47. {}
  48. virtual void link(system& value) {
  49. gp_config::assertion(!(sys), "Double linkage detected");
  50. sys = &value;
  51. sys->process_managers.emplace_back(*sys,0);
  52. }
  53. virtual gp::system::task_queue::node_ptr one(size_t) {
  54. auto v = running.pop();
  55. do{
  56. if(v) return v;
  57. v = running.pop();
  58. }while(true);
  59. }
  60. virtual void push(gp::system::task_queue::node_ptr node) {
  61. running.push(node);
  62. }
  63. virtual gp::system::task_queue::node_ptr next(size_t, gp::system::task_queue::node_ptr current) {
  64. switch(current->value->state) {
  65. case process_status::inactive:
  66. case process_status::running:
  67. running.push(current);
  68. break;
  69. case process_status::finished:
  70. to_clean.push(current);
  71. break;
  72. case process_status::zombie:
  73. naughty.push(current);
  74. break;
  75. case process_status::waiting:
  76. waiting.push(current);
  77. break;
  78. }
  79. return one(0);
  80. }
  81. virtual gp::system::scheduler& current_scheduler() {
  82. return sys->process_managers[0];
  83. }
  84. };
  85. }
  86. }