Assignment 3
Xiaobin Xu – A20497628, .edu
Qiming Lyu – A20480567, .edu
Lei Chen – A20490798, .edu
Part 1: Memory leaks and tools to find them
Write a program that allocates memory using malloc() but forgets to free it before
exiting. What happens when this program runs? Can you use gdb to find any
problems with it? How about valgrind (with the command: valgrind –leak-
check=yes null)
The following program is a test case that allocates dynamic memory but forgets to free the
memory. If it’s run in shell, everything would look normal. However, regarding the memory
leak, in general, modern general-purpose operating systems do clean up after terminated
processes. But it also depends on the OS.
Essentially, gcc can’t be used to find memory leak. Even if gcc is run in instruction level, it’s
not easy to find the problem. For this toy example, we can count whether there’s a complete
pair of malloc and free, however, which is not practical for a real project.
On the other hand, valgrind is an excellent tool to find any memory leaks. From the following
screenshot, we can see that there are 20 bytes of definitely lost, which is the exactly size that
I malloc in the test case.
Create other test cases for valgrind. Explain why you choose them and the
expected results.
Test case – uninitialized memory
For this test case, the program accesses an uninitialized array and valgrind succeeds to detect
such case. Furthermore, it is able to locate where the program uses that variable, which is
expected for the purpose of this test case.
Test case – indirectly lost
By assignment nbrs = NULL, we have just lost the last pointer to our memory data blocks.
We should have freed the memory first, but we can’t do it now because we don’t have a
pointer to the start of the data structure anymore. So this should be reported as an indirectly
lost.
Test case – still reachable
The “still reachable” category within Valgrind’s leak report refers to allocations that fit only
the first definition of “memory leak”. These blocks were not freed, but they could have been
freed (if the programmer had wanted to) because the program still was keeping track of
pointers to those memory blocks. This test case inserts ‘abort()’ between the ‘malloc’ and
‘free’, which trigger the ‘still reachable’ scenario.
Part 2: System calls to share a memory page (40%)
The design of the system calls
1) Declare share page data structure
Record reference counts and the page number, as well as the physical address pointer.
2) Setup OS for share page
• Add shp_init() in the main.c, which allow the OS to initialize the share pages.
• Initialize shpkemark and shpbounds in proc.c when new processes are found.
• Clean up in exec.c when a process exits by releasing the share pages and resetting
shpbounds and shpkeymark.
3) Share page management (vm.c)
• shp_init(): Initialize share pages by creating memory lock and setting reference count
to 0.
• shp_alloc():
1. Create the entire share pages by calling memset().
2. The new share page space starts from newshp to old shp, and it is set to zero
by default.
3. Call mappages() to map the page directory to the physical addresses.
• shp_deallocvm(): Walk through the page directory and release the page tables.
• shp_map(): Loop over the share page space and create translations from virtual
address to physical address in existing page table.
• shp_add():
1. Check the validity of key.
2. Add a number of new physical page addresses to the share page table at the
index of key.
• shp_release():
1. Acquire the share page lock.
2. Call shp_deallocvm() to deallocate page tables.
3. Loop the whole share tables, if a share page’s refcount is bigger than zero,
decrease the reference count; if the reference count is zero, just free the share
page.
4. Release the share page lock.
• shp_key_used(): Detect if this page(referenced by key) is in use.
• free_shared_page():
1. Get the share page by key.
2. Then walk through its physical addresses and free them.
3. Reset the reference count.
• get_shared_page():
1. Acquire share lock.
2. Check if the share page of the current process is already in memory. If it is the
case, just return the virtual address.
3. If it hasn’t been initialized regarding the key, call shp_alloc() to allocate the
share page. Then save it into the process structure and add those physical
addresses of the share page to the share table given a key.
4. Otherwise, just get the page number and physical addresses by key, then save
the page table to the process structure and increase the reference count.
5. Update the share space bound and key mask.
6. Release the share page lock.
3. Register functions in defs.h
4. Add additional info in the proc structure.
5. Create system calls
Sys_get_shared_page:
• Get the first argument and assign to key
• Get the second argument and assign to num_pages
• If they are valid, call get_shared_page() to get share page pointer.
Sys_free_shared_page:
• Just get the first argument and assign to key
• Then call free_shared_page the free the shared page by key.
Test cases
Two processes, one for writing to share pages, another for reading from share pages. We can
see the process with pid 0 succeeds to read the correct content which is written by the process
with pid 4. Then Pid 4 can only read empty content after pid 0 frees the share pages.
Xiaobin Xu – A20497628, .edu
Qiming Lyu – A20480567, .edu
Lei Chen – A20490798, .edu
Part 1: Memory leaks and tools to find them
Write a program that allocates memory using malloc() but forgets to free it before
exiting. What happens when this program runs? Can you use gdb to find any problems with it? How about valgrind (with the command: valgrind –leak- check=yes null)
Create other test cases for valgrind. Explain why you choose them and the expected results.
Test case – uninitialized memory
Test case – indirectly lost
Test case – still reachable
Part 2: System calls to share a memory page (40%)
The design of the system calls
1) Declare share page data structure
2) Setup OS for share page
3) Share page management (vm.c)
3. Register functions in defs.h
4. Add additional info in the proc structure.
5. Create system calls
Test cases