2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A/*
2N/A * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
2N/A * Use is subject to license terms.
2N/A */
2N/A
2N/A .file "unwind_frame.s"
2N/A
2N/A#include <SYS.h>
2N/A
2N/A/* Cancellation/thr_exit() stuff */
2N/A
2N/A/*
2N/A * _ex_unwind_local(void)
2N/A *
2N/A * Called only from _t_cancel().
2N/A * Unwind two frames and invoke _t_cancel(fp) again.
2N/A *
2N/A * Before this the call stack is: f4 f3 f2 f1 _t_cancel
2N/A * After this the call stack is: f4 f3 f2 _t_cancel
2N/A * (as if "call f1" is replaced by "call _t_cancel(fp)" in f2)
2N/A */
2N/A
2N/A ENTRY(_ex_unwind_local)
2N/A movl (%ebp), %edx / pop first frame [ back to f1() ]
2N/A movl (%edx), %ebp / pop second frame [ back to f2() ]
2N/A movl 4(%edx), %eax / save f2's return pc
2N/A movl %eax, (%edx) / mov it up for one arg
2N/A movl %edx, %esp / stack pointer at ret addr
2N/A movl %ebp, 4(%esp)
2N/A jmp _t_cancel
2N/A SET_SIZE(_ex_unwind_local)
2N/A
2N/A/*
2N/A * _ex_clnup_handler(void *arg, void (*clnup)(void *))
2N/A *
2N/A * Called only from _t_cancel().
2N/A * Unwind one frame, call the cleanup handler with argument arg from the
2N/A * restored frame, then jump to _t_cancel(fp) again from the restored frame.
2N/A */
2N/A
2N/A ENTRY(_ex_clnup_handler)
2N/A pushl %ebp / save current frame pointer
2N/A pushl 8(%esp) / first argument [arg]
2N/A movl (%ebp), %ebp / pop out one frame
2N/A call *16(%esp) / call handler [clnup]
2N/A addl $4, %esp
2N/A popl %eax / old frame pointer
2N/A lea 4(%eax), %esp / stk points to old frame
2N/A movl %ebp, 4(%esp) / _t_cancel() gets frame pointer arg
2N/A jmp _t_cancel
2N/A SET_SIZE(_ex_clnup_handler)
2N/A
2N/A/*
2N/A * _thrp_unwind(void *arg)
2N/A *
2N/A * Ignore the argument; jump to _t_cancel(fp) with caller's fp
2N/A */
2N/A ENTRY(_thrp_unwind)
2N/A movl %ebp, 4(%esp)
2N/A jmp _t_cancel
2N/A SET_SIZE(_thrp_unwind)