Skip to content

Commit

Permalink
data/lab/arena: Add page mapper arena challenge
Browse files Browse the repository at this point in the history
A challenge to exercise working with mmap().

Signed-off-by: Razvan Deaconescu <[email protected]>
  • Loading branch information
razvand committed Nov 6, 2023
1 parent 188437c commit 9ccd2db
Show file tree
Hide file tree
Showing 18 changed files with 442 additions and 1 deletion.
30 changes: 29 additions & 1 deletion content/chapters/data/lab/content/arena.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,34 @@
# Arena

Challenge tasks
Go through the practice items below to hone your skills in working with data and memory.

## Page Mapper

Navigate to the `support/page-mapper/` directory.

Your goal is to update the `src/page_mapper.c` source code file to reserve virtual pages in the address space of the current process.
Use `mmap()` to reserve virtual pages.
Use anonymous mapping (i.e. the `MAP_ANONYMOUS`) flag.
Use any permissions required.

Inside the `src/` directory, use `make` to do a quick check of the implementation.
To test it, enter the `tests/` directory and run:

```console
make check
```

In case of a correct solution, you will get an output such as:

```text
./run_all_tests.sh
test_res_1 ........................ passed ... 25
test_res_2 ........................ passed ... 25
test_res_10 ........................ passed ... 25
test_res_10_res_20 ........................ passed ... 25
Total: 100/100
```

## Memory Support

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/main
19 changes: 19 additions & 0 deletions content/chapters/data/lab/solution/page-mapper/src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
CFLAGS ?= -Wall -Wextra
CPPFLAGS ?= -I../utils

.PHONY: all clean

all: main

main: main.o page_mapper.o ../utils/log/log.o

main.o: main.c page_mapper.h

page_mapper.o: page_mapper.c page_mapper.h ../utils/utils.h

../utils/log/log.o: ../utils/log/log.c ../utils/log/log.h

clean:
-rm -f main main.o
-rm -f page_mapper.o
-rm -f *~
15 changes: 15 additions & 0 deletions content/chapters/data/lab/solution/page-mapper/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

#include "page_mapper.h"

int main(void)
{
do_map(256);
do_map(10);

return 0;
}
19 changes: 19 additions & 0 deletions content/chapters/data/lab/solution/page-mapper/src/page_mapper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: BSD-3-Clause

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>

#include "page_mapper.h"
#include "utils.h"

