From owner-freebsd-hackers@freebsd.org Fri Aug 24 13:37:38 2018 Return-Path: Delivered-To: freebsd-hackers@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 357DB108A6B7 for ; Fri, 24 Aug 2018 13:37:38 +0000 (UTC) (envelope-from sebastian.huber@embedded-brains.de) Received: from dedi548.your-server.de (dedi548.your-server.de [85.10.215.148]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C15B28646A for ; Fri, 24 Aug 2018 13:37:37 +0000 (UTC) (envelope-from sebastian.huber@embedded-brains.de) Received: from [78.46.172.2] (helo=sslproxy05.your-server.de) by dedi548.your-server.de with esmtpsa (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.85_2) (envelope-from ) id 1ftCHJ-0007UC-M6 for freebsd-hackers@freebsd.org; Fri, 24 Aug 2018 15:37:29 +0200 Received: from [82.135.62.35] (helo=mail.embedded-brains.de) by sslproxy05.your-server.de with esmtpsa (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (Exim 4.89) (envelope-from ) id 1ftCHJ-00034l-Ek for freebsd-hackers@freebsd.org; Fri, 24 Aug 2018 15:37:29 +0200 Received: from localhost (localhost.localhost [127.0.0.1]) by mail.embedded-brains.de (Postfix) with ESMTP id 79D0F2A165C for ; Fri, 24 Aug 2018 15:37:33 +0200 (CEST) Received: from mail.embedded-brains.de ([127.0.0.1]) by localhost (zimbra.eb.localhost [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id e3tnGbiBX6BF for ; Fri, 24 Aug 2018 15:37:32 +0200 (CEST) Received: from localhost (localhost.localhost [127.0.0.1]) by mail.embedded-brains.de (Postfix) with ESMTP id 8B1B32A167E for ; Fri, 24 Aug 2018 15:37:32 +0200 (CEST) X-Virus-Scanned: amavisd-new at zimbra.eb.localhost Received: from mail.embedded-brains.de ([127.0.0.1]) by localhost (zimbra.eb.localhost [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id F_UeI5raFWWK for ; Fri, 24 Aug 2018 15:37:32 +0200 (CEST) Received: from [192.168.96.149] (unknown [192.168.96.149]) by mail.embedded-brains.de (Postfix) with ESMTPSA id 62D2B2A165C for ; Fri, 24 Aug 2018 15:37:32 +0200 (CEST) Subject: Re: epoch(9) background information? From: Sebastian Huber To: FreeBSD References: Message-ID: Date: Fri, 24 Aug 2018 15:37:27 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-GB Content-Transfer-Encoding: quoted-printable X-Authenticated-Sender: smtp-embedded@poldinet.de X-Virus-Scanned: Clear (ClamAV 0.100.1/24868/Fri Aug 24 06:46:35 2018) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.27 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Aug 2018 13:37:38 -0000 Hello, I try currently to understand the epoch implementation in FreeBSD to=20 implement the API in RTEMS. If I understood epoch_wait() correctly, then this function just busy=20 waits until all conditions are satisfied. This is all right, since all=20 other participants operate with thread dispatching disabled, so the time=20 can be only influenced by interrupts and actual work. I have some questions to epoch_block_handler_preempt(). The caller of=20 epoch_wait_prempt() seems to depend on threads which are currently=20 blocked, so busy waiting is not a good idea. Some questions to the code: /* =C2=A0* epoch_block_handler_preempt is a callback from the ck code when=20 another thread is =C2=A0* currently in an epoch section. =C2=A0*/ static void epoch_block_handler_preempt(struct ck_epoch *global __unused,=20 ck_epoch_record_t *cr, =C2=A0=C2=A0=C2=A0 void *arg __unused) { =C2=A0=C2=A0=C2=A0 epoch_record_t record; =C2=A0=C2=A0=C2=A0 struct thread *td, *owner, *curwaittd; =C2=A0=C2=A0=C2=A0 struct epoch_thread *tdwait; =C2=A0=C2=A0=C2=A0 struct turnstile *ts; =C2=A0=C2=A0=C2=A0 struct lock_object *lock; =C2=A0=C2=A0=C2=A0 int spincount, gen; =C2=A0=C2=A0=C2=A0 int locksheld __unused; =C2=A0=C2=A0=C2=A0 record =3D __containerof(cr, struct epoch_record, er_= record); =C2=A0=C2=A0=C2=A0 td =3D curthread; =C2=A0=C2=A0=C2=A0 locksheld =3D td->td_locks; =C2=A0=C2=A0=C2=A0 spincount =3D 0; =C2=A0=C2=A0=C2=A0 counter_u64_add(block_count, 1); =C2=A0=C2=A0=C2=A0 /* =C2=A0=C2=A0=C2=A0 =C2=A0* We lost a race and there's no longer any thre= ads =C2=A0=C2=A0=C2=A0 =C2=A0* on the CPU in an epoch section. =C2=A0=C2=A0=C2=A0 =C2=A0*/ =C2=A0=C2=A0=C2=A0 if (TAILQ_EMPTY(&record->er_tdlist)) =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 return; =C2=A0=C2=A0=C2=A0 if (record->er_cpuid !=3D curcpu) { =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 ... ### this seems clear =C2=A0=C2=A0=C2=A0 } =C2=A0=C2=A0=C2=A0 /* =C2=A0=C2=A0=C2=A0 =C2=A0* Try to find a thread in an epoch section on t= his CPU =C2=A0=C2=A0=C2=A0 =C2=A0* waiting on a turnstile. Otherwise find the lo= west =C2=A0=C2=A0=C2=A0 =C2=A0* priority thread (highest prio value) and drop= our priority =C2=A0=C2=A0=C2=A0 =C2=A0* to match to allow it to run. =C2=A0=C2=A0=C2=A0 =C2=A0*/ =C2=A0=C2=A0=C2=A0 TAILQ_FOREACH(tdwait, &record->er_tdlist, et_link) { =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 /* =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0* Propagate our priority to = any other waiters to prevent us =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0* from starving them. They w= ill have their original priority =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0* restore on exit from epoch= _wait(). =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0*/ =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 curwaittd =3D tdwait->et_td; =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 if (!TD_IS_INHIBITED(curwaittd) &&= curwaittd->td_priority >=20 td->td_priority) { =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 critical_enter(= ); =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 thread_unlock(t= d); =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 thread_lock(cur= waittd); ### could we accidentally lower the priority here? =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 sched_prio(curw= aittd, td->td_priority); =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 thread_unlock(c= urwaittd); =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 thread_lock(td)= ; =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 critical_exit()= ; =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 } =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 if (TD_IS_INHIBITED(curwaittd) && = TD_ON_LOCK(curwaittd) && =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 ((ts =3D curwai= ttd->td_blocked) !=3D NULL)) { =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ... ### is this some sort of condition variable which wakes us up together=20 with the waiting thread? =C2=A0=C2=A0=C2=A0 =C2=A0=C2=A0=C2=A0 } =C2=A0=C2=A0=C2=A0 } ### is this a yield operation, e.g. in case we still the highest=20 priority thread, then we run immediately again? =C2=A0=C2=A0=C2=A0 /* =C2=A0=C2=A0=C2=A0 =C2=A0* We didn't find any threads actually blocked o= n a lock =C2=A0=C2=A0=C2=A0 =C2=A0* so we have nothing to do except context switc= h away. =C2=A0=C2=A0=C2=A0 =C2=A0*/ =C2=A0=C2=A0=C2=A0 counter_u64_add(switch_count, 1); =C2=A0=C2=A0=C2=A0 mi_switch(SW_VOL | SWT_RELINQUISH, NULL); =C2=A0=C2=A0=C2=A0 /* =C2=A0=C2=A0=C2=A0 =C2=A0* Release the thread lock while yielding to =C2=A0=C2=A0=C2=A0 =C2=A0* allow other threads to acquire the lock =C2=A0=C2=A0=C2=A0 =C2=A0* pointed to by TDQ_LOCKPTR(td). Else a =C2=A0=C2=A0=C2=A0 =C2=A0* deadlock like situation might happen. (HPS) =C2=A0=C2=A0=C2=A0 =C2=A0*/ =C2=A0=C2=A0=C2=A0 thread_unlock(td); =C2=A0=C2=A0=C2=A0 thread_lock(td); } --=20 Sebastian Huber, embedded brains GmbH Address : Dornierstr. 4, D-82178 Puchheim, Germany Phone : +49 89 189 47 41-16 Fax : +49 89 189 47 41-09 E-Mail : sebastian.huber@embedded-brains.de PGP : Public key available on request. Diese Nachricht ist keine gesch=C3=A4ftliche Mitteilung im Sinne des EHUG= .