From owner-freebsd-emulation@FreeBSD.ORG Thu Jun 9 14:36:28 2005 Return-Path: X-Original-To: freebsd-emulation@freebsd.org Delivered-To: freebsd-emulation@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 0330416A41C; Thu, 9 Jun 2005 14:36:28 +0000 (GMT) (envelope-from avg@icyb.net.ua) Received: from citadel.icyb.net.ua (citadel.icyb.net.ua [212.40.38.140]) by mx1.FreeBSD.org (Postfix) with ESMTP id E146543D1F; Thu, 9 Jun 2005 14:36:25 +0000 (GMT) (envelope-from avg@icyb.net.ua) Received: from [212.40.38.87] (oddity-e.topspin.kiev.ua [212.40.38.87]) by citadel.icyb.net.ua (8.8.8p3/ICyb-2.3exp) with ESMTP id RAA22957; Thu, 09 Jun 2005 17:36:06 +0300 (EEST) (envelope-from avg@icyb.net.ua) Message-ID: <42A853D5.5030003@icyb.net.ua> Date: Thu, 09 Jun 2005 17:36:05 +0300 From: Andriy Gapon User-Agent: Mozilla Thunderbird 1.0.2 (X11/20050328) X-Accept-Language: en-us, en MIME-Version: 1.0 To: Bruce Evans References: <200506090430.j594UILr099075@freefall.freebsd.org> <20050609221208.F22195@delplex.bde.org> In-Reply-To: <20050609221208.F22195@delplex.bde.org> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Cc: freebsd-emulation@freebsd.org, freebsd-gnats-submit@freebsd.org Subject: Re: kern/81951: [patch] linux emulation: getpriority() returns incorrect value X-BeenThere: freebsd-emulation@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Development of Emulators of other operating systems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Jun 2005 14:36:28 -0000 on 09.06.2005 16:17 Bruce Evans said the following: >> on 08.06.2005 23:49 Maxim Sobolev said the following: >> > Committed, thanks! >> > >> > I wonder if the setpriority(2) needs the same cure. Please clarify and >> > let me know. I'll keep the PR open till your reply. > > > I wonder why committers commit patches without fully understanding them. I wonder if you fully understood the patch, the issue and the getriority/setpriority. > >> setpriority(2) is not affected, the reason for this assymetry is in >> Linux's convention for system calls - they return both result and errno >> in the same register, positive values are reserved for results of >> successful calls and negative are reserved for -errno for failed calls. >> Thus they can not return negative priority values in getpriority(2) and >> have to shift it to positive range. There is no problem, of course, with >> passing negative values from userland to kernel. > > > Returning -1 for an error is the usual convention for syscalls and is > specified by POSIX for getpriority(). The problem is that FreeBSD's > getpriority() is highly non-POSIX-conformant (it has an off-by 20 error and > wrong semantics for NZERO, and an off-by 1 error), so it can't be mapped > to an emulator's getpriority() using the identity map except in rare cases > where the emulator's getpriority() is bug for bug compatible. But Linux's > getpriority() seems to be highly non-POSIX-conformant in a different, less > fundamentally broken way. > > POSIX specifies that the non-error range of values returned by > getpriority() > is [0, 2*{NZERO}-1]; -1 is the error indicator. Applications must subtract > NZERO to get the actual priority value. Bruce, I think you have misread POSIX specification and you are confusing two things: (1) priority - priority inside the blackbox that schedules processes versus values that should be passed to setpriotiy() and returned from getpriority(); (2) syscall internal implementation versus user-visible libc function. Regaridng #1, here's a direct quote: http://www.opengroup.org/onlinepubs/009695399/functions/getpriority.html "Upon successful completion, getpriority() shall return an integer in the range -{NZERO} to {NZERO}-1. Otherwise, -1 shall be returned and errno set to indicate the error." Also: "The getpriority() and setpriority() functions work with an offset nice value (nice value -{NZERO}). The nice value is in the range [0,2*{NZERO} -1], while the return value for getpriority() and the third parameter for setpriority() are in the range [-{NZERO},{NZERO} -1]." So this is a difference between priority as it is seen in user-land (above libc layer) and priority inside the POSIX blackbox of OS (the one in [0,2*{NZERO} -1] range). My understanding is that FreeBSD and Linux are very close to POSIXly correct implemetations with NZERO=20. In fact, Linux's implementation is completely compliant and FreeBSD allows +20 which is beyond the POSIX range. Also, -1 return value from getpriority() is a problematic point of POSIX specification not implemenations. Regarding #2, both FreeBSD and Linux in their unique ways correctly return errno/priority level from kernel-land to user-land. FreeBSD syscall returns priority already in [-{NZERO},{NZERO} -1] range; Linux syscall returns priority in [1,2*{NZERO}] range and with reversed comparison, and then (g)libc stub of getpritority performs 20-X conversion to return a correct value to application. > High non-POSIX-conformance: > FreeBSD: > NZERO is 0, so this range is null, and the actual range is [PRIO_MIN, > PRIO_MAX] = [-20, 20]; priority -1 collides with the error indicator > (the complications to handle this are documented in getpriority(3)). > NZERO is not mentioned in getpriority(3). There is no getpriority(3), only getpriority(2) and it quite rightly doesn't talk about NZERO as it is of no interest to applications and it quite rightly talks about troubles with -1 as it is a problem of interface defined by POSIX. > Linux: > NZERO is 20, so the POSIX range is [0, 39] which is usable, but the > actual range is apparently [1, 40]; the error indicator works normally. > Appalications must apparently negate the priority and add 20 to get > the actual priority (20 - pri) instead of (pri - NZERO). > > I think the reason that setpriority(2) is not affected is actually that > Linux applications know to use (20 - pri) to recover the actual priority. > > Fixing getpriority() in FreeBSD and all emulators should involve much the > same code: map the range of internal priorities [PRIO_MIN, PRIO_MAX] to > getpriority()'s range [0, 2*{SUBSYSTEM_SPECIFIC_NZERO}-1] as linearly > as possible (something like: > > pri |-> (pri - PRIO_MIN) * (2 * SUBSYSTEM_SPECIFIC_NZERO - 1) / > (PRIO_MAX - PRIO_MIN) > > but more complicated, since for if SUBSYSTEM_SPECIFIC_NZERO == 20 the > above maps the default priority 0 to (20 * 39 / 2) = 19, but 20 is > required; also for Linux there must be a negation. I think you have greatly overcomplicated thing sbecause of your original misunderstanding. Just compile a small program using getpriority/setpriority for FreeBSD, Linux and any other Unix avaialble to you, run it and you will see how simple thingx are in reality and that NZERO is not visible to userland. Read the man pages too. Yes, and try Linux emulation with and without my patch to understand what the problem with emualtion really is. -- Andriy Gapon