drake
1.0.0
|
00001 /* 00002 Copyright 2015 Nicolas Melot 00003 00004 This file is part of Drake. 00005 00006 Drake is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 Drake is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with Drake. If not, see <http://www.gnu.org/licenses/>. 00018 00019 */ 00020 00021 00022 00023 00024 #include <stdlib.h> 00025 #include <string.h> 00026 00027 #include <drake/mapping.h> 00028 #include <drake/platform.h> 00029 #include <assert.h> 00030 00031 #include "drawgraph-2.h" 00032 00033 // Mapping manipulations 00034 mapping_t* 00035 pelib_alloc_collection(mapping_t)(size_t size) 00036 { 00037 mapping_t * mapping; 00038 size_t res; 00039 00040 res = 1; 00041 mapping = malloc(sizeof(mapping_t) + sizeof(processor_t*) * size); 00042 00043 if (mapping != NULL) 00044 { 00045 mapping->proc = malloc(sizeof(processor_t*) * size); 00046 if(mapping->proc != NULL) 00047 { 00048 mapping->processor_count = 0; 00049 mapping->max_processor_count = size; 00050 mapping->task_count = 0; 00051 00052 // Makes sure the allocated memory was actually allocated 00053 if (res != 0) 00054 { 00055 return mapping; 00056 } 00057 } 00058 free(mapping->proc); 00059 free(mapping); 00060 } 00061 00062 return NULL; 00063 } 00064 00065 int 00066 pelib_free(mapping_t)(mapping_t * solution) 00067 { 00068 size_t i; 00069 00070 for (i = 0; i < solution->processor_count; i++) 00071 { 00072 pelib_free(processor_t)(solution->proc[i]); 00073 } 00074 free(solution->proc); 00075 free(solution); 00076 00077 return 1; 00078 } 00079 00080 int 00081 pelib_copy(mapping_t)(mapping_t source, mapping_t *copy) 00082 { 00083 size_t i; 00084 00085 //copy = pelib_alloc(mapping_t)(DRAKE_MAPPING_MAX_TASK_COUNT); 00086 copy->processor_count = source.processor_count; 00087 copy->task_count = source.task_count; 00088 00089 for (i = 0; i < copy->processor_count; i++) 00090 { 00091 //drake_processor_destroy(copy->proc[i]); 00092 pelib_copy(processor_t)(*source.proc[i], copy->proc[i]); 00093 } 00094 00095 return 1; 00096 } 00097 00098 int 00099 drake_mapping_insert_task(mapping_t* mapping, processor_id pid, task_t* task) 00100 { 00101 int processor_index; 00102 00103 processor_index = drake_mapping_find_processor_index(mapping, pid); 00104 00105 if (drake_processor_insert_task(mapping->proc[processor_index], task) == 1) 00106 { 00107 mapping->task_count++; 00108 00109 return 1; 00110 } 00111 else 00112 { 00113 return 0; 00114 } 00115 } 00116 int 00117 drake_mapping_remove_task(mapping_t* mapping, task_id task) 00118 { 00119 processor_id pid; 00120 00121 pid = drake_mapping_find_processor(mapping, task); 00122 00123 if (pid < mapping->processor_count && drake_processor_remove_task( 00124 mapping->proc[pid], task) == 1) 00125 { 00126 mapping->task_count--; 00127 00128 return 1; 00129 } 00130 else 00131 { 00132 return 0; 00133 } 00134 } 00135 int 00136 drake_mapping_find_processor_index(mapping_t* mapping, processor_id pid) 00137 { 00138 int i; 00139 for (i = 0; i < mapping->processor_count; i++) 00140 { 00141 if (mapping->proc[i]->id == pid) 00142 { 00143 return i; 00144 } 00145 } 00146 return i; 00147 } 00148 processor_id 00149 drake_mapping_find_processor(mapping_t* mapping, task_id tid) 00150 { 00151 int i; 00152 for (i = 0; i < mapping->processor_count; i++) 00153 { 00154 if (drake_processor_find_task(mapping->proc[i], tid) 00155 != mapping->proc[i]->handled_nodes) 00156 { 00157 return mapping->proc[i]->id; 00158 } 00159 } 00160 00161 return -1; 00162 } 00163 int 00164 drake_mapping_insert_processor(mapping_t* mapping, processor_t* processor) 00165 { 00166 // If there is room for a new processor in mapping, and this processor id was not already present 00167 if (mapping->processor_count < mapping->max_processor_count 00168 && drake_mapping_find_processor_index(mapping, processor->id) 00169 == mapping->processor_count) 00170 { 00171 mapping->proc[mapping->processor_count] = pelib_alloc_collection(processor_t)(processor->node_capacity); 00172 00173 // printf("%s: %X\n", __FUNCTION__, mapping->proc[mapping->processor_count]); 00174 00175 if (mapping->proc[mapping->processor_count] != NULL) 00176 { 00177 pelib_copy(processor_t)(*processor, mapping->proc[mapping->processor_count]); 00178 mapping->processor_count++; 00179 00180 return 1; 00181 } 00182 else 00183 { 00184 return 0; 00185 } 00186 } 00187 else 00188 { 00189 return 0; 00190 } 00191 } 00192 int 00193 drake_mapping_remove_processor(mapping_t* mapping, int processor_id) 00194 { 00195 // TODO: implement 00196 return 0; 00197 } 00198 00199 // Mapping properties 00200 int 00201 drake_mapping_violations(mapping_t* mapping) 00202 { 00203 // A mapping is correct iff every task is mapped to exactly one processor 00204 processor_id pid, found_pid; 00205 size_t i, mapped, overmapped; 00206 00207 overmapped = 0; 00208 mapped = 0; 00209 00210 for (pid = 0; pid < mapping->processor_count; pid++) 00211 { 00212 for (i = 0; i < mapping->proc[pid]->handled_nodes; i++) 00213 { 00214 found_pid = drake_mapping_find_processor(mapping, 00215 mapping->proc[pid]->task[i]->id); 00216 00217 if (found_pid == pid) // All good 00218 { 00219 mapped++; 00220 } 00221 else 00222 { 00223 if (found_pid != mapping->processor_count) // // The task is mapped to several processors 00224 { 00225 overmapped++; 00226 } 00227 // else the task is not mapped at all 00228 } 00229 } 00230 } 00231 00232 if (mapped == mapping->task_count && overmapped == 0) 00233 { 00234 return 1; 00235 } 00236 else 00237 { 00238 return 0; 00239 } 00240 } 00241 00242 // Mapping human interface 00243 FILE* 00244 pelib_printf(mapping_t)(FILE* stream, mapping_t mapping) 00245 { 00246 char *str = pelib_string(mapping_t)(mapping); 00247 fprintf(stream, "%s\n", str); 00248 00249 free(str); 00250 00251 return stream; 00252 } 00253 00254 char* 00255 pelib_string(mapping_t)(mapping_t mapping) 00256 { 00257 size_t i, total_length; 00258 char *proc_str, *str; 00259 00260 total_length = 0; 00261 for (i = 0; i < mapping.processor_count; i++) 00262 { 00263 total_length += (DRAKE_MAPPING_PROC_ID_CHAR_LENGTH 00264 + (sizeof(DRAKE_MAPPING_SEPARATOR) + DRAKE_MAPPING_NODE_CHAR_LENGTH) 00265 * mapping.proc[i]->handled_nodes + 2); 00266 } 00267 total_length++; // Provide space for the trailing character \0 00268 00269 str = malloc(sizeof(char) * total_length); 00270 str[0] = '\0'; 00271 00272 for (i = 0; i < mapping.processor_count; i++) 00273 { 00274 proc_str = pelib_string(processor_t)(*mapping.proc[i]); 00275 sprintf(&(str[strlen(str)]), "[%s]", proc_str); 00276 free(proc_str); 00277 } 00278 00279 return str; 00280 } 00281 00282 static int 00283 take_all_tasks(task_t *task) 00284 { 00285 return 1; 00286 } 00287 00288 static mapping_t* 00289 mapping_loadstr(mapping_t * mapping, char * str, int(filter)(task_t*)) 00290 { 00291 FILE * stream_str; 00292 00293 //printf("[%s] %s\n", __func__, str); 00294 stream_str = (FILE*)fmemopen((void*)str, strlen(str), "r"); 00295 // printf("file descriptor: %i\n", *stream_str); 00296 00297 mapping = drake_mapping_loadfilterfile(mapping, stream_str, filter); 00298 fclose(stream_str); 00299 //printf("%i\n", i == EOF); 00300 00301 return mapping; 00302 } 00303 00304 mapping_t* 00305 drake_mapping_loadstr(mapping_t * mapping, char * str) 00306 { 00307 return mapping_loadstr(mapping, str, take_all_tasks); 00308 } 00309 00310 mapping_t* 00311 drake_mapping_loadfilterstr(mapping_t* mapping, char* str, int (filter)(task_t*)) 00312 { 00313 //printf("[%s] %s\n", __func__, str); 00314 return mapping_loadstr(mapping, str, filter); 00315 } 00316 00317 /* TODO: draw mappings with as many tasks as in the mapping instead of 2 ^ (p - 1) */ 00318 static void 00319 mapping_draw(FILE* read, FILE* write, FILE* err) 00320 { 00321 pelib_drawgraph2_draw(read, write, err); 00322 } 00323 00324 mapping_t* 00325 drake_mapping_loadfile(mapping_t * mapping, FILE * file) 00326 { 00327 return drake_mapping_loadfilterfile(mapping, file, take_all_tasks); 00328 } 00329 00330 mapping_t* 00331 drake_mapping_loadfilterfile(mapping_t * mapping, FILE * file, int (filter)(task_t*)) 00332 { 00333 /* char line [ 128 ]; 00334 printf("[%s] ", __func__); 00335 while ( fgets ( line, sizeof line, file ) != NULL ) 00336 { 00337 fputs ( line, stdout ); 00338 } 00339 //fclose ( file ); 00340 return NULL;*/ 00341 mapping = pelib_drawgraph2_load(file, mapping, filter); 00342 //printf("[%s] ", __func__); 00343 //drake_mapping_display(mapping); 00344 return mapping; 00345 } 00346 00347 char* 00348 drake_mapping_drawstr(mapping_t * mapping, char * str) 00349 { 00350 unsigned int i, k, proc_index, task_index; 00351 size_t length; 00352 FILE *stream; 00353 00354 // Opens a stream that points to str 00355 stream = (FILE*)open_memstream(&str, &length); 00356 assert(stream != NULL); 00357 00358 // Warm-up 00359 fprintf(stream, "k = %u\n", mapping->processor_count); 00360 fprintf(stream, DRAKE_MAPPING_OUT_WARMUP); 00361 fprintf(stream, "%-*c", DRAKE_MAPPING_OUT_NODE_COLUMN_WIDTH, ':'); 00362 for (i = 0; i < mapping->processor_count; i++) 00363 { 00364 fprintf(stream, "%-*u", DRAKE_MAPPING_OUT_PROC_COLUMN_WIDTH, i + 1); 00365 } 00366 fprintf(stream, "%s\n", DRAKE_MAPPING_OUT_AFFECT); 00367 00368 for (task_index = 0; task_index < mapping->task_count; task_index++) 00369 { 00370 proc_index = drake_mapping_find_processor_index(mapping, drake_mapping_find_processor(mapping, task_index + 1)); 00371 fprintf(stream, "%-*u", DRAKE_MAPPING_OUT_NODE_COLUMN_WIDTH, task_index + 1); 00372 00373 for (k = 0; k < mapping->processor_count; k++) 00374 { 00375 if (k != proc_index) 00376 { 00377 fprintf(stream, "%-*u", DRAKE_MAPPING_OUT_PROC_COLUMN_WIDTH, 0); 00378 } 00379 else 00380 { 00381 fprintf(stream, "%-*u", DRAKE_MAPPING_OUT_PROC_COLUMN_WIDTH, 1); 00382 } 00383 } 00384 fprintf(stream, "\n"); 00385 } 00386 fprintf(stream, DRAKE_MAPPING_OUT_ENDING); 00387 00388 // Closes the stream 00389 fflush(stream); 00390 fclose(stream); 00391 00392 return str; 00393 } 00394 00395 task_t* 00396 drake_mapping_find_task(mapping_t* mapping, task_id id) 00397 { 00398 int target_task_rank, target_proc_rank; 00399 processor_t *target_proc; 00400 00401 target_proc_rank = drake_mapping_find_processor(mapping, id); 00402 if(target_proc_rank >= 0) 00403 { 00404 target_proc = mapping->proc[target_proc_rank]; 00405 target_task_rank = drake_processor_find_task(target_proc, id); 00406 00407 if(target_task_rank >= 0) 00408 { 00409 return target_proc->task[target_task_rank]; 00410 } 00411 } 00412 00413 return NULL; 00414 } 00415 00416 int 00417 drake_mapping_draw(mapping_t * mapping, FILE * file) 00418 { 00419 char * str = NULL; 00420 FILE *stream; 00421 00422 str = drake_mapping_drawstr(mapping, str); 00423 stream = (FILE*)fmemopen(str, strlen(str) + 1, "r"); 00424 00425 mapping_draw(stream, file, stderr); 00426 fclose(stream); 00427 00428 free(str); 00429 00430 return 1; 00431 } 00432