Advertisement
Guest User

a2.c

a guest
Dec 12th, 2014
298
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 3.73 KB | None | 0 0
  1. #define _GNU_SOURCE
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <stdint.h>
  6. #include <pthread.h>
  7. #include <sched.h>
  8.  
  9. #include "q3.h"
  10. //#include "q.h"
  11. //#include "qlock.h"
  12.  
  13. static struct msg *msgs;
  14.  
  15.  
  16. #define POP_CNT     7
  17. #define PUSH_CNT    7
  18.  
  19. #define MSG_CNT     (PUSH_CNT * 1000000)
  20.  
  21. static inline uint64_t
  22. rdtsc(void)
  23. {
  24.     union {
  25.         uint64_t tsc_64;
  26.         struct {
  27.             uint32_t lo_32;
  28.             uint32_t hi_32;
  29.         };
  30.     } tsc;
  31.  
  32.     asm volatile("rdtsc" :
  33.         "=a" (tsc.lo_32),
  34.         "=d" (tsc.hi_32));
  35.     return tsc.tsc_64;
  36. }
  37.  
  38. static volatile int quit = 0;
  39. static volatile int pop_total = 0;
  40. static volatile int push_total = 0;
  41.  
  42. static volatile uint64_t push_cycles = 0;
  43. static volatile uint64_t pop_cycles = 0;
  44.  
  45.  
  46. static void *
  47. pop_task(void *arg)
  48. {
  49.     struct queue *q = arg;
  50.     uint64_t start = rdtsc();
  51.     int cnt = 0;
  52.  
  53.     while (!quit)
  54.         cnt += !!pop(q);
  55.  
  56.     pop_cycles += rdtsc() - start;
  57.     pop_total += cnt;
  58.  
  59.     return NULL;
  60. }
  61.  
  62. static void *
  63. pop_flush_task(void *arg)
  64. {
  65.     struct queue *q = arg;
  66.     uint64_t start = rdtsc();
  67.  
  68.     while (!quit) {
  69.         __sync_fetch_and_add(&pop_total, !!pop(q));
  70.         if (pop_total == MSG_CNT)
  71.             quit = 1;
  72.     }
  73.  
  74.     pop_cycles += rdtsc() - start;
  75.  
  76.     return NULL;
  77. }
  78.  
  79. static void *
  80. push_task(void *arg)
  81. {
  82.     struct queue *q = arg;
  83.     uint64_t start = rdtsc();
  84.     int i;
  85.  
  86.     for (i = 0; i < MSG_CNT / PUSH_CNT; i++)
  87.         while (push(q, msgs + i) == -1);
  88.  
  89.     push_cycles += rdtsc() - start;
  90.     push_total += MSG_CNT / PUSH_CNT;
  91.     if (push_total == MSG_CNT)
  92.         quit = 1;
  93.  
  94.     return NULL;
  95. }
  96.  
  97. /* topology for Xeon E5-2670 Sandybridge */
  98. static const int socket_top[] = {
  99.     1,  2,  3,  4,  5,  6,  7,
  100.     16, 17, 18, 19, 20, 21, 22, 23,
  101.     8,  9,  10, 11, 12, 13, 14, 15,
  102.     24, 25, 26, 27, 28, 29, 30, 31
  103. };
  104.  
  105. #define CORE_ID(i)      socket_top[(i)]
  106.  
  107. static int
  108. start_thread(int id,
  109.              void *(*cb)(void *),
  110.              void *arg,
  111.              pthread_t *tid)
  112. {
  113.     pthread_t kid;
  114.     pthread_attr_t attr;
  115.     cpu_set_t cpuset;
  116.     int core_id;
  117.  
  118.     if (id < 0 || id >= sizeof(socket_top) / sizeof(int))
  119.         return -1;
  120.  
  121.     if (pthread_attr_init(&attr))
  122.         return -1;
  123.  
  124.     CPU_ZERO(&cpuset);
  125.     core_id = CORE_ID(id);
  126.     CPU_SET(core_id, &cpuset);
  127.  
  128.     if (pthread_create(&kid, &attr, cb, arg))
  129.         return -1;
  130.     if (pthread_setaffinity_np(kid, sizeof(cpu_set_t), &cpuset))
  131.         return -1;
  132.  
  133.     if (tid)
  134.         *tid = kid;
  135.  
  136.     return 0;
  137. }
  138.  
  139. static int
  140. setaffinity(int core_id)
  141. {
  142.     cpu_set_t cpuset;
  143.     pthread_t me = pthread_self();
  144.  
  145.     CPU_ZERO(&cpuset);
  146.     CPU_SET(core_id, &cpuset);
  147.  
  148.     if (pthread_setaffinity_np(me, sizeof(cpu_set_t), &cpuset))
  149.         return -1;
  150.  
  151.     return 0;
  152. }
  153.  
  154. int
  155. main(void)
  156. {
  157.     struct queue *q = qinit();
  158.     int i;
  159.     pthread_t kids[POP_CNT + PUSH_CNT];
  160.  
  161.     setaffinity(0);
  162.  
  163.     msgs = calloc(MSG_CNT, sizeof(struct msg));
  164.     for (i = 0; i < POP_CNT; i++)
  165.         start_thread(i, pop_task, q, &kids[i]);
  166.     for (; i < POP_CNT + PUSH_CNT; i++)
  167.         start_thread(i, push_task, q, &kids[i]);
  168.     for (i = 0; i < POP_CNT + PUSH_CNT; i++)
  169.         pthread_join(kids[i], NULL);
  170.  
  171.     quit = 0;
  172.  
  173.     if (pop_total < MSG_CNT) {
  174.         printf("flushing: %d\n", MSG_CNT - pop_total);
  175.         for (i = 0; i < POP_CNT; i++)
  176.             start_thread(i, pop_flush_task, q, &kids[i]);
  177.         for (i = 0; i < POP_CNT; i++)
  178.             pthread_join(kids[i], NULL);
  179.     }
  180.  
  181.     printf("pop total: %d\n", pop_total);
  182.     printf("pop cycles/msg: %lu\n", pop_cycles / pop_total);
  183.     printf("push cycles/msg: %lu\n", push_cycles / MSG_CNT);
  184.  
  185.     return 0;
  186. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement