1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/obdclass/lu_time.c
38 * Lustre Time Tracking.
39 * These are the only exported functions, they provide some generic
40 * infrastructure for managing object devices.
42 * Author: Nikita Danilov <nikita@clusterfs.com>
45 #define DEBUG_SUBSYSTEM S_CLASS
47 # define EXPORT_SYMTAB
50 /* OBD_{ALLOC,FREE}_PTR() */
51 #include <obd_support.h>
52 #include <lprocfs_status.h>
53 #include <lu_object.h>
57 LU_TIME_DEPTH_MAX = 16
61 int ltd_tos; /* top of the stack */
62 unsigned long long ltd_timestamp[LU_TIME_DEPTH_MAX];
65 /* context key constructor/destructor: lu_time_key_init, lu_time_key_fini */
66 LU_KEY_INIT_FINI(lu_time, struct lu_time_data);
68 void lu_time_key_exit(const struct lu_context *ctx,
69 struct lu_context_key *key, void *data)
71 struct lu_time_data *value = data;
72 LASSERT(value->ltd_tos == 0);
76 * Key, holding temporary buffer. This key is registered very early by
79 static struct lu_context_key lu_time_key = {
80 .lct_tags = LCT_MD_THREAD|LCT_DT_THREAD|LCT_CL_THREAD,
81 .lct_init = lu_time_key_init,
82 .lct_fini = lu_time_key_fini,
83 .lct_exit = lu_time_key_exit
86 int lu_time_global_init(void)
88 LU_CONTEXT_KEY_INIT(&lu_time_key);
89 return lu_context_key_register(&lu_time_key);
92 void lu_time_global_fini(void)
94 lu_context_key_degister(&lu_time_key);
97 int lu_time_named_init(struct lprocfs_stats **stats, const char *name,
98 cfs_proc_dir_entry_t *entry,
99 const char **names, int nr)
110 *stats = lprocfs_alloc_stats(nr, 0);
111 if (*stats != NULL) {
112 result = lprocfs_register_stats(entry, name, *stats);
114 for (i = 0; i < nr; ++i) {
115 lprocfs_counter_init(*stats, i,
116 LPROCFS_CNTR_AVGMINMAX,
128 EXPORT_SYMBOL(lu_time_named_init);
130 int lu_time_init(struct lprocfs_stats **stats, cfs_proc_dir_entry_t *entry,
131 const char **names, int nr)
133 return lu_time_named_init(stats, "stats", entry, names, nr);
135 EXPORT_SYMBOL(lu_time_init);
137 void lu_time_fini(struct lprocfs_stats **stats)
139 if (*stats != NULL) {
140 lprocfs_free_stats(stats);
144 EXPORT_SYMBOL(lu_time_fini);
146 static inline struct lu_time_data *lu_time_data_get(const struct lu_env *env)
148 return lu_context_key_get(&env->le_ctx, &lu_time_key);
151 int lu_time_is_clean(const struct lu_env *env)
153 return lu_time_data_get(env)->ltd_tos == 0;
155 EXPORT_SYMBOL(lu_time_is_clean);
157 /* from sleepometer by Andrew Morton */
158 unsigned long long lu_time_stamp_get(void)
161 * Return timestamp with microsecond precision. This has to be cheap.
164 #if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
166 * do_gettimeofday() goes backwards sometimes :(. Usethe TSC
168 unsigned long long ret;
171 do_div(ret, cpu_khz / 1000);
175 unsigned long long ret;
177 do_gettimeofday(&now);
185 * Export it, but do not advertise in headers. This is limited use only.
187 EXPORT_SYMBOL(lu_time_stamp_get);
189 void lu_lprocfs_time_start(const struct lu_env *env)
191 struct lu_time_data *ltd = lu_time_data_get(env);
193 LASSERT(0 <= ltd->ltd_tos);
194 LASSERT(ltd->ltd_tos < ARRAY_SIZE(ltd->ltd_timestamp));
195 ltd->ltd_timestamp[ltd->ltd_tos++] = lu_time_stamp_get();
197 EXPORT_SYMBOL(lu_lprocfs_time_start);
199 void lu_lprocfs_time_end(const struct lu_env *env,
200 struct lprocfs_stats *stats, int idx)
202 struct lu_time_data *ltd = lu_time_data_get(env);
206 LASSERT(0 <= ltd->ltd_tos);
207 LASSERT(ltd->ltd_tos < ARRAY_SIZE(ltd->ltd_timestamp));
208 diff = lu_time_stamp_get() - ltd->ltd_timestamp[ltd->ltd_tos];
209 if (diff >= 0 && stats != NULL)
210 lprocfs_counter_add(stats, idx, diff);
212 EXPORT_SYMBOL(lu_lprocfs_time_end);