Advertisement
Guest User

a3.c

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