1// This file is part of SmallBASIC
2//
3// Task manager
4//
5// This program is distributed under the terms of the GPL v2.0 or later
6// Download the GNU Public License (GPL) from www.gnu.org
7//
8// Copyright(C) 2000 Nicholas Christopoulos
9
10#include "common/smbas.h"
11#include "common/tasks.h"
12
13static task_t *tasks; /**< tasks table @ingroup sys */
14static int task_count; /**< total number of tasks @ingroup sys */
15static int task_index; /**< current task number @ingroup sys */
16
17/**
18 * @ingroup sys
19 *
20 * return the number of the tasks
21 *
22 * @return the number of the tasks
23 */
24int count_tasks() {
25 return task_count;
26}
27
28/**
29 * @ingroup sys
30 *
31 * return the nth task-structure
32 *
33 * @return the nth task-structure
34 */
35task_t *taskinfo(int n) {
36 return &tasks[n];
37}
38
39/**
40 * @ingroup sys
41 *
42 * initialize tasks manager
43 */
44int init_tasks() {
45 tasks = NULL;
46 task_count = 0;
47 task_index = 0;
48 ctask = NULL;
49 int tid = create_task("main");
50 activate_task(tid);
51 return tid;
52}
53
54/**
55 * @ingroup sys
56 *
57 * destroys tasks and closes task manager
58 */
59void destroy_tasks() {
60 for (int i = 0; i < task_count; i++) {
61 close_task(i);
62 }
63 task_count = 0;
64 task_index = 0;
65 ctask = NULL;
66 free(tasks);
67 tasks = NULL;
68}
69
70/**
71 * @ingroup sys
72 *
73 * create an empty new task
74 *
75 * @param name is the task name
76 * @return the task-id
77 */
78int create_task(const char *name) {
79 int tid = -1;
80
81 if (task_count == 0) {
82 // this is the first task
83 tid = task_count;
84 task_count++;
85 tasks = (task_t *) malloc(sizeof(task_t) * task_count);
86 } else {
87 // search for an available free entry
88 for (int i = 0; i < task_count; i++) {
89 if (tasks[i].status == tsk_free) {
90 tid = i;
91 break;
92 }
93 }
94
95 // create a new task
96 if (tid == -1) {
97 tid = task_count;
98 task_count++;
99 tasks = (task_t *) realloc(tasks, sizeof(task_t) * task_count);
100 }
101 }
102
103 // init task
104 memset(&tasks[tid], 0, sizeof(task_t));
105 strlcpy(tasks[tid].file, name, sizeof(tasks[0].file));
106 tasks[tid].status = tsk_ready;
107 tasks[tid].parent = task_index;
108 tasks[tid].tid = tid;
109
110 return tid;
111}
112
113/**
114 * @ingroup sys
115 *
116 * closes a task and activate the next
117 */
118void close_task(int tid) {
119 tasks[tid].status = tsk_free;
120 if (task_index == tid) {
121 ctask = NULL;
122 }
123 // select next task
124 if (task_count) {
125 if (task_index == tid) {
126 if (task_count > task_index + 1) {
127 task_index++;
128 } else {
129 task_index = 0;
130 }
131 ctask = &tasks[task_index];
132 }
133 }
134}
135
136/**
137 * @ingroup sys
138 *
139 * set active task
140 *
141 * @param tid the task-id
142 * @return the previous task-id
143 */
144int activate_task(int tid) {
145 int prev_tid = task_index;
146 task_index = tid;
147 ctask = &tasks[tid];
148 return prev_tid;
149}
150
151/**
152 * @ingroup sys
153 *
154 * search for a task
155 *
156 * @param task_name the name of the task
157 * @return the task-id; or -1 on error
158 */
159int search_task(const char *task_name) {
160 for (int i = 0; i < task_count; i++) {
161 if (strcmp(tasks[i].file, task_name) == 0) {
162 return i;
163 }
164 }
165 return -1;
166}
167