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 #ifndef MONGOC_COUNTERS_PRIVATE_H
18 #define MONGOC_COUNTERS_PRIVATE_H
19 
20 #if !defined(MONGOC_COMPILATION)
21 #error "Only <mongoc.h> can be included directly."
22 #endif
23 
24 #include <bson.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)
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(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(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 
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 
169 
170 BSON_END_DECLS
171 
172 
173 #endif /* MONGOC_COUNTERS_PRIVATE_H */
174