1/* BEGIN LICENSE BLOCK 2 * Version: CMPL 1.1 3 * 4 * The contents of this file are subject to the Cisco-style Mozilla Public 5 * License Version 1.1 (the "License"); you may not use this file except 6 * in compliance with the License. You may obtain a copy of the License 7 * at www.eclipse-clp.org/license. 8 * 9 * Software distributed under the License is distributed on an "AS IS" 10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11 * the License for the specific language governing rights and limitations 12 * under the License. 13 * 14 * The Original Code is The ECLiPSe Constraint Logic Programming System. 15 * The Initial Developer of the Original Code is Cisco Systems, Inc. 16 * Portions created by the Initial Developer are 17 * Copyright (C) 1989-2006 Cisco Systems, Inc. All Rights Reserved. 18 * 19 * Contributor(s): 20 * 21 * END LICENSE BLOCK */ 22 23/* 24 * VERSION $Id: init.c,v 1.9 2013/09/28 00:25:39 jschimpf Exp $ 25 */ 26 27/**************************************************************************** 28 * 29 * init.c 30 * ------ 31 * 32 * Initialisation routines for ECLiPSe 33 * 34 * 35 ***************************************************************************/ 36 37#include "config.h" 38#include "sepia.h" 39#include "types.h" 40#include "embed.h" 41#include "error.h" 42#include "mem.h" 43#include "dict.h" 44#include "module.h" 45#include "os_support.h" 46#include "ec_io.h" 47 48#include <errno.h> 49#include <stdio.h> /* for sprintf() */ 50#include <stdlib.h> /* for exit() */ 51 52#ifdef HAVE_STRING_H 53#include <string.h> 54#endif 55 56#ifdef HAVE_SYS_MMAN_H 57#include <sys/mman.h> 58#endif 59 60 61 62/* 63 * EXTERN declarations 64 */ 65 66extern int io_init(int flags); 67 68 69extern void bip_arith_init(int flags), 70 bip_array_init(int flags, char *installation_dir), 71 bip_comp_init(int flags), 72 bip_control_init(int flags), 73 bip_db_init(int flags), 74 bip_delay_init(int flags), 75 bip_domain_init(int flags), 76 bip_elipsys_fd_init(int flags), 77 bip_emu_init(int flags), 78 bip_gc_init(int flags), 79 bip_io_init(int flags), 80 bip_load_init(int flags), 81 bip_misc_init(int flags), 82 bip_module_init(int flags), 83 bip_op_init(int flags), 84 bip_parallel_init(), 85 bip_copy_init(int flags), 86 bip_serialize_init(int flags), 87 bip_record_init(int flags), 88 bip_store_init(int flags), 89 bip_shelf_init(int flags), 90 bip_bag_init(int flags), 91 bip_heapevent_init(int flags), 92 bip_strings_init(int flags), 93 bip_tconv_init(int flags), 94 code_init(int flags), 95 compiler_init(int flags), 96 dict_init(int flags), 97 emu_init(int flags, int vm_options), 98 error_init(int flags), 99 exit_mps(), 100 handlers_init(int flags), 101 handlers_fini(), 102 lex_init(int flags), 103 malloc_init(void), 104 megalog_boot_init(), 105 megalog_init(), 106 megalog_end(), 107 mem_init(int flags), 108 mem_fini(void), 109 module_init(int flags), 110 opaddr_init(void), 111 op_init(int flags), 112 parallel_init(), 113 msg_init(), 114 read_init(int flags), 115#ifdef SAVEDSTATES 116 save_res_init(), 117#endif 118 setup_mps(), 119 worker_init(), 120 write_init(int flags); 121 122extern void kegi_init(), 123 user_init(); 124 125extern void short_sleep(); 126 127extern void default_panic(const char *what, const char *where); 128extern char * eclipsehome(void); 129 130/* 131 * GLOBAL function declarations 132 */ 133 134void ec_worker_cleanup(void); 135 136/* 137 * LOCAL function declarations 138 */ 139 140static void _make_error_message(int err, char *where, char *buf), 141 wait_for_flag(volatile int *pflag, int mask); 142 143static char * arg1 = "Embedded ECLiPSE"; 144 145/* 146 * GLOBAL variable definitions 147 */ 148 149/* added = {} initialisation (which does nothing) to work around MinGW bug 150 with gcc 4.2 so that entry for ec_ will be generated for eclipse.def 151 (Kish Shen 2010-09-24) 152*/ 153t_eclipse_data ec_ = {}; 154 155/* TODO: move the following into ec_ on main branch */ 156char *ec_eclipse_home; /* canonical, hp_allocated */ 157 158 159/* 160 * The ec_options structure is 161 * - statically initialised 162 * - can be overwritten by the embedding application before ec_init() 163 * - is pure input, i.e. must not be changed by eclipse itself 164 * - memory pointed to by members is owned by host application, not ECLiPSe 165 */ 166 167t_eclipse_options ec_options = 168{ 169 /* option_p */ 170 0, 171 172 /* mapfile */ 173 (char *) NULL, 174 175 /* parallel_worker */ 176 0, 177 178 /* io_option */ 179 SHARED_IO, 180 181 /* Argv,Argc */ 182 (char **) &arg1, 183 1, 184 185 /* rl */ 186#if defined(HAVE_READLINE) 187 1, 188#else 189 0, 190#endif 191 192 /* localsize globalsize */ 193#if defined(HAVE_MMAP) || defined(_WIN32) 194 VIRTUAL_LOCAL_STACK_DEFAULT*MB*2*SIZEOF_WORD, 195 VIRTUAL_GLOBAL_STACK_DEFAULT*MB*2*SIZEOF_WORD, 196#else 197#define KB 1024 198#define DEFAULT_LOCAL 200*KB 199#define DEFAULT_GLOBAL 750*KB 200 DEFAULT_LOCAL,DEFAULT_GLOBAL, 201#endif 202 /* privatesize,sharedsize */ 203 VIRTUAL_HEAP_DEFAULT*MB*2*SIZEOF_WORD, 204 VIRTUAL_SHARED_DEFAULT*MB*2*SIZEOF_WORD, 205 206 /* user_panic */ 207 default_panic, 208 209 /* allocation */ 210#if defined(HAVE_MMAP) || defined(_WIN32) 211#ifdef sun4_0 212 ALLOC_FIXED, 213#else 214 ALLOC_VIRTUAL, 215#endif 216#else 217 ALLOC_PRE, 218#endif 219 220 /* default_module */ 221 "eclipse", 222 223 /* eclipse_home, input, non-canonical */ 224 (char *) 0, 225 226 /* init_flags */ 227 (INIT_SHARED|INIT_PRIVATE|INIT_ENGINE|INIT_PROCESS), 228 229 /* debug_level */ 230 0, 231 232 /* default_language */ 233 (char *) 0 234}; 235 236 237/*---------------------------------------------------------------- 238 * Initialisation 239 * 240 * init_flags indicates what parts of the system need to be 241 * initialised (bit-significant flags): 242 * 243 * INIT_SHARED shared/saveable heap 244 * REINIT_SHARED heap was restored, some info must be updated 245 * INIT_PRIVATE C variables, private heap 246 * INIT_ENGINE abstract machine 247 * INIT_PROCESS do initialisations that are needed once 248 * 249 * Initialisation is done in different situations: 250 * 251 * raw boot INIT_SHARED|INIT_PRIVATE|INIT_ENGINE|INIT_PROCESS 252 * after -r REINIT_SHARED|INIT_PROCESS|INIT_PRIVATE [|INIT_ENGINE] 253 * after -c INIT_PROCESS|INIT_PRIVATE 254 * after restore/1 REINIT_SHARED|INIT_PRIVATE [|INIT_ENGINE] 255 * after reset 0 (maybe INIT_PRIVATE) 256 *----------------------------------------------------------------*/ 257 258 259int 260eclipse_global_init(int init_flags) 261{ 262 int err; 263 264 ec_os_init(); 265 266 if (!(init_flags & (INIT_SHARED|REINIT_SHARED))) 267 { 268 /* if we attach to a heap, it must be fully initialised */ 269 wait_for_flag(&GlobalFlags, HEAP_READY); 270 } 271 272 /* 273 * convert pathname to canonical representation 274 */ 275 if (ec_options.eclipse_home) 276 { 277 char buf[MAX_PATH_LEN]; 278 (void) canonical_filename(ec_options.eclipse_home, buf); 279 if (buf[0] != '/') 280 { 281 /* This is mainly to enable the use of -D with relative path */ 282 char buf2[MAX_PATH_LEN]; 283 get_cwd(buf2, MAX_PATH_LEN); 284 strcat(buf2, buf); 285 ec_eclipse_home = strcpy((char*) hp_alloc(strlen(buf2)+1), buf2); 286 } 287 else 288 { 289 ec_eclipse_home = strcpy((char*) hp_alloc(strlen(buf)+1), buf); 290 } 291 } 292 else 293 { 294 ec_eclipse_home = strcpy((char*) hp_alloc(strlen(eclipsehome())+1), eclipsehome()); 295 } 296 297 dict_init(init_flags); 298 opaddr_init(); 299 worker_init(init_flags); 300 op_init(init_flags); 301 module_init(init_flags); /* creates modules */ 302 if ((err = io_init(init_flags)) != PSUCCEED) 303 { 304 char msg[1024]; 305 _make_error_message(err, "io_init", msg); 306 ec_bad_exit(msg); 307 } 308 bip_emu_init(init_flags); 309 bip_arith_init(init_flags); 310 bip_array_init(init_flags, ec_eclipse_home); 311 bip_comp_init(init_flags); 312 bip_control_init(init_flags); 313 bip_db_init(init_flags); 314 bip_delay_init(init_flags); 315 bip_domain_init(init_flags); 316 bip_elipsys_fd_init(init_flags); 317 bip_record_init(init_flags); 318 bip_store_init(init_flags); 319 bip_shelf_init(init_flags); 320 bip_bag_init(init_flags); 321 bip_heapevent_init(init_flags); 322 bip_parallel_init(init_flags); 323 bip_gc_init(init_flags); 324 bip_io_init(init_flags); 325 bip_op_init(init_flags); 326 bip_copy_init(init_flags); 327 bip_serialize_init(init_flags); 328 compiler_init(init_flags); 329 error_init(init_flags); 330 lex_init(init_flags); 331 read_init(init_flags); 332 write_init(init_flags); 333 bip_load_init(init_flags); 334 bip_strings_init(init_flags); 335 bip_tconv_init(init_flags); 336#ifdef SAVEDSTATES 337 save_res_init(init_flags); 338#endif 339 kegi_init(init_flags); 340 code_init(init_flags); 341 bip_module_init(init_flags); 342 if (init_flags & INIT_SHARED) megalog_boot_init(); 343 user_init(init_flags); 344 bip_misc_init(init_flags); 345 handlers_init(init_flags); 346 msg_init(init_flags); 347 if (init_flags & INIT_PRIVATE) 348 megalog_init(ec_options.option_p); /* create shared memory etc */ 349 350 return 0; 351} 352 353int 354eclipse_boot(char *initfile) 355{ 356 value v1, v2; 357 type t1, t2; 358 v1.did = enter_dict(initfile, 0); 359 t1.kernel = TDICT; 360 v2.did = d_.kernel_sepia; 361 t2.kernel = ModuleTag(d_.kernel_sepia); 362 return boot_emulc(v1, t1, v2, t2); 363} 364 365 366/* 367 * Preliminary I/O routines to be used while our own I/O is not initialised 368 */ 369 370static void 371_make_error_message(int err, char *where, char *buf) 372{ 373 extern char *ec_error_message[]; 374 if (err == SYS_ERROR) 375 sprintf(buf, "ECLiPSe: %s (%s) in %s.", ec_error_message[err], strerror(errno), where); 376 else 377 sprintf(buf, "ECLiPSe: %s in %s.", ec_error_message[err], where); 378} 379 380 381/*---------------------------------------------------------------- 382 * Shutdown code (see also p_exit(), exit/1 and halt/0) 383 * 384 * Shutdown can be requested either from Prolog (exit/1,halt/0) or 385 * from C (ec_cleanup()). In either case, we first do a cleanup at 386 * the Prolog level (running finalization goals etc), then the low 387 * level cleanup ec_cleanup1(). 388 * 389 * The cleanup is to be done such that all dynamic resources are 390 * freed, and the system can either be reinitialised by ec_init(), 391 * or, in the embedded case, the eclipse.[so,dll] can be unloaded, 392 * freeing all ECLiPSe-related resources in the process. 393 * In particular, we must take care of: 394 * - closing all I/O 395 * - destroying threads 396 * - unloading shared libraries 397 * - deallocating the engine stacks 398 * - resetting signal handlers 399 * - freeing all heap spaces 400 * - resetting all static variables to their initial state 401 * Because we destroy our shared and private heaps indiscriminately 402 * at the end, we need not be too concerned about explicitly deallo- 403 * cating all data structures that were previously allocated there. 404 * However, we must then be sure that the embedding host does not 405 * retain pointers to such (hg/hp_allocated) data. In case ECLiPSe 406 * makes any allocations with the system malloc(), these must be 407 * freed explicitly otherwise they will constitute a memory leak. 408 *----------------------------------------------------------------*/ 409 410int 411ec_cleanup1(int exit_code) 412{ 413 /* 414 * Assume Prolog-level cleanup is already done, 415 * either in ec_cleanup() or in exit/1 416 */ 417 418 if (ec_options.parallel_worker) 419 halt_system(exit_code); 420 421 ec_worker_cleanup(); 422 return PSUCCEED; 423} 424 425int Winapi 426ec_cleanup(void) 427{ 428 int res; 429 pword goal, module; 430 431 /* Do Prolog-level cleanup code: call cleanup_before_exit/0 */ 432 Make_Atom(&goal, enter_dict("cleanup_before_exit", 0)); 433 module.val.did = d_.kernel_sepia; 434 module.tag.kernel = ModuleTag(d_.kernel_sepia); 435 res = main_emulc_noexit(goal.val, goal.tag, module.val, module.tag); 436 if (!(res == PSUCCEED || res == PFAIL)) 437 return res; 438 439 return ec_cleanup1(0); 440} 441 442 443/* 444 * Cleanup one worker 445 */ 446void 447ec_worker_cleanup(void) 448{ 449 megalog_end(); 450 451 handlers_fini(); /* undo signal handler settings */ 452 /* (before shutting down emu and i/o) */ 453 454 ec_emu_fini(); /* destroy the engine */ 455 ec_embed_fini(); 456 457 /* TODO: find handles stored in the heap, and free them */ 458 459 bip_load_fini(); /* unload any shared libraries */ 460 461 flush_and_close_io(1); /* shut down I/O system */ 462 463 ec_os_fini(); /* timers, threads, sockets */ 464 465 if (ec_options.parallel_worker) 466 exit_mps(); 467 468 /* disable interrupts because we cannot serve them properly when 469 * all streams are closed */ 470 Disable_Int(); 471 472 /* finally, release all heap memory */ 473 mem_fini(); 474} 475 476/* 477 * HALT signal handler 478 */ 479int 480halt_session(void) 481{ 482 ec_cleanup(); 483 exit(0); 484} 485 486static void 487wait_for_flag(volatile int *pflag, int mask) /* volatile is important! */ 488{ 489 while (!(*pflag & mask)) 490 short_sleep(10000); 491} 492 493