0001
0002
0003
0004
0005
0006 #include <stdio.h>
0007 #include <stdlib.h>
0008 #include <string.h>
0009
0010 #include "kbuffer.h"
0011
0012 #define MISSING_EVENTS (1UL << 31)
0013 #define MISSING_STORED (1UL << 30)
0014
0015 #define COMMIT_MASK ((1 << 27) - 1)
0016
0017 enum {
0018 KBUFFER_FL_HOST_BIG_ENDIAN = (1<<0),
0019 KBUFFER_FL_BIG_ENDIAN = (1<<1),
0020 KBUFFER_FL_LONG_8 = (1<<2),
0021 KBUFFER_FL_OLD_FORMAT = (1<<3),
0022 };
0023
0024 #define ENDIAN_MASK (KBUFFER_FL_HOST_BIG_ENDIAN | KBUFFER_FL_BIG_ENDIAN)
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 struct kbuffer {
0044 unsigned long long timestamp;
0045 long long lost_events;
0046 unsigned long flags;
0047 void *subbuffer;
0048 void *data;
0049 unsigned int index;
0050 unsigned int curr;
0051 unsigned int next;
0052 unsigned int size;
0053 unsigned int start;
0054
0055 unsigned int (*read_4)(void *ptr);
0056 unsigned long long (*read_8)(void *ptr);
0057 unsigned long long (*read_long)(struct kbuffer *kbuf, void *ptr);
0058 int (*next_event)(struct kbuffer *kbuf);
0059 };
0060
0061 static void *zmalloc(size_t size)
0062 {
0063 return calloc(1, size);
0064 }
0065
0066 static int host_is_bigendian(void)
0067 {
0068 unsigned char str[] = { 0x1, 0x2, 0x3, 0x4 };
0069 unsigned int *ptr;
0070
0071 ptr = (unsigned int *)str;
0072 return *ptr == 0x01020304;
0073 }
0074
0075 static int do_swap(struct kbuffer *kbuf)
0076 {
0077 return ((kbuf->flags & KBUFFER_FL_HOST_BIG_ENDIAN) + kbuf->flags) &
0078 ENDIAN_MASK;
0079 }
0080
0081 static unsigned long long __read_8(void *ptr)
0082 {
0083 unsigned long long data = *(unsigned long long *)ptr;
0084
0085 return data;
0086 }
0087
0088 static unsigned long long __read_8_sw(void *ptr)
0089 {
0090 unsigned long long data = *(unsigned long long *)ptr;
0091 unsigned long long swap;
0092
0093 swap = ((data & 0xffULL) << 56) |
0094 ((data & (0xffULL << 8)) << 40) |
0095 ((data & (0xffULL << 16)) << 24) |
0096 ((data & (0xffULL << 24)) << 8) |
0097 ((data & (0xffULL << 32)) >> 8) |
0098 ((data & (0xffULL << 40)) >> 24) |
0099 ((data & (0xffULL << 48)) >> 40) |
0100 ((data & (0xffULL << 56)) >> 56);
0101
0102 return swap;
0103 }
0104
0105 static unsigned int __read_4(void *ptr)
0106 {
0107 unsigned int data = *(unsigned int *)ptr;
0108
0109 return data;
0110 }
0111
0112 static unsigned int __read_4_sw(void *ptr)
0113 {
0114 unsigned int data = *(unsigned int *)ptr;
0115 unsigned int swap;
0116
0117 swap = ((data & 0xffULL) << 24) |
0118 ((data & (0xffULL << 8)) << 8) |
0119 ((data & (0xffULL << 16)) >> 8) |
0120 ((data & (0xffULL << 24)) >> 24);
0121
0122 return swap;
0123 }
0124
0125 static unsigned long long read_8(struct kbuffer *kbuf, void *ptr)
0126 {
0127 return kbuf->read_8(ptr);
0128 }
0129
0130 static unsigned int read_4(struct kbuffer *kbuf, void *ptr)
0131 {
0132 return kbuf->read_4(ptr);
0133 }
0134
0135 static unsigned long long __read_long_8(struct kbuffer *kbuf, void *ptr)
0136 {
0137 return kbuf->read_8(ptr);
0138 }
0139
0140 static unsigned long long __read_long_4(struct kbuffer *kbuf, void *ptr)
0141 {
0142 return kbuf->read_4(ptr);
0143 }
0144
0145 static unsigned long long read_long(struct kbuffer *kbuf, void *ptr)
0146 {
0147 return kbuf->read_long(kbuf, ptr);
0148 }
0149
0150 static int calc_index(struct kbuffer *kbuf, void *ptr)
0151 {
0152 return (unsigned long)ptr - (unsigned long)kbuf->data;
0153 }
0154
0155 static int __next_event(struct kbuffer *kbuf);
0156
0157
0158
0159
0160
0161
0162
0163
0164 struct kbuffer *
0165 kbuffer_alloc(enum kbuffer_long_size size, enum kbuffer_endian endian)
0166 {
0167 struct kbuffer *kbuf;
0168 int flags = 0;
0169
0170 switch (size) {
0171 case KBUFFER_LSIZE_4:
0172 break;
0173 case KBUFFER_LSIZE_8:
0174 flags |= KBUFFER_FL_LONG_8;
0175 break;
0176 default:
0177 return NULL;
0178 }
0179
0180 switch (endian) {
0181 case KBUFFER_ENDIAN_LITTLE:
0182 break;
0183 case KBUFFER_ENDIAN_BIG:
0184 flags |= KBUFFER_FL_BIG_ENDIAN;
0185 break;
0186 default:
0187 return NULL;
0188 }
0189
0190 kbuf = zmalloc(sizeof(*kbuf));
0191 if (!kbuf)
0192 return NULL;
0193
0194 kbuf->flags = flags;
0195
0196 if (host_is_bigendian())
0197 kbuf->flags |= KBUFFER_FL_HOST_BIG_ENDIAN;
0198
0199 if (do_swap(kbuf)) {
0200 kbuf->read_8 = __read_8_sw;
0201 kbuf->read_4 = __read_4_sw;
0202 } else {
0203 kbuf->read_8 = __read_8;
0204 kbuf->read_4 = __read_4;
0205 }
0206
0207 if (kbuf->flags & KBUFFER_FL_LONG_8)
0208 kbuf->read_long = __read_long_8;
0209 else
0210 kbuf->read_long = __read_long_4;
0211
0212
0213 kbuf->next_event = __next_event;
0214
0215 return kbuf;
0216 }
0217
0218
0219
0220
0221
0222
0223 void kbuffer_free(struct kbuffer *kbuf)
0224 {
0225 free(kbuf);
0226 }
0227
0228 static unsigned int type4host(struct kbuffer *kbuf,
0229 unsigned int type_len_ts)
0230 {
0231 if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
0232 return (type_len_ts >> 29) & 3;
0233 else
0234 return type_len_ts & 3;
0235 }
0236
0237 static unsigned int len4host(struct kbuffer *kbuf,
0238 unsigned int type_len_ts)
0239 {
0240 if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
0241 return (type_len_ts >> 27) & 7;
0242 else
0243 return (type_len_ts >> 2) & 7;
0244 }
0245
0246 static unsigned int type_len4host(struct kbuffer *kbuf,
0247 unsigned int type_len_ts)
0248 {
0249 if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
0250 return (type_len_ts >> 27) & ((1 << 5) - 1);
0251 else
0252 return type_len_ts & ((1 << 5) - 1);
0253 }
0254
0255 static unsigned int ts4host(struct kbuffer *kbuf,
0256 unsigned int type_len_ts)
0257 {
0258 if (kbuf->flags & KBUFFER_FL_BIG_ENDIAN)
0259 return type_len_ts & ((1 << 27) - 1);
0260 else
0261 return type_len_ts >> 5;
0262 }
0263
0264
0265
0266
0267
0268 enum old_ring_buffer_type {
0269 OLD_RINGBUF_TYPE_PADDING,
0270 OLD_RINGBUF_TYPE_TIME_EXTEND,
0271 OLD_RINGBUF_TYPE_TIME_STAMP,
0272 OLD_RINGBUF_TYPE_DATA,
0273 };
0274
0275 static unsigned int old_update_pointers(struct kbuffer *kbuf)
0276 {
0277 unsigned long long extend;
0278 unsigned int type_len_ts;
0279 unsigned int type;
0280 unsigned int len;
0281 unsigned int delta;
0282 unsigned int length;
0283 void *ptr = kbuf->data + kbuf->curr;
0284
0285 type_len_ts = read_4(kbuf, ptr);
0286 ptr += 4;
0287
0288 type = type4host(kbuf, type_len_ts);
0289 len = len4host(kbuf, type_len_ts);
0290 delta = ts4host(kbuf, type_len_ts);
0291
0292 switch (type) {
0293 case OLD_RINGBUF_TYPE_PADDING:
0294 kbuf->next = kbuf->size;
0295 return 0;
0296
0297 case OLD_RINGBUF_TYPE_TIME_EXTEND:
0298 extend = read_4(kbuf, ptr);
0299 extend <<= TS_SHIFT;
0300 extend += delta;
0301 delta = extend;
0302 ptr += 4;
0303 length = 0;
0304 break;
0305
0306 case OLD_RINGBUF_TYPE_TIME_STAMP:
0307
0308 kbuf->curr = kbuf->size;
0309 kbuf->next = kbuf->size;
0310 kbuf->index = kbuf->size;
0311 return -1;
0312 default:
0313 if (len)
0314 length = len * 4;
0315 else {
0316 length = read_4(kbuf, ptr);
0317 length -= 4;
0318 ptr += 4;
0319 }
0320 break;
0321 }
0322
0323 kbuf->timestamp += delta;
0324 kbuf->index = calc_index(kbuf, ptr);
0325 kbuf->next = kbuf->index + length;
0326
0327 return type;
0328 }
0329
0330 static int __old_next_event(struct kbuffer *kbuf)
0331 {
0332 int type;
0333
0334 do {
0335 kbuf->curr = kbuf->next;
0336 if (kbuf->next >= kbuf->size)
0337 return -1;
0338 type = old_update_pointers(kbuf);
0339 } while (type == OLD_RINGBUF_TYPE_TIME_EXTEND || type == OLD_RINGBUF_TYPE_PADDING);
0340
0341 return 0;
0342 }
0343
0344 static unsigned int
0345 translate_data(struct kbuffer *kbuf, void *data, void **rptr,
0346 unsigned long long *delta, int *length)
0347 {
0348 unsigned long long extend;
0349 unsigned int type_len_ts;
0350 unsigned int type_len;
0351
0352 type_len_ts = read_4(kbuf, data);
0353 data += 4;
0354
0355 type_len = type_len4host(kbuf, type_len_ts);
0356 *delta = ts4host(kbuf, type_len_ts);
0357
0358 switch (type_len) {
0359 case KBUFFER_TYPE_PADDING:
0360 *length = read_4(kbuf, data);
0361 break;
0362
0363 case KBUFFER_TYPE_TIME_EXTEND:
0364 case KBUFFER_TYPE_TIME_STAMP:
0365 extend = read_4(kbuf, data);
0366 data += 4;
0367 extend <<= TS_SHIFT;
0368 extend += *delta;
0369 *delta = extend;
0370 *length = 0;
0371 break;
0372
0373 case 0:
0374 *length = read_4(kbuf, data) - 4;
0375 *length = (*length + 3) & ~3;
0376 data += 4;
0377 break;
0378 default:
0379 *length = type_len * 4;
0380 break;
0381 }
0382
0383 *rptr = data;
0384
0385 return type_len;
0386 }
0387
0388 static unsigned int update_pointers(struct kbuffer *kbuf)
0389 {
0390 unsigned long long delta;
0391 unsigned int type_len;
0392 int length;
0393 void *ptr = kbuf->data + kbuf->curr;
0394
0395 type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
0396
0397 if (type_len == KBUFFER_TYPE_TIME_STAMP)
0398 kbuf->timestamp = delta;
0399 else
0400 kbuf->timestamp += delta;
0401
0402 kbuf->index = calc_index(kbuf, ptr);
0403 kbuf->next = kbuf->index + length;
0404
0405 return type_len;
0406 }
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418 void *kbuffer_translate_data(int swap, void *data, unsigned int *size)
0419 {
0420 unsigned long long delta;
0421 struct kbuffer kbuf;
0422 int type_len;
0423 int length;
0424 void *ptr;
0425
0426 if (swap) {
0427 kbuf.read_8 = __read_8_sw;
0428 kbuf.read_4 = __read_4_sw;
0429 kbuf.flags = host_is_bigendian() ? 0 : KBUFFER_FL_BIG_ENDIAN;
0430 } else {
0431 kbuf.read_8 = __read_8;
0432 kbuf.read_4 = __read_4;
0433 kbuf.flags = host_is_bigendian() ? KBUFFER_FL_BIG_ENDIAN: 0;
0434 }
0435
0436 type_len = translate_data(&kbuf, data, &ptr, &delta, &length);
0437 switch (type_len) {
0438 case KBUFFER_TYPE_PADDING:
0439 case KBUFFER_TYPE_TIME_EXTEND:
0440 case KBUFFER_TYPE_TIME_STAMP:
0441 return NULL;
0442 }
0443
0444 *size = length;
0445
0446 return ptr;
0447 }
0448
0449 static int __next_event(struct kbuffer *kbuf)
0450 {
0451 int type;
0452
0453 do {
0454 kbuf->curr = kbuf->next;
0455 if (kbuf->next >= kbuf->size)
0456 return -1;
0457 type = update_pointers(kbuf);
0458 } while (type == KBUFFER_TYPE_TIME_EXTEND ||
0459 type == KBUFFER_TYPE_TIME_STAMP ||
0460 type == KBUFFER_TYPE_PADDING);
0461
0462 return 0;
0463 }
0464
0465 static int next_event(struct kbuffer *kbuf)
0466 {
0467 return kbuf->next_event(kbuf);
0468 }
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482 void *kbuffer_next_event(struct kbuffer *kbuf, unsigned long long *ts)
0483 {
0484 int ret;
0485
0486 if (!kbuf || !kbuf->subbuffer)
0487 return NULL;
0488
0489 ret = next_event(kbuf);
0490 if (ret < 0)
0491 return NULL;
0492
0493 if (ts)
0494 *ts = kbuf->timestamp;
0495
0496 return kbuf->data + kbuf->index;
0497 }
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510 int kbuffer_load_subbuffer(struct kbuffer *kbuf, void *subbuffer)
0511 {
0512 unsigned long long flags;
0513 void *ptr = subbuffer;
0514
0515 if (!kbuf || !subbuffer)
0516 return -1;
0517
0518 kbuf->subbuffer = subbuffer;
0519
0520 kbuf->timestamp = read_8(kbuf, ptr);
0521 ptr += 8;
0522
0523 kbuf->curr = 0;
0524
0525 if (kbuf->flags & KBUFFER_FL_LONG_8)
0526 kbuf->start = 16;
0527 else
0528 kbuf->start = 12;
0529
0530 kbuf->data = subbuffer + kbuf->start;
0531
0532 flags = read_long(kbuf, ptr);
0533 kbuf->size = (unsigned int)flags & COMMIT_MASK;
0534
0535 if (flags & MISSING_EVENTS) {
0536 if (flags & MISSING_STORED) {
0537 ptr = kbuf->data + kbuf->size;
0538 kbuf->lost_events = read_long(kbuf, ptr);
0539 } else
0540 kbuf->lost_events = -1;
0541 } else
0542 kbuf->lost_events = 0;
0543
0544 kbuf->index = 0;
0545 kbuf->next = 0;
0546
0547 next_event(kbuf);
0548
0549 return 0;
0550 }
0551
0552
0553
0554
0555
0556
0557
0558
0559 unsigned long long kbuffer_subbuf_timestamp(struct kbuffer *kbuf, void *subbuf)
0560 {
0561 return kbuf->read_8(subbuf);
0562 }
0563
0564
0565
0566
0567
0568
0569
0570
0571 unsigned int kbuffer_ptr_delta(struct kbuffer *kbuf, void *ptr)
0572 {
0573 unsigned int type_len_ts;
0574
0575 type_len_ts = read_4(kbuf, ptr);
0576 return ts4host(kbuf, type_len_ts);
0577 }
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588 void *kbuffer_read_event(struct kbuffer *kbuf, unsigned long long *ts)
0589 {
0590 if (!kbuf || !kbuf->subbuffer)
0591 return NULL;
0592
0593 if (kbuf->curr >= kbuf->size)
0594 return NULL;
0595
0596 if (ts)
0597 *ts = kbuf->timestamp;
0598 return kbuf->data + kbuf->index;
0599 }
0600
0601
0602
0603
0604
0605
0606
0607 unsigned long long kbuffer_timestamp(struct kbuffer *kbuf)
0608 {
0609 return kbuf->timestamp;
0610 }
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630 void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset,
0631 unsigned long long *ts)
0632 {
0633 void *data;
0634
0635 if (offset < kbuf->start)
0636 offset = 0;
0637 else
0638 offset -= kbuf->start;
0639
0640
0641 kbuffer_load_subbuffer(kbuf, kbuf->subbuffer);
0642 data = kbuffer_read_event(kbuf, ts);
0643
0644 while (kbuf->curr < offset) {
0645 data = kbuffer_next_event(kbuf, ts);
0646 if (!data)
0647 break;
0648 }
0649
0650 return data;
0651 }
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661 int kbuffer_subbuffer_size(struct kbuffer *kbuf)
0662 {
0663 return kbuf->size;
0664 }
0665
0666
0667
0668
0669
0670
0671
0672
0673
0674
0675
0676 int kbuffer_curr_index(struct kbuffer *kbuf)
0677 {
0678 return kbuf->curr;
0679 }
0680
0681
0682
0683
0684
0685
0686
0687
0688 int kbuffer_curr_offset(struct kbuffer *kbuf)
0689 {
0690 return kbuf->curr + kbuf->start;
0691 }
0692
0693
0694
0695
0696
0697
0698
0699
0700 int kbuffer_event_size(struct kbuffer *kbuf)
0701 {
0702 return kbuf->next - kbuf->index;
0703 }
0704
0705
0706
0707
0708
0709
0710
0711
0712 int kbuffer_curr_size(struct kbuffer *kbuf)
0713 {
0714 return kbuf->next - kbuf->curr;
0715 }
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726 int kbuffer_missed_events(struct kbuffer *kbuf)
0727 {
0728
0729 if (kbuf->curr)
0730 return 0;
0731
0732 return kbuf->lost_events;
0733 }
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744 void kbuffer_set_old_format(struct kbuffer *kbuf)
0745 {
0746 kbuf->flags |= KBUFFER_FL_OLD_FORMAT;
0747
0748 kbuf->next_event = __old_next_event;
0749 }
0750
0751
0752
0753
0754
0755
0756
0757 int kbuffer_start_of_data(struct kbuffer *kbuf)
0758 {
0759 return kbuf->start;
0760 }
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775 struct kbuffer_raw_info *
0776 kbuffer_raw_get(struct kbuffer *kbuf, void *subbuf, struct kbuffer_raw_info *info)
0777 {
0778 unsigned long long flags;
0779 unsigned long long delta;
0780 unsigned int type_len;
0781 unsigned int size;
0782 int start;
0783 int length;
0784 void *ptr = info->next;
0785
0786 if (!kbuf || !subbuf)
0787 return NULL;
0788
0789 if (kbuf->flags & KBUFFER_FL_LONG_8)
0790 start = 16;
0791 else
0792 start = 12;
0793
0794 flags = read_long(kbuf, subbuf + 8);
0795 size = (unsigned int)flags & COMMIT_MASK;
0796
0797 if (ptr < subbuf || ptr >= subbuf + start + size)
0798 return NULL;
0799
0800 type_len = translate_data(kbuf, ptr, &ptr, &delta, &length);
0801
0802 info->next = ptr + length;
0803
0804 info->type = type_len;
0805 info->delta = delta;
0806 info->length = length;
0807
0808 return info;
0809 }