forked from pool/boinc-client
938 lines
32 KiB
Diff
938 lines
32 KiB
Diff
diff -Naur boinc-6.2.18/client/app_stats_mac.C boinc-6.2.18-mp/client/app_stats_mac.C
|
||
--- boinc-6.2.18/client/app_stats_mac.C 2008-08-25 22:29:18.000000000 +0200
|
||
+++ boinc-6.2.18-mp/client/app_stats_mac.C 1970-01-01 01:00:00.000000000 +0100
|
||
@@ -1,715 +0,0 @@
|
||
-// Berkeley Open Infrastructure for Network Computing
|
||
-// http://boinc.berkeley.edu
|
||
-// Copyright (C) 2006 University of California
|
||
-//
|
||
-// This 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 2.1 of the License, or (at your option) any later version.
|
||
-//
|
||
-// This software 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.
|
||
-//
|
||
-// To view the GNU Lesser General Public License visit
|
||
-// http://www.gnu.org/copyleft/lesser.html
|
||
-// or write to the Free Software Foundation, Inc.,
|
||
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
-
|
||
-// This file is adapted from code originally supplied by Apple Computer, Inc.
|
||
-// The Berkeley Open Infrastructure for Network Computing project has modified
|
||
-// the original code and made additions as of September 22, 2006. The original
|
||
-// Apple Public Source License statement appears below:
|
||
-
|
||
-/*
|
||
- * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
|
||
- *
|
||
- * @APPLE_LICENSE_HEADER_START@
|
||
- *
|
||
- * The contents of this file constitute Original Code as defined in and
|
||
- * are subject to the Apple Public Source License Version 1.1 (the
|
||
- * "License"). You may not use this file except in compliance with the
|
||
- * License. Please obtain a copy of the License at
|
||
- * http://www.apple.com/publicsource and read it before using this file.
|
||
- *
|
||
- * This Original Code and all software distributed under the License are
|
||
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||
- * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
|
||
- * License for the specific language governing rights and limitations
|
||
- * under the License.
|
||
- *
|
||
- * @APPLE_LICENSE_HEADER_END@
|
||
- */
|
||
-
|
||
-// app_stats_mac.C
|
||
-//
|
||
-
|
||
-// #define _DEBUG 1
|
||
-
|
||
-// Put a safety limit on recursion
|
||
-#define MAX_DESCENDANT_LEVEL 4
|
||
-
|
||
-// Totals for non_BOINC processes are not useful because most OSs don't
|
||
-// move idle processes out of RAM, so physical memory is always full
|
||
-#define GET_NON_BOINC_INFO 0
|
||
-
|
||
-// We don't need swap space info because
|
||
-// http://developer.apple.com/documentation/Performance/Conceptual/ManagingMemory/Articles/AboutMemory.html says:
|
||
-// Unlike most UNIX-based operating systems, Mac OS X does not use a
|
||
-// preallocated swap partition for virtual memory. Instead, it uses all
|
||
-// of the available space on the machine<6E>s boot partition.
|
||
-// However, the associated overhead is not significant if we are examining
|
||
-// only BOINC descendant processes.
|
||
-#define GET_SWAP_SIZE 1
|
||
-
|
||
-// The overhead for getting CPU times is not significant if we are
|
||
-// examining only BOINC descendant processes.
|
||
-#define GET_CPU_TIMES 1
|
||
-
|
||
-
|
||
-#include <cerrno>
|
||
-#include <sys/types.h>
|
||
-#include <mach/shared_memory_server.h>
|
||
-#include <mach/mach.h>
|
||
-#include <mach/mach_error.h>
|
||
-#include <sys/sysctl.h>
|
||
-
|
||
-#include "procinfo.h"
|
||
-
|
||
-using std::vector;
|
||
-
|
||
-static int get_boinc_proc_info(int my_pid, int boinc_pid);
|
||
-static int build_proc_list (vector<PROCINFO>& pi, int boinc_pid);
|
||
-static void output_child_totals(PROCINFO& pinfo);
|
||
-static boolean_t appstats_task_update(task_t a_task, vector<PROCINFO>& piv);
|
||
-static void find_all_descendants(vector<PROCINFO>& piv, int pid, int rlvl);
|
||
-static void add_child_totals(PROCINFO& pi, vector<PROCINFO>& piv, int pid, int rlvl);
|
||
-//static void add_others(PROCINFO&, std::vector<PROCINFO>&);
|
||
-static void sig_pipe(int signo);
|
||
-
|
||
-#ifdef _DEBUG
|
||
-static void print_procinfo(PROCINFO& pinfo);
|
||
-static void vm_size_render(unsigned long long a_size);
|
||
-#endif
|
||
-
|
||
-// BOINC helper application to get info about each of the BOINC Client's
|
||
-// child processes (including all its descendants) and also totals for
|
||
-// all other processes.
|
||
-// On the Mac, much of this information is accessible only by the super-user,
|
||
-// so this helper application must be run setuid root.
|
||
-
|
||
-int main(int argc, char** argv) {
|
||
- int boinc_pid, my_pid;
|
||
- int retval;
|
||
- char buf[256];
|
||
-
|
||
- if (geteuid() != 0) // This must be run setuid root
|
||
- return EACCES;
|
||
-
|
||
- my_pid = getpid();
|
||
- boinc_pid = getppid(); // Assumes we were called by BOINC client
|
||
-
|
||
- if (argc == 2)
|
||
- boinc_pid = atoi(argv[1]); // Pass in any desired valid pid for testing
|
||
-
|
||
- if (signal(SIGPIPE, sig_pipe) == SIG_ERR) {
|
||
- fprintf(stderr, "signal error");
|
||
- return 0;
|
||
- }
|
||
-
|
||
- setbuf(stdin, 0);
|
||
- setbuf(stdout, 0);
|
||
-
|
||
- while (1) {
|
||
- if (fgets(buf, sizeof(buf), stdin) == NULL)
|
||
- return 0;
|
||
-
|
||
- if (feof(stdin))
|
||
- return 0;
|
||
-
|
||
- retval = get_boinc_proc_info(my_pid, boinc_pid);
|
||
- }
|
||
-
|
||
- return 0;
|
||
-}
|
||
-
|
||
-static int get_boinc_proc_info(int my_pid, int boinc_pid) {
|
||
- int retval;
|
||
- vector<PROCINFO> piv;
|
||
- PROCINFO child_total;
|
||
- unsigned int i;
|
||
-
|
||
-
|
||
- retval = build_proc_list(piv, boinc_pid);
|
||
- if (retval)
|
||
- return retval;
|
||
-
|
||
- for (i=0; i<piv.size(); i++) {
|
||
- PROCINFO& p = piv[i];
|
||
- if (p.parentid == boinc_pid) {
|
||
- if (p.id == my_pid)
|
||
- continue;
|
||
-
|
||
- child_total = p;
|
||
- p.is_boinc_app = true;
|
||
-#ifdef _DEBUG
|
||
- printf("\n\nSumming info for process %d and its children:\n", child_total.id);
|
||
- print_procinfo(child_total);
|
||
-#endif
|
||
- // look for child processes
|
||
- add_child_totals(child_total, piv, p.id, 0);
|
||
-#ifdef _DEBUG
|
||
- printf("Totals for process %d and its children:\n", child_total.id);
|
||
-#endif
|
||
- output_child_totals(child_total);
|
||
- }
|
||
- }
|
||
-
|
||
- memset(&child_total, 0, sizeof(child_total));
|
||
-#if 0
|
||
-#ifdef _DEBUG
|
||
- printf("\n\nSumming info for all other processes\n");
|
||
-#endif
|
||
- add_others(child_total, piv);
|
||
-#endif
|
||
- output_child_totals(child_total); // zero pid signals end of data
|
||
-
|
||
- return 0;
|
||
-}
|
||
-
|
||
-
|
||
-static void output_child_totals(PROCINFO& pinfo) {
|
||
- printf("%d %d %.0lf %.0lf %lu %lf %lf\n",
|
||
- pinfo.id, pinfo.parentid, pinfo.working_set_size, pinfo.swap_size,
|
||
- pinfo.page_fault_count, pinfo.user_time, pinfo.kernel_time);
|
||
-// fflush(stdout);
|
||
-}
|
||
-
|
||
-static int build_proc_list (vector<PROCINFO>& pi, int boinc_pid) {
|
||
- boolean_t retval = FALSE;
|
||
- kern_return_t error;
|
||
- mach_port_t appstats_port;
|
||
- processor_set_t *psets, pset;
|
||
- task_t *tasks;
|
||
- unsigned i, j, pcnt, tcnt;
|
||
- PROCINFO pinfo;
|
||
- int pid, mib[4];
|
||
- struct kinfo_proc kinfo;
|
||
- size_t kinfosize;
|
||
-
|
||
- appstats_port = mach_host_self();
|
||
-
|
||
- // First, get a list of all tasks / processes
|
||
-
|
||
- error = host_processor_sets(appstats_port, &psets, &pcnt);
|
||
- if (error != KERN_SUCCESS) {
|
||
- fprintf(stderr,
|
||
- "Error in host_processor_sets(): %s",
|
||
- mach_error_string(error));
|
||
- retval = TRUE;
|
||
- goto RETURN;
|
||
- }
|
||
-
|
||
- for (i = 0; i < pcnt; i++) {
|
||
- if (retval)
|
||
- break;
|
||
-
|
||
- error = host_processor_set_priv(appstats_port, psets[i], &pset);
|
||
- if (error != KERN_SUCCESS) {
|
||
- fprintf(stderr,
|
||
- "Error in host_processor_set_priv(): %s",
|
||
- mach_error_string(error));
|
||
- retval = TRUE;
|
||
- break;
|
||
- }
|
||
-
|
||
- error = processor_set_tasks(pset, &tasks, &tcnt);
|
||
- if (error != KERN_SUCCESS) {
|
||
- fprintf(stderr,
|
||
- "Error in processor_set_tasks(): %s",
|
||
- mach_error_string(error));
|
||
- retval = TRUE;
|
||
- break;
|
||
- }
|
||
-
|
||
- for (j = 0; j < tcnt; j++) {
|
||
- if (retval)
|
||
- break;
|
||
-
|
||
- memset(&pinfo, 0, sizeof(PROCINFO));
|
||
-
|
||
- /* Get pid for this task. */
|
||
- error = pid_for_task(tasks[j], &pid);
|
||
- if (error != KERN_SUCCESS) {
|
||
- /* Not a process, or the process is gone. */
|
||
- continue;
|
||
- }
|
||
-
|
||
- // Get parent pid for each process
|
||
- /* Get kinfo structure for this task. */
|
||
- kinfosize = sizeof(struct kinfo_proc);
|
||
- mib[0] = CTL_KERN;
|
||
- mib[1] = KERN_PROC;
|
||
- mib[2] = KERN_PROC_PID;
|
||
- mib[3] = pid;
|
||
-
|
||
- if (sysctl(mib, 4, &kinfo, &kinfosize, NULL, 0) == -1) {
|
||
- fprintf(stderr,
|
||
- "%s(): Error in sysctl(): %s", __FUNCTION__,
|
||
- strerror(errno));
|
||
- retval = TRUE;
|
||
- break;
|
||
- }
|
||
-
|
||
- if (kinfo.kp_proc.p_stat == 0) {
|
||
- /* Zombie process. */
|
||
- continue;
|
||
- }
|
||
-
|
||
- pinfo.id = pid;
|
||
- pinfo.parentid = kinfo.kp_eproc.e_ppid;
|
||
-
|
||
- pi.push_back(pinfo);
|
||
- }
|
||
- }
|
||
-
|
||
-#if ! GET_NON_BOINC_INFO
|
||
- // Next, find all BOINC's decendants and mark them for further study
|
||
- if (! retval)
|
||
- find_all_descendants(pi, boinc_pid, 0);
|
||
-#endif
|
||
-
|
||
- // Now get the process information for each descendant
|
||
- for (i = 0; i < pcnt; i++) {
|
||
- for (j = 0; j < tcnt; j++) {
|
||
- if (! retval)
|
||
- if (appstats_task_update(tasks[j], pi)) {
|
||
- retval = TRUE;
|
||
- goto RETURN;
|
||
- }
|
||
-
|
||
- /* Delete task port if it isn't our own. */
|
||
- if (tasks[j] != mach_task_self()) {
|
||
- mach_port_deallocate(mach_task_self(),
|
||
- tasks[j]);
|
||
- }
|
||
- }
|
||
-
|
||
- error = vm_deallocate((vm_map_t)mach_task_self(),
|
||
- (vm_address_t)tasks, tcnt * sizeof(task_t));
|
||
- if (error != KERN_SUCCESS) {
|
||
- if (!retval)
|
||
- fprintf(stderr,
|
||
- "Error in vm_deallocate(): %s",
|
||
- mach_error_string(error));
|
||
- retval = TRUE;
|
||
- goto RETURN;
|
||
- }
|
||
- if ((error = mach_port_deallocate(mach_task_self(),
|
||
- pset)) != KERN_SUCCESS
|
||
- || (error = mach_port_deallocate(mach_task_self(),
|
||
- psets[i])) != KERN_SUCCESS) {
|
||
- if (!retval)
|
||
- fprintf(stderr,
|
||
- "Error in mach_port_deallocate(): %s",
|
||
- mach_error_string(error));
|
||
- retval = TRUE;
|
||
- goto RETURN;
|
||
- }
|
||
- }
|
||
-
|
||
- error = vm_deallocate((vm_map_t)mach_task_self(),
|
||
- (vm_address_t)psets, pcnt * sizeof(processor_set_t));
|
||
- if (error != KERN_SUCCESS) {
|
||
- if (!retval)
|
||
- fprintf(stderr,
|
||
- "Error in vm_deallocate(): %s",
|
||
- mach_error_string(error));
|
||
- retval = TRUE;
|
||
- goto RETURN;
|
||
- }
|
||
-
|
||
- RETURN:
|
||
- return retval;
|
||
-
|
||
-}
|
||
-
|
||
-/* Update statistics for task a_task. */
|
||
-static boolean_t appstats_task_update(task_t a_task, vector<PROCINFO>& piv)
|
||
-{
|
||
- boolean_t retval;
|
||
- kern_return_t error;
|
||
- mach_msg_type_number_t count;
|
||
- task_basic_info_data_t ti;
|
||
- vm_address_t address;
|
||
- mach_port_t object_name;
|
||
- vm_region_top_info_data_t info;
|
||
- vm_size_t size;
|
||
- thread_array_t thread_table;
|
||
- unsigned int table_size;
|
||
- thread_basic_info_t thi;
|
||
- thread_basic_info_data_t thi_data;
|
||
- unsigned i;
|
||
- task_events_info_data_t events;
|
||
- vm_size_t vsize, rsize;
|
||
- PROCINFO *pinfo;
|
||
- int pid;
|
||
-
|
||
- /* Get pid for this task. */
|
||
- error = pid_for_task(a_task, &pid);
|
||
- if (error != KERN_SUCCESS) {
|
||
- /* Not a process, or the process is gone. */
|
||
- retval = FALSE;
|
||
- goto GONE;
|
||
- }
|
||
-
|
||
- for (i=0; i<piv.size(); i++) {
|
||
- pinfo = &piv[i];
|
||
- if (pinfo->id == pid)
|
||
- break;
|
||
- }
|
||
-
|
||
- if (pinfo->id != pid) {
|
||
- fprintf(stderr, "pid %d missing from list\n", pid);
|
||
- retval = FALSE;
|
||
- goto RETURN;
|
||
- }
|
||
-
|
||
-#if ! GET_NON_BOINC_INFO
|
||
- if (!pinfo->is_boinc_app) {
|
||
- retval = FALSE;
|
||
- goto RETURN;
|
||
- }
|
||
-#endif
|
||
- /*
|
||
- * Get task_info, which is used for memory usage and CPU usage
|
||
- * statistics.
|
||
- */
|
||
- count = TASK_BASIC_INFO_COUNT;
|
||
- error = task_info(a_task, TASK_BASIC_INFO, (task_info_t)&ti, &count);
|
||
- if (error != KERN_SUCCESS) {
|
||
- retval = FALSE;
|
||
- goto GONE;
|
||
- }
|
||
-
|
||
- /*
|
||
- * Get memory usage statistics.
|
||
- */
|
||
-
|
||
- /*
|
||
- * Set rsize and vsize; they require no calculation. (Well, actually,
|
||
- * we adjust vsize if traversing memory objects to not include the
|
||
- * globally shared text and data regions).
|
||
- */
|
||
- rsize = ti.resident_size;
|
||
-#if GET_SWAP_SIZE
|
||
- vsize = ti.virtual_size;
|
||
- /*
|
||
- * Iterate through the VM regions of the process and determine
|
||
- * the amount of memory of various types it has mapped.
|
||
- */
|
||
- for (address = 0; ; address += size) {
|
||
- /* Get memory region. */
|
||
- count = VM_REGION_TOP_INFO_COUNT;
|
||
- if (vm_region(a_task, &address, &size,
|
||
- VM_REGION_TOP_INFO, (vm_region_info_t)&info, &count,
|
||
- &object_name) != KERN_SUCCESS) {
|
||
- /* No more memory regions. */
|
||
- break;
|
||
- }
|
||
-
|
||
- if (address >= GLOBAL_SHARED_TEXT_SEGMENT
|
||
- && address < (GLOBAL_SHARED_DATA_SEGMENT
|
||
- + SHARED_DATA_REGION_SIZE)) {
|
||
- /* This region is private shared. */
|
||
-
|
||
- /*
|
||
- * Check if this process has the globally shared
|
||
- * text and data regions mapped in. If so, adjust
|
||
- * virtual memory size and exit loop.
|
||
- */
|
||
- if (info.share_mode == SM_EMPTY) {
|
||
- vm_region_basic_info_data_64_t b_info;
|
||
-
|
||
- count = VM_REGION_BASIC_INFO_COUNT_64;
|
||
- if (vm_region_64(a_task, &address,
|
||
- &size, VM_REGION_BASIC_INFO,
|
||
- (vm_region_info_t)&b_info, &count,
|
||
- &object_name) != KERN_SUCCESS) {
|
||
- break;
|
||
- }
|
||
-
|
||
- if (b_info.reserved) {
|
||
- vsize -= (SHARED_TEXT_REGION_SIZE + SHARED_DATA_REGION_SIZE);
|
||
- break;
|
||
- }
|
||
- }
|
||
- }
|
||
- }
|
||
-#else
|
||
- vsize = 0;
|
||
-#endif // GET_SWAP_SIZE
|
||
- pinfo->working_set_size = rsize;
|
||
- pinfo->swap_size = vsize;
|
||
-
|
||
- /*
|
||
- * Get CPU usage statistics.
|
||
- */
|
||
-
|
||
- pinfo->user_time = (double)ti.user_time.seconds + (((double)ti.user_time.microseconds)/1000000.);
|
||
- pinfo->kernel_time = (double)ti.system_time.seconds + (((double)ti.system_time.microseconds)/1000000.);
|
||
-
|
||
- /* Get number of threads. */
|
||
- error = task_threads(a_task, &thread_table, &table_size);
|
||
- if (error != KERN_SUCCESS) {
|
||
- retval = FALSE;
|
||
- goto RETURN;
|
||
- }
|
||
-
|
||
-#if GET_CPU_TIMES
|
||
- /* Iterate through threads and collect usage stats. */
|
||
- thi = &thi_data;
|
||
- for (i = 0; i < table_size; i++) {
|
||
- count = THREAD_BASIC_INFO_COUNT;
|
||
- if (thread_info(thread_table[i], THREAD_BASIC_INFO,
|
||
- (thread_info_t)thi, &count) == KERN_SUCCESS) {
|
||
- if ((thi->flags & TH_FLAGS_IDLE) == 0) {
|
||
- pinfo->user_time += (double)thi->user_time.seconds + (((double)thi->user_time.microseconds)/1000000.);
|
||
- pinfo->kernel_time += (double)thi->system_time.seconds + (((double)thi->system_time.microseconds)/1000000.);
|
||
- }
|
||
- }
|
||
- if (a_task != mach_task_self()) {
|
||
- if ((error = mach_port_deallocate(mach_task_self(),
|
||
- thread_table[i])) != KERN_SUCCESS) {
|
||
- fprintf(stderr,
|
||
- "Error in mach_port_deallocate(): %s",
|
||
- mach_error_string(error));
|
||
- retval = TRUE;
|
||
- goto RETURN;
|
||
- }
|
||
- }
|
||
- }
|
||
- if ((error = vm_deallocate(mach_task_self(), (vm_offset_t)thread_table,
|
||
- table_size * sizeof(thread_array_t)) != KERN_SUCCESS)) {
|
||
- fprintf(stderr,
|
||
- "Error in vm_deallocate(): %s",
|
||
- mach_error_string(error));
|
||
- retval = TRUE;
|
||
- goto RETURN;
|
||
- }
|
||
-#endif GET_CPU_TIMES
|
||
-
|
||
- /*
|
||
- * Get event counters.
|
||
- */
|
||
-
|
||
- count = TASK_EVENTS_INFO_COUNT;
|
||
- if (task_info(a_task, TASK_EVENTS_INFO,
|
||
- (task_info_t)&events, &count) != KERN_SUCCESS) {
|
||
- /* Error. */
|
||
- retval = FALSE;
|
||
- goto RETURN;
|
||
- } else {
|
||
- pinfo->page_fault_count = events.pageins;
|
||
- }
|
||
-
|
||
- retval = FALSE;
|
||
- RETURN:
|
||
- GONE:
|
||
-
|
||
- return retval;
|
||
-}
|
||
-
|
||
-// Scan the process table marking all the decendants of the parent
|
||
-// process. Loop thru entire table as the entries aren't in order.
|
||
-// Recurse at most 5 times to get additional child processes.
|
||
-//
|
||
-static void find_all_descendants(vector<PROCINFO>& piv, int pid, int rlvl) {
|
||
- unsigned int i;
|
||
-
|
||
- if (rlvl > MAX_DESCENDANT_LEVEL) {
|
||
- return;
|
||
- }
|
||
- for (i=0; i<piv.size(); i++) {
|
||
- PROCINFO& p = piv[i];
|
||
- if (p.parentid == pid) {
|
||
- p.is_boinc_app = true;
|
||
- // look for child process of this one
|
||
- find_all_descendants(piv, p.id, rlvl+1); // recursion - woo hoo!
|
||
- }
|
||
- }
|
||
-}
|
||
-
|
||
-// Scan the process table adding in CPU time and mem usage. Loop
|
||
-// thru entire table as the entries aren't in order. Recurse at
|
||
-// most 4 times to get additional child processes
|
||
-//
|
||
-static void add_child_totals(PROCINFO& pi, vector<PROCINFO>& piv, int pid, int rlvl) {
|
||
- unsigned int i;
|
||
-
|
||
- if (rlvl > (MAX_DESCENDANT_LEVEL - 1)) {
|
||
- return;
|
||
- }
|
||
- for (i=0; i<piv.size(); i++) {
|
||
- PROCINFO& p = piv[i];
|
||
- if (p.parentid == pid) {
|
||
- pi.kernel_time += p.kernel_time;
|
||
- pi.user_time += p.user_time;
|
||
- pi.swap_size += p.swap_size;
|
||
- pi.working_set_size += p.working_set_size;
|
||
- pi.page_fault_count += p.page_fault_count;
|
||
- p.is_boinc_app = true;
|
||
-#ifdef _DEBUG
|
||
- print_procinfo(p);
|
||
-#endif
|
||
- // look for child process of this one
|
||
- add_child_totals(pi, piv, p.id, rlvl+1); // recursion - woo hoo!
|
||
- }
|
||
- }
|
||
-}
|
||
-
|
||
-#if 0
|
||
-static void add_others(PROCINFO& pi, vector<PROCINFO>& piv) {
|
||
- unsigned int i;
|
||
-
|
||
- memset(&pi, 0, sizeof(pi));
|
||
- for (i=0; i<piv.size(); i++) {
|
||
- PROCINFO& p = piv[i];
|
||
- if (!p.is_boinc_app) {
|
||
- pi.kernel_time += p.kernel_time;
|
||
- pi.user_time += p.user_time;
|
||
- pi.swap_size += p.swap_size;
|
||
- pi.working_set_size += p.working_set_size;
|
||
- pi.page_fault_count += p.page_fault_count;
|
||
- p.is_boinc_app = true;
|
||
-#ifdef _DEBUG
|
||
- print_procinfo(p);
|
||
-#endif
|
||
- }
|
||
- }
|
||
-}
|
||
-#endif
|
||
-
|
||
-static void sig_pipe(int signo)
|
||
-{
|
||
- exit(1);
|
||
-}
|
||
-
|
||
-#ifdef _DEBUG
|
||
-static void print_procinfo(PROCINFO& pinfo) {
|
||
- unsigned long long rsize, vsize;
|
||
-
|
||
- rsize = (unsigned long long)pinfo.working_set_size;
|
||
- vsize = (unsigned long long)pinfo.swap_size;
|
||
- printf("pid=%d, ppid=%d, rm=%llu=", pinfo.id, pinfo.parentid, rsize);
|
||
- vm_size_render(rsize);
|
||
- printf("=, vm=%llu=", vsize);
|
||
- vm_size_render(vsize);
|
||
- printf(", pageins=%lu, usertime=%lf, systime=%lf\n", pinfo.page_fault_count, pinfo.user_time, pinfo.kernel_time);
|
||
-}
|
||
-
|
||
-/*
|
||
- * Render a memory size in units of B, K, M, or G, depending on the value.
|
||
- *
|
||
- * a_size is ULL, since there are places where VM sizes are capable of
|
||
- * overflowing 32 bits, particularly when VM stats are multiplied by the
|
||
- * pagesize.
|
||
- */
|
||
-static void vm_size_render(unsigned long long a_size)
|
||
-{
|
||
- if (a_size < 1024) {
|
||
- /* 1023B. */
|
||
- printf("%4lluB", a_size);
|
||
- } else if (a_size < (1024ULL * 1024ULL)) {
|
||
- /* K. */
|
||
- if (a_size < 10ULL * 1024ULL) {
|
||
- /* 9.99K */
|
||
- printf("%1.2fK",
|
||
- ((double)a_size) / 1024);
|
||
- } else if (a_size < 100ULL * 1024ULL) {
|
||
- /* 99.9K */
|
||
- printf("%2.1fK",
|
||
- ((double)a_size) / 1024);
|
||
- } else {
|
||
- /* 1023K */
|
||
- printf("%4lluK",
|
||
- a_size / 1024ULL);
|
||
- }
|
||
- } else if (a_size < (1024ULL * 1024ULL * 1024ULL)) {
|
||
- /* M. */
|
||
- if (a_size < 10ULL * 1024ULL * 1024ULL) {
|
||
- /* 9.99M */
|
||
- printf("%1.2fM",
|
||
- ((double)a_size) / (1024 * 1024));
|
||
- } else if (a_size < 100ULL * 1024ULL * 1024ULL) {
|
||
- /* 99.9M */
|
||
- printf("%2.1fM",
|
||
- ((double)a_size) / (1024 * 1024));
|
||
- } else {
|
||
- /* 1023M */
|
||
- printf("%4lluM",
|
||
- a_size / (1024ULL * 1024ULL));
|
||
- }
|
||
- } else if (a_size < (1024ULL * 1024ULL * 1024ULL * 1024ULL)) {
|
||
- /* G. */
|
||
- if (a_size < 10ULL * 1024ULL * 1024ULL * 1024ULL) {
|
||
- /* 9.99G. */
|
||
- printf("%1.2fG",
|
||
- ((double)a_size) / (1024 * 1024 * 1024));
|
||
- } else if (a_size < 100ULL * 1024ULL * 1024ULL * 1024ULL) {
|
||
- /* 99.9G. */
|
||
- printf("%2.1fG",
|
||
- ((double)a_size) / (1024 * 1024 * 1024));
|
||
- } else {
|
||
- /* 1023G */
|
||
- printf("%4lluG",
|
||
- a_size / (1024ULL * 1024ULL * 1024ULL));
|
||
- }
|
||
- } else if (a_size < (1024ULL * 1024ULL * 1024ULL * 1024ULL)) {
|
||
- /* T. */
|
||
- if (a_size < 10ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL) {
|
||
- /* 9.99T. */
|
||
- printf("%1.2fT",
|
||
- ((double)a_size) /
|
||
- (1024ULL * 1024ULL * 1024ULL * 1024ULL));
|
||
- } else if (a_size < (100ULL * 1024ULL * 1024ULL * 1024ULL
|
||
- * 1024ULL)) {
|
||
- /* 99.9T. */
|
||
- printf("%2.1fT",
|
||
- ((double)a_size) /
|
||
- (1024ULL * 1024ULL * 1024ULL * 1024ULL));
|
||
- } else {
|
||
- /* 1023T */
|
||
- printf("%4lluT",
|
||
- a_size /
|
||
- (1024ULL * 1024ULL * 1024ULL * 1024ULL));
|
||
- }
|
||
- } else {
|
||
- /* P. */
|
||
- if (a_size < (10ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL
|
||
- * 1024ULL)) {
|
||
- /* 9.99P. */
|
||
- printf("%1.2fP",
|
||
- ((double)a_size) /
|
||
- (1024ULL * 1024ULL * 1024ULL * 1024ULL
|
||
- * 1024ULL));
|
||
- } else if (a_size < (100ULL * 1024ULL * 1024ULL * 1024ULL
|
||
- * 1024ULL)) {
|
||
- /* 99.9P. */
|
||
- printf("%2.1fP",
|
||
- ((double)a_size) /
|
||
- (1024ULL * 1024ULL * 1024ULL * 1024ULL
|
||
- * 1024ULL));
|
||
- } else {
|
||
- /* 1023P */
|
||
- printf("%4lluP",
|
||
- a_size /
|
||
- (1024ULL * 1024ULL * 1024ULL * 1024ULL
|
||
- * 1024ULL));
|
||
- }
|
||
- }
|
||
-}
|
||
-#endif // _DEBUG
|
||
diff -Naur boinc-6.2.18/lib/mac/dyld_gdb.h boinc-6.2.18-mp/lib/mac/dyld_gdb.h
|
||
--- boinc-6.2.18/lib/mac/dyld_gdb.h 2008-08-25 22:27:58.000000000 +0200
|
||
+++ boinc-6.2.18-mp/lib/mac/dyld_gdb.h 1970-01-01 01:00:00.000000000 +0100
|
||
@@ -1,214 +0,0 @@
|
||
-// Berkeley Open Infrastructure for Network Computing
|
||
-// http://boinc.berkeley.edu
|
||
-// Copyright (C) 2005 University of California
|
||
-//
|
||
-// This 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 2.1 of the License, or (at your option) any later version.
|
||
-//
|
||
-// This software 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.
|
||
-//
|
||
-// To view the GNU Lesser General Public License visit
|
||
-// http://www.gnu.org/copyleft/lesser.html
|
||
-// or write to the Free Software Foundation, Inc.,
|
||
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||
-/*
|
||
- * dyld_gdb.h
|
||
- *
|
||
- */
|
||
-
|
||
-/* This is part of a backtrace generator for boinc project applications.
|
||
-*
|
||
-* Adapted from Apple Developer Technical Support Sample Code QCrashReport
|
||
-*
|
||
-* This code handles Mac OS X 10.3.x through 10.4.9. It may require some
|
||
-* adjustment for future OS versions; see the discussion of _sigtramp and
|
||
-* PowerPC Signal Stack Frames in file QBacktrace.c.
|
||
-*
|
||
-* For useful tips on using backtrace information, see Apple Tech Note 2123:
|
||
-* http://developer.apple.com/technotes/tn2004/tn2123.html#SECNOSYMBOLS
|
||
-*
|
||
-* To convert addresses to correct symbols, use the atos command-line tool:
|
||
-* atos -o path/to/executable/with/symbols address
|
||
-* Note: if address 1a23 is hex, use 0x1a23.
|
||
-*
|
||
-* To demangle mangled C++ symbols, use the c++filt command-line tool.
|
||
-* You may need to prefix C++ symbols with an additonal underscore before
|
||
-* passing them to c++filt (so they begin with two underscore characters).
|
||
-*
|
||
-* A very useful shell script to add symbols to a crash dump can be found at:
|
||
-* http://developer.apple.com/tools/xcode/symbolizingcrashdumps.html
|
||
-* Pipe the output of the shell script through c++filt to demangle C++ symbols.
|
||
-*/
|
||
-
|
||
-/*
|
||
- * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
|
||
- *
|
||
- * @APPLE_LICENSE_HEADER_START@
|
||
- *
|
||
- * This file contains Original Code and/or Modifications of Original Code
|
||
- * as defined in and that are subject to the Apple Public Source License
|
||
- * Version 2.0 (the 'License'). You may not use this file except in
|
||
- * compliance with the License. Please obtain a copy of the License at
|
||
- * http://www.opensource.apple.com/apsl/ and read it before using this
|
||
- * file.
|
||
- *
|
||
- * The Original Code and all software distributed under the License are
|
||
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
|
||
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
|
||
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
|
||
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
|
||
- * Please see the License for the specific language governing rights and
|
||
- * limitations under the License.
|
||
- *
|
||
- * @APPLE_LICENSE_HEADER_END@
|
||
- */
|
||
-#ifndef _DYLD_GDB_
|
||
-#define _DYLD_GDB_
|
||
-/*
|
||
- * This file describes the interface between gdb and dyld created for
|
||
- * MacOS X GM. Prior to MacOS X GM gdb used the dyld_debug interfaces
|
||
- * described in <mach-o/dyld_debug.h>.
|
||
- */
|
||
-
|
||
-
|
||
-#ifdef __cplusplus
|
||
-extern "C" {
|
||
-#endif
|
||
-
|
||
-
|
||
-#define OLD_GDB_DYLD_INTERFACE __ppc__ || __i386__
|
||
-
|
||
-#if OLD_GDB_DYLD_INTERFACE
|
||
-/*
|
||
- * gdb_dyld_version is the version of gdb interface that dyld is currently
|
||
- * exporting. For the interface described in this header file gdb_dyld_version
|
||
- * is 2. As the gdb/dyld interface changes this number will be incremented and
|
||
- * comments will be added as to what are the are changes for the various
|
||
- * versions.
|
||
- */
|
||
-extern unsigned int gdb_dyld_version;
|
||
-
|
||
-/*
|
||
- * gdb_dyld_state_changed is the internal dyld routine called by dyld to notify
|
||
- * gdb that the state of the data structures has changed. gdb is expected to
|
||
- * put a break point on this routine and re-read the internal dyld data
|
||
- * structures below when this break point is hit.
|
||
- */
|
||
-extern void gdb_dyld_state_changed(void);
|
||
-
|
||
-/*
|
||
- * gdb looks directly at parts of two of dyld's internal data structures. The
|
||
- * list of object file images and the list of library images. The parts of
|
||
- * these structures that gdb looks at will not change unless the value of
|
||
- * gdb_dyld_version changes. The size of these structures and the other fields
|
||
- * that gdb does not look at may change.
|
||
- *
|
||
- * struct object_images {
|
||
- * struct object_image images[NOBJECT_IMAGES];
|
||
- * unsigned long nimages;
|
||
- * struct object_images *next_images;
|
||
- * ...
|
||
- * };
|
||
- *
|
||
- * struct library_images {
|
||
- * struct library_image images[NLIBRARY_IMAGES];
|
||
- * unsigned long nimages;
|
||
- * struct library_images *next_images;
|
||
- * ...
|
||
- * };
|
||
- *
|
||
- * Both the object_image structure and the library_image structure
|
||
- * start with a structure containing the following fields:
|
||
- *
|
||
- * struct image {
|
||
- * char *physical_name; physical image name (file name)
|
||
- * unsigned long vmaddr_slide; the slide from the staticly linked address
|
||
- * struct mach_header *mh; address of the mach header of the image
|
||
- * unsigned long valid; TRUE if this is struct is valid
|
||
- * char *name; image name for reporting errors
|
||
- * ...
|
||
- * };
|
||
- *
|
||
- * In gdb_dyld_version 1 the first field was "name". In gdb_dyld_version 2 the
|
||
- * first field was changed to "physical_name" and a new fifth field "name" was
|
||
- * added. These two fields are set to the same values except in the case of
|
||
- * zero-link. In zero-link the NSLinkModule() option
|
||
- * NSLINKMODULE_OPTION_TRAILING_PHYS_NAME is used and then the physical_name is
|
||
- * the file name of the module zero-link loaded that is part of the logical
|
||
- * image "name".
|
||
- */
|
||
-
|
||
-/* object_images is the global object_images structure */
|
||
-
|
||
-/* the number of gdb_object_image structures present per bucket */
|
||
-extern unsigned int gdb_nobject_images;
|
||
-
|
||
-/* the size of each gdb_object_image structure */
|
||
-extern unsigned int gdb_object_image_size;
|
||
-
|
||
-/* library_images is the global library_images structure */
|
||
-
|
||
-/* the number of gdb_library_image structures present per bucket */
|
||
-extern unsigned int gdb_nlibrary_images;
|
||
-
|
||
-/* the size of each gdb_library_image structure */
|
||
-extern unsigned int gdb_library_image_size;
|
||
-
|
||
-#endif /* OLD_GDB_DYLD_INTERFACE */
|
||
-
|
||
-
|
||
-/*
|
||
- * Beginning in Mac OS X 10.4, there is a new mechanism for dyld to notify gdb and other about new images.
|
||
- *
|
||
- *
|
||
- */
|
||
-
|
||
-enum dyld_image_mode { dyld_image_adding=0, dyld_image_removing=1 };
|
||
-
|
||
-struct dyld_image_info {
|
||
- const struct mach_header* imageLoadAddress; /* base address image is mapped into */
|
||
- const char* imageFilePath; /* path dyld used to load the image */
|
||
- uintptr_t imageFileModDate; /* time_t of image file */
|
||
- /* if stat().st_mtime of imageFilePath does not match imageFileModDate, */
|
||
- /* then file has been modified since dyld loaded it */
|
||
-};
|
||
-
|
||
-
|
||
-typedef void (*dyld_image_notifier)(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]);
|
||
-
|
||
-/*
|
||
- * gdb looks for the symbol "_dyld_all_image_infos" in dyld. It contains the fields below.
|
||
- *
|
||
- * For a snap shot of what images are currently loaded, the infoArray fields contain a pointer
|
||
- * to an array of all images. If infoArray is NULL, it means it is being modified, come back later.
|
||
- *
|
||
- * To be notified of changes, gdb sets a break point on the notification field. The function
|
||
- * it points to is called by dyld with an array of information about what images have been added
|
||
- * (dyld_image_adding) or are about to be removed (dyld_image_removing).
|
||
- *
|
||
- * The notification is called after infoArray is updated. This means that if gdb attaches to a process
|
||
- * and infoArray is NULL, gdb can set a break point on notification and let the proccess continue to
|
||
- * run until the break point. Then gdb can inspect the full infoArray.
|
||
- */
|
||
- struct dyld_all_image_infos {
|
||
- uint32_t version; /* == 1 in Mac OS X 10.4 */
|
||
- uint32_t infoArrayCount;
|
||
- const struct dyld_image_info* infoArray;
|
||
- dyld_image_notifier notification;
|
||
- bool processDetachedFromSharedRegion;
|
||
-};
|
||
-extern struct dyld_all_image_infos dyld_all_image_infos;
|
||
-
|
||
-
|
||
-
|
||
-
|
||
-#ifdef __cplusplus
|
||
-}
|
||
-#endif
|
||
-
|
||
-#endif /* _DYLD_GDB_ */
|