Skip to content

Commit aed8e8c

Browse files
committed
Implement a generic taskingWait function to avoid explicitly dealing with correct interrupt disabling/locking order everywhere; add g_task_await_by_id to allow waiting until a task registers with an identifier
1 parent cbc2ea4 commit aed8e8c

18 files changed

+296
-134
lines changed

kernel/src/kernel/calls/syscall.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ void syscallRegisterAll()
110110
_syscallRegister(G_SYSCALL_GET_MILLISECONDS, (g_syscall_handler) syscallGetMilliseconds);
111111
_syscallRegister(G_SYSCALL_DUMP, (g_syscall_handler) syscallDump);
112112
_syscallRegister(G_SYSCALL_GET_NANOSECONDS, (g_syscall_handler) syscallGetNanoseconds);
113+
_syscallRegister(G_SYSCALL_AWAIT_TASK_BY_IDENTIFIER, (g_syscall_handler) syscallAwaitTaskByIdentifier);
113114

114115
// Memory
115116
_syscallRegister(G_SYSCALL_LOWER_MEMORY_ALLOCATE, (g_syscall_handler) syscallLowerMemoryAllocate, true);
@@ -129,7 +130,7 @@ void syscallRegisterAll()
129130
// Messages
130131
_syscallRegister(G_SYSCALL_MESSAGE_SEND, (g_syscall_handler) syscallMessageSend);
131132
_syscallRegister(G_SYSCALL_MESSAGE_RECEIVE, (g_syscall_handler) syscallMessageReceive);
132-
_syscallRegister(G_SYSCALL_MESSAGE_NEXT_TXID, (g_syscall_handler) syscallMessageNextTxid);
133+
_syscallRegister(G_SYSCALL_MESSAGE_NEXT_TXID, (g_syscall_handler) syscallMessageNextTxId);
133134

134135
// Filesystem
135136
_syscallRegister(G_SYSCALL_FS_OPEN, (g_syscall_handler) syscallFsOpen, true);

kernel/src/kernel/calls/syscall_messaging.cpp

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,17 @@
2121
#include "kernel/calls/syscall_messaging.hpp"
2222
#include "kernel/ipc/message.hpp"
2323
#include "kernel/tasking/user_mutex.hpp"
24-
#include "kernel/system/interrupts/interrupts.hpp"
2524

2625
void syscallMessageSend(g_task* task, g_syscall_send_message* data)
2726
{
2827
while((data->status = messageSend(task->id, data->receiver, data->buffer, data->length, data->transaction)) ==
2928
G_MESSAGE_SEND_STATUS_QUEUE_FULL &&
3029
data->mode == G_MESSAGE_SEND_MODE_BLOCKING)
3130
{
32-
INTERRUPTS_PAUSE;
33-
mutexAcquire(&task->lock);
34-
task->status = G_TASK_STATUS_WAITING;
35-
task->waitsFor = "message-send";
36-
mutexRelease(&task->lock);
37-
messageWaitForSend(task->id, data->receiver);
38-
taskingYield();
39-
INTERRUPTS_RESUME;
31+
taskingWait(task, __func__, [task, data]()
32+
{
33+
messageWaitForSend(task->id, data->receiver);
34+
});
4035
}
4136
messageUnwaitForSend(task->id, data->receiver);
4237
}
@@ -47,27 +42,17 @@ void syscallMessageReceive(g_task* task, g_syscall_receive_message* data)
4742
G_MESSAGE_RECEIVE_STATUS_QUEUE_EMPTY &&
4843
data->mode == G_MESSAGE_RECEIVE_MODE_BLOCKING)
4944
{
50-
/**
51-
* TODO: "Break condition" doesn't work anymore since there is no connection between mutexes and
52-
* the message wait queues. This must be somehow connected and the task waken when required.
53-
*/
45+
// TODO: "Break condition" can't work anymore:
5446
// if(data->break_condition && userMutexAcquire(task, data->break_condition, true, false))
5547
//{
5648
// data->status = G_MESSAGE_RECEIVE_STATUS_INTERRUPTED;
5749
// break;
5850
// }
59-
60-
INTERRUPTS_PAUSE;
61-
mutexAcquire(&task->lock);
62-
task->status = G_TASK_STATUS_WAITING;
63-
task->waitsFor = "message-recv";
64-
mutexRelease(&task->lock);
65-
taskingYield();
66-
INTERRUPTS_RESUME;
51+
taskingWait(task, __func__);
6752
}
6853
}
6954

