Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Fill in all the missing code in the MemoryManager.cpp (provided below). If not a

ID: 3902435 • Letter: F

Question

Fill in all the missing code in the MemoryManager.cpp (provided below). If not all the missing code was filled in the MemoryManager.cpp, I will automatically downvote.

The goal of your next project is to simulate the C heap manager which is used to allocate and deallocate dynamic memory.

The “heap” is a large pool of memory set aside by the runtime system for a program to use for dynamic variables.

The two main heap manager functions are:

malloc, used to satisfy a request for a specific number of consecutive bytes;

free, used to make allocated blocks available for future malloc requests (i.e., return them to the pool of available memory).

---------------------------------------------------------------------------------------------------------------------

blocknode.h

---------------------------------------------------------------------------------------------------------------------

#ifndef _BLOCKNODE_

#define _BLOCKNODE_

#include

using namespace std;

struct blocknode {

   unsigned int blocksize;

   bool free;

   unsigned char *blockptr;

   blocknode *prev;

   blocknode *next;

   blocknode(unsigned int sz = 0, unsigned char * p= nullptr, bool f = false, blocknode *before=nullptr, blocknode *after=nullptr) : blocksize(sz), blockptr(p), free(f), prev(before),next(after) {};

   void insertAfter(blocknode *newbnode);

   void insertBefore(blocknode *newbnode);

   void deletePrevious();

   void deleteNext();

};

ostream& operator << (ostream&, blocknode *);

#endif

---------------------------------------------------------------------------------------------------------------------

blockdata.cpp

---------------------------------------------------------------------------------------------------------------------

#include "blocknode.h"

#include

#include

using namespace std;

ostream &operator << (ostream &out, blocknode *p)

{

out << "[" << p->blocksize << ",";

if (p->free)

    out << "free";

else

    out << "allocated";

out << "]";

return out;

}

void blocknode::insertAfter(blocknode *newbnode)

{

   assert(next != nullptr); // not trailer node

   newbnode->prev = next->prev;

   newbnode->next = next;

   next = newbnode;

   newbnode->next->prev = newbnode;

}

void blocknode::insertBefore(blocknode *newbnode)

{

   assert(prev != nullptr); // not header node

   newbnode->next = prev->next;

   newbnode->prev = prev;

   prev = newbnode;

   newbnode->prev->next = newbnode;

}

void blocknode::deletePrevious()

{

   // not header and previous is not header

   assert(prev != nullptr && prev->prev != nullptr);

   blocknode * hold = prev;

   prev = hold->prev;

   prev->next = hold->next;

   delete hold;

}

  

void blocknode::deleteNext()

{

   // not trailer and next is not trailer

   assert(next != nullptr && next->next != nullptr);

   blocknode *hold = next;

   next = hold->next;

   next->prev = hold->prev;

   delete hold;

}

---------------------------------------------------------------------------------------------------------------------

MemoryManager.h

---------------------------------------------------------------------------------------------------------------------

#ifndef __MM__

#define __MM__

#include

#include

#include "blocknode.h"

using namespace std;

class MemoryManager

{

public:

    MemoryManager(unsigned int memtotal);

    unsigned char * malloc(unsigned int request);

    void free(unsigned char * ptr2block);

    void showBlockList();

private:

   blocknode *header;

   blocknode *trailer;

   unsigned int memsize;    //   heap size

   unsigned char *baseptr; //   pointer to first byte of heap

   // utilities for malloc method:

   blocknode * findFirstFit(unsigned int chunksize);

   void splitBlock(blocknode *p,unsigned int chunksize);

// utilities for free method:

   blocknode *findAllocatedBlock (unsigned char *allocated_ptr);

   void mergeForward(blocknode *p);

   void mergeBackward(blocknode *p);

};

#endif

---------------------------------------------------------------------------------------------------------------------

MemoryManager.cpp FILE TO BE COMPLETED

---------------------------------------------------------------------------------------------------------------------

