log in | register | forums
Show:
Go:
Forums
Username:

Password:

User accounts
Register new account
Forgot password
Forum stats
List of members
Search the forums

Advanced search
Recent discussions
- R-Comp reveals N.Ex.T Boxes - the successor to the i.MX6 (News:)
- RISCOSbits at Wakefield Show 2024 (News:)
- R-Comp releases Genealogy v2 (News:)
- Will we see 5.30 released at Wakefield show? (News:1)
- Sine Nomine updates RiscOSM and Impact (News:)
- Netfetch version 5.55 released (News:)
- Prizes for Wakefield Show announced (News:)
- Heretic update from R-Comp (News:)
- Wakefield Show 2024 is next Saturday (News:)
- Git client updated to 0.07 (News:2)
Latest postings RSS Feeds
RSS 2.0 | 1.0 | 0.9
Atom 0.3
Misc RDF | CDF
 
View on Mastodon
@www.iconbar.com@rss-parrot.net
Site Search
 
Article archives
The Icon Bar: Programming: Does this program hang in your Linux system?
 
  Does this program hang in your Linux system?
  Stoppers (12:50 8/10/2010)
  nunfetishist (13:45 8/10/2010)
    Stoppers (14:45 8/10/2010)
      nunfetishist (15:33 8/10/2010)
        Stoppers (20:58 8/10/2010)
          Phlamethrower (21:22 8/10/2010)
            ksattic (06:57 9/10/2010)
              Stoppers (13:27 9/10/2010)
  Stoppers (14:19 10/10/2010)
 
Simon Willcocks Message #115596, posted by Stoppers at 12: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 13:45, 8/10/2010, in reply to message #115596
nunfetishist
Today's phish is trout a la creme.

Posts: 522
No. But SIGALRM is an evil hack smile
  ^[ Log in to reply ]
 
Simon Willcocks Message #115598, posted by Stoppers at 14: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 smile
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 15:33, 8/10/2010, in reply to message #115598
nunfetishist
Today's phish is trout a la creme.

Posts: 522
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 20: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 21:22, 8/10/2010, in reply to message #115604
PhlamethrowerHot 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 smile
  ^[ Log in to reply ]
 
Simon Wilson Message #115607, posted by ksattic at 06:57, 9/10/2010, in reply to message #115605
ksattic
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. smile
  ^[ Log in to reply ]
 
Simon Willcocks Message #115608, posted by Stoppers at 13: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. smile
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 14:19, 10/10/2010, in reply to message #115596
Member
Posts: 302
A solution (or a reason) is found! grin

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. big grin



[Edited by Stoppers at 14:51, 10/10/2010]
  ^[ Log in to reply ]
 

The Icon Bar: Programming: Does this program hang in your Linux system?