From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 66C413858D1E; Mon, 19 Jun 2023 17:42:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 66C413858D1E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1687196520; bh=vamE9Zxbp1ITFEzDq7AcouHFVAe9matjNuLUUfRWCVk=; h=From:To:Subject:Date:In-Reply-To:References:From; b=xRHfKvMQ3r4ONaAwdukGgl6RUP/eHhRt8RU6bWmoelO5hZGgzqUYryrJd1ex8zLqJ Wc0Z4f99e10gQ1nNaYJHid00tjhbpYoRxaaPc6zRPSbWC4BTajYDkEgC/8JHWogGbr QXag3fHrottBXYcNu65As7LmcZM+FQy94nvCFNdQ= From: "adhemerval.zanella at linaro dot org" To: glibc-bugs@sourceware.org Subject: [Bug libc/30558] SIGEV_THREAD is badly implemented Date: Mon, 19 Jun 2023 17:41:59 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: glibc X-Bugzilla-Component: libc X-Bugzilla-Version: 2.37 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: adhemerval.zanella at linaro dot org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: unassigned at sourceware dot org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://sourceware.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://sourceware.org/bugzilla/show_bug.cgi?id=3D30558 --- Comment #7 from Adhemerval Zanella --- (In reply to Stas Sergeev from comment #6) > If I could make a wishes here, > I'd say please implement SIGEV_THREAD > on top of timerfd API. > That way you avoid messing around > signals, and can get a consistent > timer_getoverrun(). I don't think this a promising approach for POSIX timers, besides adding an extra file descriptor under the hoods (with might interfere with RLIMIT_NOFILE), the timerfd inherits over fork which would require keeping track of the user file descriptor, and adding an atfork handler to close th= em. We would also need to synthesize a sigval argument, which most likely would require even extra state that kernel already provides us for free. I created an RFC implementation to avoid the thread creation per timer trig= ger [1]: timer_create now creates a thread per SIGEV_THREAD invocation, and each thread will issue the timer callback without creating and destroying a new thread per invocation. The glibc allows the created thread to be cancellable or call pthread_exit,= and it is not fully specified how the POSIX timer should act in this case. On = the current implementation, the next timer invocation will create a new thread,= so only timer_delete will unregister the kernel timer. My RFC changes the semantic that once the callback issues pthread_exit or the thread is cancel= led, no more timers are triggered. I think I will need to implement something li= ke musl that setjmp/longjmp to avoid the abort the cancellation process, altho= ugh I am not sure if is the correct or expected semantic. Performance-wise it seems that it does use fewer CPU cycles: -- #include #include #include #include static void tf (union sigval arg) { } int main (int argc, char *argv[]) { const struct itimerspec itval =3D { { 0, 150000000 }, { 0, 150000000 }, }; struct sigevent sigev =3D { .sigev_notify =3D SIGEV_THREAD, .sigev_notify_function =3D tf, .sigev_notify_attributes =3D NULL, .sigev_value.sival_ptr =3D NULL, }; enum { count =3D 128 }; timer_t timers[count]; for (int i =3D 0; i < count; i++) { assert (timer_create (CLOCK_REALTIME, &sigev, &timers[i]) =3D=3D 0); assert (timer_settime (timers[i], 0, &itval, NULL) =3D=3D 0); } sleep (5); for (int i =3D 0; i < count; i++) assert (timer_delete (timers[i]) =3D=3D 0); sleep (2); return 0; } -- Master: $ perf stat ./timer-bench Performance counter stats for './timer-bench': 121,50 msec task-clock # 0,017 CPUs utilized 187 context-switches # 1,539 K/sec 0 cpu-migrations # 0,000 /sec 187 page-faults # 1,539 K/sec 302.445.622 cycles # 2,489 GHz=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20 (72,86%) 3.089.604 stalled-cycles-frontend # 1,02% frontend cycles idle (81,64%) 47.543.776 stalled-cycles-backend # 15,72% backend cycles idle (83,82%) 287.475.386 instructions # 0,95 insn per cycle # 0,17 stalled cycles= per insn (83,43%) 48.578.487 branches # 399,835 M/sec=20=20=20= =20=20=20=20=20=20=20=20=20=20 (72,20%) 459.578 branch-misses # 0,95% of all branche= s=20=20=20 (67,88%) 7,001998495 seconds time elapsed 0,013313000 seconds user 0,150883000 seconds sys VS my RFC branch: x86_64-linux-gnu$ perf stat ./elf/ld.so --library-path . ../timer-bench Performance counter stats for './elf/ld.so --library-path . ../timer-bench= ': 68,61 msec task-clock # 0,010 CPUs utilized 4.662 context-switches # 67,949 K/sec 161 cpu-migrations # 2,347 K/sec 326 page-faults # 4,751 K/sec 127.514.086 cycles # 1,859 GHz 3.714.619 stalled-cycles-frontend # 2,91% frontend cycles idle 10.407.556 stalled-cycles-backend # 8,16% backend cycles idle 65.273.326 instructions # 0,51 insn per cycle # 0,16 stalled cycles= per insn 13.918.731 branches # 202,866 M/sec=20=20=20= =20=20=20=20=20=20=20=20=20=20 (0,46%) branch-misses=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20 (0,00%) 7,006109877 seconds time elapsed 0,000000000 seconds user 0,079625000 seconds sys Although the extra threads might generate more context-switches/page-faults since each one will eventually call sigwaitinfo. I have not analyzed latenc= y, although I would expect to also show better results. [1] https://sourceware.org/git/?p=3Dglibc.git;a=3Dshortlog;h=3Drefs/heads/azane= lla/bz30558-posix_timer --=20 You are receiving this mail because: You are on the CC list for the bug.=