From patchwork Fri Sep 3 09:30:13 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Cochran X-Patchwork-Id: 63600 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 419B4B719D for ; Fri, 3 Sep 2010 19:30:43 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756632Ab0ICJaQ (ORCPT ); Fri, 3 Sep 2010 05:30:16 -0400 Received: from mail-bw0-f46.google.com ([209.85.214.46]:62923 "EHLO mail-bw0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755647Ab0ICJaO (ORCPT ); Fri, 3 Sep 2010 05:30:14 -0400 Received: by bwz11 with SMTP id 11so1328214bwz.19 for ; Fri, 03 Sep 2010 02:30:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:date:from:to:cc:subject :message-id:references:mime-version:content-type:content-disposition :in-reply-to:user-agent; bh=IJfFxJ7ZH8B5asxsAhUSrw1/U+XiL8k+yxGfYKXrfCw=; b=QlSlpcItZZQPYYBG+JdyUZUPKOM6qwWy1ZwMgVXXvl1R6/5Xyq3ys3FQBjT4HA/4vX sjFsYVx/NuS4W04axgEPbYe1mM7Dv225iC60xdEUiJqVXGhmeQeDYoHaxRmpu6/7PtTo xCRpf8g0rKCkPYWsaPCitptQv6H1OcfOspRJg= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent; b=xGhxZdXCf5/rsap5OjoMicKQ3wgqYd4x5Nt1Ur1CXCpJEo1/XVb2eDxs2BlUdHw26T VnL9Ix3kVuuWSeOXEaNPJQg32IHg+HRIlZgeSLoat8+U957MfKRXEBIAwH8nv3mUXrmq jWuGfK6TUMY5l33QDm/qMGP0nadvvvOZZpNsg= Received: by 10.204.141.16 with SMTP id k16mr295434bku.177.1283506212527; Fri, 03 Sep 2010 02:30:12 -0700 (PDT) Received: from riccoc20.at.omicron.at (vs162244.vserver.de [62.75.162.244]) by mx.google.com with ESMTPS id g12sm1280457bkb.14.2010.09.03.02.30.09 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 03 Sep 2010 02:30:12 -0700 (PDT) Date: Fri, 3 Sep 2010 11:30:13 +0200 From: Richard Cochran To: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH 2/2] posix clocks: introduce a sysfs presence. Message-ID: <84124d2479b8967cac2b35f852fc0fcae6ad9444.1283504065.git.richard.cochran@omicron.at> References: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.20 (2009-06-14) Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds a 'timesource' class into sysfs. Each registered POSIX clock appears by name under /sys/class/timesource. The idea is to expose to user space the dynamic mapping between clock devices and clock IDs. Signed-off-by: Richard Cochran --- Documentation/ABI/testing/sysfs-timesource | 24 ++++++++++++++++ drivers/char/mmtimer.c | 1 + include/linux/posix-timers.h | 4 +++ kernel/posix-cpu-timers.c | 2 + kernel/posix-timers.c | 40 ++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 0 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-timesource diff --git a/Documentation/ABI/testing/sysfs-timesource b/Documentation/ABI/testing/sysfs-timesource new file mode 100644 index 0000000..f991de2 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-timesource @@ -0,0 +1,24 @@ +What: /sys/class/timesource/ +Date: September 2010 +Contact: Richard Cochran +Description: + This directory contains files and directories + providing a standardized interface to the available + time sources. + +What: /sys/class/timesource// +Date: September 2010 +Contact: Richard Cochran +Description: + This directory contains the attributes of a time + source registered with the POSIX clock subsystem. + +What: /sys/class/timesource//id +Date: September 2010 +Contact: Richard Cochran +Description: + This file contains the clock ID (a non-negative + integer) of the named time source registered with the + POSIX clock subsystem. This value may be passed as the + first argument to the POSIX clock and timer system + calls. See man CLOCK_GETRES(2) and TIMER_CREATE(2). diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index ea7c99f..e9173e3 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c @@ -758,6 +758,7 @@ static int sgi_timer_set(struct k_itimer *timr, int flags, } static struct k_clock sgi_clock = { + .name = "sgi_cycle", .res = 0, .clock_set = sgi_clock_set, .clock_get = sgi_clock_get, diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index 08aa4da..64e6fee 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -67,7 +67,11 @@ struct k_itimer { } it; }; +#define KCLOCK_MAX_NAME 32 + struct k_clock { + char name[KCLOCK_MAX_NAME]; + struct device *dev; clockid_t id; int res; /* in nanoseconds */ int (*clock_getres) (const clockid_t which_clock, struct timespec *tp); diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index e1c2e7b..df9cbab 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -1611,6 +1611,7 @@ static long thread_cpu_nsleep_restart(struct restart_block *restart_block) static __init int init_posix_cpu_timers(void) { struct k_clock process = { + .name = "process_cputime", .clock_getres = process_cpu_clock_getres, .clock_get = process_cpu_clock_get, .clock_set = do_posix_clock_nosettime, @@ -1619,6 +1620,7 @@ static __init int init_posix_cpu_timers(void) .nsleep_restart = process_cpu_nsleep_restart, }; struct k_clock thread = { + .name = "thread_cputime", .clock_getres = thread_cpu_clock_getres, .clock_get = thread_cpu_clock_get, .clock_set = do_posix_clock_nosettime, diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 67fba5c..719aa11 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -46,6 +46,7 @@ #include #include #include +#include /* * Management arrays for POSIX timers. Timers are kept in slab memory @@ -135,6 +136,8 @@ static struct k_clock posix_clocks[MAX_CLOCKS]; static DECLARE_BITMAP(clocks_map, MAX_CLOCKS); static DEFINE_MUTEX(clocks_mux); /* protects 'posix_clocks' and 'clocks_map' */ +static struct class *timesource_class; + /* * These ones are defined below. */ @@ -271,20 +274,40 @@ static int posix_get_coarse_res(const clockid_t which_clock, struct timespec *tp *tp = ktime_to_timespec(KTIME_LOW_RES); return 0; } + +/* + * sysfs attributes + */ + +static ssize_t show_clock_id(struct device *dev, + struct device_attribute *attr, char *page) +{ + struct k_clock *kc = dev_get_drvdata(dev); + return snprintf(page, PAGE_SIZE-1, "%d\n", kc->id); +} + +static struct device_attribute timesource_dev_attrs[] = { + __ATTR(id, 0444, show_clock_id, NULL), + __ATTR_NULL, +}; + /* * Initialize everything, well, just everything in Posix clocks/timers ;) */ static __init int init_posix_timers(void) { struct k_clock clock_realtime = { + .name = "realtime", .clock_getres = hrtimer_get_res, }; struct k_clock clock_monotonic = { + .name = "monotonic", .clock_getres = hrtimer_get_res, .clock_get = posix_ktime_get_ts, .clock_set = do_posix_clock_nosettime, }; struct k_clock clock_monotonic_raw = { + .name = "monotonic_raw", .clock_getres = hrtimer_get_res, .clock_get = posix_get_monotonic_raw, .clock_set = do_posix_clock_nosettime, @@ -292,6 +315,7 @@ static __init int init_posix_timers(void) .nsleep = no_nsleep, }; struct k_clock clock_realtime_coarse = { + .name = "realtime_coarse", .clock_getres = posix_get_coarse_res, .clock_get = posix_get_realtime_coarse, .clock_set = do_posix_clock_nosettime, @@ -299,6 +323,7 @@ static __init int init_posix_timers(void) .nsleep = no_nsleep, }; struct k_clock clock_monotonic_coarse = { + .name = "monotonic_coarse", .clock_getres = posix_get_coarse_res, .clock_get = posix_get_monotonic_coarse, .clock_set = do_posix_clock_nosettime, @@ -306,6 +331,13 @@ static __init int init_posix_timers(void) .nsleep = no_nsleep, }; + timesource_class = class_create(NULL, "timesource"); + if (IS_ERR(timesource_class)) { + pr_err("posix-timers: failed to allocate timesource class\n"); + return PTR_ERR(timesource_class); + } + timesource_class->dev_attrs = timesource_dev_attrs; + register_posix_clock(CLOCK_REALTIME, &clock_realtime); register_posix_clock(CLOCK_MONOTONIC, &clock_monotonic); register_posix_clock(CLOCK_MONOTONIC_RAW, &clock_monotonic_raw); @@ -500,6 +532,14 @@ int register_posix_clock(const clockid_t id, struct k_clock *clock) kc = &posix_clocks[id]; *kc = *clock; kc->id = id; + kc->dev = device_create(timesource_class, NULL, MKDEV(0, 0), + kc, "%s", kc->name); + if (IS_ERR(kc->dev)) { + pr_err("failed to create device clock_id %d\n", id); + err = PTR_ERR(kc->dev); + goto out; + } + dev_set_drvdata(kc->dev, kc); set_bit(id, clocks_map); out: mutex_unlock(&clocks_mux);