Skip to content

Commit 516b82a

Browse files
committed
Avoid nested locking where possible; add scheduler preference to fix g_yield_t
Holding locks and calling other code can lead to the situation where processor 0 tries to lock ABBA and processor 1 tries BAAB, which causes a deadlock when the simultaneously reach the second lock. This pattern should avoid this.
1 parent 45c3195 commit 516b82a

File tree

16 files changed

+95
-70
lines changed

16 files changed

+95
-70
lines changed

kernel/inc/build_config.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
// version
4949
#define G_VERSION_MAJOR 0
5050
#define G_VERSION_MINOR 20
51-
#define G_VERSION_PATCH 0
51+
#define G_VERSION_PATCH 1
5252

5353
#define G_LOADER_VERSION_MAJOR 1
5454
#define G_LOADER_VERSION_MINOR 1

kernel/inc/shared/system/spinlock.hpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@
2121
#ifndef __SYSTEM_SPINLOCK__
2222
#define __SYSTEM_SPINLOCK__
2323

24-
typedef volatile int g_spinlock;
24+
typedef int g_spinlock;
2525

26-
#define G_SPINLOCK_ACQUIRE(lock) \
27-
while(!__sync_bool_compare_and_swap(&lock, 0, 1)) \
28-
asm volatile("pause");
26+
#define G_SPINLOCK_ACQUIRE(lock) \
27+
while(!__sync_bool_compare_and_swap(&lock, 0, 1)) \
28+
asm volatile("pause");
2929

30-
#define G_SPINLOCK_RELEASE(lock) lock = 0;
30+
#define G_SPINLOCK_RELEASE(lock) \
31+
do { __sync_synchronize(); lock = 0; } while(0)
3132

3233
#endif

kernel/src/kernel/calls/syscall_memory.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,16 +143,16 @@ void syscallShareMemory(g_task* task, g_syscall_share_mem* data)
143143

144144
g_virtual_address virtualRangeBase = addressRangePoolAllocate(targetProcess->virtualRangePool, pages,
145145
G_PROC_VIRTUAL_RANGE_FLAG_NONE);
146+
mutexRelease(&targetProcess->lock);
147+
146148
if(virtualRangeBase == 0)
147149
{
148150
logInfo(
149151
"%! task %i was unable to share memory area %h of size %h with task %i because there was no free virtual range",
150152
"syscall",
151153
task->id, memory, pages * G_PAGE_SIZE, targetProcess->main->id);
152-
mutexRelease(&targetProcess->lock);
153154
return;
154155
}
155-
mutexRelease(&targetProcess->lock);
156156

157157
for(uint32_t i = 0; i < pages; i++)
158158
{

kernel/src/kernel/calls/syscall_messaging.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,14 @@ void syscallMessageSend(g_task* task, g_syscall_send_message* data)
2929
G_MESSAGE_SEND_STATUS_QUEUE_FULL &&
3030
data->mode == G_MESSAGE_SEND_MODE_BLOCKING)
3131
{
32+
INTERRUPTS_PAUSE;
3233
mutexAcquire(&task->lock);
3334
task->status = G_TASK_STATUS_WAITING;
3435
task->waitsFor = "message-send";
35-
messageWaitForSend(task->id, data->receiver);
3636
mutexRelease(&task->lock);
37+
messageWaitForSend(task->id, data->receiver);
3738
taskingYield();
39+
INTERRUPTS_RESUME;
3840
}
3941
messageUnwaitForSend(task->id, data->receiver);
4042
}
@@ -55,11 +57,13 @@ void syscallMessageReceive(g_task* task, g_syscall_receive_message* data)
5557
// break;
5658
// }
5759

60+
INTERRUPTS_PAUSE;
5861
mutexAcquire(&task->lock);
5962
task->status = G_TASK_STATUS_WAITING;
6063
task->waitsFor = "message-recv";
6164
mutexRelease(&task->lock);
6265
taskingYield();
66+
INTERRUPTS_RESUME;
6367
}
6468
}
6569

kernel/src/kernel/calls/syscall_tasking.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,14 @@
3232

3333
void syscallSleep(g_task* task, g_syscall_sleep* data)
3434
{
35+
INTERRUPTS_PAUSE;
3536
mutexAcquire(&task->lock);
3637
task->status = G_TASK_STATUS_WAITING;
3738
task->waitsFor = "sleeps";
38-
clockWaitForTime(task->id, clockGetLocal()->time + data->milliseconds);
3939
mutexRelease(&task->lock);
40+
clockWaitForTime(task->id, clockGetLocal()->time + data->milliseconds);
4041
taskingYield();
42+
INTERRUPTS_RESUME;
4143
}
4244

4345
void syscallYield(g_task* task, g_syscall_yield* data)
@@ -85,12 +87,14 @@ void syscallGetProcessIdForTaskId(g_task* task, g_syscall_get_pid_for_tid* data)
8587

8688
void syscallJoin(g_task* task, g_syscall_join* data)
8789
{
90+
INTERRUPTS_PAUSE;
8891
mutexAcquire(&task->lock);
8992
task->status = G_TASK_STATUS_WAITING;
9093
task->waitsFor = "sleeps";
91-
taskingWaitForExit(data->taskId, task->id);
9294
mutexRelease(&task->lock);
95+
taskingWaitForExit(data->taskId, task->id);
9396
taskingYield();
97+
INTERRUPTS_RESUME;
9498
}
9599

