diff options
Diffstat (limited to 'newlib/libc/sys/linux/linuxthreads/tst-cancel.c')
-rw-r--r-- | newlib/libc/sys/linux/linuxthreads/tst-cancel.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/newlib/libc/sys/linux/linuxthreads/tst-cancel.c b/newlib/libc/sys/linux/linuxthreads/tst-cancel.c new file mode 100644 index 0000000..da32aaf --- /dev/null +++ b/newlib/libc/sys/linux/linuxthreads/tst-cancel.c @@ -0,0 +1,213 @@ +/* Tests for cancelation handling. */ + +#include <pthread.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> + +int fd; + +pthread_barrier_t bar; + + +static void +cleanup (void *arg) +{ + int nr = (int) (long int) arg; + char s[30]; + char *cp = stpcpy (s, "cleanup "); + *cp++ = '0' + nr; + *cp++ = '\n'; + __libc_lseek (fd, 0, SEEK_END); + __libc_write (fd, s, cp - s); +} + + +static void * +t1 (void *arg) +{ + pthread_cleanup_push (cleanup, (void *) (long int) 1); + return NULL; + pthread_cleanup_pop (0); +} + + +static void +inner (int a) +{ + pthread_cleanup_push (cleanup, (void *) (long int) a); + if (a) + return; + pthread_cleanup_pop (0); +} + + +static void * +t2 (void *arg) +{ + pthread_cleanup_push (cleanup, (void *) (long int) 2); + inner ((int) (long int) arg); + return NULL; + pthread_cleanup_pop (0); +} + + +/* This does not work yet. */ +volatile int cleanupokcnt; + +static void +cleanupok (void *arg) +{ + ++cleanupokcnt; +} + + +static void * +t3 (void *arg) +{ + pthread_cleanup_push (cleanupok, (void *) (long int) 4); + inner ((int) (long int) arg); + pthread_exit (NULL); + pthread_cleanup_pop (0); +} + + +static void +innerok (int a) +{ + pthread_cleanup_push (cleanupok, (void *) (long int) a); + pthread_exit (NULL); + pthread_cleanup_pop (0); +} + + +static void * +t4 (void *arg) +{ + pthread_cleanup_push (cleanupok, (void *) (long int) 6); + innerok ((int) (long int) arg); + pthread_cleanup_pop (0); + return NULL; +} + + +int +main (int argc, char *argv[]) +{ + pthread_t td; + int err; + char *tmp; + const char *prefix; + const char template[] = "thtstXXXXXX"; + struct stat64 st; + int result = 0; + + prefix = argc > 1 ? argv[1] : ""; + tmp = (char *) alloca (strlen (prefix) + sizeof template); + strcpy (stpcpy (tmp, prefix), template); + + fd = mkstemp (tmp); + if (fd == -1) + { + printf ("cannot create temporary file: %m"); + exit (1); + } + unlink (tmp); + + err = pthread_barrier_init (&bar, NULL, 2); + if (err != 0 ) + { + printf ("cannot create barrier: %s\n", strerror (err)); + exit (1); + } + +#ifdef NOT_YET + err = pthread_create (&td, NULL, t1, NULL); + if (err != 0) + { + printf ("cannot create thread t1: %s\n", strerror (err)); + exit (1); + } + + err = pthread_join (td, NULL); + if (err != 0) + { + printf ("cannot join thread: %s\n", strerror (err)); + exit (1); + } + + err = pthread_create (&td, NULL, t2, (void *) 3); + if (err != 0) + { + printf ("cannot create thread t2: %s\n", strerror (err)); + exit (1); + } + + err = pthread_join (td, NULL); + if (err != 0) + { + printf ("cannot join thread: %s\n", strerror (err)); + exit (1); + } + + err = pthread_create (&td, NULL, t3, (void *) 5); + if (err != 0) + { + printf ("cannot create thread t3: %s\n", strerror (err)); + exit (1); + } + + err = pthread_join (td, NULL); + if (err != 0) + { + printf ("cannot join thread: %s\n", strerror (err)); + exit (1); + } +#endif + + err = pthread_create (&td, NULL, t4, (void *) 7); + if (err != 0) + { + printf ("cannot create thread t3: %s\n", strerror (err)); + exit (1); + } + + err = pthread_join (td, NULL); + if (err != 0) + { + printf ("cannot join thread: %s\n", strerror (err)); + exit (1); + } + + if (fstat64 (fd, &st) < 0) + { + printf ("cannot stat temporary file: %m\n"); + result = 1; + } + else if (st.st_size != 0) + { + char buf[512]; + puts ("some cleanup handlers ran:"); + fflush (stdout); + __lseek (fd, 0, SEEK_SET); + while (1) + { + ssize_t n = read (fd, buf, sizeof buf); + if (n <= 0) + break; + write (STDOUT_FILENO, buf, n); + } + result = 1; + } + + // if (cleanupokcnt != 3) will be three once t3 runs + if (cleanupokcnt != 2) + { + printf ("cleanupokcnt = %d\n", cleanupokcnt); + result = 1; + } + + return result; +} |