#include

#include

#include "MemoryManager.h"

MemoryManager::MemoryManager(unsigned int memtotal)

{

   memsize = memtotal; // size of the "heap"

   baseptr = new unsigned char[memsize]; // allocate the heap

   // create empty blocknode list

   header = new blocknode();

   trailer = new blocknode();

   header->next = trailer;

   trailer->prev = header;

   // create blocknode to represent the entire heap

   blocknode * originalBlocknode = new blocknode(memsize,baseptr,true);

   header->insertAfter(originalBlocknode);

}

void MemoryManager::showBlockList()

{

     blocknode *tmp = header->next;

     while(tmp->next != trailer) {

          cout << tmp << "->";

          tmp = tmp->next;

     }

     cout << tmp << " ";

}

// Utilities for malloc

blocknode * MemoryManager:: findFirstFit(unsigned int chunksize)
{// returns a pointer to the first blocknode whose blocksize is at least chunksize;

// if there is no such blocknode, returns nullptr

}

void MemoryManager::splitBlock(blocknode *p, unsigned int chunksize)

{ // fill in missing code

}

unsigned char * MemoryManager::malloc(unsigned int request)

{ // fill in missing code

}

// Utilities for free

MemoryManager:: blocknode *findAllocatedBlock (unsigned char *allocated_ptr)

{ // returns a pointer to the first blocknode whose blockptr matches allocated_ptr;
// if no such block exists, terminates the program

}

MemoryManager:: mergeForward(blocknode *p)

{ // fill in missing code

}

void MemoryManager::mergeBackward(blocknode *p)

{ // fill in missing code

}

void MemoryManager::freee(unsigned char *ptr2block)

{ // fill in missing code

}

---------------------------------------------------------------------------------------------------------------------

testMemMgr.cpp

---------------------------------------------------------------------------------------------------------------------

#include

#include "MemoryManager.h"

using namespace std;

int main()

{

   MemoryManager heaper(50);

   cout << "After initializing" << endl;

   heaper.showBlockList();

   unsigned char * p1 = heaper.malloc(10);

   cout << "After the first malloc ";

   heaper.showBlockList();

   unsigned char *p2 = heaper.malloc(20);

   cout << "After the second malloc ";

   heaper.showBlockList();

   cout << "Asking for an un-allocatable block ";

   unsigned char *p8 = heaper.malloc(30);

   if (p8 == 0)

      cout << "Good. The call to malloc returned NULL ";

   else

      cout << "Uh-oh. Call to malloc did not return NULL as it should have ";

   cout << "Free the first block ";

   heaper.free(p1);

   heaper.showBlockList();

   cout << "Allocate a block too big for the initial open block ";

   p1 = heaper.malloc(15);

   // cout << "malloc done ";

   heaper.showBlockList();

   cout << "Free the most recently allocated block ";

   heaper.free(p1);

   heaper.showBlockList();

   cout << "Free the middle block ";

   heaper.free(p2);

   heaper.showBlockList();

   return 0;

}

---------------------------------------------------------------------------------------------------------------------

Sample Output

---------------------------------------------------------------------------------------------------------------------

After initializing

[50,free]

After the first malloc

[10,allocated]->[40,free]

After the second malloc

[10,allocated]->[20,allocated]->[20,free]

Asking for an un-allocatable blockAfter the second malloc

Good. The call to malloc returned nullptr


Free the first block

[10,free]->[20,allocated]->[20,free]

Allocate a block too big for the initial open block

[10,free]->[20,allocated]->[15,allocated]->[5,free]

Free the most recently allocated pointer

[10,free]->[20,allocated]->[20,free]

Free the middle block

[50,free]

Explanation / Answer

#include "precompiled.hpp"

#include "classfile/systemDictionary.hpp"

#include "classfile/vmSymbols.hpp"

#include "oops/oop.inline.hpp"

#include "runtime/handles.inline.hpp"

#include "runtime/javaCalls.hpp"

