1112918Sjeff/*
2112918Sjeff * Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
3112918Sjeff * All rights reserved.
4112918Sjeff *
5112918Sjeff * Redistribution and use in source and binary forms, with or without
6112918Sjeff * modification, are permitted provided that the following conditions
7112918Sjeff * are met:
8112918Sjeff * 1. Redistributions of source code must retain the above copyright
9112918Sjeff *    notice, this list of conditions and the following disclaimer.
10112918Sjeff * 2. Redistributions in binary form must reproduce the above copyright
11112918Sjeff *    notice, this list of conditions and the following disclaimer in the
12112918Sjeff *    documentation and/or other materials provided with the distribution.
13165967Simp * 3. Neither the name of the author nor the names of any co-contributors
14112918Sjeff *    may be used to endorse or promote products derived from this software
15112918Sjeff *    without specific prior written permission.
16112918Sjeff *
17112918Sjeff * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
18112918Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19112918Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20112918Sjeff * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21112918Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22112918Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23112918Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24112918Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25112918Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26112918Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27112918Sjeff * SUCH DAMAGE.
28112918Sjeff *
29112918Sjeff * $FreeBSD$
30112918Sjeff */
31144518Sdavidxu
32157457Sdavidxu#include "namespace.h"
33112918Sjeff#include <signal.h>
34112918Sjeff#include <errno.h>
35112918Sjeff#include <stdlib.h>
36112918Sjeff#include <pthread.h>
37157457Sdavidxu#include "un-namespace.h"
38144518Sdavidxu
39112918Sjeff#include "thr_private.h"
40112918Sjeff
41179662Sdavidxu#undef pthread_cleanup_push
42179662Sdavidxu#undef pthread_cleanup_pop
43179662Sdavidxu
44179662Sdavidxu/* old binary compatible interfaces */
45112918Sjeff__weak_reference(_pthread_cleanup_push, pthread_cleanup_push);
46112918Sjeff__weak_reference(_pthread_cleanup_pop, pthread_cleanup_pop);
47112918Sjeff
48112918Sjeffvoid
49179662Sdavidxu__pthread_cleanup_push_imp(void (*routine)(void *), void *arg,
50179662Sdavidxu	struct _pthread_cleanup_info *info)
51112918Sjeff{
52144518Sdavidxu	struct pthread	*curthread = _get_curthread();
53179662Sdavidxu	struct pthread_cleanup *newbuf;
54112918Sjeff
55179662Sdavidxu	newbuf = (void *)info;
56179662Sdavidxu	newbuf->routine = routine;
57179662Sdavidxu	newbuf->routine_arg = arg;
58179662Sdavidxu	newbuf->onheap = 0;
59179662Sdavidxu	newbuf->prev = curthread->cleanup;
60179662Sdavidxu	curthread->cleanup = newbuf;
61112918Sjeff}
62112918Sjeff
63112918Sjeffvoid
64179662Sdavidxu__pthread_cleanup_pop_imp(int execute)
65112918Sjeff{
66144518Sdavidxu	struct pthread	*curthread = _get_curthread();
67112918Sjeff	struct pthread_cleanup *old;
68112918Sjeff
69112918Sjeff	if ((old = curthread->cleanup) != NULL) {
70179662Sdavidxu		curthread->cleanup = old->prev;
71179662Sdavidxu		if (execute)
72112918Sjeff			old->routine(old->routine_arg);
73179662Sdavidxu		if (old->onheap)
74144518Sdavidxu			free(old);
75112918Sjeff	}
76112918Sjeff}
77179662Sdavidxu
78179662Sdavidxuvoid
79179662Sdavidxu_pthread_cleanup_push(void (*routine) (void *), void *arg)
80179662Sdavidxu{
81179662Sdavidxu	struct pthread	*curthread = _get_curthread();
82179662Sdavidxu	struct pthread_cleanup *newbuf;
83213163Sdavidxu#ifdef _PTHREAD_FORCED_UNWIND
84213159Sdavidxu	curthread->unwind_disabled = 1;
85213163Sdavidxu#endif
86179662Sdavidxu	if ((newbuf = (struct pthread_cleanup *)
87282224Spfg	    malloc(sizeof(struct pthread_cleanup))) != NULL) {
88179662Sdavidxu		newbuf->routine = routine;
89179662Sdavidxu		newbuf->routine_arg = arg;
90179662Sdavidxu		newbuf->onheap = 1;
91179662Sdavidxu		newbuf->prev = curthread->cleanup;
92179662Sdavidxu		curthread->cleanup = newbuf;
93179662Sdavidxu	}
94179662Sdavidxu}
95179662Sdavidxu
96179662Sdavidxuvoid
97179662Sdavidxu_pthread_cleanup_pop(int execute)
98179662Sdavidxu{
99179662Sdavidxu	__pthread_cleanup_pop_imp(execute);
100179662Sdavidxu}
101