70-
void syscallMessageNextTxid(g_task* task, g_syscall_message_next_txid* data)
55+
void syscallMessageNextTxId(g_task* task, g_syscall_message_next_txid* data)
7156
{
7257
data->transaction = messageNextTxId();
7358
}

kernel/src/kernel/calls/syscall_messaging.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,6 @@ void syscallMessageSend(g_task* task, g_syscall_send_message* data);
2828

2929
void syscallMessageReceive(g_task* task, g_syscall_receive_message* data);
3030

31-
void syscallMessageNextTxid(g_task * task, g_syscall_message_next_txid * data);
31+
void syscallMessageNextTxId(g_task* task, g_syscall_message_next_txid* data);
3232

3333
#endif

kernel/src/kernel/calls/syscall_system.cpp

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2020

2121
#include "kernel/calls/syscall_system.hpp"
22-
#include "kernel/system/interrupts/interrupts.hpp"
2322
#include "kernel/system/interrupts/requests.hpp"
2423
#include "kernel/system/processor/processor.hpp"
2524
#include "kernel/tasking/clock.hpp"
@@ -125,19 +124,12 @@ void syscallAwaitIrq(g_task* task, g_syscall_await_irq* data)
125124
}
126125

127126
requestsSetHandlerTask(data->irq, task->id);
128-
129-
INTERRUPTS_PAUSE;
130-
mutexAcquire(&task->lock);
131-
task->status = G_TASK_STATUS_WAITING;
132-
task->waitsFor = "irq";
133-
mutexRelease(&task->lock);
134-
135-
if(data->timeout)
127+
taskingWait(task, __func__, [data, task]()
136128
{
137-
clockUnwaitForTime(task->id);
138-
clockWaitForTime(task->id, clockGetLocal()->time + data->timeout);
139-
}
140-
141-
taskingYield();
142-
INTERRUPTS_RESUME;
129+
if(data->timeout)
130+
{
131+
clockUnwaitForTime(task->id);
132+
clockWaitForTime(task->id, clockGetLocal()->time + data->timeout);
133+
}
134+
});
143135
}

kernel/src/kernel/calls/syscall_tasking.cpp

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,10 @@
3333

3434
void syscallSleep(g_task* task, g_syscall_sleep* data)
3535
{
36-
INTERRUPTS_PAUSE;
37-
mutexAcquire(&task->lock);
38-
task->status = G_TASK_STATUS_WAITING;
39-
task->waitsFor = "sleeps";
40-
mutexRelease(&task->lock);
41-
clockWaitForTime(task->id, clockGetLocal()->time + data->milliseconds);
42-
taskingYield();
43-
INTERRUPTS_RESUME;
36+
taskingWait(task, __func__, [task, data]()
37+
{
38+
clockWaitForTime(task->id, clockGetLocal()->time + data->milliseconds);
39+
});
4440
}
4541

4642
void syscallYield(g_task* task, g_syscall_yield* data)
@@ -88,14 +84,10 @@ void syscallGetProcessIdForTaskId(g_task* task, g_syscall_get_pid_for_tid* data)
8884

8985
void syscallJoin(g_task* task, g_syscall_join* data)
9086
{
91-
INTERRUPTS_PAUSE;
92-
mutexAcquire(&task->lock);
93-
task->status = G_TASK_STATUS_WAITING;
94-
task->waitsFor = "join";
95-
mutexRelease(&task->lock);
96-
taskingWaitForExit(data->taskId, task->id);
97-
taskingYield();
98-
INTERRUPTS_RESUME;
87+
taskingWait(task, __func__, [task ,data]()
88+
{
89+
taskingWaitForExit(data->taskId, task->id);
90+
});
9991
}
10092

