Whamcloud - gitweb
LU-1347 style: removes obsolete EXPORT_SYMTAB macros
[fs/lustre-release.git] / lustre / obdclass / lu_time.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  *
34  * lustre/obdclass/lu_time.c
35  *
36  * Lustre Time Tracking.
37  * These are the only exported functions, they provide some generic
38  * infrastructure for managing object devices.
39  *
40  * Author: Nikita Danilov <nikita@clusterfs.com>
41  */
42
43 #define DEBUG_SUBSYSTEM S_CLASS
44
45 #include <obd_class.h>
46 /* OBD_{ALLOC,FREE}_PTR() */
47 #include <obd_support.h>
48 #include <lprocfs_status.h>
49 #include <lu_object.h>
50 #include <lu_time.h>
51
52 enum {
53         LU_TIME_DEPTH_MAX = 16
54 };
55
56 struct lu_time_data {
57         int                ltd_tos; /* top of the stack */
58         unsigned long long ltd_timestamp[LU_TIME_DEPTH_MAX];
59 };
60
61 /* context key constructor/destructor: lu_time_key_init, lu_time_key_fini */
62 LU_KEY_INIT_FINI(lu_time, struct lu_time_data);
63
64 void lu_time_key_exit(const struct lu_context *ctx,
65                       struct lu_context_key *key, void *data)
66 {
67         struct lu_time_data *value = data;
68         LASSERT(value->ltd_tos == 0);
69 }
70
71 /*
72  * Key, holding temporary buffer. This key is registered very early by
73  * lu_global_init().
74  */
75 static struct lu_context_key lu_time_key = {
76         .lct_tags = LCT_MD_THREAD|LCT_DT_THREAD|LCT_CL_THREAD,
77         .lct_init = lu_time_key_init,
78         .lct_fini = lu_time_key_fini,
79         .lct_exit = lu_time_key_exit
80 };
81
82 int lu_time_global_init(void)
83 {
84         LU_CONTEXT_KEY_INIT(&lu_time_key);
85         return lu_context_key_register(&lu_time_key);
86 }
87
88 void lu_time_global_fini(void)
89 {
90         lu_context_key_degister(&lu_time_key);
91 }
92
93 int lu_time_named_init(struct lprocfs_stats **stats, const char *name,
94                        cfs_proc_dir_entry_t *entry,
95                        const char **names, int nr)
96 {
97         int result;
98         int i;
99
100         ENTRY;
101
102         *stats = NULL;
103         if (nr == 0)
104                 RETURN(0);
105
106         *stats = lprocfs_alloc_stats(nr, 0);
107         if (*stats != NULL) {
108                 result = lprocfs_register_stats(entry, name, *stats);
109                 if (result == 0) {
110                         for (i = 0; i < nr; ++i) {
111                                 lprocfs_counter_init(*stats, i,
112                                                      LPROCFS_CNTR_AVGMINMAX,
113                                                      names[i], "usec");
114                         }
115                 }
116         } else
117                 result = -ENOMEM;
118
119         if (result != 0)
120                 lu_time_fini(stats);
121
122         RETURN(result);
123 }
124 EXPORT_SYMBOL(lu_time_named_init);
125
126 int lu_time_init(struct lprocfs_stats **stats, cfs_proc_dir_entry_t *entry,
127                  const char **names, int nr)
128 {
129         return lu_time_named_init(stats, "lu_stats", entry, names, nr);
130 }
131 EXPORT_SYMBOL(lu_time_init);
132
133 void lu_time_fini(struct lprocfs_stats **stats)
134 {
135         if (*stats != NULL) {
136                 lprocfs_free_stats(stats);
137                 *stats = NULL;
138         }
139 }
140 EXPORT_SYMBOL(lu_time_fini);
141
142 static inline struct lu_time_data *lu_time_data_get(const struct lu_env *env)
143 {
144         return lu_context_key_get(&env->le_ctx, &lu_time_key);
145 }
146
147 int lu_time_is_clean(const struct lu_env *env)
148 {
149         return lu_time_data_get(env)->ltd_tos == 0;
150 }
151 EXPORT_SYMBOL(lu_time_is_clean);
152
153 /* from sleepometer by Andrew Morton */
154 unsigned long long lu_time_stamp_get(void)
155 {
156         /*
157          * Return timestamp with microsecond precision. This has to be cheap.
158          */
159 //#ifdef CONFIG_X86
160 #if defined(CONFIG_X86) && !defined(CONFIG_X86_64)
161         /*
162          * do_gettimeofday() goes backwards sometimes :(.  Usethe TSC
163          */
164         unsigned long long ret;
165
166         rdtscll(ret);
167         do_div(ret, cpu_khz / 1000);
168         return ret;
169 #else
170         struct timeval now;
171         unsigned long long ret;
172
173         cfs_gettimeofday(&now);
174         ret = now.tv_sec;
175         ret *= 1000000;
176         ret += now.tv_usec;
177         return ret;
178 #endif
179 }
180 /*
181  * Export it, but do not advertise in headers. This is limited use only.
182  */
183 EXPORT_SYMBOL(lu_time_stamp_get);
184
185 void lu_lprocfs_time_start(const struct lu_env *env)
186 {
187         struct lu_time_data *ltd = lu_time_data_get(env);
188
189         LASSERT(0 <= ltd->ltd_tos);
190         LASSERT(ltd->ltd_tos < ARRAY_SIZE(ltd->ltd_timestamp));
191         ltd->ltd_timestamp[ltd->ltd_tos++] = lu_time_stamp_get();
192 }
193 EXPORT_SYMBOL(lu_lprocfs_time_start);
194
195 void lu_lprocfs_time_end(const struct lu_env *env,
196                          struct lprocfs_stats *stats, int idx)
197 {
198         struct lu_time_data *ltd = lu_time_data_get(env);
199         long long diff;
200
201         --ltd->ltd_tos;
202         LASSERT(0 <= ltd->ltd_tos);
203         LASSERT(ltd->ltd_tos < ARRAY_SIZE(ltd->ltd_timestamp));
204         diff = lu_time_stamp_get() - ltd->ltd_timestamp[ltd->ltd_tos];
205         if (diff >= 0 && stats != NULL)
206                 lprocfs_counter_add(stats, idx, diff);
207 }
208 EXPORT_SYMBOL(lu_lprocfs_time_end);