#include "services/lowMemoryDetector.hpp"

#include "services/management.hpp"

#include "services/memoryManager.hpp"

#include "services/memoryPool.hpp"

#include "services/memoryService.hpp"

#include "services/gcNotifier.hpp"

#include "utilities/dtrace.hpp"

#ifndef USDT2

HS_DTRACE_PROBE_DECL8(hotspot, mem__pool__gc__begin, char*, int, char*, int,

size_t, size_t, size_t, size_t);

HS_DTRACE_PROBE_DECL8(hotspot, mem__pool__gc__end, char*, int, char*, int,

size_t, size_t, size_t, size_t);

#endif /* !USDT2 */

MemoryManager::MemoryManager() {

_num_pools = 0;

_memory_mgr_obj = NULL;

}

void MemoryManager::add_pool(MemoryPool* pool) {

assert(_num_pools < MemoryManager::max_num_pools, "_num_pools exceeds the max");

if (_num_pools < MemoryManager::max_num_pools) {

_pools[_num_pools] = pool;

_num_pools++;

}

pool->add_manager(this);

}

MemoryManager* MemoryManager::get_code_cache_memory_manager() {

return (MemoryManager*) new CodeCacheMemoryManager();

}

GCMemoryManager* MemoryManager::get_copy_memory_manager() {

return (GCMemoryManager*) new CopyMemoryManager();

}

GCMemoryManager* MemoryManager::get_msc_memory_manager() {

return (GCMemoryManager*) new MSCMemoryManager();

}

GCMemoryManager* MemoryManager::get_parnew_memory_manager() {

return (GCMemoryManager*) new ParNewMemoryManager();

}

GCMemoryManager* MemoryManager::get_cms_memory_manager() {

return (GCMemoryManager*) new CMSMemoryManager();

}

GCMemoryManager* MemoryManager::get_psScavenge_memory_manager() {

return (GCMemoryManager*) new PSScavengeMemoryManager();

}

GCMemoryManager* MemoryManager::get_psMarkSweep_memory_manager() {

return (GCMemoryManager*) new PSMarkSweepMemoryManager();

}

GCMemoryManager* MemoryManager::get_g1YoungGen_memory_manager() {

return (GCMemoryManager*) new G1YoungGenMemoryManager();

}

GCMemoryManager* MemoryManager::get_g1OldGen_memory_manager() {

return (GCMemoryManager*) new G1OldGenMemoryManager();

}

instanceOop MemoryManager::get_memory_manager_instance(TRAPS) {

// Must do an acquire so as to force ordering of subsequent

// loads from anything _memory_mgr_obj points to or implies.

instanceOop mgr_obj = (instanceOop)OrderAccess::load_ptr_acquire(&_memory_mgr_obj);

if (mgr_obj == NULL) {

// It's ok for more than one thread to execute the code up to the locked region.

// Extra manager instances will just be gc'ed.

klassOop k = Management::sun_management_ManagementFactory_klass(CHECK_0);

instanceKlassHandle ik(THREAD, k);

Handle mgr_name = java_lang_String::create_from_str(name(), CHECK_0);

JavaValue result(T_OBJECT);

JavaCallArguments args;

args.push_oop(mgr_name); // Argument 1

Symbol* method_name = NULL;

Symbol* signature = NULL;

if (is_gc_memory_manager()) {

method_name = vmSymbols::createGarbageCollector_name();

signature = vmSymbols::createGarbageCollector_signature();

args.push_oop(Handle()); // Argument 2 (for future extension)

} else {

method_name = vmSymbols::createMemoryManager_name();

signature = vmSymbols::createMemoryManager_signature();

}

JavaCalls::call_static(&result,

ik,

method_name,

signature,

&args,

CHECK_0);

instanceOop m = (instanceOop) result.get_jobject();

instanceHandle mgr(THREAD, m);

{

// Get lock before setting _memory_mgr_obj

// since another thread may have created the instance

MutexLocker ml(Management_lock);

// Check if another thread has created the management object. We reload

// _memory_mgr_obj here because some other thread may have initialized

// it while we were executing the code before the lock.

//

// The lock has done an acquire, so the load can't float above it, but

// we need to do a load_acquire as above.

mgr_obj = (instanceOop)OrderAccess::load_ptr_acquire(&_memory_mgr_obj);

if (mgr_obj != NULL) {

return mgr_obj;

}

// Get the address of the object we created via call_special.

mgr_obj = mgr();

// Use store barrier to make sure the memory accesses associated

// with creating the management object are visible before publishing

// its address. The unlock will publish the store to _memory_mgr_obj

// because it does a release first.

OrderAccess::release_store_ptr(&_memory_mgr_obj, mgr_obj);

}

}

return mgr_obj;

}

