Acorn Arcade forums: Programming: Does this program hang in your Linux system?
|
Does this program hang in your Linux system? |
|
Stoppers (11:50 8/10/2010) nunfetishist (12:45 8/10/2010) Stoppers (13:45 8/10/2010) nunfetishist (14:33 8/10/2010) Stoppers (19:58 8/10/2010) Phlamethrower (20:22 8/10/2010) ksattic (05:57 9/10/2010) Stoppers (12:27 9/10/2010) Stoppers (13:19 10/10/2010)
|
|
Simon Willcocks |
Message #115596, posted by Stoppers at 11:50, 8/10/2010 |
Member
Posts: 302
|
(Note: Linux doesn't hang, just the program.)
Sorry about the indentation!
#include <signal.h>
#include <stdio.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h>
#include <stdint.h>
static void alrm_action( int code, siginfo_t *info, void *p ) { fprintf( stderr, "Tick" ); }
int main() { { struct sigaction action = { .sa_sigaction = alrm_action, .sa_flags = SA_SIGINFO }; sigaction( SIGALRM, &action, 0 );
int microseconds = 10000; // 1cs
struct itimerval timer_val = { .it_interval = { .tv_sec = microseconds / 1000000, .tv_usec = microseconds % 1000000 }, .it_value = { .tv_sec = microseconds / 1000000, .tv_usec = microseconds % 1000000 }, }; struct itimerval old_val;
setitimer( ITIMER_REAL, &timer_val, &old_val ); }
int x = 0; while (1) { fprintf( stderr, "+" ); if (x-- == 0) { fprintf( stderr, "\n" ); x = 100; } }
return 0; } |
|
[ Log in to reply ] |
|
Rob Kendrick |
Message #115597, posted by nunfetishist at 12:45, 8/10/2010, in reply to message #115596 |
Today's phish is trout a la creme.
Posts: 524
|
No. But SIGALRM is an evil hack |
|
[ Log in to reply ] |
|
Simon Willcocks |
Message #115598, posted by Stoppers at 13:45, 8/10/2010, in reply to message #115597 |
Member
Posts: 302
|
Thanks for trying.
No. What version kernel are you running? Processor type?
I should have said it shows up quicker if you pipe the output through grep -n Tick. (The line numbers give you an indication of how long it is between ticks.)
But SIGALRM is an evil hack Do you have any better suggestions for emulating a hardware timer? I'd rather not make a system call every few emulated instructions, if at all possible. |
|
[ Log in to reply ] |
|
Rob Kendrick |
Message #115599, posted by nunfetishist at 14:33, 8/10/2010, in reply to message #115598 |
Today's phish is trout a la creme.
Posts: 524
|
rjek@trite:~$ uname -a Linux trite 2.6.32-25-generic #44-Ubuntu SMP Fri Sep 17 20:05:27 UTC 2010 x86_64 GNU/Linux rjek@trite:~$ cat /proc/cpuinfo processor : 0 vendor_id : AuthenticAMD cpu family : 15 model : 67 model name : AMD Athlon(tm) 64 X2 Dual Core Processor 6000+ stepping : 3 cpu MHz : 3013.997 cache size : 1024 KB physical id : 0 siblings : 2 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 1 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt rdtscp lm 3dnowext 3dnow rep_good extd_apicid pni cx16 lahf_lm cmp_legacy svm extapic cr8_legacy bogomips : 6027.99 TLB size : 1024 4K pages clflush size : 64 cache_alignment : 64 address sizes : 40 bits physical, 48 bits virtual power management: ts fid vid ttp tm stc
processor : 1 vendor_id : AuthenticAMD cpu family : 15 model : 67 model name : AMD Athlon(tm) 64 X2 Dual Core Processor 6000+ stepping : 3 cpu MHz : 3013.997 cache size : 1024 KB physical id : 0 siblings : 2 core id : 1 cpu cores : 2 apicid : 1 initial apicid : 1 fpu : yes fpu_exception : yes cpuid level : 1 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt rdtscp lm 3dnowext 3dnow rep_good extd_apicid pni cx16 lahf_lm cmp_legacy svm extapic cr8_legacy bogomips : 6028.19 TLB size : 1024 4K pages clflush size : 64 cache_alignment : 64 address sizes : 40 bits physical, 48 bits virtual power management: ts fid vid ttp tm stc
rjek@trite:~$ lsb_release -a LSB Version: core-2.0-amd64:core-2.0-noarch:core-3.0-amd64:core-3.0-noarch:core-3.1-amd64:core-3.1-noarch:core-3.2-amd64:core-3.2-noarch:core-4.0-amd64:core-4.0-noarch Distributor ID: Ubuntu Description: Ubuntu 10.04.1 LTS Release: 10.04 Codename: lucid
The problem with SIGALRM is that it's "best effort"; it's not precise. And signals don't mix nicely with... well, anything at all.
Processing a SIGALRM is probably as expensive as, say, gettimeofday() and usleep(), or perhaps even a thread that usleep()s and wiggles when it wakes up. It has to context switch, stop any in-progress system calls, create a new stack and execution context, jump, return, untie all that, and where appropriate, restart the system call (or leave it to your own code to restart it when you detect EINTR etc.) |
|
[ Log in to reply ] |
|
Simon Willcocks |
Message #115604, posted by Stoppers at 19:58, 8/10/2010, in reply to message #115599 |
Member
Posts: 302
|
The problem with SIGALRM is that it's "best effort"; it's not precise. And signals don't mix nicely with... well, anything at all.
Processing a SIGALRM is probably as expensive as, say, gettimeofday() and usleep(), or perhaps even a thread that usleep()s and wiggles when it wakes up. It has to context switch, stop any in-progress system calls, create a new stack and execution context, jump, return, untie all that, and where appropriate, restart the system call (or leave it to your own code to restart it when you detect EINTR etc.) Perhaps, but processing one SIGALRM every centisecond (or whatever) is less expensive than making a system call every few hundred instructions (the single-threaded case).
The multi-threaded case could be better, provided I set the usleep according to the result of gettimeofday.
The setitimer man page says that "The system provides each process with three interval timers" and that "Timers decrement from it_value to zero, generate a signal, and reset to it_interval." (which, presumably, doesn't need to wait for the process to be scheduled), whereas the usleep page says that "The sleep may be lengthened slightly by any system activity". That sounds to me that the setitimer approach is better to emulate a regular timed interrupt (you can also read its current state at any time).
Emulating TWO regular timers (or one irregular one) is another question....
I'll give the thread approach a go, at least it shouldn't hang.
Thanks, Simon
P.S. Did anyone else try the program?
[Edited by Stoppers at 21:01, 8/10/2010] |
|
[ Log in to reply ] |
|
Jeffrey Lee |
Message #115605, posted by Phlamethrower at 20:22, 8/10/2010, in reply to message #115604 |
Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff
Posts: 15100
|
Perhaps, but processing one SIGALRM every centisecond (or whatever) is less expensive than making a system call every few hundred instructions (the single-threaded case). You could try making the code automatically adjust the number of instructions inbetween each timer check. As long as you don't cut it too fine it should be pretty resilliant to sudden changes in how much CPU time the emulator receives. E.g. if you want a centisecond timer, make the code aim to poll the system time once every millisecond.
P.S. Did anyone else try the program? Nope. I might remember to try it later if you're lucky |
|
[ Log in to reply ] |
|
Simon Wilson |
Message #115607, posted by ksattic at 05:57, 9/10/2010, in reply to message #115605 |
Finally, an avatar!
Posts: 1291
|
My Linux box is currently on a big lorry somewhere but I tried this on my Mac and it was fine. I didn't expect it to hang. Are you sure it's not the large amount of output to stderr making your terminal sluggish? You could try throttling your output in the while loop with usleep().
You could also redirect stderr to a file and see in another terminal if the file is growing in size, but this will fill up your drive pretty fast. |
|
[ Log in to reply ] |
|
Simon Willcocks |
Message #115608, posted by Stoppers at 12:27, 9/10/2010, in reply to message #115607 |
Member
Posts: 302
|
My Linux box is currently on a big lorry somewhere but I tried this on my Mac and it was fine. I didn't expect it to hang. Are you sure it's not the large amount of output to stderr making your terminal sluggish? You could try throttling your output in the while loop with usleep().
You could also redirect stderr to a file and see in another terminal if the file is growing in size, but this will fill up your drive pretty fast. I didn't expect it to hang, either. It's happening with my emulator, which is quite annoying.
It usually hangs pretty quickly on this machine, especially if I pipe the output through grep, like I suggested above. If I use gdb on it, I find that it's in a futex system call at an offset from the start of pthread_exit (that's all the debug information available, it's not actually in that function).
It might be something like this: http://lwn.net/Articles/124747/ but that was back in 2005.
There's a very similar example program here, that uses time and ctime instead of fprintf: http://ubuntuforums.org/showthread.php?t=675821
Simplified even more (and using a thread safe ctime_r instead of ctime), it still happens (processor usage almost immediately drops to background levels, gdb shows the count variables stop changing).
#include <sys/time.h> #include <signal.h>
int handler_count = 0; int loop_count = 0;
void handler(int sig) { char buf[64]; time_t t = 0; // 00:00:00 on January 1, 1970 ctime_r( &t, buf ); handler_count++; }
int main() { struct sigaction sa = { .sa_handler = handler };
sigaction(SIGALRM, &sa, 0);
struct itimerval it = { .it_value = { .tv_sec = 0, .tv_usec = 1000 }, .it_interval = { .tv_sec = 0, .tv_usec = 1000 } };
setitimer(ITIMER_REAL, &it, 0);
char buf[64]; time_t t = 0; // 00:00:00 on January 1, 1970
while(1) { ctime_r( &t, buf ); loop_count++; }
return 0; }
knoppix@Microknoppix:/tmp$ uname -a Linux Microknoppix 2.6.32.6 #8 SMP PREEMPT Thu Jan 28 10:51:16 CET 2010 i686 GNU/Linux knoppix@Microknoppix:/tmp$ cat /proc/cpuinfo processor : 0 vendor_id : AuthenticAMD cpu family : 15 model : 107 model name : AMD Athlon(tm) Dual Core Processor 5050e stepping : 2 cpu MHz : 2593.286 cache size : 512 KB physical id : 0 siblings : 2 core id : 0 cpu cores : 2 apicid : 0 initial apicid : 0 fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 1 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt rdtscp lm 3dnowext 3dnow extd_apicid pni cx16 lahf_lm cmp_legacy svm extapic cr8_legacy 3dnowprefetch bogomips : 5188.67 clflush size : 64 cache_alignment : 64 address sizes : 40 bits physical, 48 bits virtual power management: ts fid vid ttp tm stc 100mhzsteps
(ditto, core 2)
/lib/libc.so.6: file format elf32-i386 /lib/libc.so.6 architecture: i386, flags 0x00000150: HAS_SYMS, DYNAMIC, D_PAGED start address 0x4ef75cb0 |
|
[ Log in to reply ] |
|
Simon Willcocks |
Message #115613, posted by Stoppers at 13:19, 10/10/2010, in reply to message #115596 |
Member
Posts: 302
|
A solution (or a reason) is found!
On the lfs-chat mailing list I was pointed to this page:
http://www.opengroup.org/onlinepubs/000095399/functions/xsh_chap02_04.html#tag_02_04_03
It gives a list of 118 "async signal safe" functions, which doesn't include ctime or any variations on printf.
Never calling fprintf from the handler function results in much improved behaviour.
[Edited by Stoppers at 14:51, 10/10/2010] |
|
[ Log in to reply ] |
|
|
Acorn Arcade forums: Programming: Does this program hang in your Linux system? |