/* * Create a new small heap in main memory. */ void *SH_create_small_heap(void) { // Small heap has not been allocated to the thread yet void * heap = mmap(NULL, heapSize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); // Use mmap to allocate space for the new small heap. if (heap == MAP_FAILED) PRINTFMC("MMAP failed"); return heap; }
/* * Initialise the small heap. * Parameters that are allocated inside of this functions are described in the header file. */ struct shMapType *SH_init(void *ptr, pthread_t thread) { struct shMapType * shMapElement = malloc(sizeof(struct shMapType)); shMapElement->memArea = (unsigned int *) ptr; shMapElement->memAreaSize = heapSize / sizeof(unsigned int); shMapElement->memArea[0] = heapSize / sizeof(unsigned int) - 1; shMapElement->memArea[shMapElement->memAreaSize - 1] = heapSize / sizeof(unsigned int); shMapElement->thread_id = thread; shMapElement->available = 0; my_mutex_init(&shMapElement->mutex); PRINTFMC("Component created. Heap location: %p\n", shMapElement->memArea); return shMapElement; }
/* * Allocator of memory, allocates into the specified small heap */ void *SH_alloc_in_specific_heap(unsigned size, struct shMapType * shMapEntry){ if (size == 0) { //return NULL pointer after attempt to allocate 0-length memory return NULL ; } if (shMapEntry == NULL ) { if ( pthread_self() == mainThread ) { // If it is the main thread - malloc space void * result = (void *) malloc(size + sizeof(MemHeaderStruct)); listAdd(mallocList, result); log_into_file("malloc at", result, size + sizeof(MemHeaderStruct)); // Log into a file, if required. return result; } PRINTFMC("\nSize of SHList %d. Pthread_self %u. NULL returned from the list.", SHList->count, (unsigned) pthread_self()); // If nothing can be done - return NULL return NULL ; } else { return SH_alloc_at_base(size, shMapEntry); } }
/* * Initialise an Insense component and start a POSIX thread running the behaviour function from the component. */ void *component_create(behaviour_ft behaviour, int struct_size, int stack_size, int argc, void *argv[], int core) { // Define thread struct IComponent_data *this_ptr; // Allocate space for the struct #if HEAPS == HEAP_PRIVATE // Private heaps struct shMapType *heapElement = new_PrivateHeap(); // Create a new private heap (to be put to the heap map) this_ptr = DAL_alloc_in_specific_heap(struct_size, true, heapElement); // Allocate space for this_ptr in the newly created private heap if (this_ptr == NULL ) { return NULL ; } else { memset(this_ptr, 0, struct_size); } #else // Shared heap if ((this_ptr = ((struct IComponent_data *) DAL_alloc(struct_size, true))) == NULL ) { return NULL; } else { memset(this_ptr, 0, struct_size); } #endif // Initialize this->comp_create_sem my_sem_init(&(this_ptr->component_create_sem), 0); // Setup the stopped condition if (struct_size) { struct IComponent_data *t = (struct IComponent_data*) this_ptr; t->stopped = 0; } // Define new structure for arguments for the wrapper function // Whenever dealing with garbage collection, first define as NULL struct argStructType * argStruct = malloc(sizeof(struct argStructType)); argStruct->behaviour = behaviour; argStruct->argc = argc; argStruct->argv = argv; argStruct->this_ptr = this_ptr; // Create thread #if HEAPS == HEAP_PRIVATE // Private heaps pthread_mutex_lock(&thread_lock); // Lock mutex to make component thread wait until its heap has been put inserted into the heap map #endif pthread_create(&this_ptr->behav_thread, NULL, startRoutine, argStruct); // Create a POSIX thread, use wrapper function startRoutine to pass three arguments to the function running inside of the thread //Set affinity #if AFFINITY_ALGO != AFFINITY_DYNAMIC if (core != -1) { // Manually passed Core ID setAffinityToCore(this_ptr->behav_thread, core);// Use passed ID of a core } else { // Core ID was not passed to the component_create function setAffinity(this_ptr->behav_thread);// Use an algorithm defined in GlobalVars.h } getAffinityThread(this_ptr->behav_thread); // Check if setting affinity worked. Data outputted only in PRINTMC is defined. #endif // If small heaps are used, add a new entry to the map with a pointer to a newly created pthread. #if HEAPS == HEAP_PRIVATE // Private heaps heapElement->thread_id = this_ptr->behav_thread; // Put a thread id to the element to be to the map PRINTFMC("Component created. Thread ID: %x\n", heapElement->thread_id); listAdd(SHList, heapElement); pthread_mutex_unlock(&thread_lock); // Unlock mutex to permit component to continue now that its heap has been put inserted into the heap map #endif // Insert thread into the list of threads listAdd(threadList, this_ptr->behav_thread); my_sem_wait(&this_ptr->component_create_sem); // Wait for creation of the component return this_ptr; }
/* * Entry point of Multi-core Insense runtime. */ int main() { PRINTFMC("Cache line size: %dB\n", cache_line_size());PRINTFMC("Main thread: %u\n", (unsigned) pthread_self()); #if HEAPS // Small heaps // Initialize mutex if (pthread_mutex_init(&thread_lock, NULL ) != 0) { PRINTF("Mutex initialization failed.\n"); return NULL; } #else // Big heap // Initialize mutex if (pthread_mutex_init(&alloc_lock, NULL ) != 0) { PRINTF("Mutex initialization failed.\n"); return NULL ; } #endif mainThread = pthread_self(); // Note the ID of the main thread. // Create a list for storing references to p-threads threadList = listCreate(); // Create map used to store memory locations of small heaps (using Thread safe list) SHList = listCreate(); // Create map used to store memory locations what is allocated using malloc mallocList = listCreate(); // Start recording execution time #if TIMING // CPU time struct timespec start, finish; double elapsed; //clock_gettime(CLOCK_MONOTONIC, &start); // User time time_t start_t, end_t; double diff_t; time(&start_t); #endif // Call primordial_main. primordial_main(NULL ); // Join all p-threads if (threadList != NULL ) { listJoinThreads(threadList); } // Stop recording execution time #if TIMING // CPU time //clock_gettime(CLOCK_MONOTONIC, &finish); elapsed = (finish.tv_sec - start.tv_sec); elapsed += (finish.tv_nsec - start.tv_nsec) / 1000000000.0; printf("CPU: %f seconds elapsed\n", elapsed); #endif // Destroy lists and free memory listDestroy(threadList); listDestroy(SHList); listDestroy(mallocList); pthread_mutex_destroy(&thread_lock); // Destroy mutex lock used with pthreads pthread_mutex_destroy(&alloc_lock); // Destroy mutex lock used with alloc and free in the big heap scheme return 1; }
/* * Entry point of Multi-core Insense runtime. */ int main(int argc, char* argv[]) { PRINTFMC("Cache line size: %dB\n", cache_line_size()); PRINTFMC("Main thread: %u\n", (unsigned) pthread_self()); errval_t err; coreid_t mycore = disp_get_core_id(); if (argc == 2) { num_to_span = atoi(argv[1]); if(num_to_span==0) all_spanned = true; debug_printf("Spanning onto %d cores\n", num_to_span); for (int i = 1; i < num_to_span; i++) { err = domain_new_dispatcher(mycore + i, span_cb, NULL); if (err_is_fail(err)) { DEBUG_ERR(err, "failed span %d", i); } } } else { debug_printf("ERROR: Must specify number of cores to span\n"); return EXIT_FAILURE; } posixcompat_pthread_set_placement_fn(rrPlacement); while (!all_spanned) { thread_yield(); } my_mutex_init(&shared_heap_mutex); #if HEAPS == HEAP_PRIVATE // Private heaps // Initialize mutex if (pthread_mutex_init(&thread_lock, NULL ) != 0) { PRINTF("Mutex initialization failed.\n"); return -1; } #endif mainThread = pthread_self(); // Note the ID of the main thread. // Create a list for storing references to p-threads threadList = listCreate(); // Create map used to store memory locations of small heaps (using Thread safe list) SHList = listCreate(); // Create map used to store memory locations what is allocated using malloc mallocList = listCreate(); // Start recording execution time #if TIMING // CPU time uint64_t start, end; uint64_t tsc_per_ms = 0; sys_debug_get_tsc_per_ms(&tsc_per_ms); start = rdtsc(); #endif // Call primordial_main. primordial_main(NULL ); // Join all p-threads if (threadList != NULL ) { listJoinThreads(threadList); } // Stop recording execution time #if TIMING end = rdtsc(); uint64_t diff = (end - start) / tsc_per_ms; float elapsed = (diff / 1000) + ((diff % 1000) / 1000.0); printf("CPU: %f seconds elapsed\n", elapsed); #endif // Destroy lists and free memory listDestroy(threadList); listDestroy(SHList); listDestroy(mallocList); #if HEAPS == HEAP_PRIVATE pthread_mutex_destroy(&thread_lock); // Destroy mutex lock used with pthreads #endif return 0; }