Esempio n. 1
0
sg_page_stats *sg_get_page_stats_diff(){
	static sg_page_stats page_stats_diff;
#ifndef WIN32
	sg_page_stats *page_ptr;

	if(page_stats_uninit){
		page_ptr=sg_get_page_stats();
		if(page_ptr==NULL){
			return NULL;
		}
		page_stats_uninit=0;
		return page_ptr;
	}

	page_stats_diff.pages_pagein=page_stats.pages_pagein;
	page_stats_diff.pages_pageout=page_stats.pages_pageout;
	page_stats_diff.systime=page_stats.systime;

	page_ptr=sg_get_page_stats();
	if(page_ptr==NULL){
		return NULL;
	}

	page_stats_diff.pages_pagein=page_stats.pages_pagein-page_stats_diff.pages_pagein;
	page_stats_diff.pages_pageout=page_stats.pages_pageout-page_stats_diff.pages_pageout;
	page_stats_diff.systime=page_stats.systime-page_stats_diff.systime;

#else /* WIN32 */
	if(read_counter_large(SG_WIN32_PAGEIN, &page_stats_diff.pages_pagein)) {
		sg_set_error(SG_ERROR_PDHREAD, PDH_PAGEIN);
		return NULL;
	}
	if(read_counter_large(SG_WIN32_PAGEOUT, &page_stats_diff.pages_pageout)) {
		sg_set_error(SG_ERROR_PDHREAD, PDH_PAGEIN);
		return NULL;
	}
	page_stats_diff.systime = 0;
#endif /* WIN32 */

	return &page_stats_diff;
}
Esempio n. 2
0
static sg_error
sg_get_mem_stats_int(sg_mem_stats *mem_stats_buf) {

#ifdef HPUX
	struct pst_static pstat_static;
	struct pst_dynamic pstat_dynamic;
#elif defined(SOLARIS)
# ifdef _SC_PHYS_PAGES
	long phystotal;
	long physav;
# else
	kstat_ctl_t *kc;
	kstat_t *ksp;
	kstat_named_t *kn;
# endif
#elif defined(LINUX) || defined(CYGWIN)
#define LINE_BUF_SIZE 256
	char *line_ptr, line_buf[LINE_BUF_SIZE];
	long long value;
	FILE *f;
#elif defined(HAVE_HOST_STATISTICS) || defined(HAVE_HOST_STATISTICS64)
# if defined(HAVE_HOST_STATISTICS64)
	struct vm_statistics64 vm_stats;
# else
	struct vm_statistics vm_stats;
# endif
	mach_msg_type_number_t count;
	kern_return_t rc;
#elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2)
	int mib[2];
	struct uvmexp_sysctl uvm;
	size_t size = sizeof(uvm);
#elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP)
	int mib[2];
	struct uvmexp uvm;
	size_t size = sizeof(uvm);
#elif defined(FREEBSD) || defined(DFBSD)
	size_t size;
	unsigned int total_count;
	unsigned int free_count;
	unsigned int cache_count;
	unsigned int inactive_count;
#elif defined(HAVE_STRUCT_VMTOTAL)
	struct vmtotal vmtotal;
	size_t size;
#if defined(HW_PHYSMEM) || defined(HW_USERMEM)
	int mib[2];
# if defined(HW_PHYSMEM)
	u_long total_mem;
# endif
# if defined(HW_USERMEM)
	u_long user_mem;
# endif
#endif
#elif defined(AIX)
	perfstat_memory_total_t mem;
#elif defined(WIN32)
	MEMORYSTATUSEX memstats;
#endif

#if defined(HPUX)
	if (pstat_getdynamic(&pstat_dynamic, sizeof(pstat_dynamic), 1, 0) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_PSTAT, "pstat_dynamic");
	}

	/*
	 * from man pstat_getstatic:
	 *
	 * pstat_getstatic() returns information about the system.  Although
	 * this data usually does not change frequently, it may change while
	 * the system is running due to manually or automatically generated
	 * administrative changes in the associated kernel tunables, online
	 * addition/deletion of resources, or other events.  There is one
	 * global instance of this context.
	 *
	 * ==> Can't hold this value globally static.
	 */

	if( pstat_getstatic(&pstat_static, sizeof(pstat_static), 1, 0) == -1 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_PSTAT, "pstat_static");
	}

	mem_stats_buf->total = ((long long) pstat_static.physical_memory) * pstat_static.page_size;
	mem_stats_buf->free = ((long long) pstat_dynamic.psd_free) * pstat_static.page_size;
	mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free;
#elif defined(AIX)
	/* return code is number of structures returned */
	if(perfstat_memory_total(NULL, &mem, sizeof(perfstat_memory_total_t), 1) != 1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "perfstat_memory_total");
	}

	mem_stats_buf->total = (unsigned long long) mem.real_total;
	mem_stats_buf->total *= sys_page_size;
	mem_stats_buf->used  = (unsigned long long) mem.real_inuse;
	mem_stats_buf->used  *= sys_page_size;
	mem_stats_buf->cache = (unsigned long long) mem.numperm;
	mem_stats_buf->cache *= sys_page_size;
	mem_stats_buf->free  = (unsigned long long) mem.real_free;
	mem_stats_buf->free  *= sys_page_size;
#elif defined(SOLARIS)
# ifdef _SC_PHYS_PAGES
	if( ( phystotal = sysconf(_SC_PHYS_PAGES) ) < 0 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCONF, "_SC_PHYS_PAGES");
	}
	if( ( physav = sysconf(_SC_AVPHYS_PAGES) ) < 0 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCONF, "_SC_AVPHYS_PAGES");
	}
	mem_stats_buf->total = ((unsigned long long)phystotal) * ((unsigned long long)sys_page_size);
	mem_stats_buf->free = ((unsigned long long)physav) * ((unsigned long long)sys_page_size);
# else
	if( (kc = kstat_open()) == NULL ) {
		RETURN_WITH_SET_ERROR("mem", SG_ERROR_KSTAT_OPEN, NULL);
	}

	if((ksp=kstat_lookup(kc, "unix", 0, "system_pages")) == NULL) {
		RETURN_WITH_SET_ERROR("mem", SG_ERROR_KSTAT_LOOKUP, "unix,0,system_pages");
	}

	if (kstat_read(kc, ksp, 0) == -1) {
		RETURN_WITH_SET_ERROR("mem", SG_ERROR_KSTAT_READ, NULL);
	}

	if((kn=kstat_data_lookup(ksp, "physmem")) == NULL) {
		RETURN_WITH_SET_ERROR("mem", SG_ERROR_KSTAT_DATA_LOOKUP, "physmem");
	}

	mem_stats_buf->total = ((unsigned long long)kn->value.ul) * ((unsigned long long)sys_page_size);

	if((kn=kstat_data_lookup(ksp, "freemem")) == NULL) {
		RETURN_WITH_SET_ERROR("mem", SG_ERROR_KSTAT_DATA_LOOKUP, "freemem");
	}

	mem_stats_buf->free = ((unsigned long long)kn->value.ul) * ((unsigned long long)sys_page_size);
	kstat_close(kc);
# endif
	mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free;
	mem_stats_buf->cache = 0;
#elif defined(LINUX) || defined(CYGWIN)
	if ((f = fopen("/proc/meminfo", "r")) == NULL) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_OPEN, "/proc/meminfo");
	}

#define MEM_TOTAL_PREFIX	"MemTotal:"
#define MEM_FREE_PREFIX		"MemFree:"
#define MEM_CACHED_PREFIX	"Cached:"

	while ((line_ptr = fgets(line_buf, sizeof(line_buf), f)) != NULL) {
		if ( sscanf(line_buf, "%*s %lld kB", &value) != 1)
			continue;

		if (strncmp(line_buf, MEM_TOTAL_PREFIX, sizeof(MEM_TOTAL_PREFIX) - 1) == 0)
			mem_stats_buf->total = value;
		else if (strncmp(line_buf, MEM_FREE_PREFIX, sizeof(MEM_FREE_PREFIX) - 1) == 0)
			mem_stats_buf->free = value;
		else if (strncmp(line_buf, MEM_CACHED_PREFIX, sizeof(MEM_CACHED_PREFIX) - 1) == 0)
			mem_stats_buf->cache = value;
	}

	mem_stats_buf->free += mem_stats_buf->cache;

	mem_stats_buf->total *= 1024;
	mem_stats_buf->free *= 1024;
	mem_stats_buf->cache *= 1024;

#undef MEM_TOTAL_PREFIX
#undef MEM_FREE_PREFIX
#undef MEM_CACHED_PREFIX

	fclose(f);
	mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free;

#elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2)
	mib[0] = CTL_VM;
	mib[1] = VM_UVMEXP2;

	if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP2");
	}

	mem_stats_buf->total = uvm.npages;
	mem_stats_buf->cache = uvm.filepages + uvm.execpages;
	mem_stats_buf->free = uvm.free + mem_stats_buf->cache;

	mem_stats_buf->total *= uvm.pagesize;
	mem_stats_buf->cache *= uvm.pagesize;
	mem_stats_buf->free *= uvm.pagesize;

	mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free;
#elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP)
	mib[0] = CTL_VM;
	mib[1] = VM_UVMEXP;

	if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP");
	}

	mem_stats_buf->total = uvm.npages;
	mem_stats_buf->cache = 0;
# if defined(HAVE_STRUCT_UVMEXP_FILEPAGES)
	mem_stats_buf->cache += uvm.filepages;
# endif
# if defined(HAVE_STRUCT_UVMEXP_EXECPAGES)
	mem_stats_buf->cache += uvm.execpages;
# endif
	mem_stats_buf->free = uvm.free + mem_stats_buf->cache;

	mem_stats_buf->total *= uvm.pagesize;
	mem_stats_buf->cache *= uvm.pagesize;
	mem_stats_buf->free *= uvm.pagesize;

	mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free;
#elif defined(HAVE_HOST_STATISTICS) || defined(HAVE_HOST_STATISTICS64)
# if defined(HAVE_HOST_STATISTICS64)
	count = HOST_VM_INFO64_COUNT;
	rc = host_statistics64(self_host_port, HOST_VM_INFO64, (host_info64_t)(&vm_stats), &count);
# else
	count = HOST_VM_INFO_COUNT;
	rc = host_statistics(self_host_port, HOST_VM_INFO, (host_info_t)(&vm_stats), &count);
# endif
	if( rc != KERN_SUCCESS ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO_CODE( "mem", SG_ERROR_MACHCALL, rc, "host_statistics" );
	}

	/*
	 * XXX check host_info(host_basic_info) ... for memory_size */
	mem_stats_buf->free = vm_stats.free_count - vm_stats.speculative_count;
	mem_stats_buf->free += vm_stats.inactive_count;
	mem_stats_buf->free *= (size_t)sys_page_size;
	mem_stats_buf->total = vm_stats.active_count + vm_stats.wire_count +
			       vm_stats.inactive_count + vm_stats.free_count;
	mem_stats_buf->total *= (size_t)sys_page_size;
	mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free;
	mem_stats_buf->cache = 0;
