Advertisement
Guest User

gngrwzrd.lists

a guest
Oct 23rd, 2010
311
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.69 KB | None | 0 0
  1. // compiled as:
  2. // gcc gg.c -Wall -pedantic -std=c99 -pthread -D_XOPEN_SOURCE=700
  3.  
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <stdbool.h>
  7. #include <assert.h>
  8. #include <pthread.h>
  9.  
  10. typedef struct
  11. {
  12.     pthread_rwlock_t rwlock;
  13.  
  14.     // mux protects 'write_owner' and 'recursive_wlocks' for reading,
  15.     // for writing the write-lock must be acquired as well
  16.     pthread_mutex_t mux;
  17.     pthread_t write_owner;
  18.     int recursive_wlocks;
  19. } rrw_lock_t;
  20.  
  21. // initilize a rrw_lock_t
  22. int rrw_init(rrw_lock_t *rrwl)
  23. {
  24.     int res = pthread_mutex_init(&rrwl->mux, NULL);
  25.     if (res)
  26.         return res;
  27.  
  28.     res = pthread_rwlock_init(&rrwl->rwlock, NULL);
  29.     if (res)
  30.     {
  31.         pthread_mutex_destroy(&rrwl->mux);
  32.         return res;
  33.     }
  34.  
  35.     rrwl->recursive_wlocks = 0;
  36.     return 0;
  37. }
  38.  
  39. // destroy a rrw_lock_t
  40. int rrw_destroy(rrw_lock_t *rrwl)
  41. {
  42.     int r1 = pthread_rwlock_destroy(&rrwl->rwlock);
  43.     int r2 = pthread_mutex_destroy(&rrwl->mux);
  44.     if (r1)
  45.         return r1;
  46.     if (r2)
  47.         return r2;
  48.     return 0;
  49. }
  50.  
  51. // acquire rrwl->mux
  52. void rrw_acquire_mux(rrw_lock_t *rrwl)
  53. {
  54.     int res = pthread_mutex_lock(&rrwl->mux);
  55.     if (res)
  56.     {
  57.         perror("rrw_acquire_mux::pthread_mutex_lock");
  58.         exit(res);
  59.     }
  60. }
  61.  
  62. // release rrwl->mux
  63. void rrw_release_mux(rrw_lock_t *rrwl)
  64. {
  65.     int res = pthread_mutex_unlock(&rrwl->mux);
  66.     if (res)
  67.     {
  68.         perror("rrw_release_mux::pthread_mutex_unlock");
  69.         exit(res);
  70.     }
  71. }
  72.  
  73. // acquire read lock
  74. int rrw_read_lock(rrw_lock_t *rrwl)
  75. {
  76.     return pthread_rwlock_rdlock(&rrwl->rwlock);
  77. }
  78.  
  79. // release read lock
  80. int rrw_read_unlock(rrw_lock_t *rrwl)
  81. {
  82.     return pthread_rwlock_unlock(&rrwl->rwlock);
  83. }
  84.  
  85. // acquire write lock
  86. int rrw_write_lock(rrw_lock_t *rrwl)
  87. {
  88.     pthread_t self = pthread_self();
  89.     bool call_wrlock = false;
  90.     int res;
  91.  
  92.     rrw_acquire_mux(rrwl);
  93.         // check if we already own write lock
  94.         if (rrwl->recursive_wlocks &&
  95.             pthread_equal(self, rrwl->write_owner))
  96.         {
  97.             ++(rrwl->recursive_wlocks);
  98.         }
  99.         else
  100.         {
  101.             call_wrlock = true;
  102.         }
  103.     rrw_release_mux(rrwl);
  104.  
  105.     if (!call_wrlock)
  106.         return 0;
  107.  
  108.     // we don't own write lock, try to acquire it
  109.     res = pthread_rwlock_wrlock(&rrwl->rwlock);
  110.     if (res)
  111.         return res;
  112.  
  113.     rrw_acquire_mux(rrwl);
  114.         assert(rrwl->recursive_wlocks == 0);
  115.         rrwl->recursive_wlocks = 1;
  116.         rrwl->write_owner = self;
  117.     rrw_release_mux(rrwl);
  118.  
  119.     return 0;
  120. }
  121.  
  122. // release write lock
  123. int rrw_write_unlock(rrw_lock_t *rrwl)
  124. {
  125.     int res = 0;
  126.  
  127.     rrw_acquire_mux(rrwl);
  128.         // shouldn't be calling this if not the owner
  129.         assert(rrwl->recursive_wlocks &&
  130.                pthread_equal(pthread_self(), rrwl->write_owner));
  131.  
  132.         if (rrwl->recursive_wlocks > 1)
  133.         {
  134.             --(rrwl->recursive_wlocks);
  135.         }
  136.         else
  137.         {
  138.              res = pthread_rwlock_unlock(&rrwl->rwlock);
  139.              if (!res)
  140.                 rrwl->recursive_wlocks = 0;
  141.         }
  142.     rrw_release_mux(rrwl);
  143.  
  144.     return res;
  145. }
  146.  
  147.  
  148. //-----------------------------------------------------------------------------
  149. // Test code
  150.  
  151. typedef struct
  152. {
  153.     rrw_lock_t *rrwl;
  154.     int thread_num;
  155. } thread_param;
  156.  
  157. void* reader_thread(void *p)
  158. {
  159.     int counter = 0;
  160.     thread_param tp = *((thread_param*)p);
  161.     free(p);
  162.  
  163.     for (;;)
  164.     {
  165.         rrw_read_lock(tp.rrwl);
  166.         rrw_read_lock(tp.rrwl);
  167.         rrw_read_unlock(tp.rrwl);
  168.         rrw_read_unlock(tp.rrwl);
  169.         if (++counter % 10000 == 0)
  170.         {
  171.             counter = 0;
  172.             fprintf(stderr, "Reader %d alive\n", tp.thread_num);
  173.         }
  174.     }
  175.  
  176.     return 0;
  177. }
  178.  
  179. void* writer_thread(void *p)
  180. {
  181.     int counter = 0;
  182.     thread_param tp = *((thread_param*)p);
  183.     free(p);
  184.  
  185.     for (;;)
  186.     {
  187.        
  188.         rrw_write_lock(tp.rrwl);
  189.         rrw_write_lock(tp.rrwl);
  190.         rrw_write_unlock(tp.rrwl);
  191.         rrw_write_unlock(tp.rrwl);
  192.         fprintf(stderr,"writer\n");
  193.         fprintf(stderr,"writer: count: %i\n",counter);
  194.         if (++counter % 500000 == 0)
  195.         {
  196.    
  197.             counter = 0;
  198.             fprintf(stderr, "Writer %d alive\n", tp.thread_num);
  199.         }
  200.     }
  201.  
  202.     return 0;
  203. }
  204.  
  205. #define NUM_READERS 4
  206. #define NUM_WRITERS 2
  207.  
  208. int main()
  209. {
  210.     int n, res;
  211.     rrw_lock_t l;
  212.     pthread_t readers[NUM_READERS];
  213.     pthread_t writers[NUM_WRITERS];
  214.  
  215.     res = rrw_init(&l);
  216.     if (res)
  217.     {
  218.         perror("rrw_init");
  219.         exit(res);
  220.     }
  221.  
  222.     fprintf(stderr, "Starting %d readers and %d writers\n",
  223.             NUM_READERS, NUM_WRITERS);
  224.  
  225.     for (n = 0; n < NUM_READERS; ++n)
  226.     {
  227.         thread_param *tp = malloc(sizeof(thread_param));
  228.         tp->rrwl = &l;
  229.         tp->thread_num = n + 1;
  230.  
  231.         res = pthread_create(readers + n, NULL, &reader_thread, tp);
  232.         if (res)
  233.         {
  234.             perror("reader-pthread_create");
  235.             exit(res);
  236.         }
  237.     }
  238.  
  239.     for (n = 0; n < NUM_WRITERS; ++n)
  240.     {
  241.         thread_param *tp = malloc(sizeof(thread_param));
  242.         tp->rrwl = &l;
  243.         tp->thread_num = n + 1;
  244.  
  245.         res = pthread_create(writers + n, NULL, &writer_thread, tp);
  246.         if (res)
  247.         {
  248.             perror("writer-pthread_create");
  249.             exit(res);
  250.         }
  251.     }
  252.  
  253.     // currently runs for ever, make sure all threads continue to ouput to stderr
  254.  
  255.     for (n = 0; n < NUM_READERS; ++n)
  256.         pthread_join(readers[n], NULL);
  257.    
  258.     for (n = 0; n < NUM_WRITERS; ++n)
  259.         pthread_join(writers[n], NULL);
  260.  
  261.     res = rrw_destroy(&l);
  262.     if (res)
  263.         perror("rrw_destroy");
  264.     return res;
  265. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement