xref: /dragonfly/test/stress/stress2/misc/pthread.sh (revision 6e278935)
1#!/bin/sh
2
3#
4# Copyright (c) 2008 Peter Holm <pho@FreeBSD.org>
5# All rights reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27#
28# $FreeBSD$
29#
30
31# panic: spin lock held too long
32
33# Test program and scenario by Peter Wemm <peter@FreeBSD.org>
34
35. ../default.cfg
36
37odir=`pwd`
38
39cd /tmp
40sed '1,/^EOF/d' < $odir/$0 > pth.c
41cc -o pth -Wall pth.c -pthread
42rm -f pth.c
43cd $odir
44
45for i in `jot 2000`; do
46	date
47	/tmp/pth
48done
49
50rm -f /tmp/pth
51exit
52EOF
53#include <pthread.h>
54
55#include <sys/types.h>
56#include <stdlib.h>
57#include <unistd.h>
58#include <string.h>
59#include <stdio.h>
60
61static pthread_t worker1_thr;
62static pthread_t worker2_thr;
63
64static pthread_mutex_t worker_mtx;
65static pthread_cond_t worker_go;
66static pthread_cond_t worker_done;
67
68struct workitem {
69	struct workitem *next;
70	int a, b;
71};
72
73struct workitem *head;
74
75static void *
76worker(void *arg)
77{
78	struct workitem *w;
79
80	pthread_detach(pthread_self());
81	fprintf(stderr, "WORKER: started %p\n", arg); fflush(stderr);
82
83	for (;;) {
84		pthread_mutex_lock(&worker_mtx);
85		while (head == NULL) {
86			pthread_cond_wait(&worker_go, &worker_mtx);
87		}
88		w = head;
89		head = w->next;
90		pthread_mutex_unlock(&worker_mtx);
91
92		fprintf(stderr, "WORKER(%p): got work a=%d b=%d\n", arg, w->a, w->b); fflush(stderr);
93		free(w);
94		pthread_cond_signal(&worker_done);
95	}
96}
97
98void
99work_add(int a, int b)
100{
101	struct workitem *w;
102	int dowake = 0;
103
104	w = calloc(sizeof(*w), 1);
105	w->a = a;
106	w->b = b;
107	pthread_mutex_lock(&worker_mtx);
108	if (head == 0)
109		dowake = 1;
110	w->next = head;
111	head = w;
112	pthread_mutex_unlock(&worker_mtx);
113	if (dowake)
114		pthread_cond_signal(&worker_go);
115}
116
117int
118main()
119{
120        pthread_mutex_init(&worker_mtx, NULL);
121        pthread_cond_init(&worker_go, NULL);
122        pthread_cond_init(&worker_done, NULL);
123
124	fprintf(stderr, "pthread create\n"); fflush(stderr);
125        pthread_create(&worker1_thr, NULL, worker, (void *)1);
126        pthread_create(&worker2_thr, NULL, worker, (void *)2);
127
128	work_add(10, 15);
129	work_add(11, 22);
130	work_add(314, 159);
131
132	pthread_mutex_lock(&worker_mtx);
133	while (head != NULL) {
134		pthread_cond_wait(&worker_done, &worker_mtx);
135	}
136	pthread_mutex_unlock(&worker_mtx);
137
138	fprintf(stderr, "job complete\n"); fflush(stderr);
139	exit(0);
140}
141