XBT_PUBLIC xbt_mheap_t xbt_mheap_new(void* baseaddr, int options);
-XBT_PUBLIC void xbt_mheap_destroy_no_free(xbt_mheap_t md);
-
XBT_PUBLIC void* xbt_mheap_destroy(xbt_mheap_t md);
/* To get the heap used when using the legacy version malloc/free/realloc and such */
xbt_mheap_t mmalloc_get_current_heap(void);
+/* Returns true if we are using the internal mmalloc, and false if we are using the libc's malloc */
+XBT_PUBLIC int malloc_use_mmalloc(void);
+
#endif
SG_END_DECL
#include <xbt/config.hpp>
#include "simgrid/sg_config.hpp"
+#include "src/include/xbt/mmalloc.h"
#include "src/instr/instr_private.hpp"
#include "src/internal_config.h"
#include "src/kernel/context/Context.hpp"
static simgrid::config::Flag<int> cfg_context_guard_size{
"contexts/guard-size", "Guard size for contexts stacks in memory pages", default_guard_size,
[](int value) { simgrid::kernel::context::guard_size = value * xbt_pagesize; }};
- static simgrid::config::Flag<int> cfg_context_nthreads{"contexts/nthreads",
- "Number of parallel threads used to execute user contexts", 1,
- &simgrid::kernel::context::set_nthreads};
+
+ static simgrid::config::Flag<int> cfg_context_nthreads{
+ "contexts/nthreads", "Number of parallel threads used to execute user contexts", 1, [](int nthreads) {
+#if HAVE_MMALLOC
+ xbt_assert(
+ nthreads == 1 || !malloc_use_mmalloc(),
+ "Parallel simulation is forbidden in the verified program, as there is no protection against race "
+ "conditions in mmalloc itself. Please don't be so greedy and show some mercy for our implementation.");
+#endif
+ simgrid::kernel::context::set_nthreads(nthreads);
+ }};
/* synchronization mode for parallel user contexts */
#if HAVE_FUTEX_H
switch (type) {
case MMALLOC_TYPE_HEAPINFO:
- UNLOCK(mdp);
fprintf(stderr, "Asked to free a fragment in a heapinfo block. I'm confused.\n");
abort();
break;
case MMALLOC_TYPE_FREE: /* Already free */
- UNLOCK(mdp);
fprintf(stderr, "Asked to free a fragment in a block that is already free. I'm puzzled.\n");
abort();
break;
frag_nb = RESIDUAL(ptr, BLOCKSIZE) >> type;
if( mdp->heapinfo[block].busy_frag.frag_size[frag_nb] == -1){
- UNLOCK(mdp);
fprintf(stderr, "Asked to free a fragment that is already free. I'm puzzled\n");
abort();
}
if (!mdp)
return NULL;
- LOCK(mdp);
- void *ret = mmalloc(mdp, n);
- UNLOCK(mdp);
- return ret;
+ return mmalloc(mdp, n);
}
void *calloc(size_t nmemb, size_t size)
if (!mdp)
return NULL;
- LOCK(mdp);
void *ret = mmalloc(mdp, nmemb*size);
- UNLOCK(mdp);
// This was already done in the callee:
if(!(mdp->options & XBT_MHEAP_OPTION_MEMSET)) {
memset(ret, 0, nmemb * size);
if (!mdp)
return NULL;
- LOCK(mdp);
- void* ret = mrealloc(mdp, p, s);
- UNLOCK(mdp);
- return ret;
+ return mrealloc(mdp, p, s);
}
void free(void *p)
return;
xbt_mheap_t mdp = GET_HEAP();
- LOCK(mdp);
mfree(mdp, p);
- UNLOCK(mdp);
}
mdp->next_mdesc = NULL;
mdp->options = options;
- pthread_mutex_init(&mdp->mutex, NULL);
/* If we have not been passed a valid open file descriptor for the file
to map to, then open /dev/zero and use that to map to. */
while(mdp->next_mdesc)
mdp = mdp->next_mdesc;
- LOCK(mdp);
mdp->next_mdesc = (struct mdesc *)mbase;
- UNLOCK(mdp);
}
return mbase;
}
-
-
-/** Terminate access to a mmalloc managed region, but do not free its content.
- *
- * This is for example useful for the base region where ldl stores its data
- * because it leaves the place after us.
- */
-void xbt_mheap_destroy_no_free(xbt_mheap_t md)
-{
- struct mdesc *mdp = md;
-
- pthread_mutex_destroy(&mdp->mutex);
-}
-
/** Terminate access to a mmalloc managed region by unmapping all memory pages associated with the region, and closing
* the file descriptor if it is one that we opened.
mdptemp->next_mdesc = mdp->next_mdesc;
- xbt_mheap_destroy_no_free(mdp);
struct mdesc mtemp = *mdp;
/* Now unmap all the pages associated with this region by asking for a
xbt_mheap_t mdp = NULL;
if ((mdp =__mmalloc_default_mdp)){
while(mdp){
- LOCK(mdp);
mdp = mdp->next_mdesc;
}
}
xbt_mheap_t mdp = NULL;
if ((mdp =__mmalloc_default_mdp)){
while(mdp){
- UNLOCK(mdp);
mdp = mdp->next_mdesc;
}
}
struct mdesc* mdp = NULL;
if ((mdp =__mmalloc_default_mdp)){
while(mdp){
- UNLOCK(mdp);
mdp = mdp->next_mdesc;
}
}
* if such a file exists.
* */
struct mdesc {
- /** @brief Mutex locking the access to the heap */
- pthread_mutex_t mutex;
-
/** @brief Chained lists of mdescs */
struct mdesc *next_mdesc;
XBT_PUBLIC void* mmorecore(struct mdesc* mdp, ssize_t size);
-/** Thread-safety (if the mutex is already created)
- *
- * This is mandatory in the case where the user runs a parallel simulation
- * in a model-checking enabled tree. Without this protection, our malloc
- * implementation will not like multi-threading AT ALL.
- */
-#define LOCK(mdp) pthread_mutex_lock(&(mdp)->mutex)
-#define UNLOCK(mdp) pthread_mutex_unlock(&(mdp)->mutex)
-
-XBT_PRIVATE int malloc_use_mmalloc(void);
-
XBT_PRIVATE size_t mmalloc_get_bytes_used_remote(size_t heaplimit, const malloc_info* heapinfo);
/* We call dlsym during mmalloc initialization, but dlsym uses malloc.