Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
chickadee
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Incidents
Environments
Packages & Registries
Packages & Registries
Package Registry
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Matija Benko
chickadee
Commits
de1f3b4f
Commit
de1f3b4f
authored
Apr 22, 2021
by
benkma
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Lab 08 Completed
parent
8bef8dfb
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
234 additions
and
30 deletions
+234
-30
k-alloc.cc
k-alloc.cc
+201
-23
kernel.cc
kernel.cc
+15
-2
kernel.hh
kernel.hh
+1
-0
lib.hh
lib.hh
+1
-1
p-allocator.cc
p-allocator.cc
+10
-4
u-lib.hh
u-lib.hh
+6
-0
No files found.
k-alloc.cc
View file @
de1f3b4f
#include "lib.hh"
#include "kernel.hh"
#include "k-lock.hh"
static
spinlock
page_lock
;
static
uintptr_t
next_free_pa
;
static
spinlock
mem_lock
;
//static uintptr_t next_free_pa;
const
int
NUMBER_OF_FRAMES
=
MEMSIZE_PHYSICAL
/
PAGESIZE
;
// 2MB / 4KB = 512 Frames
const
int
MIN_ORDER
=
12
;
// 2^12 = 4KB
const
int
MAX_ORDER
=
21
;
// 2^21 = 2MB
struct
block
{
bool
isFree
;
int
order
;
void
*
ka
;
list_links
link_
;
static
block
*
blockAtKernelAddress
(
void
*
ka
);
static
int
minOrderForBlockOfSize
(
size_t
sz
);
static
void
split
(
int
order
);
block
*
buddy
();
void
cloalesce
();
int
frameNumber
()
{
return
ka2pa
(
ka
)
/
PAGESIZE
;};
};
block
blocks
[
NUMBER_OF_FRAMES
];
list
<
block
,
&
block
::
link_
>
freeBlockList
[
MAX_ORDER
+
1
];
void
test_kalloc
();
//DEBUGGING
#pragma GCC push_options
#pragma GCC optimize("O0")
block
*
block
::
buddy
()
{
void
*
pBuddy
=
(
void
*
)((
uint64_t
)
ka
^
(
1
<<
order
));
return
blockAtKernelAddress
(
pBuddy
);
}
int
block
::
minOrderForBlockOfSize
(
size_t
sz
)
{
int
order
=
msb
(
sz
-
1
);
if
(
order
<
MIN_ORDER
)
{
order
=
MIN_ORDER
;
}
return
order
;
}
block
*
block
::
blockAtKernelAddress
(
void
*
ka
)
{
uint64_t
pa
=
ka2pa
(
ka
);
int
frameNumber
=
pa
/
PAGESIZE
;
return
&
blocks
[
frameNumber
];
}
// init_kalloc
// Initialize stuff needed by `kalloc`. Called from `init_hardware`,
// after `physical_ranges` is initialized.
// 1-3: 3 * 4 = 4K = 12K
// 9-195: 151 * 4K = 682K
// 358-511: 154 * 4 = 4K = 616 K
void
init_kalloc
()
{
// do nothing for now
auto
irqs
=
mem_lock
.
lock
();
for
(
int
frameNumber
=
0
;
frameNumber
<
NUMBER_OF_FRAMES
;
++
frameNumber
){
void
*
pa
=
(
void
*
)
(
frameNumber
*
PAGESIZE
);
auto
range
=
physical_ranges
.
find
((
uintptr_t
)
pa
);
bool
isFree
=
range
->
type
()
==
mem_available
;
block
*
pBlock
=
&
blocks
[
frameNumber
];
pBlock
->
isFree
=
isFree
;
pBlock
->
order
=
MIN_ORDER
;
pBlock
->
ka
=
pa2kptr
<
void
*>
((
uintptr_t
)
pa
);
//log_printf("frame %d is %s\n", frameNumber, (isFree ? "Free" : "Not Free"));
if
(
isFree
)
{
freeBlockList
[
MIN_ORDER
].
push_back
(
pBlock
);
pBlock
->
cloalesce
();
}
}
mem_lock
.
unlock
(
irqs
);
test_kalloc
();
}
...
...
@@ -26,50 +94,122 @@ void init_kalloc() {
//
// The handout code does not free memory and allocates memory in units
// of pages.
#pragma GCC push_options
#pragma GCC optimize ("O0")
void
*
kalloc
(
size_t
sz
)
{
if
(
sz
==
0
||
sz
>
PAGESIZE
)
{
if
(
sz
==
0
)
{
return
nullptr
;
}
int
order
=
block
::
minOrderForBlockOfSize
(
sz
);
if
(
order
>
MAX_ORDER
)
{
return
nullptr
;
}
auto
irqs
=
page
_lock
.
lock
();
auto
irqs
=
mem
_lock
.
lock
();
void
*
ptr
=
nullptr
;
// skip over reserved and kernel memory
auto
range
=
physical_ranges
.
find
(
next_free_pa
);
while
(
range
!=
physical_ranges
.
end
())
{
if
(
range
->
type
()
==
mem_available
)
{
// use this page
ptr
=
pa2kptr
<
void
*>
(
next_free_pa
);
next_free_pa
+=
PAGESIZE
;
break
;
}
else
{
// move to next range
next_free_pa
=
range
->
last
();
++
range
;
}
if
(
freeBlockList
[
order
].
empty
()){
block
::
split
(
order
+
1
);
}
block
*
pBlock
=
freeBlockList
[
order
].
pop_front
();
page_lock
.
unlock
(
irqs
);
if
(
pBlock
)
{
ptr
=
pBlock
->
ka
;
pBlock
->
isFree
=
false
;
assert
(
pBlock
->
order
==
order
);
}
mem_lock
.
unlock
(
irqs
);
if
(
ptr
)
{
// tell sanitizers the allocated page is accessible
asan_mark_memory
(
ka2pa
(
ptr
),
PAGESIZE
,
false
);
// initialize to `int3`
memset
(
ptr
,
0xCC
,
PAGESIZE
);
log_printf
(
"kalloc of order %d returning frame %d
\n
"
,
pBlock
->
order
,
pBlock
->
frameNumber
());
}
else
{
log_printf
(
"kalloc of order %d failled
\n
"
,
order
);
}
return
ptr
;
}
//split a block at a particular order
void
block
::
split
(
int
order
)
{
//assert the passed-in parameter in legitimate
assert
(
order
>
MIN_ORDER
&&
order
<=
MAX_ORDER
+
1
);
//if we are beyond the top, then there is nothing to split
if
(
order
>
MAX_ORDER
)
{
return
;
}
// if no block at this order, then try to split at a higher order (recursion)
if
(
freeBlockList
[
order
].
empty
())
{
block
::
split
(
order
+
1
);
}
// check again to see if we can get a free block
// if not, fail
if
(
freeBlockList
[
order
].
empty
()){
return
;
}
block
*
fBlock
=
freeBlockList
[
order
].
pop_front
();
// asssert that the data structure are proper
assert
(
fBlock
->
isFree
&&
fBlock
->
order
==
order
);
// reduce the order of the block obtained and get its buddy
--
fBlock
->
order
;
block
*
pBuddy
=
fBlock
->
buddy
();
// fix up the buddy
pBuddy
->
order
=
fBlock
->
order
;
pBuddy
->
isFree
=
true
;
// add to the free block list
freeBlockList
[
fBlock
->
order
].
push_front
(
fBlock
);
freeBlockList
[
pBuddy
->
order
].
push_front
(
pBuddy
);
}
#pragma GCC pop_options
// kfree(ptr)
// Free a pointer previously returned by `kalloc`. Does nothing if
// `ptr == nullptr`.
void
kfree
(
void
*
ptr
)
{
if
(
ptr
)
{
// tell sanitizers the freed page is inaccessible
asan_mark_memory
(
ka2pa
(
ptr
),
PAGESIZE
,
true
);
if
(
!
ptr
){
return
;
}
block
*
pBlock
=
block
::
blockAtKernelAddress
(
ptr
);
assert
(
!
(
pBlock
->
isFree
));
assert
(
pBlock
->
ka
==
ptr
);
auto
irqs
=
mem_lock
.
lock
();
pBlock
->
isFree
=
true
;
freeBlockList
[
pBlock
->
order
].
push_front
(
pBlock
);
pBlock
->
cloalesce
();
mem_lock
.
unlock
(
irqs
);
}
void
block
::
cloalesce
()
{
//log_printf("Cloalesce() frame %d(%d) \n", frameNumber(), order);
if
(
order
==
MAX_ORDER
)
{
return
;
}
block
*
pBuddy
=
this
->
buddy
();
if
(
!
pBuddy
->
isFree
||
pBuddy
->
order
!=
order
){
return
;
}
freeBlockList
[
order
].
erase
(
this
);
freeBlockList
[
order
].
erase
(
pBuddy
);
++
this
->
order
;
++
pBuddy
->
order
;
if
(
ka
<
pBuddy
->
ka
){
freeBlockList
[
this
->
order
].
push_front
(
this
);
cloalesce
();
}
else
{
freeBlockList
[
pBuddy
->
order
].
push_front
(
pBuddy
);
pBuddy
->
cloalesce
();
}
log_printf
(
"kfree not implemented yet
\n
"
);
}
...
...
@@ -112,3 +252,41 @@ void operator delete[](void* ptr, std::align_val_t) noexcept {
void
operator
delete
[](
void
*
ptr
,
size_t
,
std
::
align_val_t
)
noexcept
{
kfree
(
ptr
);
}
void
test_kalloc
()
{
void
*
p1
;
void
*
p2
;
p1
=
kalloc
(
PAGESIZE
);
assert
(
p1
);
kfree
(
p1
);
p2
=
kalloc
(
PAGESIZE
);
assert
(
p2
);
kfree
(
p2
);
assert
(
p1
==
p2
);
p1
=
kalloc
(
PAGESIZE
);
p2
=
kalloc
(
PAGESIZE
);
assert
(
p1
);
assert
(
p2
);
kfree
(
p1
);
kfree
(
p2
);
assert
(
p1
!=
p2
);
p1
=
kalloc
(
1
<<
22
);
// 4 MB
assert
(
!
p1
);
p1
=
kalloc
(
1
<<
21
);
// 2 MB
assert
(
!
p1
);
p1
=
kalloc
(
1
<<
20
);
// 1 MB
assert
(
!
p1
);
p1
=
kalloc
(
1
<<
19
);
// 512 KB
p2
=
kalloc
(
1
<<
19
);
assert
(
p1
);
assert
(
!
p2
);
p2
=
kalloc
(
1
<<
18
);
//256 KB
assert
(
p2
);
kfree
(
p2
);
kfree
(
p1
);
}
#pragma GCC pop_options
kernel.cc
View file @
de1f3b4f
...
...
@@ -233,7 +233,8 @@ uintptr_t proc::syscall(regstate* regs) {
}
return
bufcache
::
get
().
sync
(
drop
);
}
case
SYSCALL_MAP_CONSOLE
:
return
syscall_map_console
(
regs
);
default:
// no such system call
log_printf
(
"%d: no such system call %u
\n
"
,
id_
,
regs
->
reg_rax
);
...
...
@@ -241,7 +242,19 @@ uintptr_t proc::syscall(regstate* regs) {
}
}
// Debugging Information
#pragma GCC push_options
#pragma GCC optimize("O0")
int
proc
::
syscall_map_console
(
regstate
*
regs
)
{
uintptr_t
addr
=
regs
->
reg_rdi
;
if
(
addr
%
PAGESIZE
||
addr
>
VA_LOWMAX
)
{
return
E_INVAL
;
}
vmiter
(
this
,
addr
).
map
(
CONSOLE_ADDR
,
PTE_PWU
);
return
0
;
}
#pragma GCC pop_options
// proc::syscall_fork(regs)
// Handle fork system call.
...
...
kernel.hh
View file @
de1f3b4f
...
...
@@ -74,6 +74,7 @@ struct __attribute__((aligned(4096))) proc {
private:
static
int
load_segment
(
const
elf_program
&
ph
,
proc_loader
&
ld
);
int
syscall_map_console
(
regstate
*
reg
);
};
#define NPROC 16
...
...
lib.hh
View file @
de1f3b4f
...
...
@@ -270,7 +270,7 @@ struct bitset_view {
// Add new system calls here.
// Your numbers should be >=128 to avoid conflicts.
#define SYSCALL_MAP_CONSOLE 128
// System call error return values
...
...
p-allocator.cc
View file @
de1f3b4f
#include "u-lib.hh"
#define ALLOC_SLOWDOWN
24
#define ALLOC_SLOWDOWN
1
/* 24 */
extern
uint8_t
end
[];
...
...
@@ -11,8 +11,14 @@ uint8_t* stack_bottom;
#pragma GCC optimize ("O0")
void
process_main
()
{
sys_kdisplay
(
KDISPLAY_MEMVIEWER
);
//sys_kdisplay(KDISPLAY_MEMVIEWER);
int
error_code
=
sys_map_console
(
console
);
assert
(
!
error_code
);
console_printf
(
0x5000
,
"Hello Professor Foster,
\n
"
);
console_printf
(
0x5000
,
"We are in week four of the quarter and I'm learning a lot of
\n
"
);
console_printf
(
0x5000
,
"C++ programming in OS!
\n
"
);
console_printf
(
0x5000
,
"--Matija Benko"
);
// Fork three new copies. (But ignore failures.)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-variable"
...
...
@@ -46,7 +52,7 @@ void process_main() {
}
sys_yield
();
if
(
rand
()
<
RAND_MAX
/
32
)
{
sys_pause
();
//
sys_pause();
}
}
...
...
u-lib.hh
View file @
de1f3b4f
...
...
@@ -309,6 +309,12 @@ pid_t sys_clone(int (*function)(void*), void* arg, char* stack_top);
assert
(
false
);
}
// sys_map_console(void*)
// Map the console at the user specified address. Return 0 on success, return E_INVAL on invalid address,
inline
int
sys_map_console
(
void
*
addr
)
{
return
make_syscall
(
SYSCALL_MAP_CONSOLE
,
reinterpret_cast
<
uintptr_t
>
(
addr
));
}
// dprintf(fd, format, ...)
// Construct a string from `format` and pass it to `sys_write(fd)`.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment