From owner-freebsd-emulation@FreeBSD.ORG Thu Jun 9 13:17:47 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 8276516A41C; Thu, 9 Jun 2005 13:17:47 +0000 (GMT) (envelope-from bde@zeta.org.au) Received: from mailout2.pacific.net.au (mailout2.pacific.net.au [61.8.0.85]) by mx1.FreeBSD.org (Postfix) with ESMTP id 0AB0A43D49; Thu, 9 Jun 2005 13:17:46 +0000 (GMT) (envelope-from bde@zeta.org.au) Received: from mailproxy1.pacific.net.au (mailproxy1.pacific.net.au [61.8.0.86]) by mailout2.pacific.net.au (8.13.4/8.13.4/Debian-1) with ESMTP id j59DHj2d008307; Thu, 9 Jun 2005 23:17:45 +1000 Received: from katana.zip.com.au (katana.zip.com.au [61.8.7.246]) by mailproxy1.pacific.net.au (8.13.4/8.13.4/Debian-1) with ESMTP id j59DHg9H019052; Thu, 9 Jun 2005 23:17:43 +1000 Date: Thu, 9 Jun 2005 23:17:44 +1000 (EST) From: Bruce Evans X-X-Sender: bde@delplex.bde.org To: Andriy Gapon In-Reply-To: <200506090430.j594UILr099075@freefall.freebsd.org> Message-ID: <20050609221208.F22195@delplex.bde.org> References: <200506090430.j594UILr099075@freefall.freebsd.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed 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 13:17:47 -0000 > 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. > 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. 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). 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. Bruce