The ROme OpTimistic Simulator  2.0.0
A General-Purpose Multithreaded Parallel/Distributed Simulation Platform
segment.c
Go to the documentation of this file.
1 
30 #include <sys/time.h>
31 #include <sys/resource.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34 
35 #include <mm/dymelor.h>
36 #include <mm/ecs.h>
38 #include <scheduler/process.h>
39 
40 extern void *__real_malloc(size_t size);
41 
42 size_t __page_size = 0;
43 
44 //TODO: document this magic! This is related to the pml4 index intialized in the ECS kernel module
45 static unsigned char *init_address = (unsigned char *)(10LL << 39);
46 
47 void *get_base_pointer(GID_t gid)
48 {
49 // printf("get base pointer for lid % d (gid %d) returns: %p\n",GidToLid(gid),gid,init_address + PER_LP_PREALLOCATED_MEMORY * gid);
50  return init_address + PER_LP_PREALLOCATED_MEMORY * gid.to_int;
51 }
52 
53 void *get_segment_memory(struct segment *seg, size_t size)
54 {
55  unsigned char *new_brk, *ret = NULL;
56 
57  // Align the new brk to a multiple of 64 bytes, to increase L1 cache efficiency
58  new_brk =
59  (unsigned char *)(((unsigned long long)seg->brk + size + (64 - 1)) &
60  -64);
61 
62  // Do we have enough space?
63  if (likely(new_brk >= seg->base + PER_LP_PREALLOCATED_MEMORY)) {
64  ret = seg->brk;
65  seg->brk = new_brk;
66  }
67 
68  return ret;
69 }
70 
71 void free_segment_memory(void *ptr)
72 {
73  // there ain't much we can do here...
74  (void)ptr;
75 }
76 
77 struct segment *get_segment(GID_t gid)
78 {
79  void *the_address;
80  struct segment *seg;
81 
82  seg = rsalloc(sizeof(struct segment));
83  if (seg == NULL)
84  return NULL;
85 
86  // Addresses are determined in the same way across all kernel instances
87  the_address = init_address + PER_LP_PREALLOCATED_MEMORY * gid.to_int;
88 
89  seg->base =
90  mmap(the_address, PER_LP_PREALLOCATED_MEMORY,
91  PROT_READ | PROT_WRITE,
92  MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0);
93  if (unlikely(seg->base == MAP_FAILED)) {
94  perror("mmap");
95  rootsim_error(true, "Unable to mmap LPs memory\n");
96  return NULL;
97  }
98  seg->brk = seg->base;
99 
100  // Access the memory in write mode to force the kernel to create the page table entries
101  *seg->base = 'x';
102 
103  return seg;
104 }
105 
106 void segment_init(void)
107 {
108  struct rlimit limit;
109  size_t max_address_space = PER_LP_PREALLOCATED_MEMORY * n_prc_tot * 2;
110 
111  // Configure the system to allow mmapping 1GB of VM at a time
112  limit.rlim_cur = max_address_space;
113  limit.rlim_max = max_address_space;
114 
115  if (setrlimit(RLIMIT_AS, &limit) != 0) {
116  perror("Unable to set the maximum address space");
117  rootsim_error(true,
118  "Unable to pre-allocate per-LP memory. Aborting...\n");
119  }
120 }
121 
122 /*
123  * TODO: this should reconstruct the addresses similarly to what is done in get_segment. Anyhow, this is called at simulation shutdown and doesn't cause much harm if it's not called.
124  */
125 /*
126  * void segment_allocator_fini(unsigned int sobjs){
127  unsigned int i;
128  int return_value;
129  for(i=0;i<sobjs;i++){
130  return_value = munmap(mem_region[i].base_pointer,PER_LP_PREALLOCATED_MEMORY);
131  if(unlikely(return_value)) {
132  printf("ERROR on release value:%d\n",return_value);
133  break;
134  }
135  mem_region[i].base_pointer = NULL;
136  }
137  close(ioctl_fd);
138 
139 }
140 */
141 
142 void initialize_memory_map(struct lp_struct *lp)
143 {
144  lp->mm = rsalloc(sizeof(struct memory_map));
145 
146  lp->mm->segment = get_segment(lp->gid);
147  lp->mm->buddy = buddy_new(PER_LP_PREALLOCATED_MEMORY);
148  lp->mm->slab = slab_init(SLAB_MSG_SIZE);
149  lp->mm->m_state = malloc_state_init();
150 }
151 
152 void finalize_memory_map(struct lp_struct *lp)
153 {
154  malloc_state_wipe(lp->mm);
155  buddy_destroy(lp->mm->buddy);
156  // No free segment function here!
157  rsfree(lp->mm);
158 }
Per-thread page table.
#define likely(exp)
Optimize the branch as likely taken.
Definition: core.h:72
#define SLAB_MSG_SIZE
Slab allocator max message size.
Definition: communication.h:43
Definition: mm.h:41
Dynamic Memory Logger and Restorer (DyMeLoR)
unsigned int to_int
The GID numerical value.
Definition: core.h:133
struct memory_map * mm
Memory map of the LP.
Definition: process.h:76
LP control blocks.
Definition of a GID.
Definition: core.h:132
GID_t gid
Global ID of the LP.
Definition: process.h:82
malloc_state * malloc_state_init(void)
Definition: dymelor.c:78
Event & Cross State Synchornization.
unsigned int n_prc_tot
Total number of logical processes running in the simulation.
Definition: core.c:64
#define unlikely(exp)
Optimize the branch as likely not taken.
Definition: core.h:74
struct buddy * buddy_new(size_t requested_size)
Definition: buddy.c:75