OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [kernel/] [marker.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Copyright (C) 2007 Mathieu Desnoyers
3
 *
4
 * This program is free software; you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation; either version 2 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
 */
18
#include <linux/module.h>
19
#include <linux/mutex.h>
20
#include <linux/types.h>
21
#include <linux/jhash.h>
22
#include <linux/list.h>
23
#include <linux/rcupdate.h>
24
#include <linux/marker.h>
25
#include <linux/err.h>
26
 
27
extern struct marker __start___markers[];
28
extern struct marker __stop___markers[];
29
 
30
/*
31
 * markers_mutex nests inside module_mutex. Markers mutex protects the builtin
32
 * and module markers, the hash table and deferred_sync.
33
 */
34
static DEFINE_MUTEX(markers_mutex);
35
 
36
/*
37
 * Marker deferred synchronization.
38
 * Upon marker probe_unregister, we delay call to synchronize_sched() to
39
 * accelerate mass unregistration (only when there is no more reference to a
40
 * given module do we call synchronize_sched()). However, we need to make sure
41
 * every critical region has ended before we re-arm a marker that has been
42
 * unregistered and then registered back with a different probe data.
43
 */
44
static int deferred_sync;
45
 
46
/*
47
 * Marker hash table, containing the active markers.
48
 * Protected by module_mutex.
49
 */
50
#define MARKER_HASH_BITS 6
51
#define MARKER_TABLE_SIZE (1 << MARKER_HASH_BITS)
52
 
53
struct marker_entry {
54
        struct hlist_node hlist;
55
        char *format;
56
        marker_probe_func *probe;
57
        void *private;
58
        int refcount;   /* Number of times armed. 0 if disarmed. */
59
        char name[0];    /* Contains name'\0'format'\0' */
60
};
61
 
62
static struct hlist_head marker_table[MARKER_TABLE_SIZE];
63
 
64
/**
65
 * __mark_empty_function - Empty probe callback
66
 * @mdata: pointer of type const struct marker
67
 * @fmt: format string
68
 * @...: variable argument list
69
 *
70
 * Empty callback provided as a probe to the markers. By providing this to a
71
 * disabled marker, we make sure the  execution flow is always valid even
72
 * though the function pointer change and the marker enabling are two distinct
73
 * operations that modifies the execution flow of preemptible code.
74
 */
75
void __mark_empty_function(const struct marker *mdata, void *private,
76
        const char *fmt, ...)
77
{
78
}
79
EXPORT_SYMBOL_GPL(__mark_empty_function);
80
 
81
/*
82
 * Get marker if the marker is present in the marker hash table.
83
 * Must be called with markers_mutex held.
84
 * Returns NULL if not present.
85
 */
86
static struct marker_entry *get_marker(const char *name)
87
{
88
        struct hlist_head *head;
89
        struct hlist_node *node;
90
        struct marker_entry *e;
91
        u32 hash = jhash(name, strlen(name), 0);
92
 
93
        head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
94
        hlist_for_each_entry(e, node, head, hlist) {
95
                if (!strcmp(name, e->name))
96
                        return e;
97
        }
98
        return NULL;
99
}
100
 
101
/*
102
 * Add the marker to the marker hash table. Must be called with markers_mutex
103
 * held.
104
 */
105
static int add_marker(const char *name, const char *format,
106
        marker_probe_func *probe, void *private)
107
{
108
        struct hlist_head *head;
109
        struct hlist_node *node;
110
        struct marker_entry *e;
111
        size_t name_len = strlen(name) + 1;
112
        size_t format_len = 0;
113
        u32 hash = jhash(name, name_len-1, 0);
114
 
115
        if (format)
116
                format_len = strlen(format) + 1;
117
        head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
118
        hlist_for_each_entry(e, node, head, hlist) {
119
                if (!strcmp(name, e->name)) {
120
                        printk(KERN_NOTICE
121
                                "Marker %s busy, probe %p already installed\n",
122
                                name, e->probe);
123
                        return -EBUSY;  /* Already there */
124
                }
125
        }
126
        /*
127
         * Using kmalloc here to allocate a variable length element. Could
128
         * cause some memory fragmentation if overused.
129
         */
130
        e = kmalloc(sizeof(struct marker_entry) + name_len + format_len,
131
                        GFP_KERNEL);
132
        if (!e)
133
                return -ENOMEM;
134
        memcpy(&e->name[0], name, name_len);
135
        if (format) {
136
                e->format = &e->name[name_len];
137
                memcpy(e->format, format, format_len);
138
                trace_mark(core_marker_format, "name %s format %s",
139
                                e->name, e->format);
140
        } else
141
                e->format = NULL;
142
        e->probe = probe;
143
        e->private = private;
144
        e->refcount = 0;
145
        hlist_add_head(&e->hlist, head);
146
        return 0;
147
}
148
 
149
/*
150
 * Remove the marker from the marker hash table. Must be called with mutex_lock
151
 * held.
152
 */
153
static void *remove_marker(const char *name)
154
{
155
        struct hlist_head *head;
156
        struct hlist_node *node;
157
        struct marker_entry *e;
158
        int found = 0;
159
        size_t len = strlen(name) + 1;
160
        void *private = NULL;
161
        u32 hash = jhash(name, len-1, 0);
162
 
163
        head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
164
        hlist_for_each_entry(e, node, head, hlist) {
165
                if (!strcmp(name, e->name)) {
166
                        found = 1;
167
                        break;
168
                }
169
        }
170
        if (found) {
171
                private = e->private;
172
                hlist_del(&e->hlist);
173
                kfree(e);
174
        }
175
        return private;
176
}
177
 
178
/*
179
 * Set the mark_entry format to the format found in the element.
180
 */
181
static int marker_set_format(struct marker_entry **entry, const char *format)
182
{
183
        struct marker_entry *e;
184
        size_t name_len = strlen((*entry)->name) + 1;
185
        size_t format_len = strlen(format) + 1;
186
 
187
        e = kmalloc(sizeof(struct marker_entry) + name_len + format_len,
188
                        GFP_KERNEL);
189
        if (!e)
190
                return -ENOMEM;
191
        memcpy(&e->name[0], (*entry)->name, name_len);
192
        e->format = &e->name[name_len];
193
        memcpy(e->format, format, format_len);
194
        e->probe = (*entry)->probe;
195
        e->private = (*entry)->private;
196
        e->refcount = (*entry)->refcount;
197
        hlist_add_before(&e->hlist, &(*entry)->hlist);
198
        hlist_del(&(*entry)->hlist);
199
        kfree(*entry);
200
        *entry = e;
201
        trace_mark(core_marker_format, "name %s format %s",
202
                        e->name, e->format);
203
        return 0;
204
}
205
 
206
/*
207
 * Sets the probe callback corresponding to one marker.
208
 */
209
static int set_marker(struct marker_entry **entry, struct marker *elem)
210
{
211
        int ret;
212
        WARN_ON(strcmp((*entry)->name, elem->name) != 0);
213
 
214
        if ((*entry)->format) {
215
                if (strcmp((*entry)->format, elem->format) != 0) {
216
                        printk(KERN_NOTICE
217
                                "Format mismatch for probe %s "
218
                                "(%s), marker (%s)\n",
219
                                (*entry)->name,
220
                                (*entry)->format,
221
                                elem->format);
222
                        return -EPERM;
223
                }
224
        } else {
225
                ret = marker_set_format(entry, elem->format);
226
                if (ret)
227
                        return ret;
228
        }
229
        elem->call = (*entry)->probe;
230
        elem->private = (*entry)->private;
231
        elem->state = 1;
232
        return 0;
233
}
234
 
235
/*
236
 * Disable a marker and its probe callback.
237
 * Note: only after a synchronize_sched() issued after setting elem->call to the
238
 * empty function insures that the original callback is not used anymore. This
239
 * insured by preemption disabling around the call site.
240
 */
241
static void disable_marker(struct marker *elem)
242
{
243
        elem->state = 0;
244
        elem->call = __mark_empty_function;
245
        /*
246
         * Leave the private data and id there, because removal is racy and
247
         * should be done only after a synchronize_sched(). These are never used
248
         * until the next initialization anyway.
249
         */
250
}
251
 
252
/**
253
 * marker_update_probe_range - Update a probe range
254
 * @begin: beginning of the range
255
 * @end: end of the range
256
 * @probe_module: module address of the probe being updated
257
 * @refcount: number of references left to the given probe_module (out)
258
 *
259
 * Updates the probe callback corresponding to a range of markers.
260
 */
261
void marker_update_probe_range(struct marker *begin,
262
        struct marker *end, struct module *probe_module,
263
        int *refcount)
264
{
265
        struct marker *iter;
266
        struct marker_entry *mark_entry;
267
 
268
        mutex_lock(&markers_mutex);
269
        for (iter = begin; iter < end; iter++) {
270
                mark_entry = get_marker(iter->name);
271
                if (mark_entry && mark_entry->refcount) {
272
                        set_marker(&mark_entry, iter);
273
                        /*
274
                         * ignore error, continue
275
                         */
276
                        if (probe_module)
277
                                if (probe_module ==
278
                        __module_text_address((unsigned long)mark_entry->probe))
279
                                        (*refcount)++;
280
                } else {
281
                        disable_marker(iter);
282
                }
283
        }
284
        mutex_unlock(&markers_mutex);
285
}
286
 
287
/*
288
 * Update probes, removing the faulty probes.
289
 * Issues a synchronize_sched() when no reference to the module passed
290
 * as parameter is found in the probes so the probe module can be
291
 * safely unloaded from now on.
292
 */
293
static void marker_update_probes(struct module *probe_module)
294
{
295
        int refcount = 0;
296
 
297
        /* Core kernel markers */
298
        marker_update_probe_range(__start___markers,
299
                        __stop___markers, probe_module, &refcount);
300
        /* Markers in modules. */
301
        module_update_markers(probe_module, &refcount);
302
        if (probe_module && refcount == 0) {
303
                synchronize_sched();
304
                deferred_sync = 0;
305
        }
306
}
307
 
308
/**
309
 * marker_probe_register -  Connect a probe to a marker
310
 * @name: marker name
311
 * @format: format string
312
 * @probe: probe handler
313
 * @private: probe private data
314
 *
315
 * private data must be a valid allocated memory address, or NULL.
316
 * Returns 0 if ok, error value on error.
317
 */
318
int marker_probe_register(const char *name, const char *format,
319
                        marker_probe_func *probe, void *private)
320
{
321
        struct marker_entry *entry;
322
        int ret = 0;
323
 
324
        mutex_lock(&markers_mutex);
325
        entry = get_marker(name);
326
        if (entry && entry->refcount) {
327
                ret = -EBUSY;
328
                goto end;
329
        }
330
        if (deferred_sync) {
331
                synchronize_sched();
332
                deferred_sync = 0;
333
        }
334
        ret = add_marker(name, format, probe, private);
335
        if (ret)
336
                goto end;
337
        mutex_unlock(&markers_mutex);
338
        marker_update_probes(NULL);
339
        return ret;
340
end:
341
        mutex_unlock(&markers_mutex);
342
        return ret;
343
}
344
EXPORT_SYMBOL_GPL(marker_probe_register);
345
 
346
/**
347
 * marker_probe_unregister -  Disconnect a probe from a marker
348
 * @name: marker name
349
 *
350
 * Returns the private data given to marker_probe_register, or an ERR_PTR().
351
 */
352
void *marker_probe_unregister(const char *name)
353
{
354
        struct module *probe_module;
355
        struct marker_entry *entry;
356
        void *private;
357
 
358
        mutex_lock(&markers_mutex);
359
        entry = get_marker(name);
360
        if (!entry) {
361
                private = ERR_PTR(-ENOENT);
362
                goto end;
363
        }
364
        entry->refcount = 0;
365
        /* In what module is the probe handler ? */
366
        probe_module = __module_text_address((unsigned long)entry->probe);
367
        private = remove_marker(name);
368
        deferred_sync = 1;
369
        mutex_unlock(&markers_mutex);
370
        marker_update_probes(probe_module);
371
        return private;
372
end:
373
        mutex_unlock(&markers_mutex);
374
        return private;
375
}
376
EXPORT_SYMBOL_GPL(marker_probe_unregister);
377
 
378
/**
379
 * marker_probe_unregister_private_data -  Disconnect a probe from a marker
380
 * @private: probe private data
381
 *
382
 * Unregister a marker by providing the registered private data.
383
 * Returns the private data given to marker_probe_register, or an ERR_PTR().
384
 */
385
void *marker_probe_unregister_private_data(void *private)
386
{
387
        struct module *probe_module;
388
        struct hlist_head *head;
389
        struct hlist_node *node;
390
        struct marker_entry *entry;
391
        int found = 0;
392
        unsigned int i;
393
 
394
        mutex_lock(&markers_mutex);
395
        for (i = 0; i < MARKER_TABLE_SIZE; i++) {
396
                head = &marker_table[i];
397
                hlist_for_each_entry(entry, node, head, hlist) {
398
                        if (entry->private == private) {
399
                                found = 1;
400
                                goto iter_end;
401
                        }
402
                }
403
        }
404
iter_end:
405
        if (!found) {
406
                private = ERR_PTR(-ENOENT);
407
                goto end;
408
        }
409
        entry->refcount = 0;
410
        /* In what module is the probe handler ? */
411
        probe_module = __module_text_address((unsigned long)entry->probe);
412
        private = remove_marker(entry->name);
413
        deferred_sync = 1;
414
        mutex_unlock(&markers_mutex);
415
        marker_update_probes(probe_module);
416
        return private;
417
end:
418
        mutex_unlock(&markers_mutex);
419
        return private;
420
}
421
EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data);
422
 
