You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
spOSMroute/base/system.c

418 lines
10 KiB

/***************************************************************************
* system.c
*
* Copyright 2009 - Steffen Pohle
* steffen@gulpe.de
****************************************************************************/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "system.h"
#include "map.h"
#include "osmroute.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#if !defined(__MINGW32CE__) && !defined(_WIN32_WCE) && !defined(__MINGW32__)
#include <sys/time.h>
#include <sys/resource.h>
#endif
time_t starttime;
/*******************************************
*
* comparsion between doubles and floats
*/
int cmpf (float f1, float f2) {
return fabs(f1-f2) <= FLT_EPSILON;
};
int cmpd (double d1, double d2) {
return fabs(d1-d2) < DBL_EPSILON;
};
#if !defined(__MINGW32CE__) && !defined(_WIN32_WCE) && !defined(__MINGW32__)
int execcall (struct s_execcall *p, char *prg, char **argv) {
if (p->used) return 0;
if ((p->pid = fork ()) < 0) {
printf ("%s:%d syscall fork error: %s\n", __FILE__, __LINE__, strerror (errno));
return 0;
}
else if (p->pid == 0) { // child //
if (execvp(prg, argv) < 0) {
printf ("%s:%d syscall execvp error:%s\n", __FILE__, __LINE__, strerror (errno));
errorexit (-1);
}
}
/* parent */
p->used = 1;
return 1;
};
int execwait (struct s_execcall *p) {
pid_t ptmp;
int status;
if (p->used == 0) return -1;
ptmp = waitpid (p->pid, &status, WNOHANG);
if (ptmp == p->pid) {
if (WIFEXITED (status)) {
p->used = 0;
return 1;
}
}
else if (ptmp == -1) {
p->used = 0;
return 1;
}
return -2;
};
#endif
// #ifndef ANDROID
void d_printf (char *fmt,...) {
va_list args;
char text1[1024];
char text2[1024];
char fn[LEN_FILENAME];
int f;
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
// return;
#endif
va_start (args, fmt);
vsnprintf (text1, 1024, fmt, args);
va_end (args);
text1[1023] = 0;
text2[1023] = 0;
snprintf (fn, LEN_FILENAME, "%slogfile.txt", cfg.logpath);
snprintf (text2, 1024, "%-6d %s", (int)(time(NULL) - starttime), text1);
#ifndef COSMROUTE
fprintf (stderr, "%s\n", text2);
#endif
f = open (fn, O_RDWR | O_CREAT, 0644);
if (f) {
lseek (f, 0, SEEK_END);
write (f, text2, strlen (text2));
#if !defined(__MINGW32CE__) && !defined(_WIN32_WCE) && !defined(__MINGW32__) && !defined(ANDROID)
write (f, "\n", 1);
#else
write (f, "\n\r", 2);
#endif
close (f);
}
};
// #endif
void d_print_init() {
int i;
char **strings;
char fn[LEN_FILENAME];
snprintf (fn, LEN_FILENAME, "%slogfile.txt", cfg.logpath);
starttime = time (NULL);
unlink (fn);
d_printf ("");
d_printf ("************************************************************");
d_printf ("* Starting *");
d_printf ("************************************************************");
d_printf ("size of datatypes in bytes - should be on all systems the same");
d_printf (" type : size ");
d_printf ("----------------+------");
d_printf ("float : %d", sizeof (float));
d_printf ("char : %d", sizeof (char));
d_printf ("uint16_t : %d", sizeof (uint16_t));
d_printf ("uint32_t : %d", sizeof (uint32_t));
d_printf ("uint64_t : %d", sizeof (uint64_t));
d_printf ("size of datatypes in bytes - can be different");
d_printf (" type : size ");
d_printf ("----------------+------");
d_printf ("long long int : %d", sizeof (long long int));
d_printf ("long int : %d", sizeof (long int));
d_printf ("int : %d INT_MIN:%d, INT_MAX:%d", sizeof (int), INT_MIN, INT_MAX);
d_printf ("short int : %d", sizeof (short int));
d_printf ("\nTest for Backtraces:");
strings = get_backtrace (&i);
if (i < 1 || strings == NULL) d_printf ("seems not to work\n");
else {
d_printf ("works: %s\n", strings[2]);
free (strings);
}
};
#define D_PRINT_COL 16
void d_print_data (char *data, int len) {
int i, j;
int val;
char txt1 [256] = {0};
char txt2 [256] = {0};
char left [256] = {0};
char right [256] = {0};
d_printf ("memdump: len:%d", len);
for (i = 0; i < len; i++) {
val = data[i] & 0x00FF;
sprintf (txt1, "%2x ", val);
if (data[i] >= ' ' && data[i] <= '~') sprintf (txt2, "%c", data[i]);
else sprintf (txt2, ".");
strncat (left, txt1, 256);
strncat (right, txt2, 256);
if ((i%D_PRINT_COL)==D_PRINT_COL-1 || i == len-1) {
sprintf (txt1, " ");
sprintf (txt2, " ");
for (j = i%D_PRINT_COL; j != 0 && j < D_PRINT_COL; j++) {
strncat (left, txt1, 256);
strncat (right, txt2, 256);
}
d_printf (" |%s | %s |", left, right);
memset (left, 0x0, 256);
memset (right, 0x0, 256);
}
}
};
unsigned long long int getticks () {
static unsigned long long int ticks = 0;
if (ticks > (unsigned long long int)(ticks+1)) {
d_printf ("%s:%d ticks+1 < ticks", __FILE__, __LINE__);
errorexit (-1);
}
return ++ticks;
};
#define SIZE 100
void errorexit (int nr) {
#if !defined(__MINGW32CE__) && !defined(_WIN32_WCE) && !defined(__MINGW32__) && !defined(ANDROID)
int j, nptrs;
void *buffer[SIZE];
char **strings;
nptrs = backtrace(buffer, SIZE);
d_printf("****************** backtrace: (needs to be linked with -Wl,--export-dynamic)");
/* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
* would produce similar output to the following: */
strings = (char **) backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
d_printf ("backtrace_symbols: %s", strerror(errno));
exit(EXIT_FAILURE);
}
for (j = 0; j < nptrs; j++)
d_printf("%s", strings[j]);
free(strings);
#endif
exit (nr);
};
void d_print_backtrace () {
#if !defined(__MINGW32CE__) && !defined(_WIN32_WCE) && !defined(__MINGW32__) && !defined(ANDROID)
int j, nptrs;
void *buffer[SIZE];
char **strings;
nptrs = backtrace(buffer, SIZE);
d_printf("****************** backtrace: (needs to be linked with -Wl,--export-dynamic)");
/* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
* would produce similar output to the following: */
strings = (char **) backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
d_printf (" backtrace_symbols: %s", strerror(errno));
exit(EXIT_FAILURE);
}
for (j = 0; j < nptrs; j++)
d_printf(" %s", strings[j]);
free(strings);
#endif
};
char **get_backtrace (int *cnt) {
#if !defined(__MINGW32CE__) && !defined(_WIN32_WCE) && !defined(__MINGW32__) && !defined(ANDROID)
void *buffer[SIZE];
char **strings;
*cnt = backtrace(buffer, SIZE);
/* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
* would produce similar output to the following: */
strings = (char **) backtrace_symbols(buffer, *cnt);
if (strings == NULL) {
d_printf ("backtrace_symbols: %s", strerror(errno));
exit(EXIT_FAILURE);
}
return strings;
#else
return NULL;
#endif
};
/*
* copy data to the givin address and return increased pointer
*/
char *mempush (void *mem, void *source, int size) {
memcpy (mem, source, size);
return mem+size;
};
char *mempop (void *mem, void *dest, int size) {
memcpy (dest, mem, size);
return mem+size;
};
char *memstrpop (void *mem, void *dest, int *size) {
uint8_t *m = mem, *d = dest;
void *mout;
while (*m != 0) {
*d = *m;
d++;
m++;
}
*d = *m;
m++;
mout = m;
*size = mout - mem;
return (char*)m;
};
#if !defined(ANDROID)
void memswap (void *mem1, void *mem2, int size) {
char data[32];
if (size > 32) {
d_printf ("memswap maximum memory size of 32 bytes overrun size:%d", size);
errorexit (-1);
}
memcpy (data, mem2, size);
memcpy (mem2, mem1, size);
memcpy (mem1, data, size);
};
#endif
int file_exist (char *fn) {
struct stat fs;
if (stat(fn, &fs) != 0)
return 0;
return 1;
};
int dir_exist (char *fn) {
struct stat fs;
if (stat(fn, &fs) == 0) {
if (S_ISDIR(fs.st_mode))
return 1;
}
return 0;
}
void d_print_stat () {
#if !defined(__MINGW32CE__) && !defined(_WIN32_WCE) && !defined(__MINGW32__) && !defined(ANDROID)
struct rusage usage;
d_printf ("getrusage:");
if (getrusage(RUSAGE_SELF, &usage) == 0) {
// d_printf ("ru_utime : %6ld user CPU time used", usage.ru_utime);
// d_printf ("ru_stime : %6ld system CPU time used", usage.ru_stime);
d_printf ("ru_maxrss : %6ld maximum resident set size", usage.ru_maxrss);
// d_printf ("ru_ixrss : %6ld integral shared memory size", usage.ru_ixrss);
// d_printf ("ru_idrss : %6ld integral unshared data size", usage.ru_idrss);
// d_printf ("ru_isrss : %6ld integral unshared stack size", usage.ru_isrss);
d_printf ("ru_minflt : %6ld page reclaims (soft page faults)", usage.ru_minflt);
d_printf ("ru_majflt : %6ld page faults (hard page faults)", usage.ru_majflt);
d_printf ("ru_nswap : %6ld swaps", usage.ru_nswap);
d_printf ("ru_inblock : %6ld block input operations", usage.ru_inblock);
d_printf ("ru_oublock : %6ld block output operations", usage.ru_oublock);
// d_printf ("ru_msgsnd : %6ld IPC messages sent", usage.ru_msgsnd);
// d_printf ("ru_msgrcv : %6ld IPC messages received", usage.ru_msgrcv);
// d_printf ("ru_nsignals: %6ld signals received", usage.ru_nsignals);
d_printf ("ru_nvcsw : %6ld voluntary context switches", usage.ru_nvcsw);
d_printf ("ru_nivcsw : %6ld involuntary context switches", usage.ru_nivcsw);
}
else d_printf ("getrusage error.");
#else
d_printf ("getrusage not implemented in windows..");
#endif
}
char _flags2text_[255] = "";
char* flags2text (int f, char *text) {
int i;
int c;
char *fn1;
char *fn2;
fn1 = text;
memset (_flags2text_, 0x0, 255);
snprintf (_flags2text_, 250, "%d:", f);
for (c = 1; (c < 0xFFFF && fn1 != NULL); c *= 2) {
fn2 = strchr (fn1, '\n');
if (fn2 == NULL) i = strlen (fn1);
else i = fn2-fn1;
if (f & c) {
if (c > 1) {
_flags2text_[strlen(_flags2text_)+1] = 0;
_flags2text_[strlen(_flags2text_)] = ',';
}
strncpy (_flags2text_+strlen(_flags2text_), fn1, i);
}
if (fn2 != NULL) fn2 += 1;
fn1 = fn2;
}
return _flags2text_;
}