1 /*
2 * Copyright 2013 MongoDB, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "mongoc-prelude.h"
18
19 #ifndef MONGOC_COUNTERS_PRIVATE_H
20 #define MONGOC_COUNTERS_PRIVATE_H
21
22 #include <bson/bson.h>
23
24 #include "mongoc.h"
25
26 #ifdef __linux__
27 #include <sched.h>
28 #include <sys/sysinfo.h>
29 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
30 defined(__OpenBSD__)
31 #include <sys/types.h>
32 #include <sys/sysctl.h>
33 #include <sys/param.h>
34 #elif defined(__hpux__)
35 #include <sys/pstat.h>
36 #endif
37
38
39 BSON_BEGIN_DECLS
40
41
42 void
43 _mongoc_counters_init (void);
44 void
45 _mongoc_counters_cleanup (void);
46
47
48 static BSON_INLINE unsigned
_mongoc_get_cpu_count(void)49 _mongoc_get_cpu_count (void)
50 {
51 #if defined(__linux__)
52 return get_nprocs ();
53 #elif defined(__hpux__)
54 struct pst_dynamic psd;
55
56 if (pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1) {
57 return psd.psd_max_proc_cnt;
58 }
59 return 1;
60 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \
61 defined(__OpenBSD__)
62 int mib[2];
63 int maxproc;
64 size_t len;
65
66 mib[0] = CTL_HW;
67 mib[1] = HW_NCPU;
68 len = sizeof (maxproc);
69
70 if (-1 == sysctl (mib, 2, &maxproc, &len, NULL, 0)) {
71 return 1;
72 }
73
74 return len;
75 #elif defined(__APPLE__) || defined(__sun) || defined(_AIX)
76 int ncpu;
77
78 ncpu = (int) sysconf (_SC_NPROCESSORS_ONLN);
79 return (ncpu > 0) ? ncpu : 1;
80 #elif defined(_MSC_VER) || defined(_WIN32)
81 SYSTEM_INFO si;
82 GetSystemInfo (&si);
83 return si.dwNumberOfProcessors;
84 #else
85 #warning "_mongoc_get_cpu_count() not supported, defaulting to 1."
86 return 1;
87 #endif
88 }
89
90
91 #define _mongoc_counter_add(v, count) bson_atomic_int64_add (&(v), (count))
92
93
94 #if defined(MONGOC_ENABLE_RDTSCP)
95 static BSON_INLINE unsigned
_mongoc_sched_getcpu(void)96 _mongoc_sched_getcpu (void)
97 {
98 volatile uint32_t rax, rdx, rcx;
99 __asm__ volatile("rdtscp\n" : "=a"(rax), "=d"(rdx), "=c"(rcx) : :);
100 unsigned node_id, core_id;
101 // node_id = (rcx & 0xFFF000)>>12; // node_id is unused
102 core_id = rcx & 0xFFF;
103 return core_id;
104 }
105 #elif defined(MONGOC_HAVE_SCHED_GETCPU)
106 #define _mongoc_sched_getcpu sched_getcpu
107 #else
108 #define _mongoc_sched_getcpu() (0)
109 #endif
110
111
112 #ifndef SLOTS_PER_CACHELINE
113 #define SLOTS_PER_CACHELINE 8
114 #endif
115
116
117 typedef struct {
118 int64_t slots[SLOTS_PER_CACHELINE];
119 } mongoc_counter_slots_t;
120
121
122 typedef struct {
123 mongoc_counter_slots_t *cpus;
124 } mongoc_counter_t;
125
126
127 #define COUNTER(ident, Category, Name, Description) \
128 extern mongoc_counter_t __mongoc_counter_##ident;
129 #include "mongoc-counters.defs"
130 #undef COUNTER
131
132
133 enum {
134 #define COUNTER(ident, Category, Name, Description) COUNTER_##ident,
135 #include "mongoc-counters.defs"
136 #undef COUNTER
137 LAST_COUNTER
138 };
139
140 #ifdef MONGOC_ENABLE_SHM_COUNTERS
141 #define COUNTER(ident, Category, Name, Description) \
142 static BSON_INLINE void mongoc_counter_##ident##_add (int64_t val) \
143 { \
144 (void) _mongoc_counter_add ( \
145 __mongoc_counter_##ident.cpus[_mongoc_sched_getcpu ()] \
146 .slots[COUNTER_##ident % SLOTS_PER_CACHELINE], \
147 val); \
148 } \
149 static BSON_INLINE void mongoc_counter_##ident##_inc (void) \
150 { \
151 mongoc_counter_##ident##_add (1); \
152 } \
153 static BSON_INLINE void mongoc_counter_##ident##_dec (void) \
154 { \
155 mongoc_counter_##ident##_add (-1); \
156 } \
157 static BSON_INLINE void mongoc_counter_##ident##_reset (void) \
158 { \
159 uint32_t i; \
160 for (i = 0; i < _mongoc_get_cpu_count (); i++) { \
161 __mongoc_counter_##ident.cpus[i] \
162 .slots[COUNTER_##ident % SLOTS_PER_CACHELINE] = 0; \
163 } \
164 bson_memory_barrier (); \
165 }
166 #include "mongoc-counters.defs"
167 #undef COUNTER
168 #else
169 /* when counters are disabled, these functions are no-ops */
170 #define COUNTER(ident, Category, Name, Description) \
171 static BSON_INLINE void mongoc_counter_##ident##_add (int64_t val) \
172 { \
173 } \
174 static BSON_INLINE void mongoc_counter_##ident##_inc (void) \
175 { \
176 } \
177 static BSON_INLINE void mongoc_counter_##ident##_dec (void) \
178 { \
179 } \
180 static BSON_INLINE void mongoc_counter_##ident##_reset (void) \
181 { \
182 }
183 #include "mongoc-counters.defs"
184 #undef COUNTER
185 #endif
186
187 BSON_END_DECLS
188
189
190 #endif /* MONGOC_COUNTERS_PRIVATE_H */
191