1 #ifndef _PROCESS_TABLE_H 2 #define _PROCESS_TABLE_H 3 #include "action.h" 4 #include "pmlheaders.h" 5 #include 6 //#include "tclinterp.h" 7 8 #define PEOS_MAX_PID (10) 9 10 #ifdef PALM 11 #define PATH_MAX 256 12 #endif 13 14 #ifdef UNIT_TEST 15 #define MAX_LOCK_ATTEMPTS (1) 16 #else 17 #define MAX_LOCK_ATTEMPTS (10) 18 #endif 19 20 typedef enum { 21 PEOS_NONE = 0x1, /* Unoccupied */ 22 PEOS_READY = 0x2, /* Just loaded, ready to run. */ 23 PEOS_RUNNING = 0x4, /* VM has executed some instructions. */ 24 PEOS_DONE = 0x8, /* Exited. */ 25 PEOS_ERROR = 0x10 /* Exited/aborted, w/error */ 26 } process_status_t ; 27 28 typedef struct peos_context_tag { 29 process_status_t status; 30 int pid; 31 Graph process_graph; 32 int num_resources; 33 char model[PATH_MAX]; 34 peos_resource_t *resources; 35 } peos_context_t; 36 37 extern int get_lock(int filedes) ; 38 39 extern int release_lock(int filedes) ; 40 extern void peos_set_loginname(char *loginname) ; 41 42 char *login_name; 43 44 extern void set_process_table_filename(char *filename) ; 45 46 char *get_script(int pid, char *act_name) ; 47 int peos_get_pid(peos_context_t *context) ; 48 peos_context_t *peos_get_context(int pid) ; 49 int peos_create_instance(char *model,peos_resource_t *resources,int num_resources) INIT_SECTION ; 50 char **peos_list_instances() KRNL_SECTION ; 51 peos_action_t *peos_list_actions(int pid, int *num_actions) KRNL_SECTION; 52 53 54 void peos_set_process_table_file(char *file_name) ; 55 56 int set_resource_binding(int pid, char *resource_name, char *resource_value) ; 57 58 char *get_resource_binding(int pid, char *resource_name) ; 59 60 char *get_resource_qualifier(int pid, char *resource_name) ; 61 62 63 #ifndef PALM 64 int load_process_table(); 65 int save_process_table(); 66 int load_proc_table(char*); 67 #else 68 void load_proc_table() ; 69 #endif 70 71 int delete_entry(int pid) ; 72 #endif 1 /* -*-C-*- 2 ***************************************************************************** 3 * 4 * File: $RCSFile: process_table.c$ 5 * Version: $Id: code-listing.txt,v 1.9 2006/10/25 02:52:32 jnoll Exp $ ($Name: $) 6 * Description: process table manipulation and i/o. 7 * Author: John Noll, Santa Clara University 8 * Created: Sun Jun 29 13:41:31 2003 9 * Modified: Thu Dec 4 11:48:43 2003 (John Noll, SCU) jnoll@carbon.cudenver.edu 10 * Language: C 11 * Package: N/A 12 * Status: $State: Exp $ 13 * 14 * (c) Copyright 2003, Santa Clara University, all rights reserved. 15 * 16 ***************************************************************************** 17 */ 18 #include 19 #include 20 #include 21 #include 22 #ifndef PALM 23 #include 24 #include 25 #include 26 #include 27 #include 28 #include 29 #endif 30 #include "graph.h" 31 32 #include "process_table.h" 33 #include "graph_engine.h" 34 #include "resources.h" 35 #include "process.h" 36 37 38 39 /* Globals. */ 40 peos_context_t process_table[PEOS_MAX_PID+1]; 41 42 int save_proc_table_xml(); 43 44 char *process_table_filename = "proc_table.dat"; 45 46 int filedes; 47 48 49 /* 50 * These functions allow manipulation of processes without access to 51 * process table. 52 */ 53 54 55 /* This function tries to get a lock for the file descriptor */ 56 57 #ifndef PALM 58 int get_lock(int fd) 59 { 60 61 struct flock lck; 62 int num_attempts = 0; 63 64 /* initialize the lock struct for a write lock */ 65 lck.l_type = F_WRLCK; /* get a write exclusive lock */ 66 lck.l_whence = 0; 67 lck.l_start = 0L; 68 lck.l_len = 0L; /* lock the whole file address space */ 69 70 while (fcntl(fd, F_SETLK, &lck) < 0) { 71 if ((errno == EAGAIN) || (errno == EACCES)) { 72 if(++num_attempts <= MAX_LOCK_ATTEMPTS) { 73 fprintf(stderr, "Attempting Process File Lock ...\n"); 74 sleep(2); 75 continue; 76 } 77 78 fprintf(stderr, "File Lock Error: File Busy \n Error Msg : %s\n", strerror(errno)); 79 return -1; 80 } 81 fprintf(stderr, "File Lock Error: Unknown Error\n"); 82 fprintf(stderr, "System Error Message: %s\n", strerror(errno)); 83 return -1; 84 } 85 86 return 1; 87 } 88 89 90 int release_lock(int fd) 91 { 92 93 struct flock lck; 94 95 lck.l_type = F_UNLCK; 96 lck.l_whence = 0; 97 lck.l_start = 0L; 98 lck.l_len = 0L; 99 100 if(fcntl(fd, F_SETLK, &lck) < 0) 101 return -1; 102 else 103 return 1; 104 } 105 #endif 106 107 void peos_set_process_table_file(char *file_name) 108 { 109 if(file_name) { 110 process_table_filename = file_name; 111 } 112 } 113 114 int peos_get_pid(peos_context_t *context) 115 { 116 int pid = context- process_table; 117 return pid >=0 && pid <= PEOS_MAX_PID ? pid : -1; 118 } 119 120 peos_context_t *peos_get_context(int pid) 121 { 122 if (pid < 0 || pid > PEOS_MAX_PID) { 123 return NULL; 124 } 125 126 return &(process_table[pid]); 127 } 128 129 char *get_script(int pid, char *act_name) 130 { 131 peos_context_t *context = peos_get_context(pid); 132 133 if (context != NULL) { 134 return get_script_graph(context -> process_graph, act_name); 135 } 136 else { 137 #ifndef PALM 138 fprintf(stderr,"\n get_script error : context not found\n"); 139 #endif 140 return NULL; 141 } 142 } 143 144 145 void peos_set_loginname(char *loginname) 146 { 147 if(loginname) { 148 login_name = loginname; 149 } 150 } 151 152 153 int set_resource_binding(int pid, char *resource_name, char *resource_value) 154 { 155 #ifndef PALM 156 int i; 157 int num_resources; 158 peos_resource_t *resources; 159 peos_context_t *context = peos_get_context(pid); 160 161 if(context == NULL) 162 return -1; 163 164 resources = context -> resources; 165 num_resources = context -> num_resources; 166 167 if(resources == NULL) 168 return -1; 169 170 for(i = 0; i < num_resources; i++) { 171 if(strcmp(resources[i].name, resource_name) == 0) { 172 if(strlen(resource_value) < RESOURCE_FIELD_LENGTH) { 173 strcpy(resources[i].value, resource_value); 174 return 1; 175 } 176 fprintf(stderr, "buffer overflow in set resource binding\n"); 177 return -1; 178 } 179 } 180 return -1; 181 #else 182 return 0; 183 #endif 184 } 185 186 char *get_resource_binding(int pid, char *resource_name) 187 { 188 #ifndef PALM 189 int i; 190 int num_resources; 191 192 peos_context_t *context = peos_get_context(pid); 193 peos_resource_t *resources; 194 if(context == NULL) return NULL; 195 resources = context -> resources; 196 num_resources = context -> num_resources; 197 if(resources == NULL) return NULL; 198 199 for(i = 0; i < num_resources; i++) { 200 if(strcmp(resources[i].name,resource_name) == 0) { 201 return resources[i].value; 202 } 203 } 204 return NULL; 205 #else 206 return NULL; 207 #endif 208 } 209 210 char *get_resource_qualifier(int pid, char *resource_name) 211 { 212 int i; 213 int num_resources; 214 215 peos_context_t *context = peos_get_context(pid); 216 peos_resource_t *resources; 217 if(context == NULL) return NULL; 218 resources = context -> resources; 219 num_resources = context -> num_resources; 220 if(resources == NULL) return NULL; 221 222 for(i = 0; i < num_resources; i++) { 223 if(strcmp(resources[i].name,resource_name) == 0) { 224 return resources[i].qualifier; 225 } 226 } 227 return NULL; 228 } 229 230 231 /* XXX remove this - it's just as easy to use the graph directly. */ 232 int make_node_lists(Graph g, peos_action_t **actions, int *num_actions, peos_other_node_t **other_nodes, int *num_other_nodes) 233 { 234 Node n; 235 int num_act = 0; 236 int num_nodes = 0; 237 int asize = INST_ARRAY_INCR; 238 int osize = INST_ARRAY_INCR; 239 peos_action_t *act_array = (peos_action_t *) calloc(asize, sizeof(peos_action_t)); 240 241 peos_other_node_t *node_array = (peos_other_node_t *) calloc(osize, sizeof(peos_other_node_t)); 242 243 if (g != NULL) { 244 for(n = g -> source;n != NULL; n = n -> next) { 245 if (n -> type == ACTION) { 246 if(num_act >= asize) { 247 asize = asize + INST_ARRAY_INCR; 248 if ((act_array = realloc(act_array,asize*sizeof(peos_action_t))) == NULL) { 249 fprintf(stderr, "Too Many Actions\n"); 250 free(act_array); 251 return -1; 252 } 253 } 254 strcpy(act_array[num_act].name, n -> name); 255 act_array[num_act].state = STATE(n); 256 act_array[num_act].script = n -> script; 257 num_act ++; 258 } 259 else { 260 if((n->type == SELECTION) || (n->type == BRANCH)) { 261 if(num_nodes >= osize) { 262 osize = osize + INST_ARRAY_INCR; 263 if((node_array = realloc(node_array,osize*sizeof(peos_other_node_t))) == NULL) { 264 fprintf(stderr,"Too many nodes\n"); 265 free(node_array); 266 return -1; 267 } 268 } 269 strcpy(node_array[num_nodes].name, n -> name); 270 node_array[num_nodes].state = STATE(n); 271 num_nodes ++; 272 } 273 } 274 } 275 *actions = act_array; 276 *num_actions = num_act; 277 *other_nodes = node_array; 278 *num_other_nodes = num_nodes; 279 return 1; 280 } 281 else { 282 free(act_array); 283 free(node_array); 284 return -1; 285 } 286 return 0; 287 } 288 289 290 /* 291 * Set state of nodes in g from state info in actions and other nodes. 292 * XXX collapse these two lists into one; there's no need to distinguish. 293 */ 294 int annotate_graph(Graph g, peos_action_t *actions, int num_actions, peos_other_node_t *other_nodes, int num_other_nodes) { 295 int i; 296 Node node; 297 for(node = g -> source; node != NULL; node = node -> next) { 298 if (node -> type == ACTION) { 299 STATE(node) = get_act_state(node -> name,actions,num_actions); 300 } 301 else { 302 if((node->type == SELECTION) || (node->type == BRANCH)) { 303 for(i=0;i < num_other_nodes; i++) { 304 if (strcmp(node->name,other_nodes[i].name)==0) { 305 STATE(node) = other_nodes[i].state; 306 STATE(node->matching) = other_nodes[i].state; 307 } 308 } 309 } 310 } 311 } 312 return 1; 313 } 314 315 #ifndef PALM 316 int load_context(FILE *in, peos_context_t *context) 317 { 318 int i; 319 int num_actions, num_other_nodes; 320 peos_action_t *actions; 321 peos_other_node_t *other_nodes; 322 char* res_value = (char*)malloc(sizeof(char) * 258); 323 324 if (!res_value) { 325 fprintf(stderr, "Error allocating memory: aborting!\n"); 326 exit(255); 327 } 328 329 if (fscanf(in, "pid: %d\n", &context->pid) != 1) 330 return 0; 331 332 if (fscanf(in, "model: %s\n", context->model) != 1) 333 return 0; 334 335 if (strcmp(context->model, "none") == 0) { 336 context->model[0] = '\0'; 337 context->process_graph = NULL; 338 } 339 340 if (fscanf(in, "status: %d\n", (int *)&context->status) != 1) 341 return 0; 342 343 if (fscanf(in, "actions: ") < 0) 344 return 0; 345 346 if (fscanf(in, "%d ", &num_actions) != 1) 347 return 0; 348 349 actions = (peos_action_t *) calloc(num_actions, sizeof(peos_action_t)); 350 351 for (i = 0; i < num_actions; i++) { 352 if (fscanf(in, "%s %d", actions[i].name,(int *)&actions[i].state) != 2) { 353 free(actions); 354 return 0; 355 } 356 actions[i].pid = context->pid; 357 } 358 359 fscanf(in, "\n"); 360 361 if (fscanf(in, "other_nodes: ") < 0) 362 return 0; 363 364 if (fscanf(in, "%d ", &num_other_nodes) != 1) 365 return 0; 366 367 other_nodes = (peos_other_node_t *)calloc(num_other_nodes, sizeof(peos_other_node_t)); 368 369 for (i = 0; i < num_other_nodes; i++) { 370 if (fscanf(in, "%s %d", other_nodes[i].name,(int *)&other_nodes[i].state) != 2) { 371 free(other_nodes); 372 return 0; 373 } 374 other_nodes[i].pid = context->pid; 375 } 376 377 fscanf(in, "\n"); 378 379 if (fscanf(in, "resources: ") < 0) 380 return 0; 381 382 if (fscanf(in, "%d ", &context->num_resources) != 1) 383 return 0; 384 385 context->resources = (peos_resource_t *)calloc(context->num_resources, sizeof(peos_resource_t)); 386 387 for (i = 0; i < context->num_resources; i++) { 388 if (fscanf(in, "%s %s", context->resources[i].name, res_value) != 2) { 389 free(context->resources); 390 return 0; 391 } 392 393 if (strlen(res_value) >= 258) 394 return 0; 395 396 if (res_value[0] != '\"' && res_value[strlen(res_value) - 1] != '\"') 397 return 0; 398 399 strncpy(context->resources[i].value, ++res_value, strlen(res_value) - 2); 400 --res_value; 401 context->resources[i].pid = context->pid; 402 } 403 404 if (fscanf(in, "\n \n") < 0) 405 return 0; 406 407 if (context->status != PEOS_NONE && context->model[0]) { 408 if ((context->process_graph = makegraph(context->model)) == NULL) 409 return 0; 410 initialize_graph(context->process_graph, context->pid); 411 } 412 413 if (context->process_graph && (annotate_graph(context->process_graph, actions, num_actions, other_nodes, num_other_nodes) < 0)) 414 return 0; 415 416 if (res_value) 417 free(res_value); 418 if (num_actions) 419 free(actions); 420 if (num_other_nodes) 421 free(other_nodes); 422 return 1; 423 } 424 #endif 425 426 #ifdef PALM 427 void load_proc_table() 428 { 429 int i; 430 431 for (i = 0; i <= PEOS_MAX_PID; i++) { 432 process_table[i].status = PEOS_NONE; 433 } 434 } 435 436 #else 437 int load_proc_table(char *file) 438 { 439 int i, status = -1; 440 FILE *in; 441 int num_proc = 0; 442 443 filedes = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 444 if (filedes < 0) { 445 fprintf(stderr, "Cannot Get Process Table File Descriptor\n"); 446 exit(EXIT_FAILURE); 447 } 448 449 if(get_lock(filedes) < 0) { 450 fprintf(stderr, "Cannot Obtain Process Table File Lock\n"); 451 exit(EXIT_FAILURE); 452 } 453 454 in = fdopen(filedes, "r+"); 455 456 for (i = 0; i <= PEOS_MAX_PID; i++) { 457 process_table[i].status = PEOS_NONE; 458 } 459 if (in) { 460 status = 0; 461 while (load_context(in, &process_table[num_proc])) 462 num_proc++; 463 /* fclose(in); */ 464 /* XXX This is an issue here. If I close the file stream or the file descriptor, I loose the lock on the file. So right now this will result in some open file streams. */ 465 } 466 else { 467 fprintf(stderr, "Error in getting file pointer for load process table"); 468 release_lock(filedes); 469 close(filedes); 470 } 471 return status; 472 } 473 #endif 474 475 476 477 int save_context(int pid, peos_context_t *context, FILE *out) 478 { 479 #ifndef PALM 480 int i; 481 int num_actions = 0; 482 int num_other_nodes = 0; 483 484 peos_action_t *actions; 485 peos_other_node_t *other_nodes; 486 487 make_node_lists(context->process_graph,&actions,&num_actions,&other_nodes,&num_other_nodes); 488 489 fprintf(out, "pid: %d\n", pid); 490 fprintf(out, "model: %s\n", context->model[0] ? context->model : "none"); 491 fprintf(out, "status: %d\n", context->status); 492 fprintf(out, "actions: "); 493 fprintf(out, "%d ", num_actions); 494 for (i = 0; i < num_actions; i++) { 495 fprintf(out, " %s %d", actions[i].name, actions[i].state); 496 } 497 498 fprintf(out, "\nother_nodes: "); 499 fprintf(out, "%d ", num_other_nodes); 500 for (i = 0; i < num_other_nodes; i++) { 501 fprintf(out, " %s %d", other_nodes[i].name, other_nodes[i].state); 502 } 503 504 fprintf(out, "\nresources: "); 505 fprintf(out, "%d ", context->num_resources); 506 for (i = 0; i < context->num_resources; i++) { 507 fprintf(out, " %s \"%s\"", context->resources[i].name, context->resources[i].value); 508 } 509 510 fprintf(out, "\n \n"); 511 return 1; 512 #else 513 return 0; 514 #endif 515 } 516 517 #ifndef PALM 518 int 519 save_proc_table(char *file) 520 { 521 int i; 522 FILE *out = fopen(file, "w"); 523 524 if (out) { 525 for (i = 0; i <= PEOS_MAX_PID; i++) { 526 save_context(i, &(process_table[i]), out); 527 } 528 release_lock(filedes); 529 fclose(out); 530 close(filedes); 531 } 532 else { 533 fprintf(stderr, "File Pointer Error: %s \n", strerror(errno)); 534 release_lock(filedes); 535 close(filedes); 536 return -1; 537 } 538 return 0; 539 } 540 541 int load_process_table() 542 { 543 return load_proc_table(process_table_filename); 544 } 545 546 int save_process_table() 547 { 548 save_proc_table_xml(); 549 return save_proc_table(process_table_filename); 550 } 551 #endif 552 553 void print_after_escaping(char *str, FILE *fp) 554 { 555 #ifndef PALM 556 int i; 557 if(str!=NULL) { 558 for(i=0; i' : fprintf(fp, ">"); 563 break; 564 case '&' : fprintf(fp, "&"); 565 break; 566 case '"' : fprintf(fp, """); 567 break; 568 default : fprintf(fp, "%c",str[i]); 569 break; 570 } 571 } 572 } 573 else fprintf(fp, "(null)"); 574 #endif 575 } 576 577 578 void print_action_node(Node n, FILE *fp) 579 { 580 #ifndef PALM 581 int num_req_resources; 582 int num_prov_resources; 583 int i; 584 peos_context_t* context; 585 peos_resource_t* proc_resources; 586 peos_resource_t *req_resources; 587 peos_resource_t *prov_resources; 588 589 req_resources = get_resource_list_action_requires(PID(n), n->name, &num_req_resources); 590 prov_resources = get_resource_list_action_provides(PID(n), n->name, &num_prov_resources); 591 context = peos_get_context(PID(n)); 592 if (context && context->num_resources > 0) { 593 proc_resources = (peos_resource_t *) calloc(context->num_resources, sizeof(peos_resource_t)); 594 for (i = 0; i < context->num_resources; i++) { 595 strcpy(proc_resources[i].name, context->resources[i].name); 596 strcpy(proc_resources[i].value, context->resources[i].value); 597 } 598 599 eval_resource_list(&proc_resources, context->num_resources); 600 fill_resource_list_value(proc_resources, context->num_resources, &req_resources, num_req_resources); 601 fill_resource_list_value(proc_resources, context->num_resources, &prov_resources, num_prov_resources); 602 } 603 604 fprintf(fp, "name,fp); 606 fprintf(fp, "\" state=\"%s\">\n", (char *)act_state_name(STATE(n))); 607 fprintf(fp, "\n"); 610 611 for(i=0; i < num_req_resources; i++) { 612 fprintf(fp, "\n",req_resources[i].qualifier); 617 } 618 619 for(i=0; i < num_prov_resources; i++) { 620 621 fprintf(fp, "\n",prov_resources[i].qualifier); 626 627 } 628 629 fprintf(fp, "\n"); 630 #endif 631 } 632 633 634 635 void print_graph(Graph g, FILE *fp) 636 { 637 #ifndef PALM 638 Node n, child, parent; 639 int i; 640 641 for(n = g->source->next; n!=NULL; n = n->next) { 642 643 for(i = 0; i < ListSize(n->predecessors); i++) { 644 parent = (Node) ListIndex(n->predecessors, i); 645 if((parent->type == SELECTION) || (parent->type == BRANCH)) { 646 fprintf(fp, "\n"); 647 } 648 } 649 650 for(i = 0; i < ListSize(n->predecessors); i++) { 651 parent = (Node) ListIndex(n->predecessors, i); 652 if(ORDER(parent) >= ORDER(n)) { 653 fprintf(fp, "\n"); 654 } 655 } 656 657 if(n->type == ACTION) { 658 print_action_node(n,fp); 659 } 660 661 if(n->type == JOIN) { 662 fprintf(fp, "\n"); 663 } 664 665 if(n->type == RENDEZVOUS) { 666 fprintf(fp, "\n"); 667 } 668 669 if(n->type == SELECTION) { 670 fprintf(fp, "\n"); 671 } 672 673 if(n->type == BRANCH) { 674 fprintf(fp, "\n"); 675 } 676 677 for(i = 0; i < ListSize(n->successors); i++) { 678 child = (Node) ListIndex(n->successors, i); 679 if(ORDER(child) <= ORDER(n)) { 680 fprintf(fp, "\n"); 681 } 682 } 683 684 for(i = 0; i < ListSize(n->successors); i++) { 685 child = (Node) ListIndex(n->successors, i); 686 if((child->type == JOIN) || (child->type == RENDEZVOUS)) { 687 fprintf(fp, "\n"); 688 } 689 } 690 } 691 #endif 692 } 693 694 695 int save_proc_table_xml() 696 { 697 #ifndef PALM 698 int i; 699 Graph g; 700 FILE *fp; 701 char *xml_filename = (char *) malloc((strlen(process_table_filename)+strlen(".xml")+1) * sizeof(char)); 702 strcpy(xml_filename, process_table_filename); 703 strcat(xml_filename, ".xml"); 704 705 fp = fopen(xml_filename, "w"); 706 fprintf(fp, "\n"); 707 708 for(i=0; i <= PEOS_MAX_PID; i++) { 709 g = process_table[i].process_graph; 710 if(g != NULL) { 711 fprintf(fp, "\n", i, process_table[i].model, process_table[i].status); 712 print_graph(g, fp); 713 fprintf(fp, "\n"); 714 } 715 } 716 fprintf(fp, "\n"); 717 fclose(fp); 718 return 0; 719 #else 720 return 0; 721 #endif 722 } 723 724 725 726 char **peos_list_instances() 727 { 728 static char *result[PEOS_MAX_PID+1]; 729 int i; 730 731 if(load_process_table() < 0) { 732 fprintf(stderr, "System Error: Cannot Load Process Table\n"); 733 exit(EXIT_FAILURE); 734 } 735 736 for (i = 0; i <= PEOS_MAX_PID; i++) { 737 result[i] = process_table[i].model; 738 } 739 result[i] = NULL; 740 741 if(save_process_table() < 0) { 742 fprintf(stderr, "System Error: Cannot Save Process Table\n"); 743 exit(EXIT_FAILURE); 744 } 745 746 return result; 747 } 748 749 int delete_entry(int pid) 750 { 751 peos_context_t *context; 752 753 if (pid >= 0 && pid <= PEOS_MAX_PID) { 754 context = &(process_table[pid]); 755 if(context -> process_graph != NULL) { 756 context->model[0] = '\0'; 757 context->status = PEOS_NONE; 758 GraphDestroy(context->process_graph); 759 context->process_graph = NULL; 760 context->num_resources = 0; 761 free(context->resources); 762 return 1; 763 } 764 else return -1; 765 } 766 else { 767 return -1; 768 } 769 } 770 771 peos_context_t *find_free_entry() 772 { 773 int i; 774 for (i = 0; i < PEOS_MAX_PID + 1; i++) { 775 process_status_t status = process_table[i].status; 776 if (status & (PEOS_NONE|PEOS_DONE|PEOS_ERROR)) { 777 return &(process_table[i]); 778 } 779 } 780 return NULL; 781 } 782 783 peos_action_t *peos_list_actions(int pid, int *num_actions) 784 { 785 786 int num_act, num_other_nodes, i; 787 peos_action_t *actions; 788 peos_other_node_t *other_nodes; 789 790 if(load_process_table() < 0) { 791 fprintf(stderr, "System Error: Cannot Load Process Table\n"); 792 exit(EXIT_FAILURE); 793 } 794 795 *num_actions = 0; 796 if (process_table[pid].status & (PEOS_DONE | PEOS_NONE | PEOS_ERROR)) { 797 if(save_process_table() < 0) { 798 fprintf(stderr, "System Error: Cannot Save Process Table\n"); 799 exit(EXIT_FAILURE); 800 } 801 return NULL; 802 } 803 804 /* 805 * update process state 806 * XXX This update is redundunt if list 807 * actions is called immediately after a create process, start, 808 * finish, abort or suspend action events. 809 * 810 */ 811 812 if (update_process_state(pid) == VM_INTERNAL_ERROR) { 813 fprintf(stderr, "System Error: Cannot Update Process state \n"); 814 return NULL; 815 } 816 817 if(make_node_lists(process_table[pid].process_graph,&actions,&num_act,&other_nodes,&num_other_nodes) == -1) { 818 if(save_process_table() < 0) { 819 fprintf(stderr, "System Error: Cannot Save Process Table\n"); 820 exit(EXIT_FAILURE); 821 } 822 return NULL; 823 } 824 825 for (i = 0; i < num_act; i++) { 826 actions[i].pid = pid; 827 } 828 829 for (i = 0; i < num_other_nodes; i++) { 830 other_nodes[i].pid = pid; 831 } 832 833 *num_actions = num_act; 834 835 if(save_process_table() < 0) { 836 fprintf(stderr, "System Error: Cannot Save Process Table\n"); 837 exit(EXIT_FAILURE); 838 } 839 840 return actions; 841 } 842 843 844 845 846 847 #ifdef UNIT_TEST 848 #include "test_process_table.c" 849 #endif