mirror of
https://git.kernel.org/pub/scm/libs/libcap/libcap.git
synced 2026-01-26 15:39:08 +00:00
This isn't fixing a known issue, but more preparing for a potential PSX mechanism error. Signed-off-by: Andrew G. Morgan <morgan@kernel.org>
109 lines
2.2 KiB
C
109 lines
2.2 KiB
C
#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");
|
|
}
|