📄 low.s
字号:
.seg "data" .asciz "@(#) low.s 1.1 92/07/30" .align 4 .seg "text"! Copyright (C) 1987 by Sun Microsystems, Inc.!! This source code is a product of Sun Microsystems, Inc. and is provided! for unrestricted use provided that this legend is included on all tape! media and as a part of the software program in whole or part. Users! may copy or modify this source code without charge, but are not authorized! to license or distribute it to anyone else except as part of a product or! program developed by the user.!! THIS PROGRAM CONTAINS SOURCE CODE COPYRIGHTED BY SUN MICROSYSTEMS, INC.! AND IS LICENSED TO SUNSOFT, INC., A SUBSIDIARY OF SUN MICROSYSTEMS, INC.! SUN MICROSYSTEMS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABLITY! OF SUCH SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT! EXPRESS OR IMPLIED WARRANTY OF ANY KIND. SUN MICROSYSTEMS, INC. DISCLAIMS! ALL WARRANTIES WITH REGARD TO SUCH SOURCE CODE, INCLUDING ALL IMPLIED! WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN! NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT,! INCIDENTAL, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING! FROM USE OF SUCH SOURCE CODE, REGARDLESS OF THE THEORY OF LIABILITY.!! This source code is provided with no support and without any obligation on! the part of Sun Microsystems, Inc. to assist in its use, correction, ! modification or enhancement.!! SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE! INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS! SOURCE CODE OR ANY PART THEREOF.!! Sun Microsystems, Inc.! 2550 Garcia Avenue! Mountain View, California 94043#include <sun4/trap.h>#include <sun4/asm_linkage.h>#include <sun4/psl.h>#include "low.h" .seg "text" .global ___schedule .global ___Curproc .global ___EventsPending .global ___AsynchLock .global ___fake_sig .global ___exchelpclean .global ___NuggetSP .global ___lwpkill .global ___AllFlushed!! assembly language support routines!! %sp (%o6) is stack pointer and points to register save area for current win.! %i7 is return address (ret will add 8 to be correct) to caller. ! %o7 is return address from call of leaf routine (use retl).! %fp (%i6) points to previous frame.! %g's are treated as temps by the compiler -- if they become truely global,! it may not be nec. to save/restore all of them since they behave like! shared memory.! %sp must point to a valid save area (16 words) when save is called.! %fp must point to a valid save area (16 words) when restore is called.! save/restore use %src in old window and %dst in new window! %sp MUST ALWAYS be valid. If you try to to sigcleanup() or restore! with a funky %sp, the kernel will do strange things. Note that! C assumes a valid %fp and can generate access to addresses above it.! __checkpoint()! Save context and reschedule.! The return address to the caller of checkpoint is in %o7.! Eventually, schedule calls swtch which! returns to the caller of checkpoint.! locals and ins are saved in register save area.! Since we call checkpoint voluntarily, %g's, %o's and %y need not be saved.! We are on a fast path after flushing the windows: if schedule() calls! swtch() directly, there is no need to flushh again.! checkpoint should be called while LOCKED. However, when! checkpoint returns via swtch, the state is UNLOCKED.LENTRY(checkpoint) ta ST_FLUSH_WINDOWS ! save all registers set 1, %g1 sethi %hi(___AllFlushed), %o2 st %g1, [%lo(___AllFlushed)+%o2] ! ___AllFlushed = TRUE! Now, we will reuse this window mercilesslly until there is a context switch.! We must be very careful to not flush or restore from this point! until we are ready, or we will store garbage in the current frame.! We are LOCKED, but this does! not prevent signals from arriving. We make sure %sp and %fp are valid! since we will call schedule() in C. Switching stacks also! ensures that if an interrupt happens,! the window flush will store the garbage on the nugget stack, not the client's. sethi %hi(___Curproc), %o2 ld [%o2 + %lo(___Curproc)], %o1 ! %o1 = __Curproc st %o7, [%o1+PC_OFFSET] ! pc when this thread resumes st %sp, [%o1+SP_OFFSET] ! save sp sethi %hi(___NuggetSP), %o1 ! get nugget stack ld [%o1 + %lo(___NuggetSP)], %sp ! switch stacks mov %sp, %fp ! valid %fp ba ___schedule + 4 ! add 4 to skip save at the beginning add %sp, -SA(MINFRAME), %sp ! simulate <%sp, %fp> paradigm wo save ! NOTREACHED ! __swtch()! switch context when not at interrupt level and the new thread! was not switched out asynchronously.! Since this was a voluntary scheduling (via a procedure call of the! thread), we don't need to worry about restoring psl and %o's which! were not saved in the save area, and %g's and %y which are not! preserved across procedure call.! Must be called while LOCKED.!! Context is restored BEFORE UNLOCK (i.e., clearing AsynchLock)! so that any interrupt will capture the correct context! (i.e., save the "backing store" version of the registers,! not the values in the registers at the time ___swtch is called).! We LOCK before calling fake_sig to prevent intrerrupts from! changing anything before fake_sig causes a scheduling decision.! We UNLOCK before testing EventsPending so a interrupt will! cause scheduling (and not just save info and set EventsPending),! even if we decided that EventsPending was false! (and then immediately got an interrupt).! Once we decided that EventsPending is true, it is safe to LOCK! again because setting EventsPending is idempotent.! If there is an interrupt just before we lock, it may cause the event! list to be cleaned out and the thread will be rescheduled here.! In that case, fake_sig may be called redundantly, but it won't hurt.! Note that lwp_full state is FALSE for fake_sig, so the pc will! be retrieved from the context, not the interrupt pc, and we will! add 8 to that to simulate the retl here.! fake_sig always returns via full_swtch.LENTRY(swtch) ta ST_FLUSH_WINDOWS ! so restore causes an underflowLENTRY(fastswtch) ! skip flush, already done sethi %hi(___Curproc), %o2 ld [%o2 + %lo(___Curproc)], %o1 ! %o1 = __Curproc ld [%o1+PC_OFFSET], %i7 ! restore pc into HIS %o7 ld [%o1+SP_OFFSET], %fp ! restore sp into HIS %o6 restore ! get back to the window where ! checkpoint was called, with underflow ! restoring %i's and %l's ! ASSERT(%sp is valid) before restore sethi %hi(___AsynchLock), %o1 clr [%o1 + %lo(___AsynchLock)] ! Allow interrupts sethi %hi(___EventsPending), %o2 ld [%o2 + %lo(___EventsPending)], %o1 cmp %g0, %o1 ! check for pending events be 1f ! none or %g0,1, %o1 ! lock before calling fake_sig sethi %hi(___AsynchLock), %o2 st %o1, [%lo(___AsynchLock) + %o2]! His state is still valid in the context block and his windows! were flushed when he was scheduled out, so no need to flush here sethi %hi(___NuggetSP), %o1 ! swtch to __NuggetSP call ___fake_sig ! process events -- fake an interrupt ld [%lo(___NuggetSP) + %o1], %sp ! don't use client sp for intr. ! ___fake_sig will save to provide %fp unimp 0 ! just in case it returns /*NOTREACHED*/1: retl ! jump to lowinit or back to caller of nop ! checkpoint! __lowinit()! Control gets here from returning from swtch() the first time a thread runs.! We copy the %i's (parameters to thread initial routine) to the %o's! to make it look like we are calling the thread with these args.! The frame is already set up to have any additional args on it, etc.!LENTRY(lowinit) mov %i0, %o0 ! put parameters to right place mov %i1, %o1 mov %i2, %o2 mov %i3, %o3 mov %i4, %o4 mov %i5, %o5 set ___lwpkill - 8, %o7 ! When dying, go here: %i7 of thread jmp %i7 ! load pc mov %i6, %o6 ! and sp! __unlock()! Unlock a critical section.! If events have occurred while LOCKED, call fake_sig (which calls! do_agent) to simulate a signal and cause all pending evnets to! be processed. Context must be saved before calling fake_sig! because fake_sig will cause a scheduling decision.! Context is saved while LOCKED to prevent signals from preserving! an incorrect state before the correct state is established.! EventsPending is tested while UNLOCKED for the same reason as! in swtch. Note that we use the nugget stack to process interrupts on:! some clients may use the area below their stack for a quick and dirty! malloc and we don't want to trash it.LENTRY(unlock) sethi %hi(___AsynchLock), %o1 ! ___AsynchLock = 0; clr [%lo(___AsynchLock) + %o1] sethi %hi(___EventsPending), %o3 ! if (___EventsPending == 0) ld [%lo(___EventsPending) + %o3], %o2 tst %o2 be 1f ! nothing to do or %g0,1, %o2 st %o2, [%lo(___AsynchLock) + %o1] ! ___AsynchLock = 1; sethi %hi(___Curproc), %o2 ld [%lo(___Curproc) + %o2], %o1 ! %o1 = __Curproc st %sp, [%o1+SP_OFFSET] ! store sp st %o7, [%o1+PC_OFFSET] ! pc when this thread resumes sethi %hi(___NuggetSP), %o1 ! switch to NuggetSP (AFTER saving state) ta ST_FLUSH_WINDOWS ! save his window state -- it's ! not kept anywhere else now call ___fake_sig ld [%lo(___NuggetSP) + %o1], %sp ! switch stacks unimp 0 ! just in case it returns ! NOTREACHED1: retl nop! __interrupt()! our own version of sigtramp with no floating point stuff saved.! called when an interrupt or trap occurs.!! On entry sp points to:! 0 - 63: window save area! 64: signal number! 68: signal code! 72: pointer to sigcontext! 76: addr parameter!! A sigcontext looks like:! 00: on signal stack flag! 04: old signal mask! 08: old sp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -