Skip to content

Commit 45c672f

Browse files
committed
Fix issue with wake on spawn, improve overall wake-handling
1 parent aa0d456 commit 45c672f

File tree

8 files changed

+50
-66
lines changed

8 files changed

+50
-66
lines changed

kernel/src/kernel/ipc/message.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -171,13 +171,7 @@ void messageUnwaitForSend(g_tid sender, g_tid receiver)
171171
void _messageWakeWaitingReceiver(g_message_queue* queue)
172172
{
173173
g_task* task = taskingGetById(queue->task);
174-
if(task)
175-
{
176-
mutexAcquire(&task->lock);
177-
if(task->status == G_TASK_STATUS_WAITING)
178-
task->status = G_TASK_STATUS_RUNNING;
179-
mutexRelease(&task->lock);
180-
}
174+
taskingWake(task);
181175
}
182176

183177
void _messageRemoveFromQueue(g_message_queue* queue, g_message_header* message)

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

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,7 @@ void requestsHandle(g_task* currentTask, uint8_t irq)
6060
if(!handlerTask)
6161
return;
6262

63-
mutexAcquire(&handlerTask->lock);
64-
if(handlerTask->status == G_TASK_STATUS_WAITING)
65-
handlerTask->status = G_TASK_STATUS_RUNNING;
66-
mutexRelease(&handlerTask->lock);
67-
63+
taskingWake(handlerTask);
6864
taskingSetCurrent(handlerTask);
6965

7066
// Once the handler has finished, let the scheduler go back to interrupted task

