image.png

хз че сказать. вот вам шедулер.

#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/queue.h>

#define MAX_PRIORITY 2

enum task_status {
	READY,
	SLEEP,
	TERMINATE,
};

struct task {
	enum task_status status;
	int id;
	uint32_t priority;
	int (*routine)(void);
	LIST_ENTRY(task) entries;
};
typedef struct task task_s;

LIST_HEAD(task_listhead, task);
typedef struct task_listhead task_listhead_s;

task_listhead_s tasks_lists[MAX_PRIORITY + 1];

int task_curr_id = 1;

int task_add(int (*routine)(void), uint32_t priority) {
	if (priority > MAX_PRIORITY) {
		return -1;
	}
	task_s *new_task_ptr;
	if (!(new_task_ptr = malloc(sizeof(*new_task_ptr)))) {
		return -1;
	}
	new_task_ptr->priority = priority;
	new_task_ptr->status = READY;
	new_task_ptr->routine = routine;
	new_task_ptr->id = task_curr_id++;
	LIST_INSERT_HEAD(tasks_lists + priority, new_task_ptr, entries);
	return new_task_ptr->id;
}

static void remove_task(task_s *task_ptr) {
	LIST_REMOVE(task_ptr, entries);
	free(task_ptr);
}

static task_s *find_task(int id) {
	task_s *found_task = NULL;
	for (size_t i = 0; i <= MAX_PRIORITY; ++i) {
		task_s *task_ptr;
		LIST_FOREACH(task_ptr, tasks_lists + i, entries) {
			if (task_ptr->id == id) {
				found_task = task_ptr;
				break;
			}
		}
	}
	return found_task;
}

int task_remove(int id) {
	task_s *task_to_rm = find_task(id);
	if (!task_to_rm) {
		return 1;
	}
	task_to_rm->status = TERMINATE;
	return 0;
}

int task_put_sleep(int id) {
	task_s *task_to_sleep = find_task(id);
	if (!task_to_sleep) {
		return 1;
	}
	task_to_sleep->status = SLEEP;
	return 0;
}

int task_wake_up(int id) {
	task_s *task_to_wakeup = find_task(id);
	if (!task_to_wakeup) {
		return 1;
	}
	task_to_wakeup->status = READY;
	return 0;
}

int task_change_priority(int id, uint32_t priority) {
	task_s *task_to_change_pr = find_task(id);
	if (!task_to_change_pr || priority > MAX_PRIORITY) {
		return 1;
	}
	task_to_change_pr->priority = priority;
	return 0;
}

void scheduler_init() {
	for (size_t i = 0u; i < MAX_PRIORITY; ++i) {
		LIST_INIT(tasks_lists + i);
	}
}

void schedule() {
	for (;;) {
		int is_active = 0;
		for (size_t i = 0u; i <= MAX_PRIORITY; ++i) {
			size_t pr = MAX_PRIORITY - i;
			task_s *task_ptr = LIST_FIRST(tasks_lists + pr);
			while (task_ptr != NULL) {
				if (task_ptr->priority != pr) {
					task_s *task_to_mv = task_ptr;
					task_ptr = LIST_NEXT(task_ptr, entries);
					LIST_REMOVE(task_to_mv, entries);
					LIST_INSERT_HEAD(tasks_lists + task_to_mv->priority, task_to_mv, entries);
					continue;
				}
				task_s *task_to_rm = NULL;
				switch (task_ptr->status) {
					case READY: {
						is_active = 1;
						int new_status = task_ptr->routine();
						task_ptr->status = new_status;
						break;
					}
					case SLEEP:
						break;
					case TERMINATE:
						task_to_rm = task_ptr;
						break;
				}
				task_ptr = LIST_NEXT(task_ptr, entries);
				if (task_to_rm) {
					remove_task(task_to_rm);
				}
			}
		}
		if (!is_active) {
			break;
		}
	}
}

int glob = 0;

int prod_id;
int prod_cnt = 10;

int cons_id;
int cons_cnt = 0;

int prod() {
	if (!prod_cnt) {
		task_remove(cons_id);
		return TERMINATE;
	}
	prod_cnt--;
	glob++;
	task_wake_up(cons_id);
	return SLEEP;
}

int cons() {
	if (!glob) {
		return SLEEP;
	}
	cons_cnt++;
	glob--;
	printf("%d\\n", cons_cnt);
	task_wake_up(prod_id);
	return SLEEP;
}

int main() {
	scheduler_init();
	prod_id = task_add(prod, 2);
	cons_id = task_add(cons, 1);
	schedule();
	return 0;
}