117 lines · 2.7 KB · C
RawDownload
/* SPDX-License-Identifier: GPL-2.0-or-later */ #ifndef _FUTEX_THREAD_H#define _FUTEX_THREAD_H#include <errno.h>#include <pthread.h>#include <stdio.h>#include <string.h>#include <unistd.h> #include "kselftest_harness.h" #define USEC_PER_SEC		1000000L#define WAIT_FOR_THREAD_SECS	1#define WAIT_FOR_THREAD_USECS	(WAIT_FOR_THREAD_SECS * USEC_PER_SEC)#define WAIT_THREAD_RETRIES	100 struct futex_thread {	pthread_t		thread;	pthread_barrier_t	barrier;	pid_t			tid;	int			(*threadfn)(void *arg);	void			*arg;	int			retval;}; static inline int __wait_for_thread(FILE *fp, struct __test_metadata *_metadata){	unsigned int sleep_time_us = WAIT_FOR_THREAD_USECS / WAIT_THREAD_RETRIES;	char buf[80] = ""; 	for (int i = 0; i < WAIT_THREAD_RETRIES; i++) {		if (!fgets(buf, sizeof(buf), fp))			return EIO;		if (!strncmp(buf, "futex", 5))			return 0;		usleep(sleep_time_us);		rewind(fp);	} 	TH_LOG("/proc/$PID/wchan contains \"%s\". Trying to continue.", buf);	return 0;} static void *__futex_thread_fn(void *arg){	struct futex_thread *t = arg; 	t->tid = gettid();	pthread_barrier_wait(&t->barrier);	t->retval = t->threadfn(t->arg);	return NULL;} /** * futex_wait_for_thread - Wait for the child thread to sleep in the futex context * @t:          Thread handle. * @_metadata:	Test metadata for TH_LOG() context */static inline int futex_wait_for_thread(struct futex_thread *t, struct __test_metadata *_metadata){	char fname[80];	FILE *fp;	int res; 	snprintf(fname, sizeof(fname), "/proc/%d/wchan", t->tid);	fp = fopen(fname, "r");	if (!fp) {		/* If /proc/... is not available, sleep */		if (errno != ENOENT)			return errno;		TH_LOG("/proc/$PID/wchan not accessible, continue with sleep()");		sleep(WAIT_FOR_THREAD_SECS);		return 0;	} 	res = __wait_for_thread(fp, _metadata);	fclose(fp);	return res;} /** * futex_thread_create - Create a new thread for testing. * @t:        The handle of the newly created thread. * @threadfn: The new thread starts execution by invoking threadfn * @arg:      The parameters passed to threadfn. */static inline int futex_thread_create(struct futex_thread *t, int (*threadfn)(void *), void *arg){	pthread_barrier_init(&t->barrier, NULL, 2); 	t->tid = 0;	t->threadfn = threadfn;	t->arg = arg; 	if (pthread_create(&t->thread, NULL, __futex_thread_fn, t) < 0) {		int ret = errno;		pthread_barrier_destroy(&t->barrier);		return ret;	} 	pthread_barrier_wait(&t->barrier);	return 0;} /** * futex_thread_destroy - Wait for and reclaim the resources of the thread. * @t:      Thread handle. */static inline int futex_thread_destroy(struct futex_thread *t){	pthread_join(t->thread, NULL);	pthread_barrier_destroy(&t->barrier);	return t->retval;} #endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t