423
/**
424
 * marker_arm - Arm a marker
425
 * @name: marker name
426
 *
427
 * Activate a marker. It keeps a reference count of the number of
428
 * arming/disarming done.
429
 * Returns 0 if ok, error value on error.
430
 */
431
int marker_arm(const char *name)
432
{
433
        struct marker_entry *entry;
434
        int ret = 0;
435
 
436
        mutex_lock(&markers_mutex);
437
        entry = get_marker(name);
438
        if (!entry) {
439
                ret = -ENOENT;
440
                goto end;
441
        }
442
        /*
443
         * Only need to update probes when refcount passes from 0 to 1.
444
         */
445
        if (entry->refcount++)
446
                goto end;
447
end:
448
        mutex_unlock(&markers_mutex);
449
        marker_update_probes(NULL);
450
        return ret;
451
}
452
EXPORT_SYMBOL_GPL(marker_arm);
453
 
454
/**
455
 * marker_disarm - Disarm a marker
456
 * @name: marker name
457
 *
458
 * Disarm a marker. It keeps a reference count of the number of arming/disarming
459
 * done.
460
 * Returns 0 if ok, error value on error.
461
 */
462
int marker_disarm(const char *name)
463
{
464
        struct marker_entry *entry;
465
        int ret = 0;
466
 
467
        mutex_lock(&markers_mutex);
468
        entry = get_marker(name);
469
        if (!entry) {
470
                ret = -ENOENT;
471
                goto end;
472
        }
473
        /*
474
         * Only permit decrement refcount if higher than 0.
475
         * Do probe update only on 1 -> 0 transition.
476
         */
477
        if (entry->refcount) {
478
                if (--entry->refcount)
479
                        goto end;
480
        } else {
481
                ret = -EPERM;
482
                goto end;
483
        }
484
end:
485
        mutex_unlock(&markers_mutex);
486
        marker_update_probes(NULL);
487
        return ret;
488
}
489
EXPORT_SYMBOL_GPL(marker_disarm);
490
 
491
/**
492
 * marker_get_private_data - Get a marker's probe private data
493
 * @name: marker name
494
 *
495
 * Returns the private data pointer, or an ERR_PTR.
496
 * The private data pointer should _only_ be dereferenced if the caller is the
497
 * owner of the data, or its content could vanish. This is mostly used to
498
 * confirm that a caller is the owner of a registered probe.
499
 */
500
void *marker_get_private_data(const char *name)
501
{
502
        struct hlist_head *head;
503
        struct hlist_node *node;
504
        struct marker_entry *e;
505
        size_t name_len = strlen(name) + 1;
506
        u32 hash = jhash(name, name_len-1, 0);
507
        int found = 0;
508
 
509
        head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];
510
        hlist_for_each_entry(e, node, head, hlist) {
511
                if (!strcmp(name, e->name)) {
512
                        found = 1;
513
                        return e->private;
514
                }
515
        }
516
        return ERR_PTR(-ENOENT);
517
}
518
EXPORT_SYMBOL_GPL(marker_get_private_data);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.