96100
void syscallSpawn(g_task* task, g_syscall_spawn* data)
@@ -141,12 +145,14 @@ void syscallKill(g_task* task, g_syscall_kill* data)
141145
g_task* target = taskingGetById(data->pid);
142146
if(target)
143147
{
148+
INTERRUPTS_PAUSE;
144149
mutexAcquire(&target->lock);
145150
data->status = G_KILL_STATUS_SUCCESSFUL;
146151
target->process->main->status = G_TASK_STATUS_DEAD;
147-
waitQueueWake(&target->waitersJoin);
148152
mutexRelease(&target->lock);
153+
waitQueueWake(&target->waitersJoin);
149154
taskingYield();
155+
INTERRUPTS_RESUME;
150156
}
151157
else
152158
{
@@ -156,8 +162,6 @@ void syscallKill(g_task* task, g_syscall_kill* data)
156162

157163
void syscallCreateTask(g_task* task, g_syscall_create_task* data)
158164
{
159-
mutexAcquire(&task->process->lock);
160-
161165
g_task* newTask = taskingCreateTask((g_virtual_address) data->initialEntry, task->process,
162166
task->process->main->securityLevel);
163167
if(newTask)
@@ -172,8 +176,6 @@ void syscallCreateTask(g_task* task, g_syscall_create_task* data)
172176
{
173177
data->status = G_CREATE_TASK_STATUS_FAILED;
174178
}
175-
176-
mutexRelease(&task->process->lock);
177179
}
178180

179181
void syscallGetTaskEntry(g_task* task, g_syscall_get_task_entry* data)

kernel/src/kernel/filesystem/filesystem.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,12 +411,14 @@ g_fs_read_status filesystemRead(g_task* task, g_fd fd, uint8_t* buffer, uint64_t
411411
panic("%! task %i tried to wait for file %i but delegate didn't provide wait-for-read implementation",
412412
"filesytem", task->id, node->id);
413413

414+
INTERRUPTS_PAUSE;
414415
mutexAcquire(&task->lock);
415416
task->status = G_TASK_STATUS_WAITING;
416417
task->waitsFor = "read";
417-
delegate->waitForRead(task->id, node);
418418
mutexRelease(&task->lock);
419+
delegate->waitForRead(task->id, node);
419420
taskingYield();
421+
INTERRUPTS_RESUME;
420422

421423
// TODO
422424
if(node->nonInterruptible && clockHasTimedOut(task->id))
@@ -503,12 +505,14 @@ g_fs_write_status filesystemWrite(g_task* task, g_fd fd, uint8_t* buffer, uint64
503505
panic("%! task %i tried to wait for file %i but delegate didn't provide wait-for-write implementation",
504506
"filesytem", task->id, node->id);
505507

508+
INTERRUPTS_PAUSE;
506509
mutexAcquire(&task->lock);
507510
task->status = G_TASK_STATUS_WAITING;
508511
task->waitsFor = "write";
509-
delegate->waitForWrite(task->id, node);
510512
mutexRelease(&task->lock);
513+
delegate->waitForWrite(task->id, node);
511514
taskingYield();
515+
INTERRUPTS_RESUME;
512516
}
513517
if(wrote > 0)
514518
{

kernel/src/kernel/ipc/message.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,17 +161,13 @@ void messageTaskRemoved(g_tid task)
161161
void messageWaitForSend(g_tid sender, g_tid receiver)
162162
{
163163
g_message_queue* queue = _messageGetQueue(receiver);
164-
mutexAcquire(&queue->lock);
165164
waitQueueAdd(&queue->waitersSend, sender);
166-
mutexRelease(&queue->lock);
167165
}
168166

169167
void messageUnwaitForSend(g_tid sender, g_tid receiver)
170168
{
171169
g_message_queue* queue = _messageGetQueue(receiver);
172-
mutexAcquire(&queue->lock);
173170
waitQueueRemove(&queue->waitersSend, sender);
174-
mutexRelease(&queue->lock);
175171
}
176172

177173
void _messageWakeWaitingReceiver(g_message_queue* queue)

kernel/src/kernel/ipc/pipes.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,9 +264,7 @@ void pipeWaitForRead(g_tid task, g_fs_phys_id pipeId)
264264
if(!pipe)
265265
return;
266266

267-
mutexAcquire(&pipe->lock);
268267
waitQueueAdd(&pipe->waitersRead, task);
269-
mutexRelease(&pipe->lock);
270268
}
271269

272270
void pipeWaitForWrite(g_tid task, g_fs_phys_id pipeId)
@@ -275,7 +273,5 @@ void pipeWaitForWrite(g_tid task, g_fs_phys_id pipeId)
275273
if(!pipe)
276274
return;
277275

278-
mutexAcquire(&pipe->lock);
279276
waitQueueAdd(&pipe->waitersWrite, task);
280-
mutexRelease(&pipe->lock);
281277
}

kernel/src/kernel/system/interrupts/interrupts.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ extern "C" volatile g_processor_state* _interruptHandler(volatile g_processor_st
9191
if(irq == 0) // Timer
9292
{
9393
clockUpdate();
94-
taskingSchedule();
94+
taskingSchedule(true);
9595
}
9696
else
9797
{

kernel/src/kernel/system/processor/processor.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,3 +313,8 @@ const uint8_t* processorGetInitialFpuState()
313313
{
314314
return _processorGetCurrent()->fpu.initialState;
315315
}
316+
317+
bool processorIsBsp()
318+
{
319+
return processorGetCurrentId() == 0;
320+
}

0 commit comments

Comments
 (0)