void MemoryManager::oops_do(OopClosure* f) {

f->do_oop((oop*) &_memory_mgr_obj);

}

GCStatInfo::GCStatInfo(int num_pools) {

// initialize the arrays for memory usage

_before_gc_usage_array = (MemoryUsage*) NEW_C_HEAP_ARRAY(MemoryUsage, num_pools);

_after_gc_usage_array = (MemoryUsage*) NEW_C_HEAP_ARRAY(MemoryUsage, num_pools);

_usage_array_size = num_pools;

clear();

}

GCStatInfo::~GCStatInfo() {

FREE_C_HEAP_ARRAY(MemoryUsage*, _before_gc_usage_array);

FREE_C_HEAP_ARRAY(MemoryUsage*, _after_gc_usage_array);

}

void GCStatInfo::set_gc_usage(int pool_index, MemoryUsage usage, bool before_gc) {

MemoryUsage* gc_usage_array;

if (before_gc) {

gc_usage_array = _before_gc_usage_array;

} else {

gc_usage_array = _after_gc_usage_array;

}

gc_usage_array[pool_index] = usage;

}

void GCStatInfo::clear() {

_index = 0;

_start_time = 0L;

_end_time = 0L;

size_t len = _usage_array_size * sizeof(MemoryUsage);

memset(_before_gc_usage_array, 0, len);

memset(_after_gc_usage_array, 0, len);

}

GCMemoryManager::GCMemoryManager() : MemoryManager() {

_num_collections = 0;

_last_gc_stat = NULL;

_last_gc_lock = new Mutex(Mutex::leaf, "_last_gc_lock", true);

_current_gc_stat = NULL;

_num_gc_threads = 1;

_notification_enabled = false;

}

GCMemoryManager::~GCMemoryManager() {

delete _last_gc_stat;

delete _last_gc_lock;

delete _current_gc_stat;

}

void GCMemoryManager::initialize_gc_stat_info() {

assert(MemoryService::num_memory_pools() > 0, "should have one or more memory pools");

_last_gc_stat = new(ResourceObj::C_HEAP) GCStatInfo(MemoryService::num_memory_pools());

_current_gc_stat = new(ResourceObj::C_HEAP) GCStatInfo(MemoryService::num_memory_pools());

// tracking concurrent collections we need two objects: one to update, and one to

// hold the publicly available "last (completed) gc" information.

}

void GCMemoryManager::gc_begin(bool recordGCBeginTime, bool recordPreGCUsage,

bool recordAccumulatedGCTime) {

assert(_last_gc_stat != NULL && _current_gc_stat != NULL, "Just checking");

if (recordAccumulatedGCTime) {

_accumulated_timer.start();

}

// _num_collections now increases in gc_end, to count completed collections

if (recordGCBeginTime) {

_current_gc_stat->set_index(_num_collections+1);

_current_gc_stat->set_start_time(Management::timestamp());

}

if (recordPreGCUsage) {

// Keep memory usage of all memory pools

for (int i = 0; i < MemoryService::num_memory_pools(); i++) {

MemoryPool* pool = MemoryService::get_memory_pool(i);

MemoryUsage usage = pool->get_memory_usage();

_current_gc_stat->set_before_gc_usage(i, usage);

#ifndef USDT2

HS_DTRACE_PROBE8(hotspot, mem__pool__gc__begin,

name(), strlen(name()),

pool->name(), strlen(pool->name()),

usage.init_size(), usage.used(),

usage.committed(), usage.max_size());

#else /* USDT2 */

HOTSPOT_MEM_POOL_GC_BEGIN(

(char *) name(), strlen(name()),

(char *) pool->name(), strlen(pool->name()),

usage.init_size(), usage.used(),

usage.committed(), usage.max_size());

#endif /* USDT2 */

}

}

}

