// This file is part of BOINC. // http://boinc.berkeley.edu // Copyright (C) 2008 University of California // // BOINC is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License // as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // BOINC is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with BOINC. If not, see . #ifndef _TASK_ #define _TASK_ #ifndef _WIN32 #include #include #endif #include "client_types.h" #include "common_defs.h" #include "app_ipc.h" #include "procinfo.h" // values for preempt_type // #define REMOVE_NEVER 0 #define REMOVE_MAYBE_USER 1 #define REMOVE_MAYBE_SCHED 2 #define REMOVE_ALWAYS 3 class CLIENT_STATE; typedef int PROCESS_ID; #define MAX_STDERR_LEN 65536 // The stderr output of an application is truncated to this length // before sending to server, // to protect against apps that write unbounded amounts. /// Represents a job in progress. /// When an active task is created, it is assigned a "slot" /// which determines the directory it runs in. /// This doesn't change over the life of the active task; /// thus the task can use the slot directory for temp files /// that BOINC doesn't know about. class ACTIVE_TASK { public: #ifdef _WIN32 HANDLE pid_handle, shm_handle; bool kill_all_children(); #endif SHMEM_SEG_NAME shmem_seg_name; RESULT* result; WORKUNIT* wup; APP_VERSION* app_version; PROCESS_ID pid; PROCINFO procinfo; //// START OF ITEMS SAVED IN STATE FILE private: public: int _task_state; /// subdirectory of slots/ where this runs int slot; /// CPU at the last checkpoint /// Note: "CPU time" refers to the sum over all episodes. /// (not counting the "lost" time after the last checkpoint /// in episodes before the current one) /// TODO: debt should be based on FLOPs, not CPU time /// CPU time at the start of current episode double checkpoint_cpu_time; /// elapsed time at last checkpoint double checkpoint_elapsed_time; /// App's estimate of how much of the work unit is done. /// Passed from the application via an API call; /// will be zero if the app doesn't use this call double fraction_done; /// most recent CPU time reported by app double current_cpu_time; //// END OF ITEMS SAVED IN STATE FILE int scheduler_state; int next_scheduler_state; // temp int signal; double episode_start_cpu_time; /// Wall time at the start of the current run interval double run_interval_start_wall_time; /// wall time at the last checkpoint double checkpoint_wall_time; /// current total elapsed (running) time double elapsed_time; /// disk used by output files and temp files of this task int current_disk_usage(double&); /// directory where process runs (relative) char slot_dir[256]; /// same, absolute /// This is used only to run graphics apps /// (that way don't have to worry about top-level dirs /// being non-readable, etc). char slot_path[512]; /// abort if total CPU exceeds this double max_cpu_time; /// abort if disk usage (in+out+temp) exceeds this double max_disk_usage; /// abort if memory usage exceeds this double max_mem_usage; bool have_trickle_down; bool send_upload_file_status; /// working set too large to run now bool too_large; bool needs_shmem; // waiting for a free shared memory segment int want_network; /// This task wants to do network comm (for F@h) /// this is passed via share-memory message (app_status channel) double abort_time; /// when we sent an abort message to this app /// kill it 5 seconds later if it doesn't exit double quit_time; /// when we sent a quit message; kill if still there after 10 sec int premature_exit_count; /// core/app shared mem segment APP_CLIENT_SHM app_client_shm; MSG_QUEUE graphics_request_queue; MSG_QUEUE process_control_queue; void set_task_state(int, const char*); inline int task_state() { return _task_state; } bool coprocs_reserved; void reserve_coprocs(); void free_coprocs(); // info related to app's graphics mode (win, screensaver, etc.) // /// mode acked by app int graphics_mode_acked; /// mode before last screensaver request int graphics_mode_before_ss; double graphics_mode_ack_timeout; #ifdef SIM double cpu_time_left; #endif #if (defined (__APPLE__) && (defined(__i386__) || defined(__x86_64__))) // PowerPC apps emulated on i386 Macs crash if running graphics int powerpc_emulated_on_i386; int is_native_i386_app(char*); #endif GRAPHICS_MSG graphics_msg; void request_graphics_mode(GRAPHICS_MSG&); int request_reread_prefs(); int request_reread_app_info(); void check_graphics_mode_ack(); int link_user_files(); int get_shmem_seg_name(); bool runnable() { return _task_state == PROCESS_UNINITIALIZED || _task_state == PROCESS_EXECUTING || _task_state == PROCESS_SUSPENDED; } ACTIVE_TASK(); ~ACTIVE_TASK(); int init(RESULT*); void cleanup_task(); int start(bool first_time); // start a process int request_exit(); // ask the process to exit gracefully, // i.e. by sending a message int request_abort(); // send "abort" message bool process_exists(); /// Kill process forcibly, /// Unix: send a SIGKILL signal, Windows: TerminateProcess() /// if restart is true, arrange for resulted to get restarted; /// otherwise it ends with an error int kill_task(bool restart); /// tell a process to stop executing (but stay in mem) /// Done by sending it a message int suspend(); /// Undo a suspend: send a message int unsuspend(); /// can be called whether or not process exists int abort_task(int exit_status, const char*); /// return true if this task has exited bool has_task_exited(); /// preempt (via suspend or quit) a running task int preempt(int preempt_type); int resume_or_start(bool); void send_network_available(); #ifdef _WIN32 void handle_exited_app(unsigned long); #else void handle_exited_app(int stat); #endif void handle_premature_exit(bool&); bool check_max_disk_exceeded(); bool get_app_status_msg(); bool get_trickle_up_msg(); double est_time_to_completion(bool for_work_fetch); bool read_stderr_file(); bool finish_file_present(); bool supports_graphics(); int write_app_init_file(); int move_trickle_file(); int handle_upload_files(); void upload_notify_app(const FILE_INFO*, const FILE_REF*); int copy_output_files(); int write(MIOFILE&); int write_gui(MIOFILE&); int parse(MIOFILE&); }; /// Represents the set of all jobs in progress class ACTIVE_TASK_SET { public: typedef std::vector active_tasks_v; active_tasks_v active_tasks; ACTIVE_TASK* lookup_pid(int); ACTIVE_TASK* lookup_result(RESULT*); void init(); bool poll(); void suspend_all(bool leave_apps_in_memory=true); void unsuspend_all(); bool is_task_executing(); void request_tasks_exit(PROJECT* p=0); int wait_for_exit(double, PROJECT* p=0); int exit_tasks(PROJECT* p=0); void kill_tasks(PROJECT* p=0); int abort_project(PROJECT*); bool get_msgs(); bool check_app_exited(); bool check_rsc_limits_exceeded(); bool check_quit_timeout_exceeded(); bool is_slot_in_use(int); bool is_slot_dir_in_use(char*); int get_free_slot(); void send_heartbeats(); void send_trickle_downs(); void report_overdue(); void handle_upload_files(); void upload_notify_app(FILE_INFO*); bool want_network(); // does any task want network? void network_available(); // notify tasks that network is available void free_mem(); bool slot_taken(int); void get_memory_usage(); bool exclusive_app_running; // graphics-related functions void graphics_poll(); void process_control_poll(); void request_reread_prefs(PROJECT*); void request_reread_app_info(); int write(MIOFILE&); int parse(MIOFILE&); }; #endif