|
54 | 54 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
|
55 | 55 | #endif
|
56 | 56 |
|
| 57 | +#ifndef unlikely |
| 58 | +#define unlikely(x) __builtin_expect(!!(x), 0) |
| 59 | +#endif |
| 60 | + |
| 61 | +#ifndef likely |
| 62 | +#define likely(x) __builtin_expect(!!(x), 1) |
| 63 | +#endif |
| 64 | + |
57 | 65 | enum {
|
58 | 66 | STATS_ENTRY_FLAG_REGISTERED = 1 << 0,
|
59 | 67 | STATS_ENTRY_FLAG_DIR = 1 << 1,
|
@@ -771,17 +779,32 @@ static int register_item(struct procstat_context *context,
|
771 | 779 | struct procstat_item *item,
|
772 | 780 | struct procstat_directory *parent)
|
773 | 781 | {
|
774 |
| - pthread_mutex_lock(&context->global_lock); |
775 |
| - if (parent) { |
| 782 | + if (likely(parent)) { |
776 | 783 | struct procstat_item *duplicate;
|
| 784 | + bool locked = false; |
| 785 | + |
| 786 | + if (unlikely(root_directory(context, parent))) { |
| 787 | + /* Only root directory can be modified concurrently by different threads */ |
| 788 | + pthread_mutex_lock(&context->global_lock); |
| 789 | + locked = true; |
| 790 | + } |
777 | 791 |
|
778 | 792 | duplicate = lookup_item_locked(parent, procstat_item_name(item), item->name_hash);
|
779 |
| - if (duplicate) { |
780 |
| - pthread_mutex_unlock(&context->global_lock); |
| 793 | + if (unlikely(duplicate)) { |
| 794 | + if (locked) |
| 795 | + pthread_mutex_unlock(&context->global_lock); |
781 | 796 | return EEXIST;
|
782 | 797 | }
|
| 798 | + |
| 799 | + if (likely(!locked)) |
| 800 | + pthread_mutex_lock(&context->global_lock); |
| 801 | + |
783 | 802 | list_add_tail(&item->entry, &parent->children);
|
| 803 | + } else { |
| 804 | + pthread_mutex_lock(&context->global_lock); |
784 | 805 | }
|
| 806 | + |
| 807 | + |
785 | 808 | item->flags |= STATS_ENTRY_FLAG_REGISTERED;
|
786 | 809 | item->refcnt = 1;
|
787 | 810 | item->parent = parent;
|
|
0 commit comments