1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/prctl.h>
#include <pthread.h>
#include <unistd.h>
#include "./weaver.h"
#include "../libcap/execable.h"
static pthread_mutex_t mu;
static pthread_cond_t cond; /* this is only used to wait on 'state' changes */
static int primed = 0;
static int counter = 0;
static int total = 0;
static int trigger = 0; /* 0=wait, 1=tick, 2=exit */
static void *run_thread(void *ignored)
{
pthread_mutex_lock(&mu);
do {
primed++;
while (trigger == 0) {
pthread_cond_signal(&cond);
pthread_cond_wait(&cond, &mu);
}
if (trigger == 1) {
counter++;
total += prctl(PR_GET_KEEPCAPS, 0, 0, 0, 0, 0)+2;
primed--;
while (trigger == 1) {
pthread_cond_signal(&cond);
pthread_cond_wait(&cond, &mu);
}
}
} while (trigger != 2);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mu);
return NULL;
}
pthread_t weaver_thread(void)
{
pthread_t th;
pthread_create(&th, NULL, run_thread, NULL);
return th;
}
void weaver_setup(void)
{
pthread_mutex_init(&mu, NULL);
pthread_cond_init(&cond, NULL);
}
int weaver_waitforit(int n)
{
pthread_mutex_lock(&mu);
counter = 0;
total = 0;
pthread_mutex_unlock(&mu);
/* be sure that the above happens before triggering */
pthread_mutex_lock(&mu);
while (primed < n) {
pthread_cond_signal(&cond);
pthread_cond_wait(&cond, &mu);
}
trigger = 1;
while (counter < n) {
pthread_cond_signal(&cond);
pthread_cond_wait(&cond, &mu);
}
trigger = 0;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mu);
return total;
}
void weaver_terminate(void)
{
pthread_mutex_lock(&mu);
trigger = 2;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mu);
}
#define N_THREADS 10
SO_MAIN(int argc, char **argv) {
int i;
pthread_t arr[N_THREADS];
weaver_setup();
for (i = 0; i < N_THREADS; i++) {
long int val = !(i & 1);
prctl(PR_SET_KEEPCAPS, val, 0, 0, 0, 0, 0);
arr[i] = weaver_thread();
}
int n = weaver_waitforit(N_THREADS);
weaver_terminate();
for (i = 0; i < N_THREADS; i++) {
pthread_join(arr[i], NULL);
}
if (n != 25) {
printf("FAILED: got=%d, want=25\n", n);
exit(1);
}
printf("PASSED\n");
}
|