// A collector MUST, even if it does not complete for some reason,

// make a TraceMemoryManagerStats object where countCollection is true,

// to ensure the current gc stat is placed in _last_gc_stat.

void GCMemoryManager::gc_end(bool recordPostGCUsage,

bool recordAccumulatedGCTime,

bool recordGCEndTime, bool countCollection,

GCCause::Cause cause) {

if (recordAccumulatedGCTime) {

_accumulated_timer.stop();

}

if (recordGCEndTime) {

_current_gc_stat->set_end_time(Management::timestamp());

}

if (recordPostGCUsage) {

int i;

// keep the last gc statistics for all memory pools

for (i = 0; i < MemoryService::num_memory_pools(); i++) {

MemoryPool* pool = MemoryService::get_memory_pool(i);

MemoryUsage usage = pool->get_memory_usage();

#ifndef USDT2

HS_DTRACE_PROBE8(hotspot, mem__pool__gc__end,

name(), strlen(name()),

pool->name(), strlen(pool->name()),

usage.init_size(), usage.used(),

usage.committed(), usage.max_size());

#else /* USDT2 */

HOTSPOT_MEM_POOL_GC_END(

(char *) name(), strlen(name()),

(char *) pool->name(), strlen(pool->name()),

usage.init_size(), usage.used(),

usage.committed(), usage.max_size());

#endif /* USDT2 */

_current_gc_stat->set_after_gc_usage(i, usage);

}

// Set last collection usage of the memory pools managed by this collector

for (i = 0; i < num_memory_pools(); i++) {

MemoryPool* pool = get_memory_pool(i);

MemoryUsage usage = pool->get_memory_usage();

// Compare with GC usage threshold

pool->set_last_collection_usage(usage);

LowMemoryDetector::detect_after_gc_memory(pool);

}

}

if (countCollection) {

_num_collections++;

// alternately update two objects making one public when complete

{

MutexLockerEx ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);

GCStatInfo *tmp = _last_gc_stat;

_last_gc_stat = _current_gc_stat;

_current_gc_stat = tmp;

// reset the current stat for diagnosability purposes

_current_gc_stat->clear();

}

if (is_notification_enabled()) {

bool isMajorGC = this == MemoryService::get_major_gc_manager();

GCNotifier::pushNotification(this, isMajorGC ? "end of major GC" : "end of minor GC",

GCCause::to_string(cause));

}

}

}

size_t GCMemoryManager::get_last_gc_stat(GCStatInfo* dest) {

MutexLockerEx ml(_last_gc_lock, Mutex::_no_safepoint_check_flag);

if (_last_gc_stat->gc_index() != 0) {

dest->set_index(_last_gc_stat->gc_index());

dest->set_start_time(_last_gc_stat->start_time());

dest->set_end_time(_last_gc_stat->end_time());

assert(dest->usage_array_size() == _last_gc_stat->usage_array_size(),

"Must have same array size");

size_t len = dest->usage_array_size() * sizeof(MemoryUsage);

memcpy(dest->before_gc_usage_array(), _last_gc_stat->before_gc_usage_array(), len);

memcpy(dest->after_gc_usage_array(), _last_gc_stat->after_gc_usage_array(), len);

}

return _last_gc_stat->gc_index();

}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote