1 2 3 4 typedef struct _counter_t { int global; // global count pthread_mutex_t glock; // global lock int local [NUMCPUS
-
- Site Admin
- Posts: 899603
- Joined: Mon Aug 02, 2021 8:13 am
1 2 3 4 typedef struct _counter_t { int global; // global count pthread_mutex_t glock; // global lock int local [NUMCPUS
getexact(counter *c) which
always returns the globally exact value of the counter
rather than an approximation.
b. Explain the factors that would affect the performance
of your extended
implementation.
c. Explain why your extended implementation cannot
deadlock.
1 2 3 4 typedef struct _counter_t { int global; // global count pthread_mutex_t glock; // global lock int local [NUMCPUS]; // per-CPU count pthread_mutex_t llock [NUMCPUS); // ... and locks int threshold; // update frequency } counter_t; 5 6 7 8 9 10 11 12 = 13 14 // init: record threshold, init locks, init values // of all local counts and global count void init (counter_t *c, int threshold) { C->threshold threshold; c->global = 0; pthread_mutex_init(&c->glock, NULL); int i; for (i = 0; i < NUMCPUS; i++) { c->local 0; pthread_mutex_init(&C->llock, NULL); } } 15 16 17 = 18 19 20 21 22 23 24 25 26 27 28 // update: usually, just grab local lock and update // local amount; once local count has risen 'threshold', // grab global lock and transfer local values to it void update (counter_t *c, int threadID, int amt) { int cpu = threadID % NUMCPUS; pthread_mutex_lock (&c->llock [cpu]); c->local[cpu] += amt; if (c->local[cpu] >= c->threshold) { // transfer to global (assumes amt>0) pthread_mutex_lock (&c->glock); c->global += c->local [cpu); pthread_mutex_unlock (&C->glock); c->local [cpu] = 0; } pthread_mutex_unlock (&c->llock[cpu]); } 30 31 32 33 34 -35 36 37 38
38 39 40 41 42 // get: just return global amount (approximate) int get (counter_t *c) { pthread_mutex_lock (&c->glock); int val c->global; pthread_mutex_unlock (&c->glock); return val; // only approximate! } = 43 44 45