#elif defined(FREEBSD) || defined(DFBSD)
	/*returns pages*/
	size = sizeof(total_count);
	if (sysctlbyname("vm.stats.vm.v_page_count", &total_count, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_page_count");
	}

	/*returns pages*/
	size = sizeof(free_count);
	if (sysctlbyname("vm.stats.vm.v_free_count", &free_count, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_free_count");
	}

	size = sizeof(inactive_count);
	if (sysctlbyname("vm.stats.vm.v_inactive_count", &inactive_count , &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_inactive_count");
	}

	size = sizeof(cache_count);
	if (sysctlbyname("vm.stats.vm.v_cache_count", &cache_count, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_cache_count");
	}

	/* Of couse nothing is ever that simple :) And I have inactive pages to
	 * deal with too. So I'm going to add them to free memory :)
	 */
	mem_stats_buf->cache = (size_t)cache_count;
	mem_stats_buf->cache *= (size_t)sys_page_size;
	mem_stats_buf->total = (size_t)total_count;
	mem_stats_buf->total *= (size_t)sys_page_size;
	mem_stats_buf->free = (size_t)free_count + inactive_count + cache_count;
	mem_stats_buf->free *= (size_t)sys_page_size;
	mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free;
#elif defined(WIN32)
	memstats.dwLength = sizeof(memstats);
	if (!GlobalMemoryStatusEx(&memstats)) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_MEMSTATUS, NULL);
	}

	mem_stats_buf->free = memstats.ullAvailPhys;
	mem_stats_buf->total = memstats.ullTotalPhys;
	mem_stats_buf->used = mem_stat.total - mem_stat.free;
	if(read_counter_large(SG_WIN32_MEM_CACHE, &mem_stats_buf->cache))
		mem_stats_buf->cache = 0;
#elif defined(HAVE_STRUCT_VMTOTAL)
	/* The code in this section is based on the code in the OpenBSD
	 * top utility, located at src/usr.bin/top/machine.c in the
	 * OpenBSD source tree.
	 *
	 * For fun, and like OpenBSD top, we will do the multiplication
	 * converting the memory stats in pages to bytes in base 2.
	 */
	size = sizeof(vmtotal);
	if (sysctl(vmtotal_mib, 2, &vmtotal, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.vmtotal");
	}

	/* Convert the raw stats to bytes, and return these to the caller
	 */
	mem_stats_buf->used = (unsigned long long)vmtotal.t_rm;   /* total real mem in use */
	mem_stats_buf->used *= sys_page_size;
	/* XXX scan top source to look how it determines cache size */
	mem_stats_buf->cache = 0;				  /* no cache stats */
	mem_stats_buf->free = (unsigned long long)vmtotal.t_free; /* free memory pages */
	mem_stats_buf->free *= sys_page_size;
# ifdef HW_PHYSMEM
	mib[0] = CTL_HW;
	mib[1] = HW_PHYSMEM;
	size = sizeof(total_mem);
	if (sysctl(mib, 2, &total_mem, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_HW.HW_PHYSMEM");
	}
	mem_stats_buf->total = total_mem;
# else
	mem_stats_buf->total = (mem_stats_buf->used + mem_stats_buf->free);
# endif
# ifdef HW_USERMEM
	mib[0] = CTL_HW;
	mib[1] = HW_USERMEM;
	size = sizeof(user_mem);
	if (sysctl(mib, 2, &user_mem, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_HW.HW_USERMEM");
	}
	mem_stats_buf->used += total_mem - user_mem;
# endif
#else
	RETURN_WITH_SET_ERROR("mem", SG_ERROR_UNSUPPORTED, OS_TYPE);
#endif

	mem_stats_buf->systime = time(NULL);

	return SG_ERROR_NONE;
}
Esempio n. 3
0
sg_host_info *sg_get_host_info()
{
    static sg_host_info general_stat;
#ifndef WIN32
    static struct utsname os;
#endif

#ifdef HPUX
    struct pst_static *pstat_static;
    time_t currtime;
    long boottime;
#endif
#ifdef SOLARIS
    time_t boottime,curtime;
    kstat_ctl_t *kc;
    kstat_t *ksp;
    kstat_named_t *kn;
#endif
#if defined(LINUX) || defined(CYGWIN)
    FILE *f;
#endif
#ifdef ALLBSD
    int mib[2];
    struct timeval boottime;
    time_t curtime;
    size_t size;
#endif
#ifdef WIN32
    unsigned long nameln;
    char *name;
    long long result;
    OSVERSIONINFOEX osinfo;
    SYSTEM_INFO sysinfo;
    char *tmp_name;
    char tmp[10];
#endif

#ifndef WIN32 /* Trust windows to be different */
    if((uname(&os)) < 0) {
        sg_set_error_with_errno(SG_ERROR_UNAME, NULL);
        return NULL;
    }

    general_stat.os_name = os.sysname;
    general_stat.os_release = os.release;
    general_stat.os_version = os.version;
    general_stat.platform = os.machine;
    general_stat.hostname = os.nodename;
#else /* WIN32 */
    if (!runonce) {
        /* these settings are static after boot, so why get them
         * constantly? */

        /* get system name */
        nameln = MAX_COMPUTERNAME_LENGTH + 1;
        name = sg_malloc(nameln);
        if(name == NULL) {
            return NULL;
        }
        if(GetComputerName(name, &nameln) == 0) {
            free(name);
            sg_set_error(SG_ERROR_HOST, "GetComputerName");
            return NULL;
        }
        if(sg_update_string(&general_stat.hostname, name)) {
            free(name);
            return NULL;
        }
        free(name);

        /* get OS name, version and build */
        ZeroMemory(&osinfo, sizeof(OSVERSIONINFOEX));
        osinfo.dwOSVersionInfoSize = sizeof(osinfo);
        if(!GetVersionEx(&osinfo)) {
            sg_set_error(SG_ERROR_HOST, "GetVersionEx");
            return NULL;
        }

        /* Release - single number */
        if(snprintf(tmp, sizeof(tmp), "%ld", osinfo.dwBuildNumber) == -1) {
            free(tmp);
            return NULL;
        }
        if(sg_update_string(&general_stat.os_release, tmp)) {
            free(tmp);
            return NULL;
        }

        /* Version */
        /* usually a single digit . single digit, eg 5.0 */
        if(snprintf(tmp, sizeof(tmp), "%ld.%ld", osinfo.dwMajorVersion,
                    osinfo.dwMinorVersion) == -1) {
            free(tmp);
            return NULL;
        }
        if(sg_update_string(&general_stat.os_version, tmp)) {
            free(tmp);
            return NULL;
        }

        /* OS name */
        tmp_name = get_os_name(osinfo);
        if(tmp_name == NULL) {
            return NULL;
        }
        if(sg_update_string(&general_stat.os_name, tmp_name)) {
            free(tmp_name);
            return NULL;
        }
        free(tmp_name);
        runonce = 1;

        /* Platform */
        GetSystemInfo(&sysinfo);
        switch(sysinfo.wProcessorArchitecture) {
        case PROCESSOR_ARCHITECTURE_INTEL:
            if(sg_update_string(&general_stat.platform,
                                "Intel")) {
                return NULL;
            }
            break;
        case PROCESSOR_ARCHITECTURE_IA64:
            if(sg_update_string(&general_stat.platform,
                                "IA64")) {
                return NULL;
            }
            break;
        case PROCESSOR_ARCHITECTURE_AMD64:
            if(sg_update_string(&general_stat.platform,
                                "AMD64")) {
                return NULL;
            }
            break;
        default:
            if(sg_update_string(&general_stat.platform,
                                "Unknown")) {
                return NULL;
            }
            break;
        }
    }
#endif /* WIN32 */

    /* get uptime */
#ifdef HPUX
    pstat_static = sg_get_pstat_static();
    if (pstat_static == NULL) {
        return NULL;
    }

    currtime = time(NULL);

    boottime = pstat_static->boot_time;

    general_stat.uptime = currtime - boottime;
#endif
#ifdef SOLARIS
    if ((kc = kstat_open()) == NULL) {
        sg_set_error(SG_ERROR_KSTAT_OPEN, NULL);
        return NULL;
    }
    if((ksp=kstat_lookup(kc, "unix", -1, "system_misc"))==NULL) {
        sg_set_error(SG_ERROR_KSTAT_LOOKUP, "unix,-1,system_misc");
        kstat_close(kc);
        return NULL;
    }
    if (kstat_read(kc, ksp, 0) == -1) {
        sg_set_error(SG_ERROR_KSTAT_READ, NULL);
        kstat_close(kc);
        return NULL;
    }
    if((kn=kstat_data_lookup(ksp, "boot_time")) == NULL) {
        sg_set_error(SG_ERROR_KSTAT_DATA_LOOKUP, "boot_time");
        kstat_close(kc);
        return NULL;
    }
    boottime=(kn->value.ui32);

    kstat_close(kc);

    time(&curtime);
    general_stat.uptime = curtime - boottime;
#endif
#if defined(LINUX) || defined(CYGWIN)
    if ((f=fopen("/proc/uptime", "r")) == NULL) {
        sg_set_error_with_errno(SG_ERROR_OPEN, "/proc/uptime");
        return NULL;
    }
    if((fscanf(f,"%lu %*d",&general_stat.uptime)) != 1) {
        sg_set_error(SG_ERROR_PARSE, NULL);
        return NULL;
    }
    fclose(f);
#endif
#ifdef ALLBSD
    mib[0] = CTL_KERN;
    mib[1] = KERN_BOOTTIME;
    size = sizeof boottime;
    if (sysctl(mib, 2, &boottime, &size, NULL, 0) < 0) {
        sg_set_error_with_errno(SG_ERROR_SYSCTL,
                                "CTL_KERN.KERN_BOOTTIME");
        return NULL;
    }
    time(&curtime);
    general_stat.uptime=curtime-boottime.tv_sec;
#endif
#ifdef WIN32
    if(read_counter_large(SG_WIN32_UPTIME, &result)) {
        sg_set_error(SG_ERROR_PDHREAD, PDH_UPTIME);
        return NULL;
    }
    general_stat.uptime = (time_t) result;
#endif

    return &general_stat;

}
Esempio n. 4
0
static sg_error
sg_get_host_info_int(sg_host_info *host_info_buf) {

#ifdef WIN32
	unsigned long nameln;
	char *name;
	long long result;
	OSVERSIONINFOEX osinfo;
	SYSTEM_INFO sysinfo;
	char *tmp_name;
	char tmp[10];
#else
	struct utsname os;
# if defined(HPUX)
	struct pst_static pstat_static;
	struct pst_dynamic pstat_dynamic;
	time_t currtime;
	long boottime;
# elif defined(SOLARIS)
	time_t boottime, curtime;
	kstat_ctl_t *kc;
	kstat_t *ksp;
	kstat_named_t *kn;
	char *isainfo = NULL;
	long isabufsz, rc;
# elif defined(LINUX) || defined(CYGWIN)
	FILE *f;
# elif defined(ALLBSD)
	int mib[2];
	struct timeval boottime;
	time_t curtime;
	size_t size;
	int ncpus;
#  if defined(HW_MACHINE_ARCH) || defined(HW_MACHINE)
	char arch_name[16];
#  endif
# elif defined(AIX)
	static perfstat_cpu_total_t cpu_total;
	sg_error rc;
#  if defined(HAVE_GETUTXENT)
	struct utmpx *ut;
#  else
	struct utmp *ut;
#  endif
# endif
#endif

	host_info_buf->ncpus = 0;
	host_info_buf->maxcpus = 0;
	host_info_buf->bitwidth = 0;
	host_info_buf->host_state = sg_unknown_configuration;
	host_info_buf->uptime = 0;
	host_info_buf->systime = 0;

#ifdef WIN32
	/* these settings are static after boot, so why get them
	 * constantly?
	 *
	 * Because we want to know some changes anyway - at least
	 * when the hostname (DNS?) changes
	 */

	/* get system name */
	nameln = MAX_COMPUTERNAME_LENGTH + 1;
	name = sg_malloc(nameln);
	if(name == NULL) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/*
	 * XXX probably GetComputerNameEx() is a better entry point ...
	 */
	if( GetComputerName(name, &nameln) == 0 ) {
		free(name);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_HOST, "GetComputerName");
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->hostname, name)) {
		free(name);
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
	free(name);

	/* get OS name, version and build */
	ZeroMemory(&osinfo, sizeof(OSVERSIONINFOEX));
	osinfo.dwOSVersionInfoSize = sizeof(osinfo);
	if(!GetVersionEx(&osinfo)) {
		RETURN_WITH_SET_ERROR("os", SG_ERROR_HOST, "GetVersionEx");
	}
	GetSystemInfo(&sysinfo);

	/* Release - single number */
	if(snprintf(tmp, sizeof(tmp), "%ld", osinfo.dwBuildNumber) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SPRINTF, NULL);
	}
	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_release, tmp)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/* Version */
	/* usually a single digit . single digit, eg 5.0 */
	if(snprintf(tmp, sizeof(tmp), "%ld.%ld", osinfo.dwMajorVersion,
				osinfo.dwMinorVersion) == -1) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_version, tmp)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/* OS name */
	tmp_name = get_os_name(osinfo, sysinfo);
	if(tmp_name == NULL) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_name, tmp_name)) {
		free(tmp_name);
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
	free(tmp_name);

	/* Platform */
	switch(sysinfo.wProcessorArchitecture) {
		case PROCESSOR_ARCHITECTURE_INTEL:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"Intel")) {
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
		case PROCESSOR_ARCHITECTURE_IA64:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"IA64")) {
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
		case PROCESSOR_ARCHITECTURE_AMD64:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"AMD64")) {
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
		default:
			if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform,
						"Unknown")){
				RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
			}
			break;
	}

	if(read_counter_large(SG_WIN32_UPTIME, &result)) {
		RETURN_WITH_SET_ERROR("os", SG_ERROR_PDHREAD, PDH_UPTIME);
	}

	host_info_buf->uptime = (time_t) result;
#else
	if((uname(&os)) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_UNAME, NULL);
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_name, os.sysname)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_release, os.release)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_version, os.version)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, os.machine)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->hostname, os.nodename)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	/* get uptime */
#ifdef HPUX
	if (pstat_getstatic(&pstat_static, sizeof(pstat_static), 1, 0) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_PSTAT, "pstat_static");
	}

	if (pstat_getdynamic(&pstat_dynamic, sizeof(pstat_dynamic), 1, 0) == -1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_PSTAT, "pstat_dynamic");
	}

	currtime = time(NULL);

	boottime = pstat_static.boot_time;

	host_info_buf->uptime = currtime - boottime;
	host_info_buf->ncpus = pstat_dynamic.psd_proc_cnt;
	host_info_buf->maxcpus = pstat_dynamic.psd_max_proc_cnt;
	host_info_buf->bitwidth = sysconf(_SC_KERNEL_BITS);

	/*
	 * TODO: getting virtualization state
	 *       1) on boostrapping this component, try loading /opt/hpvm/lib/libhpvm.so (or so)
	 *       2) get function addresses for
	 *          a) HPVM_boolean hpvm_api_server_check()
	 *          b) HPVM_boolean hpvm_api_virtmach_check()
	 *
	 * Seems to be hardware virtualization ...
	 * See: http://docstore.mik.ua/manuals/hp-ux/en/T2767-90141/index.html (hpvmpubapi(3))
	 *      http://jreypo.wordpress.com/tag/hpvm/
	 *      http://jreypo.wordpress.com/category/hp-ux/page/3/
	 *      http://h20338.www2.hp.com/enterprise/us/en/os/hpux11i-partitioning-integrity-vm.html
	 */

#elif defined(SOLARIS)
	if ((kc = kstat_open()) == NULL) {
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_OPEN, NULL);
	}

	if((ksp=kstat_lookup(kc, "unix", -1, "system_misc"))==NULL){
		kstat_close(kc);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_LOOKUP, "unix,-1,system_misc");
	}
	if (kstat_read(kc, ksp, 0) == -1) {
		kstat_close(kc);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_READ, NULL);
	}
	if((kn=kstat_data_lookup(ksp, "boot_time")) == NULL){
		kstat_close(kc);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_DATA_LOOKUP, "boot_time");
	}
	/* XXX verify on Solaris 10 if it's still ui32 */
	boottime = (kn->value.ui32);

	kstat_close(kc);

	time(&curtime);
	host_info_buf->uptime = curtime - boottime;

	host_info_buf->ncpus = sysconf(_SC_NPROCESSORS_ONLN);
	host_info_buf->maxcpus = sysconf(_SC_NPROCESSORS_CONF);
	isainfo = sg_malloc( isabufsz = (32 * sizeof(*isainfo)) );
	if( NULL == isainfo ) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}
# define MKSTR(x) #x
# if defined(SI_ARCHITECTURE_K)
#  define SYSINFO_CMD SI_ARCHITECTURE_K
# elif defined(SI_ISALIST)
#  define SYSINFO_CMD SI_ISALIST
# else
#  define SYSINFO_CMD SI_ARCHITECTURE
# endif
sysinfo_again:
	if( -1 == ( rc = sysinfo( SYSINFO_CMD, isainfo, isabufsz ) ) ) {
		free(isainfo);
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSINFO, MKSTR(SYSINFO_CMD) );
	}
	else if( rc > isabufsz ) {
		char *tmp = sg_realloc(isainfo, rc);
		if( NULL == tmp ) {
			free(isainfo);
			RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
		}
		isabufsz = rc;
		isainfo = tmp;
		goto sysinfo_again;
	}

	host_info_buf->bitwidth = get_bitwidth_by_arch_name(isainfo);
	free(isainfo);
	host_info_buf->host_state = sg_unknown_configuration;

#elif defined(LINUX) || defined(CYGWIN)
	if ((f=fopen("/proc/uptime", "r")) == NULL) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_OPEN, "/proc/uptime");
	}

#define TIME_T_SCANF_FMT (sizeof(int[(((time_t)-1)/2)%4+1]) == sizeof(int[1]) ? "%ld %*d" : "%lu %*d" )
	if((fscanf(f,TIME_T_SCANF_FMT,&host_info_buf->uptime)) != 1){
		fclose(f);
		RETURN_WITH_SET_ERROR("os", SG_ERROR_PARSE, NULL);
	}
	fclose(f);

# if defined(LINUX)
	host_info_buf->ncpus = sysconf(_SC_NPROCESSORS_ONLN);
	host_info_buf->maxcpus = sysconf(_SC_NPROCESSORS_CONF);
	if( access( "/proc/sys/kernel/vsyscall64", F_OK ) == 0 ||
	    access( "/proc/sys/abi/vsyscall32", F_OK ) == 0 ) {
		host_info_buf->bitwidth = 64;
	}
	else {
		host_info_buf->bitwidth = sysconf(_SC_LONG_BIT); // well, maybe 64-bit disabled 128-bit system o.O
	}
	host_info_buf->host_state = sg_unknown_configuration;
# endif

