Skip to content

Commit ce1abce

Browse files
fix nasty scheduler bug
1 parent 1b607ac commit ce1abce

2 files changed

Lines changed: 60 additions & 70 deletions

File tree

include/taskswitch.h

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,6 @@ typedef enum process_state_t {
2222
*/
2323
typedef uint64_t pid_t;
2424

25-
/**
26-
* @brief User ID type (reserved for future use).
27-
*/
28-
typedef uint64_t uid_t;
29-
30-
/**
31-
* @brief Group ID type (reserved for future use).
32-
*/
33-
typedef uint64_t gid_t;
34-
3525
/**
3626
* @brief Logical CPU ID type.
3727
*/
@@ -65,19 +55,19 @@ typedef bool (*activity_callback_t)(struct process_t* proc, void* opaque);
6555
typedef struct process_t {
6656
pid_t pid; /**< Unique process ID */
6757
pid_t ppid; /**< Parent process ID */
68-
uid_t uid; /**< User ID (future use) */
69-
gid_t gid; /**< Group ID (future use) */
7058
process_state_t state; /**< Running state */
7159
time_t start_time; /**< Start time (UNIX epoch) */
7260
pid_t waitpid; /**< PID being waited on */
7361
cpu_id_t cpu; /**< Logical CPU this process is assigned to */
7462
const char* directory; /**< Directory of program */
7563
const char* name; /**< Filename of program */
76-
uint64_t size; /**< Size of program in bytes */
64+
size_t size; /**< Size of program in bytes */
7765
const char* csd; /**< Current selected directory */
7866
struct basic_ctx* code; /**< BASIC interpreter context */
79-
struct process_t* prev; /**< Previous process in doubly linked list */
80-
struct process_t* next; /**< Next process in doubly linked list */
67+
struct process_t* sched_next; /**< Next process in doubly linked list */
68+
struct process_t* sched_prev; /**< Previous process in doubly linked list */
69+
struct process_t* global_next; /**< Next process in doubly linked list */
70+
struct process_t* global_prev; /**< Previous process in doubly linked list */
8171
activity_callback_t check_idle; /**< If non-null, called to check if the process should remain idle */
8272
void* idle_context; /**< Opaque context passed to the check_idle callback */
8373
} process_t;
@@ -138,7 +128,6 @@ typedef struct idle_timer {
138128
* @brief Load and start a new BASIC process.
139129
*
140130
* @param fullpath Fully qualified path to file
141-
* @param cons Associated console
142131
* @param parent_pid Parent PID, or 0 for none
143132
* @param csd Current selected directory
144133
* @return process_t* Pointer to new process details

src/taskswitch.c

Lines changed: 55 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ bool booted_from_cd(void) {
7070
return false;
7171
}
7272

73+
static bool is_basic(const char* buf, size_t size)
74+
{
75+
while (size) {
76+
uint8_t c = *buf++;
77+
if (c < 32 && c != '\t' && c != '\r' && c != '\n' && c != 27) {
78+
return false;
79+
}
80+
size--;
81+
}
82+
return true;
83+
}
84+
7385
static process_t* proc_create_common(const char* source, pid_t parent_pid, const char* csd, const char* program_name, const char* directory, size_t size)
7486
{
7587
process_t* newproc;
@@ -78,6 +90,9 @@ static process_t* proc_create_common(const char* source, pid_t parent_pid, const
7890
if (!source || !*source) {
7991
kprintf("Cannot start empty program.\n");
8092
return NULL;
93+
} else if (!is_basic(source, size)) {
94+
kprintf("This does not look like a BASIC program.\n");
95+
return NULL;
8196
}
8297

8398
newproc = kmalloc(sizeof(process_t));
@@ -106,6 +121,10 @@ static process_t* proc_create_common(const char* source, pid_t parent_pid, const
106121
newproc->cpu = logical_cpu_id();
107122
newproc->check_idle = NULL;
108123
newproc->idle_context = NULL;
124+
newproc->sched_next = NULL;
125+
newproc->sched_prev = NULL;
126+
newproc->global_next = NULL;
127+
newproc->global_prev = NULL;
109128

110129
if (!newproc->name || !newproc->directory || !newproc->csd) {
111130
basic_destroy(newproc->code);
@@ -122,23 +141,23 @@ static process_t* proc_create_common(const char* source, pid_t parent_pid, const
122141

123142
if (proc_list[newproc->cpu] == NULL) {
124143
proc_list[newproc->cpu] = newproc;
125-
newproc->next = NULL;
126-
newproc->prev = NULL;
144+
newproc->sched_next = NULL;
145+
newproc->sched_prev = NULL;
127146
} else {
128-
newproc->next = proc_list[newproc->cpu];
129-
newproc->prev = NULL;
130-
proc_list[newproc->cpu]->prev = newproc;
147+
newproc->sched_next = proc_list[newproc->cpu];
148+
newproc->sched_prev = NULL;
149+
proc_list[newproc->cpu]->sched_prev = newproc;
131150
proc_list[newproc->cpu] = newproc;
132151
}
133152

134153
if (combined_proc_list == NULL) {
135154
combined_proc_list = newproc;
136-
newproc->next = NULL;
137-
newproc->prev = NULL;
155+
newproc->global_next = NULL;
156+
newproc->global_prev = NULL;
138157
} else {
139-
newproc->next = combined_proc_list;
140-
newproc->prev = NULL;
141-
combined_proc_list->prev = newproc;
158+
newproc->global_next = combined_proc_list;
159+
newproc->global_prev = NULL;
160+
combined_proc_list->global_prev = newproc;
142161
combined_proc_list = newproc;
143162
}
144163

@@ -229,10 +248,14 @@ void proc_run(process_t* proc)
229248

230249
process_t* proc_find(pid_t pid)
231250
{
251+
process_t* proc = NULL;
232252
lock_spinlock(&combined_proc_lock);
233253
proc_id_t* id = hashmap_get(process_by_pid, &(proc_id_t){ .id = pid });
254+
if (id) {
255+
proc = id->proc;
256+
}
234257
unlock_spinlock(&combined_proc_lock);
235-
return id ? id->proc : NULL;
258+
return proc;
236259
}
237260

238261
bool proc_kill_id(pid_t id)
@@ -312,50 +335,28 @@ void proc_kill(process_t* proc)
312335
dprintf("proc_kill id %lu on cpu %d\n", proc->pid, cpu);
313336
lock_spinlock(&proc_lock[cpu]);
314337
lock_spinlock(&combined_proc_lock);
315-
for (process_t* cur = proc_list[cpu]; cur; cur = cur->next) {
316-
if (cur->pid == proc->pid) {
317-
if (proc->next == NULL && proc->prev == NULL) {
318-
// the only process!
319-
proc_list[cpu] = NULL;
320-
} else if (proc->prev == NULL && proc->next != NULL) {
321-
// first item
322-
proc_list[cpu] = proc->next;
323-
proc_list[cpu]->prev = NULL;
324-
} else if (proc->prev != NULL && proc->next == NULL) {
325-
// last item
326-
proc->prev->next = NULL;
327-
} else {
328-
// middle item
329-
proc->prev->next = proc->next;
330-
proc->next->prev = proc->prev;
331-
}
332338

333-
break;
334-
}
339+
if (proc->sched_prev == NULL) {
340+
proc_list[cpu] = proc->sched_next;
341+
} else {
342+
proc->sched_prev->sched_next = proc->sched_next;
343+
}
344+
if (proc->sched_next != NULL) {
345+
proc->sched_next->sched_prev = proc->sched_prev;
335346
}
336-
for (process_t* cur = combined_proc_list; cur; cur = cur->next) {
337-
if (cur->pid == proc->pid) {
338-
if (proc->next == NULL && proc->prev == NULL) {
339-
// the only process!
340-
combined_proc_list = NULL;
341-
} else if (proc->prev == NULL && proc->next != NULL) {
342-
// first item
343-
combined_proc_list = proc->next;
344-
combined_proc_list->prev = NULL;
345-
} else if (proc->prev != NULL && proc->next == NULL) {
346-
// last item
347-
proc->prev->next = NULL;
348-
} else {
349-
// middle item
350-
proc->prev->next = proc->next;
351-
proc->next->prev = proc->prev;
352-
}
353347

354-
break;
355-
}
348+
if (proc->global_prev == NULL) {
349+
combined_proc_list = proc->global_next;
350+
} else {
351+
proc->global_prev->global_next = proc->global_next;
352+
}
353+
if (proc->global_next != NULL) {
354+
proc->global_next->global_prev = proc->global_prev;
356355
}
357356

358-
proc_current[cpu] = proc_list[cpu];
357+
if (proc_current[cpu] == proc) {
358+
proc_current[cpu] = proc->sched_next ? proc->sched_next : proc_list[cpu];
359+
}
359360

360361
basic_destroy(proc->code);
361362
kfree_null(&proc->name);
@@ -385,7 +386,7 @@ pid_t proc_id(int64_t index)
385386
{
386387
int64_t tot = 0;
387388
lock_spinlock(&combined_proc_lock);
388-
for (process_t* cur = combined_proc_list; cur; cur = cur->next) {
389+
for (process_t* cur = combined_proc_list; cur; cur = cur->global_next) {
389390
if (tot == index) {
390391
unlock_spinlock(&combined_proc_lock);
391392
return cur->pid;
@@ -432,7 +433,7 @@ void halt_callback([[maybe_unused]] uint8_t isr, [[maybe_unused]] uint64_t error
432433
dprintf("Halting CPU#%d at request of HALT IPI\n", logical_cpu_id());
433434
register_shutdown_ap();
434435
interrupts_off();
435-
while(true) {
436+
while (true) {
436437
__asm__ __volatile__("hlt");
437438
}
438439
}
@@ -520,10 +521,10 @@ void proc_timer()
520521
return;
521522
}
522523

523-
if (proc_current[cpu]->next == NULL) {
524+
if (proc_current[cpu]->sched_next == NULL) {
524525
proc_current[cpu] = proc_list[cpu];
525526
} else {
526-
proc_current[cpu] = proc_current[cpu]->next;
527+
proc_current[cpu] = proc_current[cpu]->sched_next;
527528
}
528529

529530
unlock_spinlock(&proc_lock[cpu]);

0 commit comments

Comments
 (0)