10193
void syscallSpawn(g_task* task, g_syscall_spawn* data)
@@ -175,7 +167,8 @@ void syscallCreateTask(g_task* task, g_syscall_create_task* data)
175167
if(data->coreAffinity == G_TASK_CORE_AFFINITY_NONE)
176168
{
177169
taskingAssignBalanced(newTask);
178-
} else
170+
}
171+
else
179172
{
180173
taskingAssignOnCore(data->coreAffinity, newTask);
181174
}
@@ -293,6 +286,21 @@ void syscallRegisterTaskIdentifier(g_task* task, g_syscall_task_id_register* dat
293286
data->successful = taskingDirectoryRegister(data->identifier, task->id, task->securityLevel);
294287
}
295288

289+
void syscallAwaitTaskByIdentifier(g_task* task, g_syscall_task_await_by_id* data)
290+
{
291+
g_tid target;
292+
while((target = taskingDirectoryGet(data->identifier)) == G_TID_NONE)
293+
{
294+
taskingWait(task, __func__, [data, task]()
295+
{
296+
clockWaitForTime(task->id, clockGetLocal()->time + 100);
297+
taskingDirectoryWaitForRegister(data->identifier, task->id);
298+
});
299+
clockUnwaitForTime(task->id);
300+
}
301+
data->task = target;
302+
}
303+
296304
void syscallGetTaskForIdentifier(g_task* task, g_syscall_task_id_get* data)
297305
{
298306
data->resultTaskId = taskingDirectoryGet(data->identifier);

kernel/src/kernel/calls/syscall_tasking.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ void syscallSetWorkingDirectory(g_task* task, g_syscall_set_working_directory* d
7070

7171
void syscallRegisterTaskIdentifier(g_task* task, g_syscall_task_id_register* data);
7272

73+
void syscallAwaitTaskByIdentifier(g_task* task, g_syscall_task_await_by_id* data);
74+
7375
void syscallGetTaskForIdentifier(g_task* task, g_syscall_task_id_get* data);
7476

7577
void syscallDump();

kernel/src/kernel/memory/heap.cpp

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -108,26 +108,6 @@ uint32_t heapGetUsedAmount()
108108
return heapAmountInUse;
109109
}
110110

111-
void* operator new(size_t size)
112-
{
113-
return heapAllocate(size);
114-
}
115-
116-
void* operator new[](size_t size)
117-
{
118-
return heapAllocate(size);
119-
}
120-
121-
void operator delete(void* m)
122-
{
123-
heapFree(m);
124-
}
125-
126-
void operator delete[](void* m)
127-
{
128-
heapFree(m);
129-
}
130-
131111
bool _heapExpand()
132112
{
133113
if(heapEnd + G_KERNEL_HEAP_EXPAND_STEP > G_KERNEL_HEAP_END)
@@ -154,4 +134,4 @@ bool _heapExpand()
154134
logDebug("%! expanded to end %h (%ikb in use)", "kernheap", heapEnd, heapAmountInUse / 1024);
155135

156136
return true;
157-
}
137+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2+
* *
3+
* Ghost, a micro-kernel based operating system for the x86 architecture *
4+
* Copyright (C) 2015, Max Schlüssel <[email protected]> *
5+
* *
6+
* This program is free software: you can redistribute it and/or modify *
7+
* it under the terms of the GNU General Public License as published by *
8+
* the Free Software Foundation, either version 3 of the License, or *
9+
* (at your option) any later version. *
10+
* *
11+
* This program is distributed in the hope that it will be useful, *
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14+
* GNU General Public License for more details. *
15+
* *
16+
* You should have received a copy of the GNU General Public License *
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
18+
* *
19+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20+
21+
#include "kernel/memory/heap.hpp"
22+
#include "shared/panic.hpp"
23+
24+
// The functions in this file are implemented as defined in the Itanium C++ ABI
25+
// standard. These functions are required by GCC for special cases, see the
26+
// individual documentation for details.
27+
28+
namespace std
29+
{
30+
[[noreturn]] void __throw_bad_function_call()
31+
{
32+
panic("bad function call");
33+
}
34+
}
35+
36+
void* operator new(size_t size, void* ptr) noexcept
37+
{
38+
return ptr;
39+
}
40+
41+
void* operator new[](size_t size, void* ptr) noexcept
42+
{
43+
return ptr;
44+
}
45+
46+
void* operator new(size_t size)
47+
{
48+
return heapAllocate(size);
49+
}
50+
51+
void* operator new[](size_t size)
52+
{
53+
return heapAllocate(size);
54+
}
55+
56+
void operator delete(void* m)
57+
{
58+
heapFree(m);
59+
}
60+
61+
void operator delete[](void* m)
62+
{
63+
heapFree(m);
64+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2+
* *
3+
* Ghost, a micro-kernel based operating system for the x86 architecture *
4+
* Copyright (C) 2015, Max Schlüssel <[email protected]> *
5+
* *
6+
* This program is free software: you can redistribute it and/or modify *
7+
* it under the terms of the GNU General Public License as published by *
8+
* the Free Software Foundation, either version 3 of the License, or *
9+
* (at your option) any later version. *
10+
* *
11+
* This program is distributed in the hope that it will be useful, *
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14+
* GNU General Public License for more details. *
15+
* *
16+
* You should have received a copy of the GNU General Public License *
17+
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
18+
* *
19+
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
20+
21+
#ifndef __ITANIUM_CXX_ABI_SUPPORT__
22+
#define __ITANIUM_CXX_ABI_SUPPORT__
23+
24+
#include <bits/std_function.h>
25+
26+
// Must be defined because we use -ffreestanding which causes these to not be
27+
// available when trying to use std::function
28+
void* operator new(size_t size, void* ptr) noexcept;
29+
void* operator new[](size_t size, void* ptr) noexcept;
30+
31+
#endif

kernel/src/kernel/tasking/tasking.cpp

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -513,17 +513,11 @@ g_spawn_result taskingSpawn(g_fd fd, g_security_level securityLevel)
513513
taskingStateReset(child, (g_address) &taskingSpawnEntry, G_SECURITY_LEVEL_KERNEL);
514514

515515
// Start thread & wait for spawn to finish
516-
INTERRUPTS_PAUSE;
517-
child->spawnFinished = false;
518-
519-
mutexAcquire(&parent->lock);
520-
parent->status = G_TASK_STATUS_WAITING;
521-
parent->waitsFor = "spawn";
522-
mutexRelease(&parent->lock);
523-
524-
taskingAssignBalanced(child);
525-
taskingYield();
526-
INTERRUPTS_RESUME;
516+
taskingWait(parent, __func__, [child]()
517+
{
518+
child->spawnFinished = false;
519+
taskingAssignBalanced(child);
520+
});
527521

528522
// Take result
529523
res.status = res.process->spawnArgs->status;
@@ -569,16 +563,12 @@ void taskingFinalizeSpawn(g_task* task)
569563
task->securityLevel = process->spawnArgs->securityLevel;
570564
taskingStateReset(task, process->spawnArgs->entry, task->securityLevel);
571565

572-
task->spawnFinished = true;
573-
auto parent = taskingGetById(process->spawnArgs->parent);
574-
taskingWake(parent);
575-
576-
mutexAcquire(&task->lock);
577-
task->status = G_TASK_STATUS_WAITING;
578-
task->waitsFor = "wake-after-spawn";
579-
mutexRelease(&task->lock);
580-
taskingYield();
581-
INTERRUPTS_RESUME;
566+
taskingWait(task, __func__, [task, process]()
567+
{
568+
task->spawnFinished = true;
569+
auto parent = taskingGetById(process->spawnArgs->parent);
570+
taskingWake(parent);
571+
});
582572
}
583573

584574
void taskingWaitForExit(g_tid joinedTid, g_tid waiter)
@@ -602,3 +592,16 @@ void taskingWake(g_task* task)
602592
mutexRelease(&task->lock);
603593
}
604594
}
595+
596+
void taskingWait(g_task* task, const char* debugName, const std::function<void ()>& beforeYield)
597+
{
598+
INTERRUPTS_PAUSE;
599+
mutexAcquire(&task->lock);
600+
task->status = G_TASK_STATUS_WAITING;
601+
task->waitsFor = debugName;
602+
mutexRelease(&task->lock);
603+
if(beforeYield)
604+
beforeYield();
605+
taskingYield();
606+
INTERRUPTS_RESUME;
607+
}

0 commit comments

Comments
 (0)