#elif defined(ALLBSD)
	mib[0] = CTL_KERN;
	mib[1] = KERN_BOOTTIME;
	size = sizeof(boottime);
	if (sysctl(mib, 2, &boottime, &size, NULL, 0) < 0) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_KERN.KERN_BOOTTIME");
	}
	time(&curtime);
	host_info_buf->uptime= curtime - boottime.tv_sec;

# if defined(HW_NCPU)
	mib[0] = CTL_HW;
	mib[1] = HW_NCPU;
	size = sizeof(int);
	if( sysctl( mib, 2, &ncpus, &size, NULL, 0 ) < 0 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_NCPU" );
	}
# endif
# if defined(HW_MACHINE_ARCH)
	mib[0] = CTL_HW;
	mib[1] = HW_MACHINE_ARCH;
	size = sizeof(arch_name);
	if( sysctl( mib, 2, arch_name, &size, NULL, 0 ) == 0 ) {
		host_info_buf->bitwidth = get_bitwidth_by_arch_name(arch_name);
	}
	else {
# endif
# if defined(HW_MACHINE)
	mib[0] = CTL_HW;
	mib[1] = HW_MACHINE;
	size = sizeof(arch_name);
	if( sysctl( mib, 2, arch_name, &size, NULL, 0 ) == 0 ) {
		host_info_buf->bitwidth = get_bitwidth_by_arch_name(arch_name);
	}
	else {
		SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_MACHINE" );
	}
# elif defined(HW_MACHINE_ARCH)
		SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_MACHINE_ARCH" );
# endif
# if defined(HW_MACHINE_ARCH)
	}
# endif
	host_info_buf->host_state = sg_unknown_configuration; /* details must be analysed "manually", no syscall */
	host_info_buf->maxcpus = (unsigned)ncpus;
# if defined(HW_NCPUONLINE)
	/* use knowledge about number of cpu's online, when available instead of assuming all of them */
	mib[0] = CTL_HW;
	mib[1] = HW_NCPUONLINE;
	size = sizeof(int);
	if( sysctl( mib, 2, &ncpus, &size, NULL, 0 ) < 0 ) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_NCPUONLINE" );
	}
# endif
	host_info_buf->ncpus = (unsigned)ncpus;

#elif defined(AIX)
	if(perfstat_cpu_total(NULL, &cpu_total, sizeof(cpu_total), 1) != 1) {
		RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "perfstat_cpu_total");
	}

	if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, cpu_total.description)) {
		RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() );
	}

	host_info_buf->ncpus = cpu_total.ncpus;
	host_info_buf->maxcpus = cpu_total.ncpus_cfg;
	host_info_buf->bitwidth = sysconf(_SC_AIX_KERNEL_BITMODE);
	if( sysconf(_SC_LPAR_ENABLED) > 0 ) {
		host_info_buf->host_state = sg_hardware_virtualized;
	}
	else {
		host_info_buf->host_state = sg_physical_host;
	}

#ifdef ENABLE_THREADS
	if( SG_ERROR_NONE != ( rc = sg_lock_mutex("utmp") ) ) {
		RETURN_FROM_PREVIOUS_ERROR( "os", rc );
	}
#endif
# if defined(HAVE_GETUTXENT)
#  define UTENTFN getutxent
#  define UTENTTM ut->ut_tv.tv_sec
	setutxent();
# else
#  define UTENTFN getutent
#  define UTENTTM ut->ut_time
	setutent();
# endif
	while( NULL != ( ut = UTENTFN() ) ) {
		if( ut->ut_type == BOOT_TIME ) {
			host_info_buf->uptime = time(NULL) - UTENTTM;
			break;
		}
	}
# if defined(HAVE_GETUTXENT)
	endutxent();
# else
	endutent();
# endif
#ifdef ENABLE_THREADS
	if( SG_ERROR_NONE != ( rc = sg_unlock_mutex("utmp") ) ) {
		RETURN_FROM_PREVIOUS_ERROR( "os", rc );
	}
#endif
#else
	RETURN_WITH_SET_ERROR("os", SG_ERROR_UNSUPPORTED, OS_TYPE);
#endif
#endif /* WIN32 */

	host_info_buf->systime = time(NULL);

	return SG_ERROR_NONE;
}