void do_map(unsigned int num_pages)
{
/* TODO 2: Obtain page size. */
long page_size = sysconf(_SC_PAGESIZE);
void *ptr;

/* TODO 2: Map pages in memory using mmap(). */
ptr = mmap(NULL, num_pages * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
DIE(ptr == NULL, "mmap");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: BSD-3-Clause */

#ifndef ON_COMMAND_H_
#define ON_COMMAND_H_ 1

void do_map(unsigned int num_pages);

#endif
19 changes: 19 additions & 0 deletions content/chapters/data/lab/support/page-mapper/src/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
CFLAGS ?= -Wall -Wextra
CPPFLAGS ?= -I../utils

.PHONY: all clean

all: main

main: main.o page_mapper.o ../utils/log/log.o

main.o: main.c page_mapper.h

page_mapper.o: page_mapper.c page_mapper.h ../utils/utils.h

../utils/log/log.o: ../utils/log/log.c ../utils/log/log.h

clean:
-rm -f main main.o
-rm -f page_mapper.o
-rm -f *~
15 changes: 15 additions & 0 deletions content/chapters/data/lab/support/page-mapper/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

#include "page_mapper.h"

int main(void)
{
do_map(256);
do_map(10);

return 0;
}
15 changes: 15 additions & 0 deletions content/chapters/data/lab/support/page-mapper/src/page_mapper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: BSD-3-Clause

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>

#include "page_mapper.h"
#include "utils.h"

void do_map(unsigned int num_pages)
{
/* TODO: Obtain page size. */

/* TODO: Map pages in memory using mmap(). */
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: BSD-3-Clause */

#ifndef ON_COMMAND_H_
#define ON_COMMAND_H_ 1

void do_map(unsigned int num_pages);

#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/test
44 changes: 44 additions & 0 deletions content/chapters/data/lab/support/page-mapper/tests/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
SRC_PATH ?= ../src
FULL_SRC_PATH = $(realpath $(SRC_PATH))
CPPFLAGS = -I. -I$(realpath $(SRC_PATH)) -I../utils
CFLAGS = -Wall -Wextra
# Remove the line below to disable debugging support.
CFLAGS += -g -O0

SRCS = $(wildcard test*.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
EXECS = $(patsubst %.c,%,$(SRCS))


.PHONY: all src check lint clean

all: src $(EXECS)

$(EXECS): %:%.o graded_test.o $(SRC_PATH)/page_mapper.o ../utils/log/log.o | src
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)

$(OBJS): %.o:%.c graded_test.h

graded_test.o: graded_test.c graded_test.h

../utils/log/log.o: ../utils/log/log.c ../utils/log/log.h

src:
make -C $(FULL_SRC_PATH)

check:
make -C $(FULL_SRC_PATH) clean
make clean
make -i SRC_PATH=$(FULL_SRC_PATH)
./run_all_tests.sh

lint:
-cd .. && checkpatch.pl -f src/*.c tests/*.c tests/*/*.c
-cd .. && checkpatch.pl -f checker/*.sh tests/*.sh
-cd .. && cpplint --recursive src/ tests/ checker/
-cd .. && shellcheck checker/*.sh tests/*.sh

clean:
-rm -f *~
-rm -f graded_test.o $(OBJS)
-rm -f $(EXECS)
117 changes: 117 additions & 0 deletions content/chapters/data/lab/support/page-mapper/tests/graded_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// SPDX-License-Identifier: BSD-3-Clause

#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>

#include "./graded_test.h"

static void my_itoa(size_t num, char *a)
{
unsigned char digit3;
unsigned char digit2;
unsigned char digit1;

/* Print at most 3 decimal digits. */
if (num > 999)
num = 999;

digit1 = num % 10;
num /= 10;
digit2 = num % 10;
num /= 10;
digit3 = num % 10;

if (digit3 == 0)
a[0] = ' ';
else
a[0] = '0' + digit3;

if (digit2 == 0)
a[1] = ' ';
else
a[1] = '0' + digit2;

a[2] = '0' + digit1;
}

/*
* Print test result. Printed message should fit in 72 characters.
*
* Print format is:
*
* description ...................... passed ... NNN
* description ...................... failed ... NNN
* 32 chars 24 chars 6 3 3
*/

static void print_test(const char *description, int result, size_t points)
{
/* Make these global linkage, so it's only allocated once. */
static char print_buffer[74];
static const char failed[] = "failed";
static const char passed[] = "passed";
size_t i;
size_t len;

/* Collect description in print_buffer. */
len = MIN(strlen(description), 32);
for (i = 0; i < len; i++)
print_buffer[i] = description[i];
for (i = len; i < 32; i++)
print_buffer[i] = ' ';
print_buffer[32] = ' ';

/* Collect dots in print_buffer. */
for (i = 0; i < 24; i++)
print_buffer[33+i] = '.';
print_buffer[57] = ' ';

/* Collect passed / failed. */
for (i = 0; i < 6; i++) {
if (result == 1)
print_buffer[58+i] = passed[i];
else
print_buffer[58+i] = failed[i];
}
print_buffer[64] = ' ';

/* Collect dots in print_buffer. */
for (i = 0; i < 3; i++)
print_buffer[65+i] = '.';
print_buffer[68] = ' ';

/* Collect number. */
if (result == 1) {
my_itoa(points, &print_buffer[69]);
} else {
print_buffer[69] = ' ';
print_buffer[70] = ' ';
print_buffer[71] = '0';
}

/* Collect newline. */
print_buffer[72] = '\n';

write(1, print_buffer, 73);
}

void run_test(struct graded_test *test)
{
int res;

res = test->function();
print_test(test->description, res, test->points);
#ifdef EXIT_IF_FAIL
exit(EXIT_FAILURE);
#endif
}

void run_tests(struct graded_test *tests, size_t count)
{
size_t i;

for (i = 0; i < count; i++)
run_test(&tests[i]);
}
18 changes: 18 additions & 0 deletions content/chapters/data/lab/support/page-mapper/tests/graded_test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: BSD-3-Clause */

#ifndef GRADED_TEST_H_
#define GRADED_TEST_H_ 1

/* test function prototype */
typedef int (*test_f)(void);

struct graded_test {
test_f function; /* test/evaluation function */
char *description; /* test description */
size_t points; /* points for each test */
};

void run_test(struct graded_test *test);
void run_tests(struct graded_test *tests, size_t count);

#endif /* GRADED_TEST_H_ */
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash
# SPDX-License-Identifier: BSD-3-Clause

(
./test
) | tee results.txt

total=$(grep '\( passed \| failed \)' results.txt | rev | cut -d ' ' -f 1 | rev | paste -s -d'+' | bc)
echo ""
echo -n "Total: "
echo -n " "
LC_ALL=C printf "%3d/100\n" "$total"

rm results.txt
Loading

0 comments on commit 9ccd2db

Please sign in to comment.