kernel/src/kernel/tasking/clock.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,7 @@ void clockWakeWaiters(g_clock_local* local)
103103
while(local->waiters && local->time >= local->waiters->wakeTime)
104104
{
105105
g_task* task = taskingGetById(local->waiters->task);
106-
if(task)
107-
{
108-
mutexAcquire(&task->lock);
109-
task->status = G_TASK_STATUS_RUNNING;
110-
mutexRelease(&task->lock);
111-
}
106+
taskingWake(task);
112107

113108
auto next = local->waiters->next;
114109
heapFree(local->waiters);

kernel/src/kernel/tasking/task.hpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ struct g_task_entry
182182

183183
struct g_process_spawn_arguments
184184
{
185+
g_tid parent;
185186
g_fd fd;
186187
g_security_level securityLevel;
187188
g_address entry;
@@ -268,11 +269,6 @@ struct g_process
268269
*/
269270
g_process_spawn_arguments* spawnArgs;
270271

271-
/**
272-
* List of tasks that wait for the result of spawning.
273-
*/
274-
g_wait_queue waitersSpawn;
275-
276272
/**
277273
* List of on-demand file-to-memory mappings.
278274
*/

kernel/src/kernel/tasking/tasking.cpp

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,10 @@ void taskingDestroyProcess(g_process* process)
370370

371371
g_task* taskingCreateTask(g_virtual_address eip, g_process* process, g_security_level level)
372372
{
373-
g_task* task = (g_task*) heapAllocateClear(sizeof(g_task));
373+
auto task = (g_task*) heapAllocateClear(sizeof(g_task));
374+
if(!task)
375+
return nullptr;
376+
374377
_taskingInitializeTask(task, process, level);
375378
task->type = G_TASK_TYPE_DEFAULT;
376379

@@ -479,13 +482,13 @@ void taskingProcessKillAllTasks(g_pid pid)
479482

480483
g_spawn_result taskingSpawn(g_fd fd, g_security_level securityLevel)
481484
{
482-
g_task* caller = taskingGetCurrentTask();
485+
g_task* parent = taskingGetCurrentTask();
483486

484487
// Create target process & task
485-
g_spawn_result res;
488+
g_spawn_result res{};
486489
res.process = taskingCreateProcess(securityLevel);
487-
g_task* newTask = taskingCreateTask(0, res.process, securityLevel);
488-
if(!newTask)
490+
g_task* child = taskingCreateTask(0, res.process, securityLevel);
491+
if(!child)
489492
{
490493
logInfo("%! failed to create main thread to spawn binary", "elf");
491494
res.status = G_SPAWN_STATUS_TASKING_ERROR;
@@ -494,42 +497,35 @@ g_spawn_result taskingSpawn(g_fd fd, g_security_level securityLevel)
494497

495498
// Clone FD to target process
496499
g_fd targetFd;
497-
auto cloneStat = filesystemProcessCloneDescriptor(caller->process->id, fd, res.process->id, G_FD_NONE, &targetFd);
500+
auto cloneStat = filesystemProcessCloneDescriptor(parent->process->id, fd, res.process->id, G_FD_NONE, &targetFd);
498501
if(cloneStat != G_FS_CLONEFD_SUCCESSFUL)
499502
{
500-
logInfo("%! failed to clone executable FD to target process", "elf");
503+
logInfo("%! failed to clone binary FD to target process", "elf");
501504
res.status = G_SPAWN_STATUS_IO_ERROR;
502505
return res;
503506
}
504507

505508
// Provide spawn arguments
506509
res.process->spawnArgs = (g_process_spawn_arguments*) heapAllocateClear(sizeof(g_process_spawn_arguments));
510+
res.process->spawnArgs->parent = parent->id;
507511
res.process->spawnArgs->fd = targetFd;
508512
res.process->spawnArgs->securityLevel = securityLevel;
509513

510514
// Set kernel-level entry
511-
taskingStateReset(newTask, (g_address) &taskingSpawnEntry, G_SECURITY_LEVEL_KERNEL);
515+
taskingStateReset(child, (g_address) &taskingSpawnEntry, G_SECURITY_LEVEL_KERNEL);
512516

513517
// Start thread & wait for spawn to finish
514-
newTask->spawnFinished = false;
518+
INTERRUPTS_PAUSE;
519+
child->spawnFinished = false;
515520

516-
mutexAcquire(&caller->lock);
517-
caller->status = G_TASK_STATUS_WAITING;
518-
caller->waitsFor = "spawn";
519-
mutexRelease(&caller->lock);
520-
waitQueueAdd(&res.process->waitersSpawn, caller->id);
521-
taskingAssignBalanced(newTask);
521+
mutexAcquire(&parent->lock);
522+
parent->status = G_TASK_STATUS_WAITING;
523+
parent->waitsFor = "spawn";
524+
mutexRelease(&parent->lock);
522525

523-
while(!newTask->spawnFinished)
524-
{
525-
INTERRUPTS_PAUSE;
526-
mutexAcquire(&caller->lock);
527-
caller->status = G_TASK_STATUS_WAITING;
528-
caller->waitsFor = "spawn-rep";
529-
mutexRelease(&caller->lock);
530-
taskingYield();
531-
INTERRUPTS_RESUME;
532-
}
526+
taskingAssignBalanced(child);
527+
taskingYield();
528+
INTERRUPTS_RESUME;
533529

534530
// Take result
535531
res.status = res.process->spawnArgs->status;
@@ -556,7 +552,8 @@ void taskingSpawnEntry()
556552
if(loadRes.status != G_SPAWN_STATUS_SUCCESSFUL)
557553
{
558554
logInfo("%! failed to load binary to current address space", "elf");
559-
waitQueueWake(&process->waitersSpawn);
555+
auto parent = taskingGetById(process->spawnArgs->parent);
556+
taskingWake(parent);
560557
taskingExit();
561558
}
562559

@@ -569,16 +566,18 @@ void taskingSpawnEntry()
569566

570567
void taskingFinalizeSpawn(g_task* task)
571568
{
569+
INTERRUPTS_PAUSE;
572570
auto process = task->process;
573571
task->securityLevel = process->spawnArgs->securityLevel;
574572
taskingStateReset(task, process->spawnArgs->entry, task->securityLevel);
575-
waitQueueWake(&process->waitersSpawn);
576573

577-
INTERRUPTS_PAUSE;
574+
task->spawnFinished = true;
575+
auto parent = taskingGetById(process->spawnArgs->parent);
576+
taskingWake(parent);
577+
578578
mutexAcquire(&task->lock);
579579
task->status = G_TASK_STATUS_WAITING;
580580
task->waitsFor = "wake-after-spawn";
581-
task->spawnFinished = true;
582581
mutexRelease(&task->lock);
583582
taskingYield();
584583
INTERRUPTS_RESUME;
@@ -594,3 +593,14 @@ void taskingWaitForExit(g_tid joinedTid, g_tid waiter)
594593
waitQueueAdd(&task->waitersJoin, waiter);
595594
mutexRelease(&task->process->lock);
596595
}
596+
597+
void taskingWake(g_task* task)
598+
{
599+
if(task)
600+
{
601+
mutexAcquire(&task->lock);
602+
if(task->status == G_TASK_STATUS_WAITING)
603+
task->status = G_TASK_STATUS_RUNNING;
604+
mutexRelease(&task->lock);
605+
}
606+
}

kernel/src/kernel/tasking/tasking.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,4 +252,9 @@ void taskingFinalizeSpawn(g_task* task);
252252
*/
253253
void taskingWaitForExit(g_tid task, g_tid waiter);
254254

255+
/**
256+
* Wakes the task.
257+
*/
258+
void taskingWake(g_task* task);
259+
255260
#endif

kernel/src/kernel/tasking/user_mutex.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -255,13 +255,7 @@ void _userMutexWakeWaitingTasks(g_user_mutex_entry* entry)
255255
while(waiter)
256256
{
257257
g_task* wakeTask = taskingGetById(waiter->task);
258-
if(wakeTask)
259-
{
260-
mutexAcquire(&wakeTask->lock);
261-
if(wakeTask->status == G_TASK_STATUS_WAITING)
262-
wakeTask->status = G_TASK_STATUS_RUNNING;
263-
mutexRelease(&wakeTask->lock);
264-
}
258+
taskingWake(wakeTask);
265259

266260
auto next = waiter->next;
267261
heapFree(waiter);

kernel/src/kernel/utils/wait_queue.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,7 @@ void waitQueueWake(g_wait_queue* queue)
7474
while(waiter)
7575
{
7676
g_task* task = taskingGetById(waiter->task);
77-
if(task)
78-
{
79-
mutexAcquire(&task->lock);
80-
if(task->status == G_TASK_STATUS_WAITING)
81-
task->status = G_TASK_STATUS_RUNNING;
82-
mutexRelease(&task->lock);
83-
}
77+
taskingWake(task);
8478

8579
auto next = waiter->next;
8680
heapFree(waiter);

0 commit comments

Comments
 (0)